diff options
Diffstat (limited to 'source/blender/blenkernel')
261 files changed, 5914 insertions, 4395 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 9162ed56655..76c610fb5bd 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_DERIVEDMESH_H__ -#define __BKE_DERIVEDMESH_H__ +#pragma once /** \file * \ingroup bke @@ -382,7 +381,6 @@ void DM_calc_loop_tangents(DerivedMesh *dm, #ifndef NDEBUG char *DM_debug_info(DerivedMesh *dm); void DM_debug_print(DerivedMesh *dm); -void DM_debug_print_cdlayers(CustomData *cdata); bool DM_is_valid(DerivedMesh *dm); #endif @@ -390,5 +388,3 @@ bool DM_is_valid(DerivedMesh *dm); #ifdef __cplusplus } #endif - -#endif /* __BKE_DERIVEDMESH_H__ */ diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 104582be932..e08604f02ad 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_ACTION_H__ -#define __BKE_ACTION_H__ +#pragma once /** \file * \ingroup bke @@ -32,6 +31,7 @@ extern "C" { #endif /* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */ +struct AnimationEvalContext; struct FCurve; struct Main; struct Object; @@ -128,6 +128,8 @@ void BKE_pose_channel_free(struct bPoseChannel *pchan); void BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user); void BKE_pose_channel_runtime_reset(struct bPoseChannel_Runtime *runtime); +void BKE_pose_channel_runtime_reset_on_copy(struct bPoseChannel_Runtime *runtime); + void BKE_pose_channel_runtime_free(struct bPoseChannel_Runtime *runtime); void BKE_pose_channel_free_bbone_cache(struct bPoseChannel_Runtime *runtime); @@ -152,12 +154,15 @@ void BKE_pose_copy_data_ex(struct bPose **dst, const bool copy_constraints); void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool copy_constraints); void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from); +void BKE_pose_channel_session_uuid_generate(struct bPoseChannel *pchan); struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name); struct bPoseChannel *BKE_pose_channel_active(struct Object *ob); struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob); struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name); struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name); +void BKE_pose_check_uuids_unique_and_report(const struct bPose *pose); + #ifndef NDEBUG bool BKE_pose_channels_is_valid(const struct bPose *pose); #endif @@ -202,14 +207,14 @@ void what_does_obaction(struct Object *ob, struct bPose *pose, struct bAction *act, char groupname[], - float cframe); + const struct AnimationEvalContext *anim_eval_context); /* for proxy */ void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto, const struct bPoseChannel *pchanfrom); bool BKE_pose_copy_result(struct bPose *to, struct bPose *from); -/* clear all transforms */ -void BKE_pose_rest(struct bPose *pose); +/* Clear transforms. */ +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); @@ -217,5 +222,3 @@ void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose); #ifdef __cplusplus }; #endif - -#endif diff --git a/source/blender/blenkernel/BKE_addon.h b/source/blender/blenkernel/BKE_addon.h index 741be17bb25..73e3f6e41dc 100644 --- a/source/blender/blenkernel/BKE_addon.h +++ b/source/blender/blenkernel/BKE_addon.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_ADDON_H__ -#define __BKE_ADDON_H__ +#pragma once /** \file * \ingroup bke @@ -56,5 +55,3 @@ void BKE_addon_free(struct bAddon *addon); #ifdef __cplusplus } #endif - -#endif /* __BKE_ADDON_H__ */ diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h index 5aeaf4405f5..189e45f4fe5 100644 --- a/source/blender/blenkernel/BKE_anim_data.h +++ b/source/blender/blenkernel/BKE_anim_data.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_ANIM_DATA_H__ -#define __BKE_ANIM_DATA_H__ +#pragma once /** \file * \ingroup bke @@ -71,7 +70,11 @@ bool BKE_animdata_copy_id(struct Main *bmain, const int flag); /* Copy AnimData Actions */ -void BKE_animdata_copy_id_action(struct Main *bmain, struct ID *id, const bool set_newid); +void BKE_animdata_copy_id_action(struct Main *bmain, struct ID *id); + +void BKE_animdata_duplicate_id_action(struct Main *bmain, + struct ID *id, + const uint duplicate_flags); /* Merge copies of data from source AnimData block */ typedef enum eAnimData_MergeCopy_Modes { @@ -94,5 +97,3 @@ void BKE_animdata_merge_copy(struct Main *bmain, #ifdef __cplusplus } #endif - -#endif /* __BKE_ANIM_DATA_H__*/ diff --git a/source/blender/blenkernel/BKE_anim_path.h b/source/blender/blenkernel/BKE_anim_path.h index 4de853303ad..ae2d13530ed 100644 --- a/source/blender/blenkernel/BKE_anim_path.h +++ b/source/blender/blenkernel/BKE_anim_path.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_ANIM_PATH_H__ -#define __BKE_ANIM_PATH_H__ +#pragma once /** \file * \ingroup bke @@ -47,5 +46,3 @@ bool where_on_path(const struct Object *ob, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_anim_visualization.h b/source/blender/blenkernel/BKE_anim_visualization.h index 5dcbfa0919e..fb7875a112e 100644 --- a/source/blender/blenkernel/BKE_anim_visualization.h +++ b/source/blender/blenkernel/BKE_anim_visualization.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_ANIM_VISUALIZATION_H__ -#define __BKE_ANIM_VISUALIZATION_H__ +#pragma once /** \file * \ingroup bke @@ -52,5 +51,3 @@ struct bMotionPath *animviz_verify_motionpaths(struct ReportList *reports, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 4a2ad28f90f..ef74bb61a7e 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_ANIMSYS_H__ -#define __BKE_ANIMSYS_H__ +#pragma once /** \file * \ingroup bke @@ -48,6 +47,23 @@ struct bAction; struct bActionGroup; struct bContext; +/* Container for data required to do FCurve and Driver evaluation. */ +typedef struct AnimationEvalContext { + /* For drivers, so that they have access to the dependency graph and the current view layer. See + * T77086. */ + struct Depsgraph *depsgraph; + + /* FCurves and Drivers can be evaluated at a different time than the current scene time, for + * example when evaluating NLA strips. This means that, even though the current time is stored in + * the dependency graph, we need an explicit evaluation time. */ + float eval_time; +} AnimationEvalContext; + +AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, + float eval_time); +AnimationEvalContext BKE_animsys_eval_context_construct_at( + const AnimationEvalContext *anim_eval_context, float eval_time); + /* ************************************* */ /* KeyingSets API */ @@ -131,17 +147,18 @@ bool BKE_animdata_fix_paths_remove(struct ID *id, const char *path); /* -------------------------------------- */ +typedef struct AnimationBasePathChange { + struct AnimationBasePathChange *next, *prev; + const char *src_basepath; + const char *dst_basepath; +} AnimationBasePathChange; + /* Move animation data from src to destination if it's paths are based on basepaths */ -void BKE_animdata_separate_by_basepath(struct Main *bmain, +void BKE_animdata_transfer_by_basepath(struct Main *bmain, struct ID *srcID, struct ID *dstID, struct ListBase *basepaths); -/* Move F-Curves from src to destination if it's path is based on basepath */ -void action_move_fcurves_by_basepath(struct bAction *srcAct, - struct bAction *dstAct, - const char basepath[]); - char *BKE_animdata_driver_path_hack(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, @@ -172,11 +189,12 @@ void BKE_fcurves_id_cb(struct ID *id, ID_FCurve_Edit_Callback func, void *user_d typedef struct NlaKeyframingContext NlaKeyframingContext; -struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *cache, - struct PointerRNA *ptr, - struct AnimData *adt, - float ctime, - const bool flush_to_original); +struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( + struct ListBase *cache, + struct PointerRNA *ptr, + struct AnimData *adt, + const struct AnimationEvalContext *anim_eval_context, + const bool flush_to_original); bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, struct PointerRNA *prop_ptr, struct PropertyRNA *prop, @@ -209,7 +227,7 @@ bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float /* Evaluation loop for evaluating animation data */ void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, - float ctime, + const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, const bool flush_to_original); @@ -229,14 +247,14 @@ void BKE_animsys_evaluate_all_animation(struct Main *main, /* Evaluate Action (F-Curve Bag) */ void animsys_evaluate_action(struct PointerRNA *ptr, struct bAction *act, - float ctime, + const struct AnimationEvalContext *anim_eval_context, const bool flush_to_original); /* Evaluate Action Group */ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, struct bActionGroup *agrp, - float ctime); + const struct AnimationEvalContext *anim_eval_context); /* ************************************* */ @@ -257,5 +275,3 @@ void BKE_animsys_update_driver_array(struct ID *id); #ifdef __cplusplus } #endif - -#endif /* __BKE_ANIMSYS_H__*/ diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index e49fc260810..b8a4497c7be 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_APPDIR_H__ -#define __BKE_APPDIR_H__ +#pragma once /** \file * \ingroup bli @@ -101,5 +100,3 @@ enum { #ifdef __cplusplus } #endif - -#endif /* __BKE_APPDIR_H__ */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 6fb6675a05a..6d48397b1af 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_ARMATURE_H__ -#define __BKE_ARMATURE_H__ +#pragma once /** \file * \ingroup bke @@ -123,22 +122,24 @@ void get_objectspace_bone_matrix(struct Bone *bone, float M_accumulatedMatrix[4][4], int root, int posed); -void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]); -void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float mat[3][3]); +void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3]); +void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3]); void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll); void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll); /* Common Conversions Between Co-ordinate Spaces */ -void BKE_armature_mat_world_to_pose(struct Object *ob, float inmat[4][4], float outmat[4][4]); +void BKE_armature_mat_world_to_pose(struct Object *ob, + const float inmat[4][4], + float outmat[4][4]); void BKE_armature_loc_world_to_pose(struct Object *ob, const float inloc[3], float outloc[3]); void BKE_armature_mat_pose_to_bone(struct bPoseChannel *pchan, - float inmat[4][4], + const float inmat[4][4], float outmat[4][4]); void BKE_armature_loc_pose_to_bone(struct bPoseChannel *pchan, const float inloc[3], float outloc[3]); void BKE_armature_mat_bone_to_pose(struct bPoseChannel *pchan, - float inmat[4][4], + const float inmat[4][4], float outmat[4][4]); void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], float pose_mat[4][4], @@ -147,13 +148,13 @@ void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph, struct Object *ob, struct bPoseChannel *pchan, - float inmat[4][4], + const float inmat[4][4], float outmat[4][4]); -void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, float mat[3][3], bool use_compat); -void BKE_pchan_rot_to_mat3(const struct bPoseChannel *pchan, float mat[3][3]); -void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, float mat[4][4], bool use_comat); -void BKE_pchan_to_mat4(const struct bPoseChannel *pchan, float chan_mat[4][4]); +void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, const float mat[3][3], bool use_compat); +void BKE_pchan_rot_to_mat3(const struct bPoseChannel *pchan, float r_mat[3][3]); +void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, const float mat[4][4], bool use_comat); +void BKE_pchan_to_mat4(const struct bPoseChannel *pchan, float r_mat[4][4]); void BKE_pchan_calc_mat(struct bPoseChannel *pchan); /* Simple helper, computes the offset bone matrix. */ @@ -387,5 +388,3 @@ void BKE_armature_deform_coords_with_editmesh(const struct Object *ob_arm, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_autoexec.h b/source/blender/blenkernel/BKE_autoexec.h index bb847d49a4b..84d83ae5d30 100644 --- a/source/blender/blenkernel/BKE_autoexec.h +++ b/source/blender/blenkernel/BKE_autoexec.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_AUTOEXEC_H__ -#define __BKE_AUTOEXEC_H__ +#pragma once /** \file * \ingroup bke @@ -29,5 +28,3 @@ bool BKE_autoexec_match(const char *path); #ifdef __cplusplus } #endif - -#endif /* __BKE_AUTOEXEC_H__ */ diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 3feba4b3a66..abc0ce1f092 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_BLENDER_H__ -#define __BKE_BLENDER_H__ +#pragma once /** \file * \ingroup bke @@ -54,5 +53,3 @@ void BKE_blender_atexit(void); #ifdef __cplusplus } #endif - -#endif /* __BKE_BLENDER_H__ */ diff --git a/source/blender/blenkernel/BKE_blender_copybuffer.h b/source/blender/blenkernel/BKE_blender_copybuffer.h index ca20d3d9bba..1dd6d495276 100644 --- a/source/blender/blenkernel/BKE_blender_copybuffer.h +++ b/source/blender/blenkernel/BKE_blender_copybuffer.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_BLENDER_COPYBUFFER_H__ -#define __BKE_BLENDER_COPYBUFFER_H__ +#pragma once /** \file * \ingroup bke @@ -48,5 +47,3 @@ int BKE_copybuffer_paste(struct bContext *C, #ifdef __cplusplus } #endif - -#endif /* __BKE_BLENDER_COPYBUFFER_H__ */ diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h index 4ecedbbfc1e..e5ce91df3fb 100644 --- a/source/blender/blenkernel/BKE_blender_undo.h +++ b/source/blender/blenkernel/BKE_blender_undo.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_BLENDER_UNDO_H__ -#define __BKE_BLENDER_UNDO_H__ +#pragma once /** \file * \ingroup bke @@ -41,5 +40,3 @@ void BKE_memfile_undo_free(struct MemFileUndoData *mfu); #ifdef __cplusplus } #endif - -#endif /* __BKE_BLENDER_UNDO_H__ */ diff --git a/source/blender/blenkernel/BKE_blender_user_menu.h b/source/blender/blenkernel/BKE_blender_user_menu.h index 805a343b976..8d00cde488e 100644 --- a/source/blender/blenkernel/BKE_blender_user_menu.h +++ b/source/blender/blenkernel/BKE_blender_user_menu.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_BLENDER_USER_MENU_H__ -#define __BKE_BLENDER_USER_MENU_H__ +#pragma once /** \file * \ingroup bke @@ -43,5 +42,3 @@ void BKE_blender_user_menu_item_free_list(struct ListBase *lb); #ifdef __cplusplus } #endif - -#endif /* __BKE_BLENDER_USER_MENU_H__ */ diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 229b5193e9c..ae0a669bfb3 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_BLENDER_VERSION_H__ -#define __BKE_BLENDER_VERSION_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -32,7 +31,7 @@ extern "C" { */ /* Blender major and minor version. */ -#define BLENDER_VERSION 290 +#define BLENDER_VERSION 291 /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ @@ -40,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 5 +#define BLENDER_FILE_SUBVERSION 0 /* 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 @@ -54,5 +53,3 @@ const char *BKE_blender_version_string(void); #ifdef __cplusplus } #endif - -#endif /* __BKE_BLENDER_VERSION_H__ */ diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index e835137bfa1..94d203eeb2c 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_BLENDFILE_H__ -#define __BKE_BLENDFILE_H__ +#pragma once /** \file * \ingroup bke @@ -81,5 +80,3 @@ void BKE_blendfile_write_partial_end(struct Main *bmain_src); #ifdef __cplusplus } #endif - -#endif /* __BKE_BLENDFILE_H__ */ diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h index f9fd814b5f2..c9e6f0e7346 100644 --- a/source/blender/blenkernel/BKE_boids.h +++ b/source/blender/blenkernel/BKE_boids.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_BOIDS_H__ -#define __BKE_BOIDS_H__ +#pragma once /** \file * \ingroup bke @@ -62,5 +61,3 @@ BoidState *boid_get_current_state(BoidSettings *boids); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_bpath.h b/source/blender/blenkernel/BKE_bpath.h index cc8dd0d5b33..787dc4d1147 100644 --- a/source/blender/blenkernel/BKE_bpath.h +++ b/source/blender/blenkernel/BKE_bpath.h @@ -20,8 +20,7 @@ * so for BPath we don't need to malloc */ -#ifndef __BKE_BPATH_H__ -#define __BKE_BPATH_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -92,5 +91,3 @@ void BKE_bpath_absolute_convert(struct Main *bmain, #ifdef __cplusplus } #endif - -#endif /* __BKE_BPATH_H__ */ diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 4e9430ab3e1..af299c917eb 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_BRUSH_H__ -#define __BKE_BRUSH_H__ +#pragma once /** \file * \ingroup bke @@ -157,5 +156,3 @@ void BKE_brush_debug_print_state(struct Brush *br); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 5d7e8fe743e..e973bee9e20 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2006 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_BVHUTILS_H__ -#define __BKE_BVHUTILS_H__ +#pragma once /** \file * \ingroup bke @@ -263,5 +262,3 @@ void bvhcache_free(struct BVHCache *bvh_cache); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h index 596085f9c6f..9912b4e4b70 100644 --- a/source/blender/blenkernel/BKE_cachefile.h +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_CACHEFILE_H__ -#define __BKE_CACHEFILE_H__ +#pragma once /** \file * \ingroup bke @@ -66,5 +65,3 @@ void BKE_cachefile_reader_free(struct CacheFile *cache_file, struct CacheReader #ifdef __cplusplus } #endif - -#endif /* __BKE_CACHEFILE_H__ */ diff --git a/source/blender/blenkernel/BKE_callbacks.h b/source/blender/blenkernel/BKE_callbacks.h index 284948da634..fadba5644de 100644 --- a/source/blender/blenkernel/BKE_callbacks.h +++ b/source/blender/blenkernel/BKE_callbacks.h @@ -18,8 +18,7 @@ * \ingroup bke */ -#ifndef __BKE_CALLBACKS_H__ -#define __BKE_CALLBACKS_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -88,5 +87,3 @@ void BKE_callback_global_finalize(void); #ifdef __cplusplus } #endif - -#endif /* __BKE_CALLBACKS_H__ */ diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 812f5d520d7..533d5ae13cd 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_CAMERA_H__ -#define __BKE_CAMERA_H__ +#pragma once /** \file * \ingroup bke @@ -167,5 +166,3 @@ void BKE_camera_background_image_clear(struct Camera *cam); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_ccg.h b/source/blender/blenkernel/BKE_ccg.h index ad1e05ee367..acdaa81da8d 100644 --- a/source/blender/blenkernel/BKE_ccg.h +++ b/source/blender/blenkernel/BKE_ccg.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_CCG_H__ -#define __BKE_CCG_H__ +#pragma once /** \file * \ingroup bke @@ -166,5 +165,3 @@ BLI_INLINE CCGElem *CCG_elem_next(const CCGKey *key, CCGElem *elem) #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index dd7d20c0407..e997678001f 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -26,8 +26,7 @@ * \note This is deprecated & should eventually be removed. */ -#ifndef __BKE_CDDERIVEDMESH_H__ -#define __BKE_CDDERIVEDMESH_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -49,5 +48,3 @@ struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index f25482570b1..5af37829577 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) Blender Foundation. * All rights reserved. */ -#ifndef __BKE_CLOTH_H__ -#define __BKE_CLOTH_H__ +#pragma once /** \file * \ingroup bke @@ -93,10 +92,10 @@ typedef struct Cloth { struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ struct EdgeSet *edgeset; /* used for selfcollisions */ int last_frame; - float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */ - float average_acceleration[3]; /* Moving average of overall acceleration. */ - struct MEdge *edges; /* Used for hair collisions. */ - struct GHash *sew_edge_graph; /* Sewing edges represented using a GHash */ + float initial_mesh_volume; /* Initial volume of the mesh. Used for pressure */ + float average_acceleration[3]; /* Moving average of overall acceleration. */ + struct MEdge *edges; /* Used for hair collisions. */ + struct EdgeSet *sew_edge_graph; /* Sewing edges represented using a GHash */ } Cloth; /** @@ -307,5 +306,3 @@ void cloth_parallel_transport_hair_frame(float mat[3][3], #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 4cf33640ebd..f4393742dff 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_COLLECTION_H__ -#define __BKE_COLLECTION_H__ +#pragma once /** \file * \ingroup bke @@ -56,6 +55,10 @@ void BKE_collection_add_from_object(struct Main *bmain, struct Scene *scene, const struct Object *ob_src, struct Collection *collection_dst); +void BKE_collection_add_from_collection(struct Main *bmain, + struct Scene *scene, + struct Collection *collection_src, + struct Collection *collection_dst); void BKE_collection_free(struct Collection *collection); bool BKE_collection_delete(struct Main *bmain, struct Collection *collection, bool hierarchy); @@ -149,7 +152,8 @@ bool BKE_collection_move(struct Main *bmain, bool relative_after, struct Collection *collection); -bool BKE_collection_find_cycle(struct Collection *new_ancestor, struct Collection *collection); +bool BKE_collection_cycle_find(struct Collection *new_ancestor, struct Collection *collection); +bool BKE_collection_cycles_fix(struct Main *bmain, struct Collection *collection); bool BKE_collection_has_collection(struct Collection *parent, struct Collection *collection); @@ -250,5 +254,3 @@ void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter); #ifdef __cplusplus } #endif - -#endif /* __BKE_COLLECTION_H__ */ diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index c3ecd0b7ed0..579adb61057 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) Blender Foundation. * All rights reserved. */ -#ifndef __BKE_COLLISION_H__ -#define __BKE_COLLISION_H__ +#pragma once /** \file * \ingroup bke @@ -178,5 +177,3 @@ void BKE_collider_cache_free(struct ListBase **colliders); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_colorband.h b/source/blender/blenkernel/BKE_colorband.h index 355682671fe..6ac96a1ed36 100644 --- a/source/blender/blenkernel/BKE_colorband.h +++ b/source/blender/blenkernel/BKE_colorband.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_COLORBAND_H__ -#define __BKE_COLORBAND_H__ +#pragma once /** \file * \ingroup bke @@ -47,5 +46,3 @@ void BKE_colorband_update_sort(struct ColorBand *coba); #ifdef __cplusplus } #endif - -#endif /* __BKE_COLORBAND_H__ */ diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 0623e0e5395..1ada83c0163 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2006 Blender Foundation. * All rights reserved. */ -#ifndef __BKE_COLORTOOLS_H__ -#define __BKE_COLORTOOLS_H__ +#pragma once /** \file * \ingroup bke @@ -70,7 +69,7 @@ void BKE_curvemapping_changed(struct CurveMapping *cumap, const bool rem_doubles void BKE_curvemapping_changed_all(struct CurveMapping *cumap); /* call before _all_ evaluation functions */ -void BKE_curvemapping_initialize(struct CurveMapping *cumap); +void BKE_curvemapping_init(struct CurveMapping *cumap); /* keep these (const CurveMap) - to help with thread safety */ /* single curve, no table check */ @@ -152,5 +151,3 @@ bool BKE_color_managed_colorspace_settings_equals( #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 8d7fe875c37..94349f4db22 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_CONSTRAINT_H__ -#define __BKE_CONSTRAINT_H__ +#pragma once /** \file * \ingroup bke @@ -224,5 +223,3 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 70ca29d5795..eb26f1c3969 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_CONTEXT_H__ -#define __BKE_CONTEXT_H__ +#pragma once /** \file * \ingroup bke @@ -312,6 +311,8 @@ int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list); int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list); int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list); +bool CTX_wm_interface_locked(const bContext *C); + /* Gets pointer to the dependency graph. * If it doesn't exist yet, it will be allocated. * @@ -344,5 +345,3 @@ struct Depsgraph *CTX_data_depsgraph_on_load(const bContext *C); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h index 6ac6b17d468..b95be70379f 100644 --- a/source/blender/blenkernel/BKE_crazyspace.h +++ b/source/blender/blenkernel/BKE_crazyspace.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_CRAZYSPACE_H__ -#define __BKE_CRAZYSPACE_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -65,5 +64,3 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index d32ab474229..0bd4e3a7582 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_CURVE_H__ -#define __BKE_CURVE_H__ +#pragma once /** \file * \ingroup bke @@ -98,15 +97,15 @@ bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max bool BKE_curve_center_median(struct Curve *cu, float cent[3]); bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]); void BKE_curve_transform_ex(struct Curve *cu, - float mat[4][4], + const float mat[4][4], const bool do_keys, const bool do_props, const float unit_scale); void BKE_curve_transform(struct Curve *cu, - float mat[4][4], + const float mat[4][4], const bool do_keys, const bool do_props); -void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys); +void BKE_curve_translate(struct Curve *cu, const float offset[3], const bool do_keys); void BKE_curve_material_index_remove(struct Curve *cu, int index); bool BKE_curve_material_index_used(struct Curve *cu, int index); void BKE_curve_material_index_clear(struct Curve *cu); @@ -140,7 +139,7 @@ void BKE_curve_nurbs_vert_coords_apply(struct ListBase *lb, float (*BKE_curve_nurbs_key_vert_coords_alloc(struct ListBase *lb, float *key, int *r_vert_len))[3]; -void BKE_curve_nurbs_key_vert_tilts_apply(struct ListBase *lb, float *key); +void BKE_curve_nurbs_key_vert_tilts_apply(struct ListBase *lb, const float *key); void BKE_curve_editNurb_keyIndex_delCV(struct GHash *keyindex, const void *cv); void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex); @@ -339,5 +338,3 @@ void BKE_curve_deform_co(const struct Object *ob_curve, #ifdef __cplusplus } #endif - -#endif /* __BKE_CURVE_H__ */ diff --git a/source/blender/blenkernel/BKE_curveprofile.h b/source/blender/blenkernel/BKE_curveprofile.h index 877ab887138..9c72a866fa9 100644 --- a/source/blender/blenkernel/BKE_curveprofile.h +++ b/source/blender/blenkernel/BKE_curveprofile.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_CURVEPROFILE_H__ -#define __BKE_CURVEPROFILE_H__ +#pragma once /** \file * \ingroup bke @@ -72,7 +71,7 @@ void BKE_curveprofile_create_samples(struct CurveProfile *profile, bool sample_straight_edges, struct CurveProfilePoint *r_samples); -void BKE_curveprofile_initialize(struct CurveProfile *profile, short segments_len); +void BKE_curveprofile_init(struct CurveProfile *profile, short segments_len); /* Called for a complete update of the widget after modifications */ enum { @@ -101,5 +100,3 @@ void BKE_curveprofile_blend_read(struct BlendDataReader *reader, struct CurvePro #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 42beda352f5..92bfa3a9490 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -22,8 +22,7 @@ * \brief CustomData interface, see also DNA_customdata_types.h. */ -#ifndef __BKE_CUSTOMDATA_H__ -#define __BKE_CUSTOMDATA_H__ +#pragma once #include "BLI_sys_types.h" #include "BLI_utildefines.h" @@ -455,6 +454,7 @@ bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool f bool CustomData_layer_validate(struct CustomDataLayer *layer, const uint totitems, const bool do_fixes); +void CustomData_layers__print(struct CustomData *data); /* External file storage */ @@ -574,5 +574,3 @@ void CustomData_data_transfer(const struct MeshPairRemap *me_remap, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_customdata_file.h b/source/blender/blenkernel/BKE_customdata_file.h index 2be2f71a168..f9f02204bb9 100644 --- a/source/blender/blenkernel/BKE_customdata_file.h +++ b/source/blender/blenkernel/BKE_customdata_file.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_CUSTOMDATA_FILE_H__ -#define __BKE_CUSTOMDATA_FILE_H__ +#pragma once /** \file * \ingroup bke @@ -60,5 +59,3 @@ CDataFileLayer *cdf_layer_add(CDataFile *cdf, int type, const char *name, size_t #ifdef __cplusplus } #endif - -#endif /* __BKE_CUSTOMDATA_FILE_H__ */ diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h index a723a9ed38c..d861baba14d 100644 --- a/source/blender/blenkernel/BKE_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_DATA_TRANSFER_H__ -#define __BKE_DATA_TRANSFER_H__ +#pragma once #include "BKE_customdata.h" @@ -181,5 +180,3 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, #ifdef __cplusplus } #endif - -#endif /* __BKE_DATA_TRANSFER_H__ */ diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 04b85aebb39..35111d5240e 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_DEFORM_H__ -#define __BKE_DEFORM_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -111,7 +110,7 @@ void BKE_defvert_sync_mapped(struct MDeformVert *dvert_dst, const int *flip_map, const int flip_map_len, const bool use_ensure); -void BKE_defvert_remap(struct MDeformVert *dvert, int *map, const int map_len); +void BKE_defvert_remap(struct MDeformVert *dvert, const int *map, const int map_len); void BKE_defvert_flip(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len); void BKE_defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, @@ -166,5 +165,3 @@ void BKE_defvert_weight_to_rgb(float r_rgb[3], const float weight); #ifdef __cplusplus } #endif - -#endif /* __BKE_DEFORM_H__ */ diff --git a/source/blender/blenkernel/BKE_derived_node_tree.hh b/source/blender/blenkernel/BKE_derived_node_tree.hh deleted file mode 100644 index 2ed96f0c60d..00000000000 --- a/source/blender/blenkernel/BKE_derived_node_tree.hh +++ /dev/null @@ -1,498 +0,0 @@ -/* - * 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. - */ - -#ifndef __BKE_DERIVED_NODE_TREE_HH__ -#define __BKE_DERIVED_NODE_TREE_HH__ - -/** \file - * \ingroup bke - * - * DerivedNodeTree provides a flattened view on a bNodeTree, i.e. node groups are inlined. It - * builds on top of NodeTreeRef and supports similar queries efficiently. - * - * Every inlined node remembers its path to the parent ("call stack"). - * - * Unlinked group node inputs are handled separately from other sockets. - * - * There is a dot graph exporter for debugging purposes. - */ - -#include "BKE_node_tree_ref.hh" - -namespace blender::bke { - -class DSocket; -class DInputSocket; -class DOutputSocket; -class DNode; -class DParentNode; -class DGroupInput; -class DerivedNodeTree; - -class DSocket : NonCopyable, NonMovable { - protected: - DNode *node_; - const SocketRef *socket_ref_; - uint id_; - - friend DerivedNodeTree; - - public: - const DNode &node() const; - - uint id() const; - uint index() const; - - bool is_input() const; - bool is_output() const; - - const DSocket &as_base() const; - const DInputSocket &as_input() const; - const DOutputSocket &as_output() const; - - PointerRNA *rna() const; - StringRefNull idname() const; - StringRefNull name() const; - - const SocketRef &socket_ref() const; - bNodeSocket *bsocket() const; - - bool is_available() const; -}; - -class DInputSocket : public DSocket { - private: - Vector<DOutputSocket *> linked_sockets_; - Vector<DGroupInput *> linked_group_inputs_; - - friend DerivedNodeTree; - - public: - const InputSocketRef &socket_ref() const; - - Span<const DOutputSocket *> linked_sockets() const; - Span<const DGroupInput *> linked_group_inputs() const; - - bool is_linked() const; -}; - -class DOutputSocket : public DSocket { - private: - Vector<DInputSocket *> linked_sockets_; - - friend DerivedNodeTree; - - public: - const OutputSocketRef &socket_ref() const; - Span<const DInputSocket *> linked_sockets() const; -}; - -class DGroupInput : NonCopyable, NonMovable { - private: - const InputSocketRef *socket_ref_; - DParentNode *parent_; - Vector<DInputSocket *> linked_sockets_; - uint id_; - - friend DerivedNodeTree; - - public: - const InputSocketRef &socket_ref() const; - bNodeSocket *bsocket() const; - const DParentNode *parent() const; - Span<const DInputSocket *> linked_sockets() const; - uint id() const; - StringRefNull name() const; -}; - -class DNode : NonCopyable, NonMovable { - private: - const NodeRef *node_ref_; - DParentNode *parent_; - - Span<DInputSocket *> inputs_; - Span<DOutputSocket *> outputs_; - - uint id_; - - friend DerivedNodeTree; - - public: - const NodeRef &node_ref() const; - const DParentNode *parent() const; - - Span<const DInputSocket *> inputs() const; - Span<const DOutputSocket *> outputs() const; - - const DInputSocket &input(uint index) const; - const DOutputSocket &output(uint index) const; - - uint id() const; - - PointerRNA *rna() const; - StringRefNull idname() const; - StringRefNull name() const; - - private: - void destruct_with_sockets(); -}; - -class DParentNode : NonCopyable, NonMovable { - private: - const NodeRef *node_ref_; - DParentNode *parent_; - uint id_; - - friend DerivedNodeTree; - - public: - const DParentNode *parent() const; - const NodeRef &node_ref() const; - uint id() const; -}; - -using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>; - -class DerivedNodeTree : NonCopyable, NonMovable { - private: - LinearAllocator<> allocator_; - bNodeTree *btree_; - Vector<DNode *> nodes_by_id_; - Vector<DGroupInput *> group_inputs_; - Vector<DParentNode *> parent_nodes_; - - Vector<DSocket *> sockets_by_id_; - Vector<DInputSocket *> input_sockets_; - Vector<DOutputSocket *> output_sockets_; - - Map<const bNodeType *, Vector<DNode *>> nodes_by_type_; - - public: - DerivedNodeTree(bNodeTree *btree, NodeTreeRefMap &node_tree_refs); - ~DerivedNodeTree(); - - Span<const DNode *> nodes() const; - Span<const DNode *> nodes_by_type(StringRefNull idname) const; - Span<const DNode *> nodes_by_type(const bNodeType *nodetype) const; - - Span<const DSocket *> sockets() const; - Span<const DInputSocket *> input_sockets() const; - Span<const DOutputSocket *> output_sockets() const; - - Span<const DGroupInput *> group_inputs() const; - - std::string to_dot() const; - - private: - /* Utility functions used during construction. */ - void insert_nodes_and_links_in_id_order(const NodeTreeRef &tree_ref, - DParentNode *parent, - Vector<DNode *> &all_nodes); - DNode &create_node(const NodeRef &node_ref, - DParentNode *parent, - MutableSpan<DSocket *> r_sockets_map); - void expand_groups(Vector<DNode *> &all_nodes, - Vector<DGroupInput *> &all_group_inputs, - Vector<DParentNode *> &all_parent_nodes, - NodeTreeRefMap &node_tree_refs); - void expand_group_node(DNode &group_node, - Vector<DNode *> &all_nodes, - Vector<DGroupInput *> &all_group_inputs, - Vector<DParentNode *> &all_parent_nodes, - NodeTreeRefMap &node_tree_refs); - void create_group_inputs_for_unlinked_inputs(DNode &node, - Vector<DGroupInput *> &all_group_inputs); - void relink_group_inputs(const NodeTreeRef &group_ref, - Span<DNode *> nodes_by_id, - DNode &group_node); - void relink_group_outputs(const NodeTreeRef &group_ref, - Span<DNode *> nodes_by_id, - DNode &group_node); - void remove_expanded_group_interfaces(Vector<DNode *> &all_nodes); - void remove_unused_group_inputs(Vector<DGroupInput *> &all_group_inputs); - void store_in_this_and_init_ids(Vector<DNode *> &&all_nodes, - Vector<DGroupInput *> &&all_group_inputs, - Vector<DParentNode *> &&all_parent_nodes); -}; - -/* -------------------------------------------------------------------- - * DSocket inline methods. - */ - -inline const DNode &DSocket::node() const -{ - return *node_; -} - -inline uint DSocket::id() const -{ - return id_; -} - -inline uint DSocket::index() const -{ - return socket_ref_->index(); -} - -inline bool DSocket::is_input() const -{ - return socket_ref_->is_input(); -} - -inline bool DSocket::is_output() const -{ - return socket_ref_->is_output(); -} - -inline const DSocket &DSocket::as_base() const -{ - return *this; -} - -inline const DInputSocket &DSocket::as_input() const -{ - return *(DInputSocket *)this; -} - -inline const DOutputSocket &DSocket::as_output() const -{ - return *(DOutputSocket *)this; -} - -inline PointerRNA *DSocket::rna() const -{ - return socket_ref_->rna(); -} - -inline StringRefNull DSocket::idname() const -{ - return socket_ref_->idname(); -} - -inline StringRefNull DSocket::name() const -{ - return socket_ref_->name(); -} - -inline const SocketRef &DSocket::socket_ref() const -{ - return *socket_ref_; -} - -inline bNodeSocket *DSocket::bsocket() const -{ - return socket_ref_->bsocket(); -} - -inline bool DSocket::is_available() const -{ - return (socket_ref_->bsocket()->flag & SOCK_UNAVAIL) == 0; -} - -/* -------------------------------------------------------------------- - * DInputSocket inline methods. - */ - -inline const InputSocketRef &DInputSocket::socket_ref() const -{ - return socket_ref_->as_input(); -} - -inline Span<const DOutputSocket *> DInputSocket::linked_sockets() const -{ - return linked_sockets_.as_span(); -} - -inline Span<const DGroupInput *> DInputSocket::linked_group_inputs() const -{ - return linked_group_inputs_.as_span(); -} - -inline bool DInputSocket::is_linked() const -{ - return linked_sockets_.size() > 0 || linked_group_inputs_.size() > 0; -} - -/* -------------------------------------------------------------------- - * DOutputSocket inline methods. - */ - -inline const OutputSocketRef &DOutputSocket::socket_ref() const -{ - return socket_ref_->as_output(); -} - -inline Span<const DInputSocket *> DOutputSocket::linked_sockets() const -{ - return linked_sockets_.as_span(); -} - -/* -------------------------------------------------------------------- - * DGroupInput inline methods. - */ - -inline const InputSocketRef &DGroupInput::socket_ref() const -{ - return *socket_ref_; -} - -inline bNodeSocket *DGroupInput::bsocket() const -{ - return socket_ref_->bsocket(); -} - -inline const DParentNode *DGroupInput::parent() const -{ - return parent_; -} - -inline Span<const DInputSocket *> DGroupInput::linked_sockets() const -{ - return linked_sockets_.as_span(); -} - -inline uint DGroupInput::id() const -{ - return id_; -} - -inline StringRefNull DGroupInput::name() const -{ - return socket_ref_->name(); -} - -/* -------------------------------------------------------------------- - * DNode inline methods. - */ - -inline const NodeRef &DNode::node_ref() const -{ - return *node_ref_; -} - -inline const DParentNode *DNode::parent() const -{ - return parent_; -} - -inline Span<const DInputSocket *> DNode::inputs() const -{ - return inputs_; -} - -inline Span<const DOutputSocket *> DNode::outputs() const -{ - return outputs_; -} - -inline const DInputSocket &DNode::input(uint index) const -{ - return *inputs_[index]; -} - -inline const DOutputSocket &DNode::output(uint index) const -{ - return *outputs_[index]; -} - -inline uint DNode::id() const -{ - return id_; -} - -inline PointerRNA *DNode::rna() const -{ - return node_ref_->rna(); -} - -inline StringRefNull DNode::idname() const -{ - return node_ref_->idname(); -} - -inline StringRefNull DNode::name() const -{ - return node_ref_->name(); -} - -/* -------------------------------------------------------------------- - * DParentNode inline methods. - */ - -inline const DParentNode *DParentNode::parent() const -{ - return parent_; -} - -inline const NodeRef &DParentNode::node_ref() const -{ - return *node_ref_; -} - -inline uint DParentNode::id() const -{ - return id_; -} - -/* -------------------------------------------------------------------- - * DerivedNodeTree inline methods. - */ - -inline Span<const DNode *> DerivedNodeTree::nodes() const -{ - return nodes_by_id_.as_span(); -} - -inline Span<const DNode *> DerivedNodeTree::nodes_by_type(StringRefNull idname) const -{ - const bNodeType *nodetype = nodeTypeFind(idname.data()); - return this->nodes_by_type(nodetype); -} - -inline Span<const DNode *> DerivedNodeTree::nodes_by_type(const bNodeType *nodetype) const -{ - const Vector<DNode *> *nodes = nodes_by_type_.lookup_ptr(nodetype); - if (nodes == nullptr) { - return {}; - } - else { - return nodes->as_span(); - } -} - -inline Span<const DSocket *> DerivedNodeTree::sockets() const -{ - return sockets_by_id_.as_span(); -} - -inline Span<const DInputSocket *> DerivedNodeTree::input_sockets() const -{ - return input_sockets_.as_span(); -} - -inline Span<const DOutputSocket *> DerivedNodeTree::output_sockets() const -{ - return output_sockets_.as_span(); -} - -inline Span<const DGroupInput *> DerivedNodeTree::group_inputs() const -{ - return group_inputs_.as_span(); -} - -} // namespace blender::bke - -#endif /* __BKE_DERIVED_NODE_TREE_HH__ */ diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index b7e4acdc636..7e1a6e54ede 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_DISPLIST_H__ -#define __BKE_DISPLIST_H__ +#pragma once /** \file * \ingroup bke @@ -119,5 +118,3 @@ void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_displist_tangent.h b/source/blender/blenkernel/BKE_displist_tangent.h index 5e1c6ac8a21..c91c2c97dda 100644 --- a/source/blender/blenkernel/BKE_displist_tangent.h +++ b/source/blender/blenkernel/BKE_displist_tangent.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_DISPLIST_TANGENT_H__ -#define __BKE_DISPLIST_TANGENT_H__ +#pragma once /** \file * \ingroup bke @@ -30,5 +29,3 @@ void BKE_displist_tangent_calc(const DispList *dl, float (*fnormals)[3], float ( #ifdef __cplusplus } #endif - -#endif /* __BKE_DISPLIST_TANGENT_H__ */ diff --git a/source/blender/blenkernel/BKE_duplilist.h b/source/blender/blenkernel/BKE_duplilist.h index 71b6d06b450..c142d5338d1 100644 --- a/source/blender/blenkernel/BKE_duplilist.h +++ b/source/blender/blenkernel/BKE_duplilist.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_DUPLILIST_H__ -#define __BKE_DUPLILIST_H__ +#pragma once /** \file * \ingroup bke @@ -52,7 +51,7 @@ typedef struct DupliObject { /* Persistent identifier for a dupli object, for inter-frame matching of * objects with motion blur, or inter-update matching for syncing. */ - int persistent_id[16]; /* 2*MAX_DUPLI_RECUR */ + int persistent_id[8]; /* MAX_DUPLI_RECUR */ /* Particle this dupli was generated from. */ struct ParticleSystem *particle_system; @@ -64,5 +63,3 @@ typedef struct DupliObject { #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index 5e3603a8339..99b58b2f40a 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_DYNAMICPAINT_H__ -#define __BKE_DYNAMICPAINT_H__ +#pragma once /** \file * \ingroup bke @@ -124,5 +123,3 @@ void dynamicPaint_outputSurfaceImage(struct DynamicPaintSurface *surface, #ifdef __cplusplus } #endif - -#endif /* __BKE_DYNAMICPAINT_H__ */ diff --git a/source/blender/blenkernel/BKE_editlattice.h b/source/blender/blenkernel/BKE_editlattice.h index c587ddb551b..be791487c27 100644 --- a/source/blender/blenkernel/BKE_editlattice.h +++ b/source/blender/blenkernel/BKE_editlattice.h @@ -18,8 +18,7 @@ * \ingroup bke */ -#ifndef __BKE_EDITLATTICE_H__ -#define __BKE_EDITLATTICE_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -34,5 +33,3 @@ void BKE_editlattice_load(struct Object *obedit); #ifdef __cplusplus } #endif - -#endif /* __BKE_EDITLATTICE_H__ */ diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 9bd62858902..819e91b438e 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_EDITMESH_H__ -#define __BKE_EDITMESH_H__ +#pragma once /** \file * \ingroup bke @@ -107,5 +106,3 @@ struct BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em); #ifdef __cplusplus } #endif - -#endif /* __BKE_EDITMESH_H__ */ diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h index b8d1e26fad2..8f8e573ee2f 100644 --- a/source/blender/blenkernel/BKE_editmesh_bvh.h +++ b/source/blender/blenkernel/BKE_editmesh_bvh.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_EDITMESH_BVH_H__ -#define __BKE_EDITMESH_BVH_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -104,5 +103,3 @@ enum { #ifdef __cplusplus } #endif - -#endif /* __BKE_EDITMESH_BVH_H__ */ diff --git a/source/blender/blenkernel/BKE_editmesh_cache.h b/source/blender/blenkernel/BKE_editmesh_cache.h index 6c812098b2e..bc2a70124fe 100644 --- a/source/blender/blenkernel/BKE_editmesh_cache.h +++ b/source/blender/blenkernel/BKE_editmesh_cache.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_EDITMESH_CACHE_H__ -#define __BKE_EDITMESH_CACHE_H__ +#pragma once /** \file * \ingroup bke @@ -41,5 +40,3 @@ bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em, #ifdef __cplusplus } #endif - -#endif /* __BKE_EDITMESH_CACHE_H__ */ diff --git a/source/blender/blenkernel/BKE_editmesh_tangent.h b/source/blender/blenkernel/BKE_editmesh_tangent.h index 27f24438528..0e3f063ae44 100644 --- a/source/blender/blenkernel/BKE_editmesh_tangent.h +++ b/source/blender/blenkernel/BKE_editmesh_tangent.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_EDITMESH_TANGENT_H__ -#define __BKE_EDITMESH_TANGENT_H__ +#pragma once /** \file * \ingroup bke @@ -39,5 +38,3 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em, #ifdef __cplusplus } #endif - -#endif /* __BKE_EDITMESH_TANGENT_H__ */ diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 0518ce8ffa3..0585f67703c 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_EFFECT_H__ -#define __BKE_EFFECT_H__ +#pragma once /** \file * \ingroup bke @@ -283,5 +282,3 @@ void BKE_sim_debug_data_clear_category(const char *category); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index c3a597e29b9..3717eb0f282 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_FCURVE_H__ -#define __BKE_FCURVE_H__ +#pragma once /** \file * \ingroup bke @@ -36,6 +35,7 @@ struct FCurve; struct FModifier; struct AnimData; +struct AnimationEvalContext; struct BezTriple; struct LibraryForeachIDData; struct PathResolvedRNA; @@ -271,7 +271,7 @@ void testhandles_fcurve(struct FCurve *fcu, eBezTriple_Flag sel_flag, const bool void sort_time_fcurve(struct FCurve *fcu); short test_time_fcurve(struct FCurve *fcu); -void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]); +void correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2]); /* -------- Evaluation -------- */ @@ -281,10 +281,12 @@ float evaluate_fcurve_only_curve(struct FCurve *fcu, float evaltime); float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, struct ChannelDriver *driver_orig, - float evaltime); + const struct AnimationEvalContext *anim_eval_context); bool BKE_fcurve_is_empty(struct FCurve *fcu); /* evaluate fcurve and store value */ -float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime); +float calculate_fcurve(struct PathResolvedRNA *anim_rna, + struct FCurve *fcu, + const struct AnimationEvalContext *anim_eval_context); /* ************* F-Curve Samples API ******************** */ @@ -312,5 +314,3 @@ void fcurve_store_samples( #ifdef __cplusplus } #endif - -#endif /* __BKE_FCURVE_H__*/ diff --git a/source/blender/blenkernel/BKE_fcurve_driver.h b/source/blender/blenkernel/BKE_fcurve_driver.h index 563ed408ed7..5b4da4a78a4 100644 --- a/source/blender/blenkernel/BKE_fcurve_driver.h +++ b/source/blender/blenkernel/BKE_fcurve_driver.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_FCURVE_DRIVER_H__ -#define __BKE_FCURVE_DRIVER_H__ +#pragma once /** \file * \ingroup bke @@ -30,6 +29,7 @@ extern "C" { #endif +struct AnimationEvalContext; struct ChannelDriver; struct DriverTarget; struct DriverVar; @@ -97,10 +97,8 @@ void BKE_driver_invalidate_expression(struct ChannelDriver *driver, float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver *driver, struct ChannelDriver *driver_orig, - const float evaltime); + const struct AnimationEvalContext *anim_eval_context); #ifdef __cplusplus } #endif - -#endif /* __BKE_FCURVE_DRIVER_H__*/ diff --git a/source/blender/blenkernel/BKE_fluid.h b/source/blender/blenkernel/BKE_fluid.h index c958afb212e..88a5492d85b 100644 --- a/source/blender/blenkernel/BKE_fluid.h +++ b/source/blender/blenkernel/BKE_fluid.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_FLUID_H__ -#define __BKE_FLUID_H__ +#pragma once /** \file * \ingroup bke @@ -37,7 +36,7 @@ struct Main; struct Scene; typedef float (*BKE_Fluid_BresenhamFn)( - float *result, float *input, int res[3], int *pixel, float *tRay, float correct); + float *result, const float *input, int res[3], int *pixel, float *tRay, float correct); struct Mesh *BKE_fluid_modifier_do(struct FluidModifierData *fmd, struct Depsgraph *depsgraph, @@ -56,9 +55,9 @@ bool BKE_fluid_reallocate_fluid(struct FluidDomainSettings *fds, int res[3], int void BKE_fluid_reallocate_copy_fluid(struct FluidDomainSettings *fds, int o_res[3], int n_res[3], - int o_min[3], - int n_min[3], - int o_max[3], + const int o_min[3], + const int n_min[3], + const int o_max[3], int o_shift[3], int n_shift[3]); void BKE_fluid_cache_free_all(struct FluidDomainSettings *fds, struct Object *ob); @@ -101,5 +100,3 @@ void BKE_fluid_flow_behavior_set(struct Object *object, #ifdef __cplusplus } #endif - -#endif /* __BKE_FLUID_H__ */ diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index 35f7d8b7d53..b23ccbe25ff 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_FONT_H__ -#define __BKE_FONT_H__ +#pragma once /** \file * \ingroup bke @@ -102,5 +101,3 @@ void BKE_vfont_clipboard_get(char32_t **r_text_buf, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h index 888a3d96aa2..47f0b547d83 100644 --- a/source/blender/blenkernel/BKE_freestyle.h +++ b/source/blender/blenkernel/BKE_freestyle.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_FREESTYLE_H__ -#define __BKE_FREESTYLE_H__ +#pragma once /** \file * \ingroup bke @@ -66,5 +65,3 @@ void BKE_freestyle_lineset_unique_name(FreestyleConfig *config, FreestyleLineSet #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 61c270202f1..9ffd496616d 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_GLOBAL_H__ -#define __BKE_GLOBAL_H__ +#pragma once /** \file * \ingroup bke @@ -145,18 +144,19 @@ enum { G_DEBUG_DEPSGRAPH_TIME = (1 << 11), /* depsgraph timing statistics and messages */ G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 12), /* single threaded depsgraph */ G_DEBUG_DEPSGRAPH_PRETTY = (1 << 13), /* use pretty colors in depsgraph messages */ + G_DEBUG_DEPSGRAPH_UUID = (1 << 14), /* use pretty colors in depsgraph messages */ G_DEBUG_DEPSGRAPH = (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_EVAL | G_DEBUG_DEPSGRAPH_TAG | - G_DEBUG_DEPSGRAPH_TIME), - G_DEBUG_SIMDATA = (1 << 14), /* sim debug data display */ - G_DEBUG_GPU_MEM = (1 << 15), /* gpu memory in status bar */ - G_DEBUG_GPU = (1 << 16), /* gpu debug */ - G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/ - G_DEBUG_GPU_SHADERS = (1 << 18), /* GLSL shaders */ - G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 19), /* force gpu workarounds bypassing detections. */ - G_DEBUG_XR = (1 << 20), /* XR/OpenXR messages */ - G_DEBUG_XR_TIME = (1 << 21), /* XR/OpenXR timing messages */ - - G_DEBUG_GHOST = (1 << 20), /* Debug GHOST module. */ + G_DEBUG_DEPSGRAPH_TIME | G_DEBUG_DEPSGRAPH_UUID), + G_DEBUG_SIMDATA = (1 << 15), /* sim debug data display */ + G_DEBUG_GPU_MEM = (1 << 16), /* gpu memory in status bar */ + G_DEBUG_GPU = (1 << 17), /* gpu debug */ + G_DEBUG_IO = (1 << 18), /* IO Debugging (for Collada, ...)*/ + G_DEBUG_GPU_SHADERS = (1 << 19), /* GLSL shaders */ + G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 20), /* force gpu workarounds bypassing detections. */ + G_DEBUG_XR = (1 << 21), /* XR/OpenXR messages */ + G_DEBUG_XR_TIME = (1 << 22), /* XR/OpenXR timing messages */ + + G_DEBUG_GHOST = (1 << 23), /* Debug GHOST module. */ }; #define G_DEBUG_ALL \ @@ -223,5 +223,3 @@ extern Global G; #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index cd434566e43..6defc2ffd68 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -17,8 +17,7 @@ * This is a new part of Blender */ -#ifndef __BKE_GPENCIL_H__ -#define __BKE_GPENCIL_H__ +#pragma once /** \file * \ingroup bke @@ -280,5 +279,3 @@ void BKE_gpencil_update_layer_parent(const struct Depsgraph *depsgraph, struct O #ifdef __cplusplus } #endif - -#endif /* __BKE_GPENCIL_H__ */ diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h index cf6f9074bda..3fbd0ce1a51 100644 --- a/source/blender/blenkernel/BKE_gpencil_curve.h +++ b/source/blender/blenkernel/BKE_gpencil_curve.h @@ -17,8 +17,7 @@ * This is a new part of Blender */ -#ifndef __BKE_GPENCIL_CURVE_H__ -#define __BKE_GPENCIL_CURVE_H__ +#pragma once /** \file * \ingroup bke @@ -43,5 +42,3 @@ void BKE_gpencil_convert_curve(struct Main *bmain, #ifdef __cplusplus } #endif - -#endif /* __BKE_GPENCIL_CURVE_H__ */ diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index b79bbf3948f..0abd87d3d4e 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -17,8 +17,7 @@ * This is a new part of Blender */ -#ifndef __BKE_GPENCIL_GEOM_H__ -#define __BKE_GPENCIL_GEOM_H__ +#pragma once /** \file * \ingroup bke @@ -76,7 +75,21 @@ void BKE_gpencil_stroke_fill_triangulate(struct bGPDstroke *gps); void BKE_gpencil_stroke_geometry_update(struct bGPDstroke *gps); void BKE_gpencil_stroke_uv_update(struct bGPDstroke *gps); -void BKE_gpencil_transform(struct bGPdata *gpd, float mat[4][4]); +void BKE_gpencil_transform(struct bGPdata *gpd, const float mat[4][4]); + +typedef struct GPencilPointCoordinates { + /* This is used when doing "move only origin" in object_data_transform.c. + * pressure is needs to be stored here as it is tied to object scale. */ + float co[3]; + float pressure; +} GPencilPointCoordinates; + +int BKE_gpencil_stroke_point_count(struct bGPdata *gpd); +void BKE_gpencil_point_coords_get(struct bGPdata *gpd, GPencilPointCoordinates *elem_data); +void BKE_gpencil_point_coords_apply(struct bGPdata *gpd, const GPencilPointCoordinates *elem_data); +void BKE_gpencil_point_coords_apply_with_mat4(struct bGPdata *gpd, + const GPencilPointCoordinates *elem_data, + const float mat[4][4]); bool BKE_gpencil_stroke_sample(struct bGPDstroke *gps, const float dist, const bool select); bool BKE_gpencil_stroke_smooth(struct bGPDstroke *gps, int i, float inf); @@ -98,6 +111,8 @@ bool BKE_gpencil_stroke_shrink(struct bGPDstroke *gps, const float dist); float BKE_gpencil_stroke_length(const struct bGPDstroke *gps, bool use_3d); +void BKE_gpencil_stroke_set_random_color(struct bGPDstroke *gps); + void BKE_gpencil_convert_mesh(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, @@ -109,10 +124,9 @@ void BKE_gpencil_convert_mesh(struct Main *bmain, const float matrix[4][4], const int frame_offset, const bool use_seams, - const bool use_faces); + const bool use_faces, + const bool simple_material); #ifdef __cplusplus } #endif - -#endif /* __BKE_GPENCIL_GEOM_H__ */ diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index ac5f4607838..8eafbe04a14 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_GPENCIL_MODIFIER_H__ -#define __BKE_GPENCIL_MODIFIER_H__ +#pragma once /** \file * \ingroup bke @@ -316,5 +315,3 @@ struct bGPDframe *BKE_gpencil_frame_retime_get(struct Depsgraph *depsgraph, #ifdef __cplusplus } #endif - -#endif /* __BKE_GPENCIL_MODIFIER_H__ */ diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h index ea515416b58..bf386e099e0 100644 --- a/source/blender/blenkernel/BKE_hair.h +++ b/source/blender/blenkernel/BKE_hair.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_HAIR_H__ -#define __BKE_HAIR_H__ +#pragma once /** \file * \ingroup bke @@ -61,5 +60,3 @@ extern void (*BKE_hair_batch_cache_free_cb)(struct Hair *hair); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 56c50c22bf4..8a4fc78eb97 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_ICONS_H__ -#define __BKE_ICONS_H__ +#pragma once /** \file * \ingroup bke @@ -173,5 +172,3 @@ int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type); #ifdef __cplusplus } #endif - -#endif /* __BKE_ICONS_H__ */ diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index dc01e8ea27b..58629cde6ec 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_IDPROP_H__ -#define __BKE_IDPROP_H__ +#pragma once /** \file * \ingroup bke @@ -200,5 +199,3 @@ void IDP_print(const struct IDProperty *prop); #ifdef __cplusplus } #endif - -#endif /* __BKE_IDPROP_H__ */ diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h index a823693e126..aefba9ef02a 100644 --- a/source/blender/blenkernel/BKE_idtype.h +++ b/source/blender/blenkernel/BKE_idtype.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_IDTYPE_H__ -#define __BKE_IDTYPE_H__ +#pragma once /** \file * \ingroup bke @@ -47,9 +46,9 @@ enum { }; typedef struct IDCacheKey { - /* The session uuid of the ID owning the cached data. */ + /* The session UUID of the ID owning the cached data. */ unsigned int id_session_uuid; - /* Value uniquely indentifying the cache whithin its ID. + /* Value uniquely identifying the cache within its ID. * Typically the offset of its member in the data-block struct, but can be anything. */ size_t offset_in_ID; /* Actual address of the cached data to save and restore. */ @@ -59,7 +58,7 @@ typedef struct IDCacheKey { uint BKE_idtype_cache_key_hash(const void *key_v); bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v); -/* ********** Prototypes for IDTypeInfo callbacks. ********** */ +/* ********** Prototypes for #IDTypeInfo callbacks. ********** */ typedef void (*IDTypeInitDataFunction)(struct ID *id); @@ -76,9 +75,15 @@ typedef void (*IDTypeMakeLocalFunction)(struct Main *bmain, struct ID *id, const typedef void (*IDTypeForeachIDFunction)(struct ID *id, struct LibraryForeachIDData *data); +typedef enum eIDTypeInfoCacheCallbackFlags { + /** Indicates to the callback that that cache may be stored in the .blend file, so its pointer + * should not be cleared at read-time. */ + IDTYPE_CACHE_CB_FLAGS_PERSISTENT = 1 << 0, +} eIDTypeInfoCacheCallbackFlags; typedef void (*IDTypeForeachCacheFunctionCallback)(struct ID *id, const struct IDCacheKey *cache_key, void **cache_p, + uint flags, void *user_data); typedef void (*IDTypeForeachCacheFunction)(struct ID *id, IDTypeForeachCacheFunctionCallback function_callback, @@ -229,8 +234,14 @@ short BKE_idtype_idcode_from_index(const int index); short BKE_idtype_idcode_iter_step(int *index); +/* Some helpers/wrappers around callbacks defined in #IDTypeInfo, dealing e.g. with embedded IDs. + * XXX Ideally those would rather belong to #BKE_lib_id, but using callback function pointers makes + * this hard to do properly if we want to avoid headers includes in headers. */ + +void BKE_idtype_id_foreach_cache(struct ID *id, + IDTypeForeachCacheFunctionCallback function_callback, + void *user_data); + #ifdef __cplusplus } #endif - -#endif /* __BKE_IDTYPE_H__ */ diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 1e5573ab014..f052ba400fc 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_IMAGE_H__ -#define __BKE_IMAGE_H__ +#pragma once /** \file * \ingroup bke @@ -55,6 +54,7 @@ void BKE_image_free_packedfiles(struct Image *image); void BKE_image_free_views(struct Image *image); void BKE_image_free_buffers(struct Image *image); void BKE_image_free_buffers_ex(struct Image *image, bool do_lock); +void BKE_image_free_gputextures(struct Image *ima); /* call from library */ void BKE_image_free(struct Image *image); @@ -274,6 +274,10 @@ void BKE_image_free_anim_ibufs(struct Image *ima, int except_frame); /* does all images with type MOVIE or SEQUENCE */ void BKE_image_all_free_anim_ibufs(struct Main *bmain, int except_frame); +void BKE_image_free_all_gputextures(struct Main *bmain); +void BKE_image_free_anim_gputextures(struct Main *bmain); +void BKE_image_free_old_gputextures(struct Main *bmain); + bool BKE_image_memorypack(struct Image *ima); void BKE_image_packfiles(struct ReportList *reports, struct Image *ima, const char *basepath); void BKE_image_packfiles_from_mem(struct ReportList *reports, @@ -362,6 +366,30 @@ bool BKE_image_has_loaded_ibuf(struct Image *image); struct ImBuf *BKE_image_get_ibuf_with_name(struct Image *image, const char *name); struct ImBuf *BKE_image_get_first_ibuf(struct Image *image); +/* Not to be use directly. */ +struct GPUTexture *BKE_image_create_gpu_texture_from_ibuf(struct Image *image, struct ImBuf *ibuf); + +/* Get the GPUTexture for a given `Image`. + * + * `iuser` and `ibuf` are mutual exclusive parameters. The caller can pass the `ibuf` when already + * available. It is also required when requesting the GPUTexture for a render result. */ +struct GPUTexture *BKE_image_get_gpu_texture(struct Image *image, + struct ImageUser *iuser, + struct ImBuf *ibuf); +struct GPUTexture *BKE_image_get_gpu_tiles(struct Image *image, + struct ImageUser *iuser, + struct ImBuf *ibuf); +struct GPUTexture *BKE_image_get_gpu_tilemap(struct Image *image, + struct ImageUser *iuser, + struct ImBuf *ibuf); + +void BKE_image_update_gputexture( + struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h); +void BKE_image_paint_set_mipmap(struct Main *bmain, bool mipmap); + +/* Delayed free of OpenGL buffers by main thread */ +void BKE_image_free_unused_gpu_textures(void); + struct RenderSlot *BKE_image_add_renderslot(struct Image *ima, const char *name); bool BKE_image_remove_renderslot(struct Image *ima, struct ImageUser *iuser, int slot); struct RenderSlot *BKE_image_get_renderslot(struct Image *ima, int slot); @@ -370,5 +398,3 @@ bool BKE_image_clear_renderslot(struct Image *ima, struct ImageUser *iuser, int #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_image_save.h b/source/blender/blenkernel/BKE_image_save.h index 8dfece944ff..0620442d998 100644 --- a/source/blender/blenkernel/BKE_image_save.h +++ b/source/blender/blenkernel/BKE_image_save.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_IMAGE_SAVE_H__ -#define __BKE_IMAGE_SAVE_H__ +#pragma once #include "DNA_scene_types.h" @@ -62,5 +61,3 @@ bool BKE_image_save(struct ReportList *reports, #ifdef __cplusplus } #endif - -#endif /* __BKE_IMAGE_SAVE_H__ */ diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h index ab5d2f66441..40b9f738bfd 100644 --- a/source/blender/blenkernel/BKE_ipo.h +++ b/source/blender/blenkernel/BKE_ipo.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_IPO_H__ -#define __BKE_IPO_H__ +#pragma once /** \file * \ingroup bke @@ -37,5 +36,3 @@ void do_versions_ipos_to_animato(struct Main *main); #ifdef __cplusplus }; #endif - -#endif diff --git a/source/blender/blenkernel/BKE_kelvinlet.h b/source/blender/blenkernel/BKE_kelvinlet.h index b8290730751..b3966d3ca4a 100644 --- a/source/blender/blenkernel/BKE_kelvinlet.h +++ b/source/blender/blenkernel/BKE_kelvinlet.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) Blender Foundation. * All rights reserved. */ -#ifndef __BKE_KELVINLET_H__ -#define __BKE_KELVINLET_H__ +#pragma once /** \file * \ingroup bke @@ -81,5 +80,3 @@ void BKE_kelvinlet_twist(float r_elem_disp[3], #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 6581891062c..e67df194431 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_KEY_H__ -#define __BKE_KEY_H__ +#pragma once /** \file * \ingroup bke @@ -51,6 +50,12 @@ void key_curve_normal_weights(float t, float data[4], int type); float *BKE_key_evaluate_object_ex(struct Object *ob, int *r_totelem, float *arr, size_t arr_size); float *BKE_key_evaluate_object(struct Object *ob, int *r_totelem); +int BKE_keyblock_element_count_from_shape(const struct Key *key, const int shape_index); +int BKE_keyblock_element_count(const struct Key *key); + +size_t BKE_keyblock_element_calc_size_from_shape(const struct Key *key, const int shape_index); +size_t BKE_keyblock_element_calc_size(const struct Key *key); + bool BKE_key_idtype_support(const short id_type); struct Key **BKE_key_from_id_p(struct ID *id); @@ -74,6 +79,10 @@ void BKE_keyblock_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb); void BKE_keyblock_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt); int BKE_keyblock_curve_element_count(struct ListBase *nurb); +void BKE_keyblock_curve_data_transform(const struct ListBase *nurb, + const float mat[4][4], + const void *src, + void *dst); void BKE_keyblock_update_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb); void BKE_keyblock_convert_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb); void BKE_keyblock_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb); @@ -104,8 +113,28 @@ bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index); bool BKE_keyblock_is_basis(struct Key *key, const int index); +/* -------------------------------------------------------------------- */ +/** \name Key-Block Data Access + * \{ */ + +void BKE_keyblock_data_get_from_shape(const struct Key *key, + float (*arr)[3], + const int shape_index); +void BKE_keyblock_data_get(const struct Key *key, float (*arr)[3]); + +void BKE_keyblock_data_set_with_mat4(struct Key *key, + const int shape_index, + const float (*vertices)[3], + const float mat[4][4]); +void BKE_keyblock_curve_data_set_with_mat4(struct Key *key, + const struct ListBase *nurb, + const int shape_index, + const void *data, + const float mat[4][4]); +void BKE_keyblock_data_set(struct Key *key, const int shape_index, const void *data); + +/** \} */ + #ifdef __cplusplus }; #endif - -#endif /* __BKE_KEY_H__ */ diff --git a/source/blender/blenkernel/BKE_keyconfig.h b/source/blender/blenkernel/BKE_keyconfig.h index bc33cc2669e..ab42d5742ea 100644 --- a/source/blender/blenkernel/BKE_keyconfig.h +++ b/source/blender/blenkernel/BKE_keyconfig.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_KEYCONFIG_H__ -#define __BKE_KEYCONFIG_H__ +#pragma once /** \file * \ingroup bke @@ -76,5 +75,3 @@ void BKE_keyconfig_pref_filter_items(struct UserDef *userdef, #ifdef __cplusplus } #endif - -#endif /* __BKE_KEYCONFIG_H__ */ diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index bb23ad63020..03c57d4caac 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_LATTICE_H__ -#define __BKE_LATTICE_H__ +#pragma once /** \file * \ingroup bke @@ -67,8 +66,8 @@ void BKE_lattice_minmax_dl(struct Object *ob, struct Lattice *lt, float min[3], void BKE_lattice_minmax(struct Lattice *lt, float min[3], float max[3]); void BKE_lattice_center_median(struct Lattice *lt, float cent[3]); void BKE_lattice_center_bounds(struct Lattice *lt, float cent[3]); -void BKE_lattice_translate(struct Lattice *lt, float offset[3], bool do_keys); -void BKE_lattice_transform(struct Lattice *lt, float mat[4][4], bool do_keys); +void BKE_lattice_translate(struct Lattice *lt, const float offset[3], bool do_keys); +void BKE_lattice_transform(struct Lattice *lt, const float mat[4][4], bool do_keys); bool BKE_lattice_is_any_selected(const struct Lattice *lt); @@ -140,5 +139,3 @@ void BKE_lattice_deform_coords_with_editmesh(const struct Object *ob_lattice, #ifdef __cplusplus } #endif - -#endif /* __BKE_LATTICE_H__ */ diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 7a0252e6813..7fe932edf31 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_LAYER_H__ -#define __BKE_LAYER_H__ +#pragma once /** \file * \ingroup bke @@ -416,5 +415,3 @@ bool BKE_view_layer_filter_edit_mesh_has_edges(struct Object *ob, void *user_dat #ifdef __cplusplus } #endif - -#endif /* __BKE_LAYER_H__ */ diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index bc72afdd08d..a2cbe537349 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_LIB_ID_H__ -#define __BKE_LIB_ID_H__ +#pragma once /** \file * \ingroup bke @@ -229,7 +228,6 @@ bool BKE_id_copy(struct Main *bmain, const struct ID *id, struct ID **newid); bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag); struct ID *BKE_id_copy_for_duplicate(struct Main *bmain, struct ID *id, - const bool is_owner_id_liboverride, const uint duplicate_flags); void BKE_lib_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b); @@ -268,7 +266,8 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const struct ID *id, char void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const struct ID *id, const bool add_lib_hint, - char separator_char); + char separator_char, + int *r_prefix_len); char *BKE_id_to_unique_string_key(const struct ID *id); @@ -291,5 +290,3 @@ void BKE_id_reorder(const struct ListBase *lb, struct ID *id, struct ID *relativ #ifdef __cplusplus } #endif - -#endif /* __BKE_LIB_ID_H__ */ diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index 411df66fe36..5843992b25c 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_LIB_OVERRIDE_H__ -#define __BKE_LIB_OVERRIDE_H__ +#pragma once /** \file * \ingroup bke @@ -50,9 +49,8 @@ struct IDOverrideLibraryPropertyOperation; struct Main; struct PointerRNA; struct PropertyRNA; - -void BKE_lib_override_library_enable(const bool do_enable); -bool BKE_lib_override_library_is_enabled(void); +struct Scene; +struct ViewLayer; struct IDOverrideLibrary *BKE_lib_override_library_init(struct ID *local_id, struct ID *reference_id); @@ -66,6 +64,15 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain, struct ID *reference_id, const bool do_tagged_remap); bool BKE_lib_override_library_create_from_tag(struct Main *bmain); +void BKE_lib_override_library_dependencies_tag(struct Main *bmain, + struct ID *id_root, + const uint tag, + const bool do_create_main_relashionships); +bool BKE_lib_override_library_create(struct Main *bmain, + struct Scene *scene, + struct ViewLayer *view_layer, + struct ID *id_root, + struct ID *id_reference); struct IDOverrideLibraryProperty *BKE_lib_override_library_property_find( struct IDOverrideLibrary *override, const char *rna_path); @@ -111,6 +118,9 @@ bool BKE_lib_override_library_status_check_reference(struct Main *bmain, struct bool BKE_lib_override_library_operations_create(struct Main *bmain, struct ID *local); void BKE_lib_override_library_main_operations_create(struct Main *bmain, const bool force_auto); +void BKE_lib_override_library_id_reset(struct Main *bmain, struct ID *id_root); +void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain, struct ID *id_root); + void BKE_lib_override_library_operations_tag(struct IDOverrideLibraryProperty *override_property, const short tag, const bool do_set); @@ -130,7 +140,7 @@ void BKE_lib_override_library_main_update(struct Main *bmain); /* For now, we just use a temp main list. */ typedef struct Main OverrideLibraryStorage; -OverrideLibraryStorage *BKE_lib_override_library_operations_store_initialize(void); +OverrideLibraryStorage *BKE_lib_override_library_operations_store_init(void); struct ID *BKE_lib_override_library_operations_store_start( struct Main *bmain, OverrideLibraryStorage *override_storage, struct ID *local); void BKE_lib_override_library_operations_store_end(OverrideLibraryStorage *override_storage, @@ -140,5 +150,3 @@ void BKE_lib_override_library_operations_store_finalize(OverrideLibraryStorage * #ifdef __cplusplus } #endif - -#endif /* __BKE_LIB_OVERRIDE_H__ */ diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h index c5a25e8e7af..b6abe0bf18c 100644 --- a/source/blender/blenkernel/BKE_lib_query.h +++ b/source/blender/blenkernel/BKE_lib_query.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2014 by Blender Foundation. * All rights reserved. */ -#ifndef __BKE_LIB_QUERY_H__ -#define __BKE_LIB_QUERY_H__ +#pragma once /** \file * \ingroup bke @@ -182,5 +181,3 @@ void BKE_library_indirectly_used_data_tag_clear(struct Main *bmain); #ifdef __cplusplus } #endif - -#endif /* __BKE_LIB_QUERY_H__ */ diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h index 8129b9dbafb..fb14e340d8b 100644 --- a/source/blender/blenkernel/BKE_lib_remap.h +++ b/source/blender/blenkernel/BKE_lib_remap.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_LIB_REMAP_H__ -#define __BKE_LIB_REMAP_H__ +#pragma once /** \file * \ingroup bke @@ -113,5 +112,3 @@ void BKE_library_callback_remap_editor_id_reference_set( #ifdef __cplusplus } #endif - -#endif /* __BKE_LIB_REMAP_H__ */ diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 7883d740b0a..3981a4c14ea 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_LIBRARY_H__ -#define __BKE_LIBRARY_H__ +#pragma once /** \file * \ingroup bke @@ -39,5 +38,3 @@ void BKE_library_filepath_set(struct Main *bmain, struct Library *lib, const cha #ifdef __cplusplus } #endif - -#endif /* __BKE_LIBRARY_H__ */ diff --git a/source/blender/blenkernel/BKE_light.h b/source/blender/blenkernel/BKE_light.h index ead27ec8002..026e5d1a13b 100644 --- a/source/blender/blenkernel/BKE_light.h +++ b/source/blender/blenkernel/BKE_light.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_LIGHT_H__ -#define __BKE_LIGHT_H__ +#pragma once /** \file * \ingroup bke @@ -44,5 +43,3 @@ void BKE_light_eval(struct Depsgraph *depsgraph, struct Light *la); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_lightprobe.h b/source/blender/blenkernel/BKE_lightprobe.h index 6304f61a1f4..e66d4ef75ca 100644 --- a/source/blender/blenkernel/BKE_lightprobe.h +++ b/source/blender/blenkernel/BKE_lightprobe.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_LIGHTPROBE_H__ -#define __BKE_LIGHTPROBE_H__ +#pragma once /** \file * \ingroup bke @@ -39,5 +38,3 @@ struct LightProbe *BKE_lightprobe_copy(struct Main *bmain, const struct LightPro #ifdef __cplusplus } #endif - -#endif /* __BKE_LIGHTPROBE_H__ */ diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h index b086f244923..19238c4d090 100644 --- a/source/blender/blenkernel/BKE_linestyle.h +++ b/source/blender/blenkernel/BKE_linestyle.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_LINESTYLE_H__ -#define __BKE_LINESTYLE_H__ +#pragma once /** \file * \ingroup bke @@ -106,5 +105,3 @@ void BKE_linestyle_default_shader(const struct bContext *C, FreestyleLineStyle * #ifdef __cplusplus } #endif - -#endif /* __BKE_LINESTYLE_H__ */ diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index b7c70168a49..2187ab6b9f5 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_MAIN_H__ -#define __BKE_MAIN_H__ +#pragma once /** \file * \ingroup bke @@ -250,5 +249,3 @@ int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); #ifdef __cplusplus } #endif - -#endif /* __BKE_MAIN_H__ */ diff --git a/source/blender/blenkernel/BKE_main_idmap.h b/source/blender/blenkernel/BKE_main_idmap.h index e392b7db60e..b89714cefa4 100644 --- a/source/blender/blenkernel/BKE_main_idmap.h +++ b/source/blender/blenkernel/BKE_main_idmap.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_MAIN_IDMAP_H__ -#define __BKE_MAIN_IDMAP_H__ +#pragma once /** \file * \ingroup bke @@ -69,5 +68,3 @@ struct ID *BKE_main_idmap_lookup_uuid(struct IDNameLib_Map *id_typemap, #ifdef __cplusplus } #endif - -#endif /* __BKE_MAIN_IDMAP_H__ */ diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index dca677343ce..ab731c5e42f 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_MASK_H__ -#define __BKE_MASK_H__ +#pragma once /** \file * \ingroup bke @@ -331,5 +330,3 @@ void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle, #ifdef __cplusplus } #endif - -#endif /* __BKE_MASK_H__ */ diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 225d966a51a..a30d7d55985 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_MATERIAL_H__ -#define __BKE_MATERIAL_H__ +#pragma once /** \file * \ingroup bke @@ -84,7 +83,8 @@ void BKE_object_material_assign( void BKE_object_material_array_assign(struct Main *bmain, struct Object *ob, struct Material ***matar, - short totcol); + int totcol, + const bool to_object_only); short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma); bool BKE_object_material_slot_add(struct Main *bmain, struct Object *ob); @@ -135,5 +135,3 @@ void BKE_material_eval(struct Depsgraph *depsgraph, struct Material *material); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 5f51f528d14..f2ad23a35f1 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_MBALL_H__ -#define __BKE_MBALL_H__ +#pragma once /** \file * \ingroup bke @@ -92,5 +91,3 @@ extern void (*BKE_mball_batch_cache_free_cb)(struct MetaBall *mb); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h index 4e0649cf930..0ffbcf5bb05 100644 --- a/source/blender/blenkernel/BKE_mball_tessellate.h +++ b/source/blender/blenkernel/BKE_mball_tessellate.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_MBALL_TESSELLATE_H__ -#define __BKE_MBALL_TESSELLATE_H__ +#pragma once /** \file * \ingroup bke @@ -38,5 +37,3 @@ void BKE_mball_cubeTable_free(void); #ifdef __cplusplus } #endif - -#endif /* __BKE_MBALL_TESSELLATE_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 7d989bfcf69..045563f8e52 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_MESH_H__ -#define __BKE_MESH_H__ +#pragma once /** \file * \ingroup bke @@ -231,7 +230,7 @@ void BKE_mesh_nomain_to_meshkey(struct Mesh *mesh_src, struct Mesh *mesh_dst, st /* vertex level transformations & checks (no derived mesh) */ bool BKE_mesh_minmax(const struct Mesh *me, float r_min[3], float r_max[3]); -void BKE_mesh_transform(struct Mesh *me, float mat[4][4], bool do_keys); +void BKE_mesh_transform(struct Mesh *me, const float mat[4][4], bool do_keys); void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys); void BKE_mesh_ensure_navmesh(struct Mesh *me); @@ -513,13 +512,13 @@ void BKE_mesh_loops_to_mface_corners(struct CustomData *fdata, void BKE_mesh_loops_to_tessdata(struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface, - int *polyindices, + const int *polyindices, unsigned int (*loopindices)[4], const int num_faces); void BKE_mesh_tangent_loops_to_tessdata(struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface, - int *polyindices, + const int *polyindices, unsigned int (*loopindices)[4], const int num_faces, const char *layer_name); @@ -707,5 +706,3 @@ BLI_INLINE int BKE_mesh_origindex_mface_mpoly(const int *index_mf_to_mpoly, #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh_iterators.h b/source/blender/blenkernel/BKE_mesh_iterators.h index f7eaa7f69b8..103e7b5b78f 100644 --- a/source/blender/blenkernel/BKE_mesh_iterators.h +++ b/source/blender/blenkernel/BKE_mesh_iterators.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_MESH_ITERATORS_H__ -#define __BKE_MESH_ITERATORS_H__ +#pragma once /** \file * \ingroup bke @@ -70,5 +69,3 @@ void BKE_mesh_foreach_mapped_vert_coords_get(struct Mesh *me_eval, #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_ITERATORS_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index 9864cc4d28d..140a60dbdb7 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_MESH_MAPPING_H__ -#define __BKE_MESH_MAPPING_H__ +#pragma once /** \file * \ingroup bke @@ -199,7 +198,7 @@ void BKE_mesh_loop_islands_clear(MeshIslandStore *island_store); void BKE_mesh_loop_islands_free(MeshIslandStore *island_store); void BKE_mesh_loop_islands_add(MeshIslandStore *islands, const int item_num, - int *item_indices, + const int *item_indices, const int num_island_items, int *island_item_indices, const int num_innercut_items, @@ -258,5 +257,3 @@ int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge, #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_MAPPING_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh_mirror.h b/source/blender/blenkernel/BKE_mesh_mirror.h index 0a68d028e35..2c6920a18bf 100644 --- a/source/blender/blenkernel/BKE_mesh_mirror.h +++ b/source/blender/blenkernel/BKE_mesh_mirror.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_MESH_MIRROR_H__ -#define __BKE_MESH_MIRROR_H__ +#pragma once /** \file * \ingroup bke @@ -49,5 +48,3 @@ struct Mesh *BKE_mesh_mirror_apply_mirror_on_axis(struct MirrorModifierData *mmd #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_MIRROR_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh_remap.h b/source/blender/blenkernel/BKE_mesh_remap.h index fff89e50744..d9b6ab3813e 100644 --- a/source/blender/blenkernel/BKE_mesh_remap.h +++ b/source/blender/blenkernel/BKE_mesh_remap.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_MESH_REMAP_H__ -#define __BKE_MESH_REMAP_H__ +#pragma once /** \file * \ingroup bke @@ -234,5 +233,3 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode, #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_REMAP_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h index 24f95f7ed20..2265fa6e105 100644 --- a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h +++ b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_MESH_REMESH_VOXEL_H__ -#define __BKE_MESH_REMESH_VOXEL_H__ +#pragma once /** \file * \ingroup bke @@ -66,5 +65,3 @@ void BKE_remesh_reproject_sculpt_face_sets(struct Mesh *target, struct Mesh *sou #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_REMESH_VOXEL_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h index 468ec6a44cd..adb7c357049 100644 --- a/source/blender/blenkernel/BKE_mesh_runtime.h +++ b/source/blender/blenkernel/BKE_mesh_runtime.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_MESH_RUNTIME_H__ -#define __BKE_MESH_RUNTIME_H__ +#pragma once /** \file * \ingroup bke @@ -111,5 +110,3 @@ bool BKE_mesh_runtime_is_valid(struct Mesh *me_eval); #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_RUNTIME_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h index 7b686f112aa..96eaa23ce71 100644 --- a/source/blender/blenkernel/BKE_mesh_tangent.h +++ b/source/blender/blenkernel/BKE_mesh_tangent.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_MESH_TANGENT_H__ -#define __BKE_MESH_TANGENT_H__ +#pragma once /** \file * \ingroup bke @@ -87,5 +86,3 @@ void BKE_mesh_calc_loop_tangent_step_0(const struct CustomData *loopData, #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_TANGENT_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh_wrapper.h b/source/blender/blenkernel/BKE_mesh_wrapper.h index 00e2dd08726..2fe264fd0f7 100644 --- a/source/blender/blenkernel/BKE_mesh_wrapper.h +++ b/source/blender/blenkernel/BKE_mesh_wrapper.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_MESH_WRAPPER_H__ -#define __BKE_MESH_WRAPPER_H__ +#pragma once /** \file * \ingroup bke @@ -55,5 +54,3 @@ void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const struct Mesh *me, #ifdef __cplusplus } #endif - -#endif /* __BKE_MESH_WRAPPER_H__ */ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index e16a9284425..f9590696c2e 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_MODIFIER_H__ -#define __BKE_MODIFIER_H__ +#pragma once /** \file * \ingroup bke @@ -543,5 +542,3 @@ struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index dbd6eb15bf2..958fbef1f97 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_MOVIECLIP_H__ -#define __BKE_MOVIECLIP_H__ +#pragma once /** \file * \ingroup bke @@ -113,6 +112,11 @@ bool BKE_movieclip_put_frame_if_possible(struct MovieClip *clip, struct MovieClipUser *user, struct ImBuf *ibuf); +struct GPUTexture *BKE_movieclip_get_gpu_texture(struct MovieClip *clip, + struct MovieClipUser *cuser); + +void BKE_movieclip_free_gputexture(struct MovieClip *clip); + /* Dependency graph evaluation. */ void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, @@ -132,5 +136,3 @@ void BKE_movieclip_eval_selection_update(struct Depsgraph *depsgraph, struct Mov #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 15ba72ef5b5..db2dc7ec87f 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_MULTIRES_H__ -#define __BKE_MULTIRES_H__ +#pragma once /** \file * \ingroup bke @@ -235,5 +234,3 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3] #endif #include "intern/multires_inline.h" - -#endif /* __BKE_MULTIRES_H__ */ diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 2be8d657bf4..8b3231e5302 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_NLA_H__ -#define __BKE_NLA_H__ +#pragma once /** \file * \ingroup bke @@ -149,5 +148,3 @@ float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index bdcbe2129c8..ef46bc0f202 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_NODE_H__ -#define __BKE_NODE_H__ +#pragma once /** \file * \ingroup bke @@ -101,6 +100,30 @@ typedef struct bNodeSocketTemplate { char identifier[64]; /* generated from name */ } bNodeSocketTemplate; +/* Use `void *` for callbacks that require C++. This is rather ugly, but works well for now. This + * would not be necessary if we would use bNodeSocketType and bNodeType only in C++ code. + * However, achieving this requires quite a few changes currently. */ +#ifdef __cplusplus +namespace blender { +namespace nodes { +class SocketMFNetworkBuilder; +class NodeMFNetworkBuilder; +} // namespace nodes +namespace fn { +class MFDataType; +} +} // namespace blender + +using NodeExpandInMFNetworkFunction = void (*)(blender::nodes::NodeMFNetworkBuilder &builder); +using SocketGetMFDataTypeFunction = blender::fn::MFDataType (*)(); +using SocketExpandInMFNetworkFunction = void (*)(blender::nodes::SocketMFNetworkBuilder &builder); + +#else +typedef void *NodeExpandInMFNetworkFunction; +typedef void *SocketGetMFDataTypeFunction; +typedef void *SocketExpandInMFNetworkFunction; +#endif + /** * \brief Defines a socket type. * @@ -153,6 +176,11 @@ typedef struct bNodeSocketType { /* Callback to free the socket type. */ void (*free_self)(struct bNodeSocketType *stype); + + /* Returns the multi-function data type of this socket type. */ + SocketGetMFDataTypeFunction get_mf_data_type; + /* Expands the socket into a multi-function node that outputs the socket value. */ + SocketExpandInMFNetworkFunction expand_in_mf_network; } bNodeSocketType; typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, @@ -267,6 +295,9 @@ typedef struct bNodeType { /* gpu */ NodeGPUExecFunction gpufunc; + /* Expands the bNode into nodes in a multi-function network, which will be evaluated later on. */ + NodeExpandInMFNetworkFunction expand_in_mf_network; + /* RNA integration */ ExtensionRNA rna_ext; } bNodeType; @@ -1299,6 +1330,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define SIM_NODE_EMIT_PARTICLES 1009 #define SIM_NODE_TIME 1010 #define SIM_NODE_PARTICLE_ATTRIBUTE 1011 +#define SIM_NODE_AGE_REACHED_EVENT 1012 +#define SIM_NODE_KILL_PARTICLE 1013 /** \} */ @@ -1311,6 +1344,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define FN_NODE_FLOAT_COMPARE 1202 #define FN_NODE_GROUP_INSTANCE_ID 1203 #define FN_NODE_COMBINE_STRINGS 1204 +#define FN_NODE_OBJECT_TRANSFORMS 1205 +#define FN_NODE_RANDOM_FLOAT 1206 /** \} */ @@ -1332,5 +1367,3 @@ extern struct bNodeSocketType NodeSocketTypeUndefined; #ifdef __cplusplus } #endif - -#endif /* __BKE_NODE_H__ */ diff --git a/source/blender/blenkernel/BKE_node_tree_ref.hh b/source/blender/blenkernel/BKE_node_tree_ref.hh deleted file mode 100644 index e25849cb569..00000000000 --- a/source/blender/blenkernel/BKE_node_tree_ref.hh +++ /dev/null @@ -1,445 +0,0 @@ -/* - * 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. - */ - -#ifndef __BKE_NODE_TREE_REF_HH__ -#define __BKE_NODE_TREE_REF_HH__ - -/** \file - * \ingroup bke - * - * NodeTreeRef makes querying information about a bNodeTree more efficient. It is an immutable data - * structure. It should not be used after anymore, after the underlying node tree changed. - * - * The following queries are supported efficiently: - * - socket -> index of socket - * - socket -> directly linked sockets - * - socket -> linked sockets when skipping reroutes - * - socket -> node - * - socket/node -> rna pointer - * - node -> inputs/outputs - * - node -> tree - * - tree -> all nodes - * - tree -> all (input/output) sockets - * - idname -> nodes - * - * Every socket has an id. The id-space is shared between input and output sockets. - * When storing data per socket, it is often better to use the id as index into an array, instead - * of a hash table. - * - * Every node has an id as well. The same rule regarding hash tables applies. - * - * There is an utility to export this data structure as graph in dot format. - */ - -#include "BLI_array.hh" -#include "BLI_linear_allocator.hh" -#include "BLI_map.hh" -#include "BLI_string_ref.hh" -#include "BLI_timeit.hh" -#include "BLI_utility_mixins.hh" -#include "BLI_vector.hh" - -#include "BKE_node.h" - -#include "DNA_node_types.h" - -#include "RNA_access.h" - -namespace blender::bke { - -class SocketRef; -class InputSocketRef; -class OutputSocketRef; -class NodeRef; -class NodeTreeRef; - -class SocketRef : NonCopyable, NonMovable { - protected: - NodeRef *node_; - bNodeSocket *bsocket_; - bool is_input_; - uint id_; - uint index_; - PointerRNA rna_; - Vector<SocketRef *> linked_sockets_; - Vector<SocketRef *> directly_linked_sockets_; - - friend NodeTreeRef; - - public: - Span<const SocketRef *> linked_sockets() const; - Span<const SocketRef *> directly_linked_sockets() const; - bool is_linked() const; - - const NodeRef &node() const; - const NodeTreeRef &tree() const; - - uint id() const; - uint index() const; - - bool is_input() const; - bool is_output() const; - - const SocketRef &as_base() const; - const InputSocketRef &as_input() const; - const OutputSocketRef &as_output() const; - - PointerRNA *rna() const; - - StringRefNull idname() const; - StringRefNull name() const; - - bNodeSocket *bsocket() const; - bNode *bnode() const; - bNodeTree *btree() const; -}; - -class InputSocketRef final : public SocketRef { - public: - Span<const OutputSocketRef *> linked_sockets() const; - Span<const OutputSocketRef *> directly_linked_sockets() const; -}; - -class OutputSocketRef final : public SocketRef { - public: - Span<const InputSocketRef *> linked_sockets() const; - Span<const InputSocketRef *> directly_linked_sockets() const; -}; - -class NodeRef : NonCopyable, NonMovable { - private: - NodeTreeRef *tree_; - bNode *bnode_; - PointerRNA rna_; - uint id_; - Vector<InputSocketRef *> inputs_; - Vector<OutputSocketRef *> outputs_; - - friend NodeTreeRef; - - public: - const NodeTreeRef &tree() const; - - Span<const InputSocketRef *> inputs() const; - Span<const OutputSocketRef *> outputs() const; - - const InputSocketRef &input(uint index) const; - const OutputSocketRef &output(uint index) const; - - bNode *bnode() const; - bNodeTree *btree() const; - - PointerRNA *rna() const; - StringRefNull idname() const; - StringRefNull name() const; - - uint id() const; - - bool is_reroute_node() const; - bool is_group_node() const; - bool is_group_input_node() const; - bool is_group_output_node() const; -}; - -class NodeTreeRef : NonCopyable, NonMovable { - private: - LinearAllocator<> allocator_; - bNodeTree *btree_; - Vector<NodeRef *> nodes_by_id_; - Vector<SocketRef *> sockets_by_id_; - Vector<InputSocketRef *> input_sockets_; - Vector<OutputSocketRef *> output_sockets_; - Map<const bNodeType *, Vector<NodeRef *>> nodes_by_type_; - - public: - NodeTreeRef(bNodeTree *btree); - ~NodeTreeRef(); - - Span<const NodeRef *> nodes() const; - Span<const NodeRef *> nodes_by_type(StringRefNull idname) const; - Span<const NodeRef *> nodes_by_type(const bNodeType *nodetype) const; - - Span<const SocketRef *> sockets() const; - Span<const InputSocketRef *> input_sockets() const; - Span<const OutputSocketRef *> output_sockets() const; - - bNodeTree *btree() const; - - std::string to_dot() const; - - private: - /* Utility functions used during construction. */ - InputSocketRef &find_input_socket(Map<bNode *, NodeRef *> &node_mapping, - bNode *bnode, - bNodeSocket *bsocket); - OutputSocketRef &find_output_socket(Map<bNode *, NodeRef *> &node_mapping, - bNode *bnode, - bNodeSocket *bsocket); - void find_targets_skipping_reroutes(OutputSocketRef &socket_ref, Vector<SocketRef *> &r_targets); -}; - -/* -------------------------------------------------------------------- - * SocketRef inline methods. - */ - -inline Span<const SocketRef *> SocketRef::linked_sockets() const -{ - return linked_sockets_.as_span(); -} - -inline Span<const SocketRef *> SocketRef::directly_linked_sockets() const -{ - return directly_linked_sockets_.as_span(); -} - -inline bool SocketRef::is_linked() const -{ - return linked_sockets_.size() > 0; -} - -inline const NodeRef &SocketRef::node() const -{ - return *node_; -} - -inline const NodeTreeRef &SocketRef::tree() const -{ - return node_->tree(); -} - -inline uint SocketRef::id() const -{ - return id_; -} - -inline uint SocketRef::index() const -{ - return index_; -} - -inline bool SocketRef::is_input() const -{ - return is_input_; -} - -inline bool SocketRef::is_output() const -{ - return !is_input_; -} - -inline const SocketRef &SocketRef::as_base() const -{ - return *this; -} - -inline const InputSocketRef &SocketRef::as_input() const -{ - BLI_assert(this->is_input()); - return *(const InputSocketRef *)this; -} - -inline const OutputSocketRef &SocketRef::as_output() const -{ - BLI_assert(this->is_output()); - return *(const OutputSocketRef *)this; -} - -inline PointerRNA *SocketRef::rna() const -{ - return const_cast<PointerRNA *>(&rna_); -} - -inline StringRefNull SocketRef::idname() const -{ - return bsocket_->idname; -} - -inline StringRefNull SocketRef::name() const -{ - return bsocket_->name; -} - -inline bNodeSocket *SocketRef::bsocket() const -{ - return bsocket_; -} - -inline bNode *SocketRef::bnode() const -{ - return node_->bnode(); -} - -inline bNodeTree *SocketRef::btree() const -{ - return node_->btree(); -} - -/* -------------------------------------------------------------------- - * InputSocketRef inline methods. - */ - -inline Span<const OutputSocketRef *> InputSocketRef::linked_sockets() const -{ - return linked_sockets_.as_span().cast<const OutputSocketRef *>(); -} - -inline Span<const OutputSocketRef *> InputSocketRef::directly_linked_sockets() const -{ - return directly_linked_sockets_.as_span().cast<const OutputSocketRef *>(); -} - -/* -------------------------------------------------------------------- - * OutputSocketRef inline methods. - */ - -inline Span<const InputSocketRef *> OutputSocketRef::linked_sockets() const -{ - return linked_sockets_.as_span().cast<const InputSocketRef *>(); -} - -inline Span<const InputSocketRef *> OutputSocketRef::directly_linked_sockets() const -{ - return directly_linked_sockets_.as_span().cast<const InputSocketRef *>(); -} - -/* -------------------------------------------------------------------- - * NodeRef inline methods. - */ - -inline const NodeTreeRef &NodeRef::tree() const -{ - return *tree_; -} - -inline Span<const InputSocketRef *> NodeRef::inputs() const -{ - return inputs_.as_span(); -} - -inline Span<const OutputSocketRef *> NodeRef::outputs() const -{ - return outputs_.as_span(); -} - -inline const InputSocketRef &NodeRef::input(uint index) const -{ - return *inputs_[index]; -} - -inline const OutputSocketRef &NodeRef::output(uint index) const -{ - return *outputs_[index]; -} - -inline bNode *NodeRef::bnode() const -{ - return bnode_; -} - -inline bNodeTree *NodeRef::btree() const -{ - return tree_->btree(); -} - -inline PointerRNA *NodeRef::rna() const -{ - return const_cast<PointerRNA *>(&rna_); -} - -inline StringRefNull NodeRef::idname() const -{ - return bnode_->idname; -} - -inline StringRefNull NodeRef::name() const -{ - return bnode_->name; -} - -inline uint NodeRef::id() const -{ - return id_; -} - -inline bool NodeRef::is_reroute_node() const -{ - return bnode_->type == NODE_REROUTE; -} - -inline bool NodeRef::is_group_node() const -{ - return bnode_->type == NODE_GROUP; -} - -inline bool NodeRef::is_group_input_node() const -{ - return bnode_->type == NODE_GROUP_INPUT; -} - -inline bool NodeRef::is_group_output_node() const -{ - return bnode_->type == NODE_GROUP_OUTPUT; -} - -/* -------------------------------------------------------------------- - * NodeRef inline methods. - */ - -inline Span<const NodeRef *> NodeTreeRef::nodes() const -{ - return nodes_by_id_.as_span(); -} - -inline Span<const NodeRef *> NodeTreeRef::nodes_by_type(StringRefNull idname) const -{ - const bNodeType *nodetype = nodeTypeFind(idname.data()); - return this->nodes_by_type(nodetype); -} - -inline Span<const NodeRef *> NodeTreeRef::nodes_by_type(const bNodeType *nodetype) const -{ - const Vector<NodeRef *> *nodes = nodes_by_type_.lookup_ptr(nodetype); - if (nodes == nullptr) { - return {}; - } - else { - return nodes->as_span(); - } -} - -inline Span<const SocketRef *> NodeTreeRef::sockets() const -{ - return sockets_by_id_.as_span(); -} - -inline Span<const InputSocketRef *> NodeTreeRef::input_sockets() const -{ - return input_sockets_.as_span(); -} - -inline Span<const OutputSocketRef *> NodeTreeRef::output_sockets() const -{ - return output_sockets_.as_span(); -} - -inline bNodeTree *NodeTreeRef::btree() const -{ - return btree_; -} - -} // namespace blender::bke - -#endif /* __BKE_NODE_TREE_REF_HH__ */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index d830a35dda0..215f4043e34 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_OBJECT_H__ -#define __BKE_OBJECT_H__ +#pragma once /** \file * \ingroup bke @@ -139,26 +138,26 @@ bool BKE_object_obdata_is_libdata(const struct Object *ob); struct Object *BKE_object_duplicate(struct Main *bmain, struct Object *ob, - const uint dupflag, + uint dupflag, const uint duplicate_options); void BKE_object_obdata_size_init(struct Object *ob, const float scale); -void BKE_object_scale_to_mat3(struct Object *ob, float mat[3][3]); -void BKE_object_rot_to_mat3(const struct Object *ob, float mat[3][3], bool use_drot); -void BKE_object_mat3_to_rot(struct Object *ob, float mat[3][3], bool use_compat); -void BKE_object_to_mat3(struct Object *ob, float mat[3][3]); -void BKE_object_to_mat4(struct Object *ob, float mat[4][4]); +void BKE_object_scale_to_mat3(struct Object *ob, float r_mat[3][3]); +void BKE_object_rot_to_mat3(const struct Object *ob, float r_mat[3][3], bool use_drot); +void BKE_object_mat3_to_rot(struct Object *ob, float r_mat[3][3], bool use_compat); +void BKE_object_to_mat3(struct Object *ob, float r_mat[3][3]); +void BKE_object_to_mat4(struct Object *ob, float r_mat[4][4]); void BKE_object_apply_mat4(struct Object *ob, - float mat[4][4], + const float mat[4][4], const bool use_compat, const bool use_parent); void BKE_object_apply_mat4_ex(struct Object *ob, - float mat[4][4], + const float mat[4][4], struct Object *parent, - float parentinv[4][4], + const float parentinv[4][4], const bool use_compat); -void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]); +void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4]); bool BKE_object_pose_context_check(const struct Object *ob); struct Object *BKE_object_pose_armature_get(struct Object *ob); @@ -188,7 +187,7 @@ struct Base **BKE_object_pose_base_array_get(struct ViewLayer *view_layer, struct View3D *v3d, unsigned int *r_bases_len); -void BKE_object_get_parent_matrix(struct Object *ob, struct Object *par, float parentmat[4][4]); +void BKE_object_get_parent_matrix(struct Object *ob, struct Object *par, float r_parentmat[4][4]); 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, @@ -199,7 +198,7 @@ void BKE_object_where_is_calc_time(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, float ctime); -void BKE_object_where_is_calc_mat4(struct Object *ob, float obmat[4][4]); +void BKE_object_where_is_calc_mat4(struct Object *ob, float r_obmat[4][4]); /* possibly belong in own moduke? */ struct BoundBox *BKE_boundbox_alloc_unit(void); @@ -207,12 +206,12 @@ void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], cons void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]); void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]); void BKE_boundbox_minmax(const struct BoundBox *bb, - float obmat[4][4], + const float obmat[4][4], float r_min[3], float r_max[3]); struct BoundBox *BKE_object_boundbox_get(struct Object *ob); -void BKE_object_dimensions_get(struct Object *ob, float vec[3]); +void BKE_object_dimensions_get(struct Object *ob, float r_vec[3]); void BKE_object_dimensions_set_ex(struct Object *ob, const float value[3], int axis_mask, @@ -233,7 +232,7 @@ bool BKE_object_minmax_dupli(struct Depsgraph *depsgraph, /* sometimes min-max isn't enough, we need to loop over each point */ void BKE_object_foreach_display_point(struct Object *ob, - float obmat[4][4], + const float obmat[4][4], void (*func_cb)(const float[3], void *), void *user_data); void BKE_scene_foreach_display_point(struct Depsgraph *depsgraph, @@ -413,5 +412,3 @@ void BKE_object_to_mesh_clear(struct Object *object); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h index 410cb862aa7..a10158254c2 100644 --- a/source/blender/blenkernel/BKE_object_deform.h +++ b/source/blender/blenkernel/BKE_object_deform.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_OBJECT_DEFORM_H__ -#define __BKE_OBJECT_DEFORM_H__ +#pragma once /** \file * \ingroup bke @@ -33,7 +32,7 @@ struct Object; struct bDeformGroup; /* General vgroup operations */ -void BKE_object_defgroup_remap_update_users(struct Object *ob, int *map); +void BKE_object_defgroup_remap_update_users(struct Object *ob, const int *map); bool BKE_object_defgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot); @@ -95,5 +94,3 @@ void BKE_object_defgroup_mirror_selection(struct Object *ob, #ifdef __cplusplus } #endif - -#endif /* __BKE_OBJECT_DEFORM_H__ */ diff --git a/source/blender/blenkernel/BKE_object_facemap.h b/source/blender/blenkernel/BKE_object_facemap.h index 83780d8fad5..10cb4a54bde 100644 --- a/source/blender/blenkernel/BKE_object_facemap.h +++ b/source/blender/blenkernel/BKE_object_facemap.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_OBJECT_FACEMAP_H__ -#define __BKE_OBJECT_FACEMAP_H__ +#pragma once /** \file * \ingroup bke @@ -48,5 +47,3 @@ void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, #ifdef __cplusplus } #endif - -#endif /* __BKE_OBJECT_FACEMAP_H__ */ diff --git a/source/blender/blenkernel/BKE_ocean.h b/source/blender/blenkernel/BKE_ocean.h index 6ce2e13cf18..1f8cdf27eb1 100644 --- a/source/blender/blenkernel/BKE_ocean.h +++ b/source/blender/blenkernel/BKE_ocean.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_OCEAN_H__ -#define __BKE_OCEAN_H__ +#pragma once #include <stdbool.h> @@ -70,8 +69,10 @@ typedef struct OceanCache { struct Ocean *BKE_ocean_add(void); void BKE_ocean_free_data(struct Ocean *oc); void BKE_ocean_free(struct Ocean *oc); -bool BKE_ocean_ensure(struct OceanModifierData *omd); -void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd); +bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution); +void BKE_ocean_init_from_modifier(struct Ocean *ocean, + struct OceanModifierData const *omd, + const int resolution); void BKE_ocean_init(struct Ocean *o, int M, @@ -135,5 +136,3 @@ float BLI_ocean_spectrum_jonswap(const struct Ocean *oc, const float kx, const f #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_outliner_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h index 9f4ebffdcf4..94bf0f622d6 100644 --- a/source/blender/blenkernel/BKE_outliner_treehash.h +++ b/source/blender/blenkernel/BKE_outliner_treehash.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_OUTLINER_TREEHASH_H__ -#define __BKE_OUTLINER_TREEHASH_H__ +#pragma once /** \file * \ingroup bke @@ -59,5 +58,3 @@ void BKE_outliner_treehash_free(void *treehash); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index fb2578b81b0..1e8721045cd 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_PACKEDFILE_H__ -#define __BKE_PACKEDFILE_H__ +#pragma once /** \file * \ingroup bke @@ -125,5 +124,3 @@ void BKE_packedfile_id_unpack(struct Main *bmain, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index e08d3fe26fb..4e520948bcb 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -17,13 +17,13 @@ * All rights reserved. */ -#ifndef __BKE_PAINT_H__ -#define __BKE_PAINT_H__ +#pragma once /** \file * \ingroup bke */ +#include "BLI_bitmap.h" #include "BLI_utildefines.h" #include "DNA_object_enums.h" @@ -41,6 +41,7 @@ struct EdgeSet; struct GHash; struct GridPaintMask; struct ImagePool; +struct ListBase; struct MLoop; struct MLoopTri; struct MVert; @@ -259,10 +260,20 @@ typedef struct SculptPoseIKChain { /* Cloth Brush */ typedef struct SculptClothLengthConstraint { - int v1; - int v2; + /* Elements that are affected by the constraint. */ + /* Element a should always be a mesh vertex with the index stored in elem_index_a as it is always + * deformed. Element b could be another vertex of the same mesh or any other position (arbitrary + * point, position for a previous state). In that case, elem_index_a and elem_index_b should be + * the same to avoid affecting two different vertices when solving the constraints. + * *elem_position points to the position which is owned by the element. */ + int elem_index_a; + float *elem_position_a; + + int elem_index_b; + float *elem_position_b; float length; + float strength; } SculptClothLengthConstraint; typedef struct SculptClothSimulation { @@ -272,6 +283,11 @@ typedef struct SculptClothSimulation { int capacity_length_constraints; float *length_constraint_tweak; + /* Position anchors for deformation brushes. These positions are modified by the brush and the + * final positions of the simulated vertices are updated with constraints that use these points + * as targets. */ + float (*deformation_pos)[3]; + float mass; float damping; @@ -279,7 +295,9 @@ typedef struct SculptClothSimulation { float (*pos)[3]; float (*init_pos)[3]; float (*prev_pos)[3]; + float (*last_iteration_pos)[3]; + struct ListBase *collider_list; } SculptClothSimulation; typedef struct SculptPersistentBase { @@ -291,6 +309,9 @@ typedef struct SculptPersistentBase { typedef struct SculptVertexInfo { /* Idexed by vertex, stores and ID of its topologycally connected component. */ int *connected_component; + + /* Indexed by base mesh vertex index, stores if that vertex is a boundary. */ + BLI_bitmap *boundary; } SculptVertexInfo; typedef struct SculptFakeNeighbors { @@ -314,6 +335,9 @@ typedef struct SculptSession { int level; } multires; + /* Depsgraph for the Cloth Brush solver to get the colliders. */ + struct Depsgraph *depsgraph; + /* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */ struct MVert *mvert; struct MPoly *mpoly; @@ -447,6 +471,10 @@ void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss); void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder); void BKE_sculptsession_bm_to_me_for_render(struct Object *object); +/* Create new color layer on object if it doesn't have one and if experimental feature set has + * sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */ +void BKE_sculpt_color_layer_create_if_needed(struct Object *object); + void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph, struct Object *ob_orig, bool need_pmap, @@ -463,6 +491,10 @@ struct PBVH *BKE_sculpt_object_pbvh_ensure(struct Depsgraph *depsgraph, struct O void BKE_sculpt_bvh_update_from_ccg(struct PBVH *pbvh, struct SubdivCCG *subdiv_ccg); +/* This ensure that all elements in the mesh (both vertices and grids) have their visibility + * updated according to the face sets. */ +void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg); + bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d); enum { @@ -473,5 +505,3 @@ enum { #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index a22cb9ef126..7d317538f44 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -20,8 +20,7 @@ * Copyright 2011-2012 AutoCRC */ -#ifndef __BKE_PARTICLE_H__ -#define __BKE_PARTICLE_H__ +#pragma once /** \file * \ingroup bke @@ -217,7 +216,7 @@ typedef struct ParticleCollision { /** Collision modifier for current object. */ struct CollisionModifierData *md; - /** Time factor of previous collision, needed for substracting face velocity. */ + /** Time factor of previous collision, needed for subtracting face velocity. */ float f; float fac1, fac2; @@ -365,6 +364,10 @@ struct ModifierData *object_add_particle_system(struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name); +struct ModifierData *object_copy_particle_system(struct Main *bmain, + struct Scene *scene, + struct Object *ob, + const struct ParticleSystem *psys_orig); void object_remove_particle_system(struct Main *bmain, struct Scene *scene, struct Object *ob); struct ParticleSettings *BKE_particlesettings_add(struct Main *bmain, const char *name); struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, @@ -576,7 +579,7 @@ void psys_particle_on_dm(struct Mesh *mesh_final, /* particle_system.c */ void distribute_particles(struct ParticleSimulationData *sim, int from); -void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa); +void init_particle(struct ParticleSimulationData *sim, struct ParticleData *pa); void psys_calc_dmcache(struct Object *ob, struct Mesh *mesh_final, struct Mesh *mesh_original, @@ -627,5 +630,3 @@ extern void (*BKE_particle_batch_cache_free_cb)(struct ParticleSystem *psys); #ifdef __cplusplus } #endif - -#endif /* __BKE_PARTICLE_H__ */ diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 87875314aec..9826dfaa4a5 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_PBVH_H__ -#define __BKE_PBVH_H__ +#pragma once /** \file * \ingroup bke @@ -224,7 +223,7 @@ void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]); unsigned int **BKE_pbvh_grid_hidden(const PBVH *pbvh); int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden, - int *grid_indices, + const int *grid_indices, int totgrid, int gridsize); @@ -264,6 +263,7 @@ void BKE_pbvh_node_mark_redraw(PBVHNode *node); void BKE_pbvh_node_mark_normals_update(PBVHNode *node); void BKE_pbvh_node_mark_topology_update(PBVHNode *node); void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden); +bool BKE_pbvh_node_fully_hidden_get(PBVHNode *node); void BKE_pbvh_node_fully_masked_set(PBVHNode *node, int fully_masked); bool BKE_pbvh_node_fully_masked_get(PBVHNode *node); void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked); @@ -488,5 +488,3 @@ void BKE_pbvh_node_color_buffer_free(PBVH *pbvh); #ifdef __cplusplus } #endif - -#endif /* __BKE_PBVH_H__ */ diff --git a/source/blender/blenkernel/BKE_persistent_data_handle.hh b/source/blender/blenkernel/BKE_persistent_data_handle.hh new file mode 100644 index 00000000000..bcc84f9c9d0 --- /dev/null +++ b/source/blender/blenkernel/BKE_persistent_data_handle.hh @@ -0,0 +1,129 @@ +/* + * 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. + */ + +#pragma once + +/** \file + * \ingroup bke + * + * A PersistentDataHandle is a weak reference to some data in a Blender file. The handle itself is + * just a number. A PersistentDataHandleMap is used to convert between handles and the actual data. + */ + +#include "BLI_map.hh" + +#include "DNA_ID.h" + +struct Object; + +namespace blender::bke { + +class PersistentDataHandleMap; + +class PersistentDataHandle { + private: + /* Negative values indicate that the handle is "empty". */ + int32_t handle_; + + friend PersistentDataHandleMap; + + protected: + PersistentDataHandle(int handle) : handle_(handle) + { + } + + public: + PersistentDataHandle() : handle_(-1) + { + } + + friend bool operator==(const PersistentDataHandle &a, const PersistentDataHandle &b) + { + return a.handle_ == b.handle_; + } + + friend bool operator!=(const PersistentDataHandle &a, const PersistentDataHandle &b) + { + return !(a == b); + } + + friend std::ostream &operator<<(std::ostream &stream, const PersistentDataHandle &a) + { + stream << a.handle_; + return stream; + } + + uint64_t hash() const + { + return (uint64_t)handle_; + } +}; + +class PersistentIDHandle : public PersistentDataHandle { + friend PersistentDataHandleMap; + using PersistentDataHandle::PersistentDataHandle; +}; + +class PersistentObjectHandle : public PersistentIDHandle { + friend PersistentDataHandleMap; + using PersistentIDHandle::PersistentIDHandle; +}; + +class PersistentDataHandleMap { + private: + Map<int32_t, ID *> id_by_handle_; + Map<ID *, int32_t> handle_by_id_; + + public: + void add(int32_t handle, ID &id) + { + BLI_assert(handle >= 0); + handle_by_id_.add(&id, handle); + id_by_handle_.add(handle, &id); + } + + PersistentIDHandle lookup(ID *id) const + { + const int handle = handle_by_id_.lookup_default(id, -1); + return PersistentIDHandle(handle); + } + + PersistentObjectHandle lookup(Object *object) const + { + const int handle = handle_by_id_.lookup_default((ID *)object, -1); + return PersistentObjectHandle(handle); + } + + ID *lookup(const PersistentIDHandle &handle) const + { + ID *id = id_by_handle_.lookup_default(handle.handle_, nullptr); + return id; + } + + Object *lookup(const PersistentObjectHandle &handle) const + { + ID *id = this->lookup((const PersistentIDHandle &)handle); + if (id == nullptr) { + return nullptr; + } + if (GS(id->name) != ID_OB) { + return nullptr; + } + return (Object *)id; + } +}; + +} // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index b0973ed458c..c5bf94cc0c8 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_POINTCACHE_H__ -#define __BKE_POINTCACHE_H__ +#pragma once /** \file * \ingroup bke @@ -86,12 +85,10 @@ struct ListBase; struct Main; struct Object; struct ParticleKey; -struct ParticleSimulationState; struct ParticleSystem; struct PointCache; struct RigidBodyWorld; struct Scene; -struct Simulation; struct SoftBody; struct ViewLayer; @@ -147,7 +144,7 @@ typedef struct PTCacheID { /* copies point data to cache data */ int (*write_point)(int index, void *calldata, void **data, int cfra); /* copies cache cata to point data */ - void (*read_point)(int index, void *calldata, void **data, float cfra, float *old_data); + void (*read_point)(int index, void *calldata, void **data, float cfra, const float *old_data); /* interpolated between previously read point data and cache data */ void (*interpolate_point)(int index, void *calldata, @@ -155,7 +152,7 @@ typedef struct PTCacheID { float cfra, float cfra1, float cfra2, - float *old_data); + const float *old_data); /* copies point data to cache data */ int (*write_stream)(PTCacheFile *pf, void *calldata); @@ -296,7 +293,6 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface); void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw); -void BKE_ptcache_id_from_sim_particles(PTCacheID *pid, struct ParticleSimulationState *state); PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache); void BKE_ptcache_ids_from_object(struct ListBase *lb, @@ -390,5 +386,3 @@ void BKE_ptcache_invalidate(struct PointCache *cache); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_pointcloud.h b/source/blender/blenkernel/BKE_pointcloud.h index d641d3feb62..b2e7e1d23ee 100644 --- a/source/blender/blenkernel/BKE_pointcloud.h +++ b/source/blender/blenkernel/BKE_pointcloud.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_POINTCLOUD_H__ -#define __BKE_POINTCLOUD_H__ +#pragma once /** \file * \ingroup bke @@ -64,5 +63,3 @@ extern void (*BKE_pointcloud_batch_cache_free_cb)(struct PointCloud *pointcloud) #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index 063c0831a0d..5b22918e84c 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_REPORT_H__ -#define __BKE_REPORT_H__ +#pragma once /** \file * \ingroup bke @@ -69,5 +68,3 @@ bool BKE_report_write_file(const char *filepath, ReportList *reports, const char #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index b4aa0ac2b93..c2059144388 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -22,8 +22,7 @@ * \brief API for Blender-side Rigid Body stuff */ -#ifndef __BKE_RIGIDBODY_H__ -#define __BKE_RIGIDBODY_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -162,5 +161,3 @@ void BKE_rigidbody_object_sync_transforms(struct Depsgraph *depsgraph, #ifdef __cplusplus } #endif - -#endif /* __BKE_RIGIDBODY_H__ */ diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 800370318c4..8cd86593873 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_SCENE_H__ -#define __BKE_SCENE_H__ +#pragma once /** \file * \ingroup bke @@ -260,5 +259,3 @@ void BKE_scene_eval_sequencer_sequences(struct Depsgraph *depsgraph, struct Scen #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 91f241018ec..edab543fc37 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_SCREEN_H__ -#define __BKE_SCREEN_H__ +#pragma once /** \file * \ingroup bke @@ -73,7 +72,7 @@ typedef struct SpaceType { /* Initial allocation, after this WM will call init() too. Some editors need * area and scene data (e.g. frame range) to set their initial scrolling. */ - struct SpaceLink *(*new)(const struct ScrArea *area, const struct Scene *scene); + struct SpaceLink *(*create)(const struct ScrArea *area, const struct Scene *scene); /* not free spacelink itself */ void (*free)(struct SpaceLink *sl); @@ -142,7 +141,13 @@ typedef struct ARegionType { void (*exit)(struct wmWindowManager *wm, struct ARegion *region); /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *C, struct ARegion *region); - /* Handler to draw overlays. This handler is called every draw loop. */ + /** + * Handler to draw overlays. This handler is called every draw loop. + * + * \note Some editors should return early if the interface is locked + * (check with #CTX_wm_interface_locked) to avoid accessing scene data + * that another thread may be modifying + */ void (*draw_overlay)(const struct bContext *C, struct ARegion *region); /* optional, compute button layout before drawing for dynamic size */ void (*layout)(const struct bContext *C, struct ARegion *region); @@ -430,5 +435,3 @@ void BKE_screen_header_alignment_reset(struct bScreen *screen); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index a50f9b24c61..b6d901c8ef2 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_SEQUENCER_H__ -#define __BKE_SEQUENCER_H__ +#pragma once /** \file * \ingroup bke @@ -285,6 +284,11 @@ void BKE_sequence_reload_new_file(struct Main *bmain, struct Scene *scene, struct Sequence *seq, const bool lock_range); +void BKE_sequence_movie_reload_if_needed(struct Main *bmain, + struct Scene *scene, + struct Sequence *seq, + bool *r_was_reloaded, + bool *r_can_produce_frames); int BKE_sequencer_evaluate_frame(struct Scene *scene, int cfra); int BKE_sequencer_get_shown_sequences(struct ListBase *seqbasep, int cfra, @@ -522,6 +526,9 @@ typedef struct Sequence *(*SeqLoadFn)(struct bContext *, ListBase *, struct SeqL struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine, int type); +/* Generate new UUID for the given sequence. */ +void BKE_sequence_session_uuid_generate(struct Sequence *sequence); + void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq); void BKE_sequence_init_colorspace(struct Sequence *seq); @@ -619,9 +626,16 @@ void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int cfra); bool BKE_sequencer_check_scene_recursion(struct Scene *scene, struct ReportList *reports); +bool BKE_sequencer_render_loop_check(struct Sequence *seq_main, struct Sequence *seq); +void BKE_sequencer_flag_for_removal(struct Scene *scene, + struct ListBase *seqbase, + struct Sequence *seq); +void BKE_sequencer_remove_flagged_sequences(struct Scene *scene, struct ListBase *seqbase); + +/* A debug and development function which checks whether sequences have unique UUIDs. + * Errors will be reported to the console. */ +void BKE_sequencer_check_uuids_unique_and_report(const struct Scene *scene); #ifdef __cplusplus } #endif - -#endif /* __BKE_SEQUENCER_H__ */ diff --git a/source/blender/blenkernel/BKE_sequencer_offscreen.h b/source/blender/blenkernel/BKE_sequencer_offscreen.h index cc822e97270..90d3f80320a 100644 --- a/source/blender/blenkernel/BKE_sequencer_offscreen.h +++ b/source/blender/blenkernel/BKE_sequencer_offscreen.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_SEQUENCER_OFFSCREEN_H__ -#define __BKE_SEQUENCER_OFFSCREEN_H__ +#pragma once /** \file * \ingroup bke @@ -52,5 +51,3 @@ extern SequencerDrawView sequencer_view3d_fn; #ifdef __cplusplus } #endif - -#endif /* __BKE_SEQUENCER_H__ */ diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index 31e14c6c884..1eb52b389d1 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_SHADER_FX_H__ -#define __BKE_SHADER_FX_H__ +#pragma once /** \file * \ingroup bke @@ -189,5 +188,3 @@ bool BKE_shaderfx_has_gpencil(struct Object *ob); #ifdef __cplusplus } #endif - -#endif /* __BKE_SHADER_FX_H__ */ diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 83129bed5f7..bcf702ea797 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) Blender Foundation. * All rights reserved. */ -#ifndef __BKE_SHRINKWRAP_H__ -#define __BKE_SHRINKWRAP_H__ +#pragma once /** \file * \ingroup bke @@ -192,5 +191,3 @@ void BKE_shrinkwrap_snap_point_to_surface(const struct ShrinkwrapTreeData *tree, #ifdef __cplusplus } #endif - -#endif /* __BKE_SHRINKWRAP_H__ */ diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h index ff6aaa5e30e..2c436f2bff8 100644 --- a/source/blender/blenkernel/BKE_simulation.h +++ b/source/blender/blenkernel/BKE_simulation.h @@ -14,8 +14,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_SIMULATION_H__ -#define __BKE_SIMULATION_H__ +#pragma once + +#include "DNA_simulation_types.h" #ifdef __cplusplus extern "C" { @@ -23,16 +24,34 @@ extern "C" { struct Depsgraph; struct Main; -struct Simulation; +struct Scene; void *BKE_simulation_add(struct Main *bmain, const char *name); void BKE_simulation_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Simulation *simulation); +void BKE_simulation_update_dependencies(struct Simulation *simulation, struct Main *bmain); + +SimulationState *BKE_simulation_state_add(Simulation *simulation, + const char *type, + const char *name); +void BKE_simulation_state_remove(Simulation *simulation, SimulationState *state); +void BKE_simulation_state_remove_all(Simulation *simulation); +void BKE_simulation_state_reset(Simulation *simulation, SimulationState *state); +void BKE_simulation_state_reset_all(Simulation *simulation); +SimulationState *BKE_simulation_state_try_find_by_name(Simulation *simulation, const char *name); +SimulationState *BKE_simulation_state_try_find_by_name_and_type(Simulation *simulation, + const char *name, + const char *type); +void BKE_simulation_state_copy_data(const SimulationState *src_state, SimulationState *dst_state); #ifdef __cplusplus } #endif -#endif /* __BKE_SIMULATION_H__ */ +#ifdef __cplusplus + +template<typename StateType> const char *BKE_simulation_get_state_type_name(); + +#endif diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index e4012094b74..28d299679ed 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) Blender Foundation. * All rights reserved. */ -#ifndef __BKE_SOFTBODY_H__ -#define __BKE_SOFTBODY_H__ +#pragma once /** \file * \ingroup bke @@ -76,5 +75,3 @@ extern void SB_estimate_transform(Object *ob, float lloc[3], float lrot[3][3], f #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index b93591b7b60..57ce33a239f 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_SOUND_H__ -#define __BKE_SOUND_H__ +#pragma once /** \file * \ingroup bke @@ -194,5 +193,3 @@ void BKE_sound_evaluate(struct Depsgraph *depsgraph, struct Main *bmain, struct #ifdef __cplusplus } #endif - -#endif /* __BKE_SOUND_H__ */ diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h index 54bb7274e4b..b01824dd794 100644 --- a/source/blender/blenkernel/BKE_speaker.h +++ b/source/blender/blenkernel/BKE_speaker.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_SPEAKER_H__ -#define __BKE_SPEAKER_H__ +#pragma once /** \file * \ingroup bke @@ -35,5 +34,3 @@ struct Speaker *BKE_speaker_copy(struct Main *bmain, const struct Speaker *spk); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h index ff11f581cc4..32c571e5f91 100644 --- a/source/blender/blenkernel/BKE_studiolight.h +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_STUDIOLIGHT_H__ -#define __BKE_STUDIOLIGHT_H__ +#pragma once /** \file * \ingroup bke @@ -168,5 +167,3 @@ void BKE_studiolight_unset_icon_id(StudioLight *sl, int icon_id); #ifdef __cplusplus } #endif - -#endif /* __BKE_STUDIOLIGHT_H__ */ diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h index 1323938e479..96a79d753cf 100644 --- a/source/blender/blenkernel/BKE_subdiv.h +++ b/source/blender/blenkernel/BKE_subdiv.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_SUBDIV_H__ -#define __BKE_SUBDIV_H__ +#pragma once #include "BLI_compiler_compat.h" #include "BLI_sys_types.h" @@ -302,5 +301,3 @@ BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_char(char edge_crease); #endif #include "intern/subdiv_inline.h" - -#endif /* __BKE_SUBDIV_H__ */ diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index 78e91d3ad2f..2277eb27ef1 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_SUBDIV_CCG_H__ -#define __BKE_SUBDIV_CCG_H__ +#pragma once #include "BKE_DerivedMesh.h" #include "BKE_customdata.h" @@ -313,6 +312,22 @@ void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg, int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index); +typedef enum SubdivCCGAdjacencyType { + SUBDIV_CCG_ADJACENT_NONE, + SUBDIV_CCG_ADJACENT_VERTEX, + SUBDIV_CCG_ADJACENT_EDGE, +} SubdivCCGAdjacencyType; + +/* Returns if a grid coordinates is adjacent to a coarse mesh edge, vertex or nothing. If it is + * adjacent to an edge, r_v1 and r_v2 will be set to the two vertices of that edge. If it is + * adjacent to a vertex, r_v1 and r_v2 will be the index of that vertex. */ +SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg, + const SubdivCCGCoord *coord, + const MLoop *mloop, + const MPoly *mpoly, + int *r_v1, + int *r_v2); + /* Get array which is indexed by face index and contains index of a first grid of the face. * * The "ensure" version allocates the mapping if it's not know yet and stores it in the subdiv_ccg @@ -322,8 +337,8 @@ int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int gri const int *BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG *subdiv_ccg); const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg); +void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index); + #ifdef __cplusplus } #endif - -#endif /* __BKE_SUBDIV_CCG_H__ */ diff --git a/source/blender/blenkernel/BKE_subdiv_deform.h b/source/blender/blenkernel/BKE_subdiv_deform.h index 735cd20a6c8..1cdb8d2c794 100644 --- a/source/blender/blenkernel/BKE_subdiv_deform.h +++ b/source/blender/blenkernel/BKE_subdiv_deform.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_SUBDIV_DEFORM_H__ -#define __BKE_SUBDIV_DEFORM_H__ +#pragma once #include "BLI_sys_types.h" @@ -48,5 +47,3 @@ void BKE_subdiv_deform_coarse_vertices(struct Subdiv *subdiv, #ifdef __cplusplus } #endif - -#endif /* __BKE_SUBDIV_DEFORM_H__ */ diff --git a/source/blender/blenkernel/BKE_subdiv_eval.h b/source/blender/blenkernel/BKE_subdiv_eval.h index aa27df88be8..204e802da6e 100644 --- a/source/blender/blenkernel/BKE_subdiv_eval.h +++ b/source/blender/blenkernel/BKE_subdiv_eval.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_SUBDIV_EVAL_H__ -#define __BKE_SUBDIV_EVAL_H__ +#pragma once #include "BLI_sys_types.h" @@ -149,5 +148,3 @@ void BKE_subdiv_eval_limit_patch_resolution_point_and_short_normal(struct Subdiv #ifdef __cplusplus } #endif - -#endif /* __BKE_SUBDIV_EVAL_H__ */ diff --git a/source/blender/blenkernel/BKE_subdiv_foreach.h b/source/blender/blenkernel/BKE_subdiv_foreach.h index bef141b5ac5..a351b9a3d11 100644 --- a/source/blender/blenkernel/BKE_subdiv_foreach.h +++ b/source/blender/blenkernel/BKE_subdiv_foreach.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_SUBDIV_FOREACH_H__ -#define __BKE_SUBDIV_FOREACH_H__ +#pragma once #include "BLI_sys_types.h" @@ -178,5 +177,3 @@ bool BKE_subdiv_foreach_subdiv_geometry(struct Subdiv *subdiv, #ifdef __cplusplus } #endif - -#endif /* __BKE_SUBDIV_FOREACH_H__ */ diff --git a/source/blender/blenkernel/BKE_subdiv_mesh.h b/source/blender/blenkernel/BKE_subdiv_mesh.h index 9928c41a92b..73a3e8ed02e 100644 --- a/source/blender/blenkernel/BKE_subdiv_mesh.h +++ b/source/blender/blenkernel/BKE_subdiv_mesh.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_SUBDIV_MESH_H__ -#define __BKE_SUBDIV_MESH_H__ +#pragma once #include "BLI_sys_types.h" @@ -53,5 +52,3 @@ struct Mesh *BKE_subdiv_to_mesh(struct Subdiv *subdiv, #ifdef __cplusplus } #endif - -#endif /* __BKE_SUBDIV)MESH_H__ */ diff --git a/source/blender/blenkernel/BKE_subdiv_topology.h b/source/blender/blenkernel/BKE_subdiv_topology.h index cc32b4c03b3..42bd9392aa4 100644 --- a/source/blender/blenkernel/BKE_subdiv_topology.h +++ b/source/blender/blenkernel/BKE_subdiv_topology.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_SUBDIV_TOPOLOGY_H__ -#define __BKE_SUBDIV_TOPOLOGY_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -35,5 +34,3 @@ int BKE_subdiv_topology_num_fvar_layers_get(const struct Subdiv *subdiv); #ifdef __cplusplus } #endif - -#endif /* __BKE_SUBDIV_TOPOLOGY_H__ */ diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 0ed58180ffa..07bbeafb1ae 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_SUBSURF_H__ -#define __BKE_SUBSURF_H__ +#pragma once /** \file * \ingroup bke @@ -158,5 +157,3 @@ typedef struct CCGDerivedMesh { #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 51d589e61c3..289ad351429 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_TEXT_H__ -#define __BKE_TEXT_H__ +#pragma once /** \file * \ingroup bke @@ -118,5 +117,3 @@ void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_text_suggestions.h b/source/blender/blenkernel/BKE_text_suggestions.h index d618fcd6d11..f54e45b6c2f 100644 --- a/source/blender/blenkernel/BKE_text_suggestions.h +++ b/source/blender/blenkernel/BKE_text_suggestions.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2008, Blender Foundation * All rights reserved. */ -#ifndef __BKE_TEXT_SUGGESTIONS_H__ -#define __BKE_TEXT_SUGGESTIONS_H__ +#pragma once /** \file * \ingroup bke @@ -85,5 +84,3 @@ void texttool_docs_clear(void); #ifdef __cplusplus } #endif - -#endif /* __BKE_TEXT_SUGGESTIONS_H__ */ diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 43ef2b1ba7f..c4c2498c2b1 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_TEXTURE_H__ -#define __BKE_TEXTURE_H__ +#pragma once /** \file * \ingroup bke @@ -102,5 +101,3 @@ void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *po #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index bb88fbf863b..2d763132923 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_TRACKING_H__ -#define __BKE_TRACKING_H__ +#pragma once /** \file * \ingroup bke @@ -493,5 +492,3 @@ void BKE_tracking_get_rna_path_prefix_for_plane_track( #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h index b32c3e315ff..4f933ca7a87 100644 --- a/source/blender/blenkernel/BKE_undo_system.h +++ b/source/blender/blenkernel/BKE_undo_system.h @@ -13,8 +13,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_UNDO_SYSTEM_H__ -#define __BKE_UNDO_SYSTEM_H__ +#pragma once /** \file * \ingroup bke @@ -212,5 +211,3 @@ void BKE_undosys_print(UndoStack *ustack); #ifdef __cplusplus } #endif - -#endif /* __BKE_UNDO_SYSTEM_H__ */ diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h index 4f9ff61c9a6..a797c5555ff 100644 --- a/source/blender/blenkernel/BKE_unit.h +++ b/source/blender/blenkernel/BKE_unit.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_UNIT_H__ -#define __BKE_UNIT_H__ +#pragma once /** \file * \ingroup bke @@ -93,5 +92,3 @@ enum { #ifdef __cplusplus } #endif - -#endif /* __BKE_UNIT_H__ */ diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h index 224f3ede45d..b3437454f31 100644 --- a/source/blender/blenkernel/BKE_volume.h +++ b/source/blender/blenkernel/BKE_volume.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_VOLUME_H__ -#define __BKE_VOLUME_H__ +#pragma once /** \file * \ingroup bke @@ -159,5 +158,3 @@ openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *vo struct VolumeGrid *grid, const bool clear); #endif - -#endif diff --git a/source/blender/blenkernel/BKE_volume_render.h b/source/blender/blenkernel/BKE_volume_render.h index 5c3cd0102cf..a42f24a5312 100644 --- a/source/blender/blenkernel/BKE_volume_render.h +++ b/source/blender/blenkernel/BKE_volume_render.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_VOLUME_RENDER_H__ -#define __BKE_VOLUME_RENDER_H__ +#pragma once /** \file * \ingroup bke @@ -66,5 +65,3 @@ float BKE_volume_density_scale(const struct Volume *volume, const float matrix[4 #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h index 8a6afd8a753..5ff1ba2c6f5 100644 --- a/source/blender/blenkernel/BKE_workspace.h +++ b/source/blender/blenkernel/BKE_workspace.h @@ -18,8 +18,7 @@ * \ingroup bke */ -#ifndef __BKE_WORKSPACE_H__ -#define __BKE_WORKSPACE_H__ +#pragma once #include "BLI_compiler_attrs.h" @@ -112,5 +111,3 @@ void BKE_workspace_id_tag_all_visible(struct Main *bmain, int tag) ATTR_NONNULL( #ifdef __cplusplus } #endif - -#endif /* __BKE_WORKSPACE_H__ */ diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h index 3c8f8547b46..82830facccc 100644 --- a/source/blender/blenkernel/BKE_world.h +++ b/source/blender/blenkernel/BKE_world.h @@ -16,8 +16,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ -#ifndef __BKE_WORLD_H__ -#define __BKE_WORLD_H__ +#pragma once /** \file * \ingroup bke @@ -39,5 +38,3 @@ void BKE_world_eval(struct Depsgraph *depsgraph, struct World *world); #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index 79605e99306..97f998cc1c1 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_WRITEAVI_H__ -#define __BKE_WRITEAVI_H__ +#pragma once /** \file * \ingroup bke @@ -73,5 +72,3 @@ void BKE_movie_filepath_get(char *string, #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 467e6ab7242..4c966c55e41 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __BKE_WRITEFFMPEG_H__ -#define __BKE_WRITEFFMPEG_H__ +#pragma once /** \file * \ingroup bke @@ -100,5 +99,3 @@ void BKE_ffmpeg_context_free(void *context_v); # endif #endif - -#endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index b9054d29752..ada341ff570 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../bmesh ../depsgraph ../draw + ../functions ../gpencil_modifiers ../gpu ../ikplugin @@ -35,7 +36,7 @@ set(INC ../makesrna ../modifiers ../nodes - ../physics + ../simulation ../shader_fx ../render/extern/include ../../../intern/ghost @@ -99,6 +100,7 @@ set(SRC intern/context.c intern/crazyspace.c intern/curve.c + intern/curve_bevel.c intern/curve_decimate.c intern/curve_deform.c intern/curveprofile.c @@ -106,7 +108,6 @@ set(SRC intern/customdata_file.c intern/data_transfer.c intern/deform.c - intern/derived_node_tree.cc intern/displist.c intern/displist_tangent.c intern/dynamicpaint.c @@ -134,6 +135,7 @@ set(SRC intern/idtype.c intern/image.c intern/image_gen.c + intern/image_gpu.c intern/image_save.c intern/ipo.c intern/kelvinlet.c @@ -187,7 +189,6 @@ set(SRC intern/multires_unsubdivide.c intern/nla.c intern/node.c - intern/node_tree_ref.cc intern/object.c intern/object_deform.c intern/object_dupli.c @@ -296,7 +297,6 @@ set(SRC BKE_customdata_file.h BKE_data_transfer.h BKE_deform.h - BKE_derived_node_tree.hh BKE_displist.h BKE_displist_tangent.h BKE_duplilist.h @@ -322,6 +322,7 @@ set(SRC BKE_idprop.h BKE_idtype.h BKE_image.h + BKE_image_save.h BKE_ipo.h BKE_kelvinlet.h BKE_key.h @@ -356,7 +357,6 @@ set(SRC BKE_multires.h BKE_nla.h BKE_node.h - BKE_node_tree_ref.hh BKE_object.h BKE_object_deform.h BKE_object_facemap.h @@ -365,6 +365,7 @@ set(SRC BKE_packedFile.h BKE_paint.h BKE_particle.h + BKE_persistent_data_handle.hh BKE_pbvh.h BKE_pointcache.h BKE_pointcloud.h @@ -373,6 +374,7 @@ set(SRC BKE_scene.h BKE_screen.h BKE_sequencer.h + BKE_sequencer_offscreen.h BKE_shader_fx.h BKE_shrinkwrap.h BKE_simulation.h @@ -411,6 +413,7 @@ set(SRC intern/multires_inline.h intern/multires_reshape.h intern/multires_unsubdivide.h + intern/ocean_intern.h intern/pbvh_intern.h intern/subdiv_converter.h intern/subdiv_inline.h @@ -424,6 +427,7 @@ set(LIB bf_bmesh bf_depsgraph bf_draw + bf_functions bf_gpencil_modifiers bf_gpu bf_ikplugin @@ -436,7 +440,7 @@ set(LIB bf_intern_opensubdiv # Uses stub when disabled. bf_modifiers bf_nodes - bf_physics + bf_simulation bf_rna bf_shader_fx ) @@ -694,3 +698,16 @@ blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") # Needed so we can use dna_type_offsets.h for defaults initialization. add_dependencies(bf_blenkernel bf_dna) + + +if(WITH_GTESTS) + set(TEST_SRC + intern/armature_test.cc + intern/fcurve_test.cc + ) + set(TEST_INC + ../editors/include + ) + include(GTestTesting) + blender_add_test_lib(bf_blenkernel_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}") +endif() diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 98deddb4316..8d8301362b3 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -32,8 +32,6 @@ #include "CCGSubSurf.h" #include "CCGSubSurf_intern.h" -#include "GPU_glew.h" - /***/ int BKE_ccg_gridsize(int level) @@ -177,9 +175,7 @@ static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSiz if (v == e->v0) { return &EDGE_getLevelData(e)[dataSize * (levelBase + x)]; } - else { - return &EDGE_getLevelData(e)[dataSize * (levelBase + (1 << lvl) - x)]; - } + return &EDGE_getLevelData(e)[dataSize * (levelBase + (1 << lvl) - x)]; } static void _edge_free(CCGEdge *e, CCGSubSurf *ss) @@ -260,46 +256,45 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, if (subdivLevels < 1) { return NULL; } - else { - CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss)); - ss->allocatorIFC = *allocatorIFC; - ss->allocator = allocator; + CCGSubSurf *ss = allocatorIFC->alloc(allocator, sizeof(*ss)); - ss->vMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator); - ss->eMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator); - ss->fMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator); + ss->allocatorIFC = *allocatorIFC; + ss->allocator = allocator; - ss->meshIFC = *ifc; + ss->vMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator); + ss->eMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator); + ss->fMap = ccg_ehash_new(0, &ss->allocatorIFC, ss->allocator); - ss->subdivLevels = subdivLevels; - ss->numGrids = 0; - ss->allowEdgeCreation = 0; - ss->defaultCreaseValue = 0; - ss->defaultEdgeUserData = NULL; + ss->meshIFC = *ifc; - ss->useAgeCounts = 0; - ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0; + ss->subdivLevels = subdivLevels; + ss->numGrids = 0; + ss->allowEdgeCreation = 0; + ss->defaultCreaseValue = 0; + ss->defaultEdgeUserData = NULL; - ss->calcVertNormals = 0; - ss->normalDataOffset = 0; + ss->useAgeCounts = 0; + ss->vertUserAgeOffset = ss->edgeUserAgeOffset = ss->faceUserAgeOffset = 0; - ss->allocMask = 0; + ss->calcVertNormals = 0; + ss->normalDataOffset = 0; - ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); - ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); + ss->allocMask = 0; - ss->currentAge = 0; + ss->q = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); + ss->r = CCGSUBSURF_alloc(ss, ss->meshIFC.vertDataSize); - ss->syncState = eSyncState_None; + ss->currentAge = 0; - ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL; - ss->lenTempArrays = 0; - ss->tempVerts = NULL; - ss->tempEdges = NULL; + ss->syncState = eSyncState_None; - return ss; - } + ss->oldVMap = ss->oldEMap = ss->oldFMap = NULL; + ss->lenTempArrays = 0; + ss->tempVerts = NULL; + ss->tempEdges = NULL; + + return ss; } void ccgSubSurf_free(CCGSubSurf *ss) @@ -378,7 +373,7 @@ CCGError ccgSubSurf_setSubdivisionLevels(CCGSubSurf *ss, int subdivisionLevels) if (subdivisionLevels <= 0) { return eCCGError_InvalidValue; } - else if (subdivisionLevels != ss->subdivLevels) { + if (subdivisionLevels != ss->subdivLevels) { ss->numGrids = 0; ss->subdivLevels = subdivisionLevels; ccg_ehash_free(ss->vMap, (EHEntryFreeFP)_vert_free, ss); @@ -420,12 +415,10 @@ CCGError ccgSubSurf_setUseAgeCounts( (faceUserOffset + 4 > ss->meshIFC.faceUserSize)) { return eCCGError_InvalidValue; } - else { - ss->useAgeCounts = 1; - ss->vertUserAgeOffset = vertUserOffset; - ss->edgeUserAgeOffset = edgeUserOffset; - ss->faceUserAgeOffset = faceUserOffset; - } + ss->useAgeCounts = 1; + ss->vertUserAgeOffset = vertUserOffset; + ss->edgeUserAgeOffset = edgeUserOffset; + ss->faceUserAgeOffset = faceUserOffset; } else { ss->useAgeCounts = 0; @@ -441,10 +434,8 @@ CCGError ccgSubSurf_setCalcVertexNormals(CCGSubSurf *ss, int useVertNormals, int if (normalDataOffset < 0 || normalDataOffset + 12 > ss->meshIFC.vertDataSize) { return eCCGError_InvalidValue; } - else { - ss->calcVertNormals = 1; - ss->normalDataOffset = normalDataOffset; - } + ss->calcVertNormals = 1; + ss->normalDataOffset = normalDataOffset; } else { ss->calcVertNormals = 0; @@ -512,19 +503,17 @@ CCGError ccgSubSurf_syncVertDel(CCGSubSurf *ss, CCGVertHDL vHDL) if (ss->syncState != eSyncState_Partial) { return eCCGError_InvalidSyncState; } - else { - void **prevp; - CCGVert *v = ccg_ehash_lookupWithPrev(ss->vMap, vHDL, &prevp); - if (!v || v->numFaces || v->numEdges) { - return eCCGError_InvalidValue; - } - else { - *prevp = v->next; - _vert_free(v, ss); - } + void **prevp; + CCGVert *v = ccg_ehash_lookupWithPrev(ss->vMap, vHDL, &prevp); + + if (!v || v->numFaces || v->numEdges) { + return eCCGError_InvalidValue; } + *prevp = v->next; + _vert_free(v, ss); + return eCCGError_None; } @@ -533,19 +522,17 @@ CCGError ccgSubSurf_syncEdgeDel(CCGSubSurf *ss, CCGEdgeHDL eHDL) if (ss->syncState != eSyncState_Partial) { return eCCGError_InvalidSyncState; } - else { - void **prevp; - CCGEdge *e = ccg_ehash_lookupWithPrev(ss->eMap, eHDL, &prevp); - if (!e || e->numFaces) { - return eCCGError_InvalidValue; - } - else { - *prevp = e->next; - _edge_unlinkMarkAndFree(e, ss); - } + void **prevp; + CCGEdge *e = ccg_ehash_lookupWithPrev(ss->eMap, eHDL, &prevp); + + if (!e || e->numFaces) { + return eCCGError_InvalidValue; } + *prevp = e->next; + _edge_unlinkMarkAndFree(e, ss); + return eCCGError_None; } @@ -554,19 +541,17 @@ CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) if (ss->syncState != eSyncState_Partial) { return eCCGError_InvalidSyncState; } - else { - void **prevp; - CCGFace *f = ccg_ehash_lookupWithPrev(ss->fMap, fHDL, &prevp); - if (!f) { - return eCCGError_InvalidValue; - } - else { - *prevp = f->next; - _face_unlinkMarkAndFree(f, ss); - } + void **prevp; + CCGFace *f = ccg_ehash_lookupWithPrev(ss->fMap, fHDL, &prevp); + + if (!f) { + return eCCGError_InvalidValue; } + *prevp = f->next; + _face_unlinkMarkAndFree(f, ss); + return eCCGError_None; } @@ -1264,9 +1249,7 @@ int ccgSubSurf_getEdgeLevelSize(const CCGSubSurf *ss, int level) if (level < 1 || level > ss->subdivLevels) { return -1; } - else { - return ccg_edgesize(level); - } + return ccg_edgesize(level); } int ccgSubSurf_getGridSize(const CCGSubSurf *ss) { @@ -1277,9 +1260,7 @@ int ccgSubSurf_getGridLevelSize(const CCGSubSurf *ss, int level) if (level < 1 || level > ss->subdivLevels) { return -1; } - else { - return ccg_gridsize(level); - } + return ccg_gridsize(level); } int ccgSubSurf_getSimpleSubdiv(const CCGSubSurf *ss) @@ -1299,9 +1280,7 @@ int ccgSubSurf_getVertAge(CCGSubSurf *ss, CCGVert *v) byte *userData = ccgSubSurf_getVertUserData(ss, v); return ss->currentAge - *((int *)&userData[ss->vertUserAgeOffset]); } - else { - return 0; - } + return 0; } void *ccgSubSurf_getVertUserData(CCGSubSurf *ss, CCGVert *v) { @@ -1316,9 +1295,7 @@ CCGFace *ccgSubSurf_getVertFace(CCGVert *v, int index) if (index < 0 || index >= v->numFaces) { return NULL; } - else { - return v->faces[index]; - } + return v->faces[index]; } int ccgSubSurf_getVertNumEdges(CCGVert *v) { @@ -1329,9 +1306,7 @@ CCGEdge *ccgSubSurf_getVertEdge(CCGVert *v, int index) if (index < 0 || index >= v->numEdges) { return NULL; } - else { - return v->edges[index]; - } + return v->edges[index]; } void *ccgSubSurf_getVertData(CCGSubSurf *ss, CCGVert *v) { @@ -1342,9 +1317,7 @@ void *ccgSubSurf_getVertLevelData(CCGSubSurf *ss, CCGVert *v, int level) if (level < 0 || level > ss->subdivLevels) { return NULL; } - else { - return ccg_vert_getCo(v, level, ss->meshIFC.vertDataSize); - } + return ccg_vert_getCo(v, level, ss->meshIFC.vertDataSize); } /* Edge accessors */ @@ -1359,9 +1332,7 @@ int ccgSubSurf_getEdgeAge(CCGSubSurf *ss, CCGEdge *e) byte *userData = ccgSubSurf_getEdgeUserData(ss, e); return ss->currentAge - *((int *)&userData[ss->edgeUserAgeOffset]); } - else { - return 0; - } + return 0; } void *ccgSubSurf_getEdgeUserData(CCGSubSurf *ss, CCGEdge *e) { @@ -1376,9 +1347,7 @@ CCGFace *ccgSubSurf_getEdgeFace(CCGEdge *e, int index) if (index < 0 || index >= e->numFaces) { return NULL; } - else { - return e->faces[index]; - } + return e->faces[index]; } CCGVert *ccgSubSurf_getEdgeVert0(CCGEdge *e) { @@ -1401,9 +1370,7 @@ void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level) if (level < 0 || level > ss->subdivLevels) { return NULL; } - else { - return ccg_edge_getCo(e, level, x, ss->meshIFC.vertDataSize); - } + return ccg_edge_getCo(e, level, x, ss->meshIFC.vertDataSize); } float ccgSubSurf_getEdgeCrease(CCGEdge *e) { @@ -1422,9 +1389,7 @@ int ccgSubSurf_getFaceAge(CCGSubSurf *ss, CCGFace *f) byte *userData = ccgSubSurf_getFaceUserData(ss, f); return ss->currentAge - *((int *)&userData[ss->faceUserAgeOffset]); } - else { - return 0; - } + return 0; } void *ccgSubSurf_getFaceUserData(CCGSubSurf *ss, CCGFace *f) { @@ -1442,18 +1407,14 @@ CCGVert *ccgSubSurf_getFaceVert(CCGFace *f, int index) if (index < 0 || index >= f->numVerts) { return NULL; } - else { - return FACE_getVerts(f)[index]; - } + return FACE_getVerts(f)[index]; } CCGEdge *ccgSubSurf_getFaceEdge(CCGFace *f, int index) { if (index < 0 || index >= f->numVerts) { return NULL; } - else { - return FACE_getEdges(f)[index]; - } + return FACE_getEdges(f)[index]; } int ccgSubSurf_getFaceEdgeIndex(CCGFace *f, CCGEdge *e) { diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index 2e5100db6de..e1805a9c512 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __CCGSUBSURF_H__ -#define __CCGSUBSURF_H__ +#pragma once /** \file * \ingroup bke @@ -210,5 +209,3 @@ void ccgEdgeIterator_next(CCGEdgeIterator *ei); CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *fi); int ccgFaceIterator_isStopped(CCGFaceIterator *fi); void ccgFaceIterator_next(CCGFaceIterator *fi); - -#endif /* __CCGSUBSURF_H__ */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_inline.h b/source/blender/blenkernel/intern/CCGSubSurf_inline.h index 86012bd2a43..8aa1fede57d 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_inline.h +++ b/source/blender/blenkernel/intern/CCGSubSurf_inline.h @@ -18,8 +18,7 @@ * \ingroup bke */ -#ifndef __CCGSUBSURF_INLINE_H__ -#define __CCGSUBSURF_INLINE_H__ +#pragma once BLI_INLINE int ccg_gridsize(int level) { @@ -274,5 +273,3 @@ BLI_INLINE void VertDataAvg4(float v[], v[i] = (a[i] + b[i] + c[i] + d[i]) * 0.25f; } } - -#endif /* __CCGSUBSURF_INLINE_H__ */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_intern.h b/source/blender/blenkernel/intern/CCGSubSurf_intern.h index 7c35d2ccfce..82ca22e193a 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_intern.h +++ b/source/blender/blenkernel/intern/CCGSubSurf_intern.h @@ -18,8 +18,7 @@ * \ingroup bke */ -#ifndef __CCGSUBSURF_INTERN_H__ -#define __CCGSUBSURF_INTERN_H__ +#pragma once /** * Definitions which defines internal behavior of CCGSubSurf. @@ -286,5 +285,3 @@ void ccgSubSurf__dumpCoords(CCGSubSurf *ss); #endif #include "CCGSubSurf_inline.h" - -#endif /* __CCGSUBSURF_INTERN_H__ */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_legacy.c b/source/blender/blenkernel/intern/CCGSubSurf_legacy.c index f3f681baa01..8fc9afd58f1 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_legacy.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_legacy.c @@ -38,9 +38,7 @@ static void *_edge_getCoVert(CCGEdge *e, CCGVert *v, int lvl, int x, int dataSiz if (v == e->v0) { return &EDGE_getLevelData(e)[dataSize * (levelBase + x)]; } - else { - return &EDGE_getLevelData(e)[dataSize * (levelBase + (1 << lvl) - x)]; - } + return &EDGE_getLevelData(e)[dataSize * (levelBase + (1 << lvl) - x)]; } /* *************************************************** */ @@ -65,9 +63,8 @@ static CCGVert *_edge_getOtherVert(CCGEdge *e, CCGVert *vQ) if (vQ == e->v0) { return e->v1; } - else { - return e->v0; - } + + return e->v0; } static float *_face_getIFNoEdge(CCGFace *f, @@ -111,15 +108,13 @@ static float EDGE_getSharpness(CCGEdge *e, int lvl) if (!lvl) { return e->crease; } - else if (!e->crease) { + if (!e->crease) { return 0.0f; } - else if (e->crease - lvl < 0.0f) { + if (e->crease - lvl < 0.0f) { return 0.0f; } - else { - return e->crease - lvl; - } + return e->crease - lvl; } typedef struct CCGSubSurfCalcSubdivData { diff --git a/source/blender/blenkernel/intern/CCGSubSurf_util.c b/source/blender/blenkernel/intern/CCGSubSurf_util.c index 58d5f2e0495..bc63d8b97f7 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_util.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_util.c @@ -304,7 +304,7 @@ void ccgSubSurf__dumpCoords(CCGSubSurf *ss) } for (x = 0; x < gridSize; x++) { float *co = FACE_getIECo(f, subdivLevels, S, x); - printf("face index=%d. cornder=%d, ie_index=%d, coord=(%f, %f, %f)\n", + printf("face index=%d. corner=%d, ie_index=%d, coord=(%f, %f, %f)\n", index, S, x, diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 8a5be6b9cb3..af4829691c2 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -80,11 +80,9 @@ //#define USE_MODIFIER_VALIDATE #ifdef USE_MODIFIER_VALIDATE -# define ASSERT_IS_VALID_DM(dm) (BLI_assert((dm == NULL) || (DM_is_valid(dm) == true))) # define ASSERT_IS_VALID_MESH(mesh) \ (BLI_assert((mesh == NULL) || (BKE_mesh_is_valid(mesh) == true))) #else -# define ASSERT_IS_VALID_DM(dm) # define ASSERT_IS_VALID_MESH(mesh) #endif @@ -424,15 +422,14 @@ int DM_release(DerivedMesh *dm) return 1; } - else { - CustomData_free_temporary(&dm->vertData, dm->numVertData); - CustomData_free_temporary(&dm->edgeData, dm->numEdgeData); - CustomData_free_temporary(&dm->faceData, dm->numTessFaceData); - CustomData_free_temporary(&dm->loopData, dm->numLoopData); - CustomData_free_temporary(&dm->polyData, dm->numPolyData); - return 0; - } + CustomData_free_temporary(&dm->vertData, dm->numVertData); + CustomData_free_temporary(&dm->edgeData, dm->numEdgeData); + CustomData_free_temporary(&dm->faceData, dm->numTessFaceData); + CustomData_free_temporary(&dm->loopData, dm->numLoopData); + CustomData_free_temporary(&dm->polyData, dm->numPolyData); + + return 0; } void DM_DupPolys(DerivedMesh *source, DerivedMesh *target) @@ -693,11 +690,9 @@ static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free) if (em) { return get_editbmesh_orco_verts(em); } - else { - return BKE_mesh_orco_verts_get(ob); - } + return BKE_mesh_orco_verts_get(ob); } - else if (layer == CD_CLOTH_ORCO) { + if (layer == CD_CLOTH_ORCO) { /* apply shape key for cloth, this should really be solved * by a more flexible customdata system, but not simple */ if (!em) { @@ -1060,9 +1055,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } continue; } - else { - BKE_modifier_set_error(md, "Sculpt: Hide, Mask and optimized display disabled"); - } + BKE_modifier_set_error(md, "Sculpt: Hide, Mask and optimized display disabled"); } if (need_mapping && !BKE_modifier_supports_mapping(md)) { @@ -2363,32 +2356,6 @@ void DM_debug_print(DerivedMesh *dm) MEM_freeN(str); } -void DM_debug_print_cdlayers(CustomData *data) -{ - int i; - const CustomDataLayer *layer; - - printf("{\n"); - - for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) { - - const char *name = CustomData_layertype_name(layer->type); - const int size = CustomData_sizeof(layer->type); - const char *structname; - int structnum; - CustomData_file_write_info(layer->type, &structname, &structnum); - printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n", - name, - structname, - layer->type, - (const void *)layer->data, - size, - (int)(MEM_allocN_len(layer->data) / size)); - } - - printf("}\n"); -} - bool DM_is_valid(DerivedMesh *dm) { const bool do_verbose = true; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index b35d2183408..85ac2c693cb 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -37,6 +37,7 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" #include "BLI_math.h" +#include "BLI_session_uuid.h" #include "BLI_string_utils.h" #include "BLI_utildefines.h" @@ -482,6 +483,11 @@ void action_groups_clear_tempflags(bAction *act) /* *************** Pose channels *************** */ +void BKE_pose_channel_session_uuid_generate(bPoseChannel *pchan) +{ + pchan->runtime.session_uuid = BLI_session_uuid_generate(); +} + /** * Return a pointer to the pose channel of the given name * from this pose. @@ -524,6 +530,8 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name) /* If not, create it and add it */ chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); + BKE_pose_channel_session_uuid_generate(chan); + BLI_strncpy(chan->name, name, sizeof(chan->name)); chan->custom_scale = 1.0f; @@ -698,6 +706,10 @@ void BKE_pose_copy_data_ex(bPose **dst, id_us_plus((ID *)pchan->custom); } + if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) { + BKE_pose_channel_session_uuid_generate(pchan); + } + /* warning, O(n2) here, if done without the hash, but these are rarely used features. */ if (pchan->custom_tx) { pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name); @@ -726,7 +738,7 @@ void BKE_pose_copy_data_ex(bPose **dst, pchan->draw_data = NULL; /* Drawing cache, no need to copy. */ /* Runtime data, no need to copy. */ - memset(&pchan->runtime, 0, sizeof(pchan->runtime)); + BKE_pose_channel_runtime_reset_on_copy(&pchan->runtime); } /* for now, duplicate Bone Groups too when doing this */ @@ -956,6 +968,14 @@ void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime) memset(runtime, 0, sizeof(*runtime)); } +/* Reset all non-persistent fields. */ +void BKE_pose_channel_runtime_reset_on_copy(bPoseChannel_Runtime *runtime) +{ + const SessionUUID uuid = runtime->session_uuid; + memset(runtime, 0, sizeof(*runtime)); + runtime->session_uuid = uuid; +} + /** Deallocates runtime cache of a pose channel */ void BKE_pose_channel_runtime_free(bPoseChannel_Runtime *runtime) { @@ -1512,8 +1532,10 @@ short action_get_item_transforms(bAction *act, Object *ob, bPoseChannel *pchan, /* ************** Pose Management Tools ****************** */ -/* for do_all_pose_actions, clears the pose. Now also exported for proxy and tools */ -void BKE_pose_rest(bPose *pose) +/** + * Zero the pose transforms for the entire pose or only for selected bones. + */ +void BKE_pose_rest(bPose *pose, bool selected_bones_only) { bPoseChannel *pchan; @@ -1525,6 +1547,9 @@ void BKE_pose_rest(bPose *pose) memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset)); for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (selected_bones_only && pchan->bone != NULL && (pchan->bone->flag & BONE_SELECTED) == 0) { + continue; + } zero_v3(pchan->loc); zero_v3(pchan->eul); unit_qt(pchan->quat); @@ -1612,8 +1637,12 @@ void BKE_pose_tag_recalc(Main *bmain, bPose *pose) /* For the calculation of the effects of an Action at the given frame on an object * This is currently only used for the Action Constraint */ -void what_does_obaction( - Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe) +void what_does_obaction(Object *ob, + Object *workob, + bPose *pose, + bAction *act, + char groupname[], + const AnimationEvalContext *anim_eval_context) { bActionGroup *agrp = BKE_action_group_find_name(act, groupname); @@ -1669,7 +1698,7 @@ void what_does_obaction( RNA_id_pointer_create(&workob->id, &id_ptr); /* execute action for this group only */ - animsys_evaluate_action_group(&id_ptr, act, agrp, cframe); + animsys_evaluate_action_group(&id_ptr, act, agrp, anim_eval_context); } else { AnimData adt = {NULL}; @@ -1680,6 +1709,33 @@ void what_does_obaction( adt.action = act; /* execute effects of Action on to workob (or it's PoseChannels) */ - BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false); + } +} + +void BKE_pose_check_uuids_unique_and_report(const bPose *pose) +{ + if (pose == NULL) { + return; } + + struct GSet *used_uuids = BLI_gset_new( + BLI_session_uuid_ghash_hash, BLI_session_uuid_ghash_compare, "sequencer used uuids"); + + LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) { + const SessionUUID *session_uuid = &pchan->runtime.session_uuid; + if (!BLI_session_uuid_is_generated(session_uuid)) { + printf("Pose channel %s does not have UUID generated.\n", pchan->name); + continue; + } + + if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) { + printf("Pose channel %s has duplicate UUID generated.\n", pchan->name); + continue; + } + + BLI_gset_insert(used_uuids, (void *)session_uuid); + } + + BLI_gset_free(used_uuids, NULL); } diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 841fdaa3b2c..038a0d14ddb 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -130,9 +130,7 @@ AnimData *BKE_animdata_from_id(ID *id) IdAdtTemplate *iat = (IdAdtTemplate *)id; return iat->adt; } - else { - return NULL; - } + return NULL; } /* Add AnimData to the given ID-block. In order for this to work, we assume that @@ -161,9 +159,7 @@ AnimData *BKE_animdata_add_id(ID *id) return iat->adt; } - else { - return NULL; - } + return NULL; } /* Action Setter --------------------------------------- */ @@ -379,17 +375,19 @@ bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const int flag) return true; } -void BKE_animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid) +static void animdata_copy_id_action(Main *bmain, + ID *id, + const bool set_newid, + const bool do_linked_id) { - const bool is_id_liboverride = ID_IS_OVERRIDE_LIBRARY(id); AnimData *adt = BKE_animdata_from_id(id); if (adt) { - if (adt->action && (!is_id_liboverride || !ID_IS_LINKED(adt->action))) { + if (adt->action && (do_linked_id || !ID_IS_LINKED(adt->action))) { id_us_min((ID *)adt->action); adt->action = set_newid ? ID_NEW_SET(adt->action, BKE_action_copy(bmain, adt->action)) : BKE_action_copy(bmain, adt->action); } - if (adt->tmpact && (!is_id_liboverride || !ID_IS_LINKED(adt->tmpact))) { + if (adt->tmpact && (do_linked_id || !ID_IS_LINKED(adt->tmpact))) { id_us_min((ID *)adt->tmpact); adt->tmpact = set_newid ? ID_NEW_SET(adt->tmpact, BKE_action_copy(bmain, adt->tmpact)) : BKE_action_copy(bmain, adt->tmpact); @@ -397,12 +395,27 @@ void BKE_animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid) } bNodeTree *ntree = ntreeFromID(id); if (ntree) { - BKE_animdata_copy_id_action(bmain, &ntree->id, set_newid); + animdata_copy_id_action(bmain, &ntree->id, set_newid, do_linked_id); } /* Note that collections are not animatable currently, so no need to handle scenes' master * collection here. */ } +void BKE_animdata_copy_id_action(Main *bmain, ID *id) +{ + const bool is_id_liboverride = ID_IS_OVERRIDE_LIBRARY(id); + animdata_copy_id_action(bmain, id, false, !is_id_liboverride); +} + +void BKE_animdata_duplicate_id_action(struct Main *bmain, + struct ID *id, + const eDupli_ID_Flags duplicate_flags) +{ + if (duplicate_flags & USER_DUP_ACT) { + animdata_copy_id_action(bmain, id, true, (duplicate_flags & USER_DUP_LINKED_ID) != 0); + } +} + /* Merge copies of the data from the src AnimData into the destination AnimData */ void BKE_animdata_merge_copy( Main *bmain, ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers) @@ -492,24 +505,43 @@ static bool animpath_matches_basepath(const char path[], const char basepath[]) return (path && basepath) && STRPREFIX(path, basepath); } +static void animpath_update_basepath(FCurve *fcu, + const char *old_basepath, + const char *new_basepath) +{ + BLI_assert(animpath_matches_basepath(fcu->rna_path, old_basepath)); + if (STREQ(old_basepath, new_basepath)) { + return; + } + + char *new_path = BLI_sprintfN("%s%s", new_basepath, fcu->rna_path + strlen(old_basepath)); + MEM_freeN(fcu->rna_path); + fcu->rna_path = new_path; +} + /* Move F-Curves in src action to dst action, setting up all the necessary groups * for this to happen, but only if the F-Curves being moved have the appropriate * "base path". * - This is used when data moves from one data-block to another, causing the * F-Curves to need to be moved over too */ -void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const char basepath[]) +static void action_move_fcurves_by_basepath(bAction *srcAct, + bAction *dstAct, + const char *src_basepath, + const char *dst_basepath) { FCurve *fcu, *fcn = NULL; /* sanity checks */ - if (ELEM(NULL, srcAct, dstAct, basepath)) { + if (ELEM(NULL, srcAct, dstAct, src_basepath, dst_basepath)) { if (G.debug & G_DEBUG) { CLOG_ERROR(&LOG, - "srcAct: %p, dstAct: %p, basepath: %p has insufficient info to work with", + "srcAct: %p, dstAct: %p, src_basepath: %p, dst_basepath: %p has insufficient " + "info to work with", (void *)srcAct, (void *)dstAct, - (void *)basepath); + (void *)src_basepath, + (void *)dst_basepath); } return; } @@ -527,7 +559,7 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha /* should F-Curve be moved over? * - we only need the start of the path to match basepath */ - if (animpath_matches_basepath(fcu->rna_path, basepath)) { + if (animpath_matches_basepath(fcu->rna_path, src_basepath)) { bActionGroup *agrp = NULL; /* if grouped... */ @@ -549,6 +581,8 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha /* perform the migration now */ action_groups_remove_channel(srcAct, fcu); + animpath_update_basepath(fcu, src_basepath, dst_basepath); + if (agrp) { action_groups_add_channel(dstAct, agrp, fcu); } @@ -581,14 +615,31 @@ void action_move_fcurves_by_basepath(bAction *srcAct, bAction *dstAct, const cha } } +static void animdata_move_drivers_by_basepath(AnimData *srcAdt, + AnimData *dstAdt, + const char *src_basepath, + const char *dst_basepath) +{ + LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &srcAdt->drivers) { + if (animpath_matches_basepath(fcu->rna_path, src_basepath)) { + animpath_update_basepath(fcu, src_basepath, dst_basepath); + BLI_remlink(&srcAdt->drivers, fcu); + BLI_addtail(&dstAdt->drivers, fcu); + + /* TODO: add depsgraph flushing calls? */ + } + } +} + /* Transfer the animation data from srcID to dstID where the srcID * animation data is based off "basepath", creating new AnimData and - * associated data as necessary + * associated data as necessary. + * + * basepaths is a list of AnimationBasePathChange. */ -void BKE_animdata_separate_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBase *basepaths) +void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBase *basepaths) { AnimData *srcAdt = NULL, *dstAdt = NULL; - LinkData *ld; /* sanity checks */ if (ELEM(NULL, srcID, dstID)) { @@ -630,35 +681,19 @@ void BKE_animdata_separate_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa } /* loop over base paths, trying to fix for each one... */ - for (ld = basepaths->first; ld; ld = ld->next) { - const char *basepath = (const char *)ld->data; - action_move_fcurves_by_basepath(srcAdt->action, dstAdt->action, basepath); + LISTBASE_FOREACH (const AnimationBasePathChange *, basepath_change, basepaths) { + action_move_fcurves_by_basepath(srcAdt->action, + dstAdt->action, + basepath_change->src_basepath, + basepath_change->dst_basepath); } } /* drivers */ if (srcAdt->drivers.first) { - FCurve *fcu, *fcn = NULL; - - /* check each driver against all the base paths to see if any should go */ - for (fcu = srcAdt->drivers.first; fcu; fcu = fcn) { - fcn = fcu->next; - - /* try each basepath in turn, but stop on the first one which works */ - for (ld = basepaths->first; ld; ld = ld->next) { - const char *basepath = (const char *)ld->data; - - if (animpath_matches_basepath(fcu->rna_path, basepath)) { - /* just need to change lists */ - BLI_remlink(&srcAdt->drivers, fcu); - BLI_addtail(&dstAdt->drivers, fcu); - - /* TODO: add depsgraph flushing calls? */ - - /* can stop now, as moved already */ - break; - } - } + LISTBASE_FOREACH (const AnimationBasePathChange *, basepath_change, basepaths) { + animdata_move_drivers_by_basepath( + srcAdt, dstAdt, basepath_change->src_basepath, basepath_change->dst_basepath); } } } @@ -775,10 +810,9 @@ static char *rna_path_rename_fix(ID *owner_id, MEM_freeN(oldpath); return newPath; } - else { - /* still couldn't resolve the path... so, might as well just leave it alone */ - MEM_freeN(newPath); - } + + /* still couldn't resolve the path... so, might as well just leave it alone */ + MEM_freeN(newPath); } } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 5e4b280d0d0..5b5e32f1d81 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -538,7 +538,7 @@ static void animsys_write_orig_anim_rna(PointerRNA *ptr, */ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, - float ctime, + const AnimationEvalContext *anim_eval_context, bool flush_to_original) { /* Calculate then execute each curve. */ @@ -557,7 +557,7 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, } PathResolvedRNA anim_rna; if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context); BKE_animsys_write_rna_setting(&anim_rna, curval); if (flush_to_original) { animsys_write_orig_anim_rna(ptr, fcu->rna_path, fcu->array_index, curval); @@ -569,8 +569,26 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, /* ***************************************** */ /* Driver Evaluation */ +AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, + float eval_time) +{ + AnimationEvalContext ctx = { + .depsgraph = depsgraph, + .eval_time = eval_time, + }; + return ctx; +} + +AnimationEvalContext BKE_animsys_eval_context_construct_at( + const AnimationEvalContext *anim_eval_context, float eval_time) +{ + return BKE_animsys_eval_context_construct(anim_eval_context->depsgraph, eval_time); +} + /* Evaluate Drivers */ -static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime) +static void animsys_evaluate_drivers(PointerRNA *ptr, + AnimData *adt, + const AnimationEvalContext *anim_eval_context) { FCurve *fcu; @@ -591,7 +609,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime * before adding new to only be done when drivers only changed. */ PathResolvedRNA anim_rna; if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context); ok = BKE_animsys_write_rna_setting(&anim_rna, curval); } @@ -619,9 +637,8 @@ static void action_idcode_patch_check(ID *id, bAction *act) if (ELEM(NULL, id, act)) { return; } - else { - idcode = GS(id->name); - } + + idcode = GS(id->name); /* the actual checks... hopefully not too much of a performance hit in the long run... */ if (act->idroot == 0) { @@ -648,7 +665,10 @@ static void action_idcode_patch_check(ID *id, bAction *act) /* ----------------------------------------- */ /* Evaluate Action Group */ -void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *agrp, float ctime) +void animsys_evaluate_action_group(PointerRNA *ptr, + bAction *act, + bActionGroup *agrp, + const AnimationEvalContext *anim_eval_context) { FCurve *fcu; @@ -670,7 +690,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0 && !BKE_fcurve_is_empty(fcu)) { PathResolvedRNA anim_rna; if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context); BKE_animsys_write_rna_setting(&anim_rna, curval); } } @@ -680,7 +700,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * /* Evaluate Action (F-Curve Bag) */ static void animsys_evaluate_action_ex(PointerRNA *ptr, bAction *act, - float ctime, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ @@ -691,15 +711,15 @@ static void animsys_evaluate_action_ex(PointerRNA *ptr, action_idcode_patch_check(ptr->owner_id, act); /* calculate then execute each curve */ - animsys_evaluate_fcurves(ptr, &act->curves, ctime, flush_to_original); + animsys_evaluate_fcurves(ptr, &act->curves, anim_eval_context, flush_to_original); } void animsys_evaluate_action(PointerRNA *ptr, bAction *act, - float ctime, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { - animsys_evaluate_action_ex(ptr, act, ctime, flush_to_original); + animsys_evaluate_action_ex(ptr, act, anim_eval_context, flush_to_original); } /* ***************************************** */ @@ -717,18 +737,19 @@ static float nlastrip_get_influence(NlaStrip *strip, float cframe) /* there is some blend-in */ return fabsf(cframe - strip->start) / (strip->blendin); } - else if (IS_EQF(strip->blendout, 0.0f) == false && (cframe >= (strip->end - strip->blendout))) { + if (IS_EQF(strip->blendout, 0.0f) == false && (cframe >= (strip->end - strip->blendout))) { /* there is some blend-out */ return fabsf(strip->end - cframe) / (strip->blendout); } - else { - /* in the middle of the strip, we should be full strength */ - return 1.0f; - } + + /* in the middle of the strip, we should be full strength */ + return 1.0f; } /* evaluate the evaluation time and influence for the strip, storing the results in the strip */ -static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool flush_to_original) +static void nlastrip_evaluate_controls(NlaStrip *strip, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) { /* now strip's evaluate F-Curves for these settings (if applicable) */ if (strip->fcurves.first) { @@ -738,7 +759,7 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); /* execute these settings as per normal */ - animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, ctime, flush_to_original); + animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, anim_eval_context, flush_to_original); } /* analytically generate values for influence and time (if applicable) @@ -746,17 +767,18 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool * in case the override has been turned off. */ if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0) { - strip->influence = nlastrip_get_influence(strip, ctime); + strip->influence = nlastrip_get_influence(strip, anim_eval_context->eval_time); } /* Bypass evaluation time computation if time mapping is disabled. */ if ((strip->flag & NLASTRIP_FLAG_NO_TIME_MAP) != 0) { - strip->strip_time = ctime; + strip->strip_time = anim_eval_context->eval_time; return; } if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0) { - strip->strip_time = nlastrip_get_frame(strip, ctime, NLATIME_CONVERT_EVAL); + strip->strip_time = nlastrip_get_frame( + strip, anim_eval_context->eval_time, NLATIME_CONVERT_EVAL); } /* if user can control the evaluation time (using F-Curves), consider the option which allows @@ -770,12 +792,16 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime, const bool } /* gets the strip active at the current time for a list of strips for evaluation purposes */ -NlaEvalStrip *nlastrips_ctime_get_strip( - ListBase *list, ListBase *strips, short index, float ctime, const bool flush_to_original) +NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, + ListBase *strips, + short index, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) { NlaStrip *strip, *estrip = NULL; NlaEvalStrip *nes; short side = 0; + float ctime = anim_eval_context->eval_time; /* loop over strips, checking if they fall within the range */ for (strip = strips->first; strip; strip = strip->next) { @@ -854,7 +880,9 @@ NlaEvalStrip *nlastrips_ctime_get_strip( */ /* TODO: this sounds a bit hacky having a few isolated F-Curves * stuck on some data it operates on... */ - nlastrip_evaluate_controls(estrip, ctime, flush_to_original); + AnimationEvalContext clamped_eval_context = BKE_animsys_eval_context_construct_at( + anim_eval_context, ctime); + nlastrip_evaluate_controls(estrip, &clamped_eval_context, flush_to_original); if (estrip->influence <= 0.0f) { return NULL; } @@ -876,8 +904,12 @@ NlaEvalStrip *nlastrips_ctime_get_strip( } /* evaluate controls for the relevant extents of the bordering strips... */ - nlastrip_evaluate_controls(estrip->prev, estrip->start, flush_to_original); - nlastrip_evaluate_controls(estrip->next, estrip->end, flush_to_original); + AnimationEvalContext start_eval_context = BKE_animsys_eval_context_construct_at( + anim_eval_context, estrip->start); + AnimationEvalContext end_eval_context = BKE_animsys_eval_context_construct_at( + anim_eval_context, estrip->end); + nlastrip_evaluate_controls(estrip->prev, &start_eval_context, flush_to_original); + nlastrip_evaluate_controls(estrip->next, &end_eval_context, flush_to_original); break; } @@ -1115,12 +1147,10 @@ static int nlaevalchan_validate_index(NlaEvalChannel *nec, int index) return -1; } - else { - return 0; - } + return 0; } -/* Initialise default values for NlaEvalChannel from the property data. */ +/* Initialize default values for NlaEvalChannel from the property data. */ static void nlaevalchan_get_default_values(NlaEvalChannel *nec, float *r_values) { PointerRNA *ptr = &nec->key.ptr; @@ -1209,15 +1239,13 @@ static char nlaevalchan_detect_mix_mode(NlaEvalChannelKey *key, int length) if (subtype == PROP_QUATERNION && length == 4) { return NEC_MIX_QUATERNION; } - else if (subtype == PROP_AXISANGLE && length == 4) { + if (subtype == PROP_AXISANGLE && length == 4) { return NEC_MIX_AXIS_ANGLE; } - else if (RNA_property_flag(key->prop) & PROP_PROPORTIONAL) { + if (RNA_property_flag(key->prop) & PROP_PROPORTIONAL) { return NEC_MIX_MULTIPLY; } - else { - return NEC_MIX_ADD; - } + return NEC_MIX_ADD; } /* Verify that an appropriate NlaEvalChannel for this property exists. */ @@ -1454,10 +1482,9 @@ static bool nla_invert_combine_value(int mix_mode, /* Division by zero. */ return false; } - else { - *r_value = base_value * powf(target_value / old_value, 1.0f / influence); - return true; - } + + *r_value = base_value * powf(target_value / old_value, 1.0f / influence); + return true; case NEC_MIX_QUATERNION: default: @@ -1802,6 +1829,7 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { ListBase tmp_modifiers = {NULL, NULL}; @@ -1843,13 +1871,15 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr, tmp_nes.strip_mode = NES_TIME_TRANSITION_START; tmp_nes.strip = s1; nlaeval_snapshot_init(&snapshot1, channels, snapshot); - nlastrip_evaluate(ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot1, flush_to_original); + nlastrip_evaluate( + ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot1, anim_eval_context, flush_to_original); /* second strip */ tmp_nes.strip_mode = NES_TIME_TRANSITION_END; tmp_nes.strip = s2; nlaeval_snapshot_init(&snapshot2, channels, snapshot); - nlastrip_evaluate(ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, flush_to_original); + nlastrip_evaluate( + ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, anim_eval_context, flush_to_original); /* accumulate temp-buffer and full-buffer, using the 'real' strip */ nlaeval_snapshot_mix_and_free(channels, snapshot, &snapshot1, &snapshot2, nes->strip_time); @@ -1864,6 +1894,7 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { ListBase tmp_modifiers = {NULL, NULL}; @@ -1884,13 +1915,16 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr, /* find the child-strip to evaluate */ evaltime = (nes->strip_time * (strip->end - strip->start)) + strip->start; - tmp_nes = nlastrips_ctime_get_strip(NULL, &strip->strips, -1, evaltime, flush_to_original); + AnimationEvalContext child_context = BKE_animsys_eval_context_construct_at(anim_eval_context, + evaltime); + tmp_nes = nlastrips_ctime_get_strip(NULL, &strip->strips, -1, &child_context, flush_to_original); /* directly evaluate child strip into accumulation buffer... * - there's no need to use a temporary buffer (as it causes issues [T40082]) */ if (tmp_nes) { - nlastrip_evaluate(ptr, channels, &tmp_modifiers, tmp_nes, snapshot, flush_to_original); + nlastrip_evaluate( + ptr, channels, &tmp_modifiers, tmp_nes, snapshot, &child_context, flush_to_original); /* free temp eval-strip */ MEM_freeN(tmp_nes); @@ -1906,6 +1940,7 @@ void nlastrip_evaluate(PointerRNA *ptr, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { NlaStrip *strip = nes->strip; @@ -1928,10 +1963,12 @@ void nlastrip_evaluate(PointerRNA *ptr, nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes, snapshot); break; case NLASTRIP_TYPE_TRANSITION: /* transition */ - nlastrip_evaluate_transition(ptr, channels, modifiers, nes, snapshot, flush_to_original); + nlastrip_evaluate_transition( + ptr, channels, modifiers, nes, snapshot, anim_eval_context, flush_to_original); break; case NLASTRIP_TYPE_META: /* meta */ - nlastrip_evaluate_meta(ptr, channels, modifiers, nes, snapshot, flush_to_original); + nlastrip_evaluate_meta( + ptr, channels, modifiers, nes, snapshot, anim_eval_context, flush_to_original); break; default: /* do nothing */ @@ -2079,7 +2116,7 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels, static bool animsys_evaluate_nla(NlaEvalData *echannels, PointerRNA *ptr, AnimData *adt, - float ctime, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original, NlaKeyframingContext *r_context) { @@ -2127,7 +2164,8 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, } /* otherwise, get strip to evaluate for this channel */ - nes = nlastrips_ctime_get_strip(&estrips, &nlt->strips, track_index, ctime, flush_to_original); + nes = nlastrips_ctime_get_strip( + &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original); if (nes) { nes->track = nlt; } @@ -2193,7 +2231,8 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, /* add this to our list of evaluation strips */ if (r_context == NULL) { - nlastrips_ctime_get_strip(&estrips, &dummy_trackslist, -1, ctime, flush_to_original); + nlastrips_ctime_get_strip( + &estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original); } /* If computing the context for keyframing, store data there instead of the list. */ else { @@ -2203,7 +2242,7 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, NLASTRIP_EXTEND_HOLD; r_context->eval_strip = nes = nlastrips_ctime_get_strip( - NULL, &dummy_trackslist, -1, ctime, flush_to_original); + NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original); /* These setting combinations require no data from strips below, so exit immediately. */ if ((nes == NULL) || @@ -2228,7 +2267,13 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, /* 2. for each strip, evaluate then accumulate on top of existing channels, * but don't set values yet. */ for (nes = estrips.first; nes; nes = nes->next) { - nlastrip_evaluate(ptr, echannels, NULL, nes, &echannels->eval_snapshot, flush_to_original); + nlastrip_evaluate(ptr, + echannels, + NULL, + nes, + &echannels->eval_snapshot, + anim_eval_context, + flush_to_original); } /* 3. free temporary evaluation data that's not used elsewhere */ @@ -2242,7 +2287,7 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels, */ static void animsys_calculate_nla(PointerRNA *ptr, AnimData *adt, - float ctime, + const AnimationEvalContext *anim_eval_context, const bool flush_to_original) { NlaEvalData echannels; @@ -2250,7 +2295,7 @@ static void animsys_calculate_nla(PointerRNA *ptr, nlaeval_init(&echannels); /* evaluate the NLA stack, obtaining a set of values to flush */ - if (animsys_evaluate_nla(&echannels, ptr, adt, ctime, flush_to_original, NULL)) { + if (animsys_evaluate_nla(&echannels, ptr, adt, anim_eval_context, flush_to_original, NULL)) { /* reset any channels touched by currently inactive actions to default value */ animsys_evaluate_nla_domain(ptr, &echannels, adt); @@ -2264,7 +2309,7 @@ static void animsys_calculate_nla(PointerRNA *ptr, CLOG_WARN(&LOG, "NLA Eval: Stopgap for active action on NLA Stack - no strips case"); } - animsys_evaluate_action(ptr, adt->action, ctime, flush_to_original); + animsys_evaluate_action(ptr, adt->action, anim_eval_context, flush_to_original); } /* free temp data */ @@ -2282,11 +2327,12 @@ static void animsys_calculate_nla(PointerRNA *ptr, * \param ptr: RNA pointer to the Object with the animation. * \return Keyframing context, or NULL if not necessary. */ -NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *cache, - struct PointerRNA *ptr, - struct AnimData *adt, - float ctime, - const bool flush_to_original) +NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( + struct ListBase *cache, + struct PointerRNA *ptr, + struct AnimData *adt, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) { /* No remapping needed if NLA is off or no action. */ if ((adt == NULL) || (adt->action == NULL) || (adt->nla_tracks.first == NULL) || @@ -2309,7 +2355,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *ca ctx->adt = adt; nlaeval_init(&ctx->nla_channels); - animsys_evaluate_nla(&ctx->nla_channels, ptr, adt, ctime, flush_to_original, ctx); + animsys_evaluate_nla(&ctx->nla_channels, ptr, adt, anim_eval_context, flush_to_original, ctx); BLI_assert(ELEM(ctx->strip.act, NULL, adt->action)); BLI_addtail(cache, ctx); @@ -2499,8 +2545,11 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) * and that the flags for which parts of the anim-data settings need to be recalculated * have been set already by the depsgraph. Now, we use the recalc */ -void BKE_animsys_evaluate_animdata( - ID *id, AnimData *adt, float ctime, eAnimData_Recalc recalc, const bool flush_to_original) +void BKE_animsys_evaluate_animdata(ID *id, + AnimData *adt, + const AnimationEvalContext *anim_eval_context, + eAnimData_Recalc recalc, + const bool flush_to_original) { PointerRNA id_ptr; @@ -2523,11 +2572,11 @@ void BKE_animsys_evaluate_animdata( /* evaluate NLA-stack * - active action is evaluated as part of the NLA stack as the last item */ - animsys_calculate_nla(&id_ptr, adt, ctime, flush_to_original); + animsys_calculate_nla(&id_ptr, adt, anim_eval_context, flush_to_original); } /* evaluate Active Action only */ else if (adt->action) { - animsys_evaluate_action_ex(&id_ptr, adt->action, ctime, flush_to_original); + animsys_evaluate_action_ex(&id_ptr, adt->action, anim_eval_context, flush_to_original); } } @@ -2537,7 +2586,7 @@ void BKE_animsys_evaluate_animdata( * - Drivers should be in the appropriate order to be evaluated without problems... */ if (recalc & ADT_RECALC_DRIVERS) { - animsys_evaluate_drivers(&id_ptr, adt, ctime); + animsys_evaluate_drivers(&id_ptr, adt, anim_eval_context); } /* always execute 'overrides' @@ -2565,6 +2614,8 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float } const bool flush_to_original = DEG_is_active(depsgraph); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + ctime); /* macros for less typing * - only evaluate animation data for id if it has users (and not just fake ones) @@ -2575,7 +2626,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float for (id = first; id; id = id->next) { \ if (ID_REAL_USERS(id) > 0) { \ AnimData *adt = BKE_animdata_from_id(id); \ - BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2594,9 +2645,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float if (ntp->nodetree) { \ AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \ BKE_animsys_evaluate_animdata( \ - &ntp->nodetree->id, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \ + &ntp->nodetree->id, adt2, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); \ } \ - BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2713,7 +2764,10 @@ void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id) * which should get handled as part of the dependency graph instead. */ DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime); const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM, flush_to_original); + + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + ctime); + BKE_animsys_evaluate_animdata(id, adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); } void BKE_animsys_update_driver_array(ID *id) @@ -2775,7 +2829,9 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCu if (BKE_animsys_store_rna_setting(&id_ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { /* Evaluate driver, and write results to COW-domain destination */ const float ctime = DEG_get_ctime(depsgraph); - const float curval = calculate_fcurve(&anim_rna, fcu, ctime); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, ctime); + const float curval = calculate_fcurve(&anim_rna, fcu, &anim_eval_context); ok = BKE_animsys_write_rna_setting(&anim_rna, curval); /* Flush results & status codes to original data for UI (T59984) */ diff --git a/source/blender/blenkernel/intern/anim_visualization.c b/source/blender/blenkernel/intern/anim_visualization.c index 04dbe4102cc..a6f63c2ba95 100644 --- a/source/blender/blenkernel/intern/anim_visualization.c +++ b/source/blender/blenkernel/intern/anim_visualization.c @@ -184,10 +184,8 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, /* return/use this as it is already valid length */ return mpath; } - else { - /* clear the existing path (as the range has changed), and reallocate below */ - animviz_free_motionpath_cache(mpath); - } + /* clear the existing path (as the range has changed), and reallocate below */ + animviz_free_motionpath_cache(mpath); } } else { diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 8189385a69d..2cc715464ad 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -56,7 +56,7 @@ # ifdef WITH_BINRELOC # include "binreloc.h" # endif -/* mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */ +/* #mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */ # include <unistd.h> #endif /* WIN32 */ @@ -120,7 +120,7 @@ static char *blender_version_decimal(const int ver) } /** - * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath, + * Concatenates path_base, (optional) path_sep and (optional) folder_name into \a targetpath, * returning true if result points to a directory. */ static bool test_path(char *targetpath, @@ -138,14 +138,14 @@ static bool test_path(char *targetpath, BLI_strncpy(tmppath, path_base, sizeof(tmppath)); } - /* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */ + /* Rare cases folder_name is omitted (when looking for `~/.config/blender/2.xx` dir only). */ if (folder_name) { BLI_join_dirfile(targetpath, targetpath_len, tmppath, folder_name); } else { BLI_strncpy(targetpath, tmppath, targetpath_len); } - /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile) + /* FIXME: why is "//" on front of \a tmppath expanded to "/" (by BLI_join_dirfile) * if folder_name is specified but not otherwise? */ if (BLI_is_dir(targetpath)) { @@ -154,13 +154,12 @@ static bool test_path(char *targetpath, #endif return true; } - else { + #ifdef PATH_DEBUG - printf("\t%s missing: %s\n", __func__, targetpath); + printf("\t%s missing: %s\n", __func__, targetpath); #endif - // targetpath[0] = '\0'; - return false; - } + // targetpath[0] = '\0'; + return false; } /** @@ -181,18 +180,17 @@ static bool test_env_path(char *path, const char *envvar) #endif return true; } - else { - path[0] = '\0'; + + path[0] = '\0'; #ifdef PATH_DEBUG - printf("\t%s env %s missing: %s\n", __func__, envvar, env); + printf("\t%s env %s missing: %s\n", __func__, envvar, env); #endif - return false; - } + return false; } /** * Constructs in \a targetpath the name of a directory relative to a version-specific - * subdirectory in the parent directory of the Blender executable. + * sub-directory in the parent directory of the Blender executable. * * \param targetpath: String to return path * \param folder_name: Optional folder name within version-specific directory @@ -272,10 +270,8 @@ static bool get_path_environment(char *targetpath, if (subfolder_name) { return test_path(targetpath, targetpath_len, user_path, NULL, subfolder_name); } - else { - BLI_strncpy(targetpath, user_path, FILE_MAX); - return true; - } + BLI_strncpy(targetpath, user_path, FILE_MAX); + return true; } return false; } @@ -300,10 +296,8 @@ static bool get_path_environment_notest(char *targetpath, BLI_join_dirfile(targetpath, targetpath_len, user_path, subfolder_name); return true; } - else { - BLI_strncpy(targetpath, user_path, FILE_MAX); - return true; - } + BLI_strncpy(targetpath, user_path, FILE_MAX); + return true; } return false; } @@ -313,7 +307,7 @@ static bool get_path_environment_notest(char *targetpath, * \param targetpath: String to return path * \param folder_name: default name of folder within user area * \param subfolder_name: optional name of subfolder within folder - * \param ver: Blender version, used to construct a subdirectory name + * \param ver: Blender version, used to construct a sub-directory name * \return true if it was able to construct such a path. */ static bool get_path_user(char *targetpath, @@ -347,9 +341,8 @@ static bool get_path_user(char *targetpath, if (subfolder_name) { return test_path(targetpath, targetpath_len, user_path, folder_name, subfolder_name); } - else { - return test_path(targetpath, targetpath_len, user_path, NULL, folder_name); - } + + return test_path(targetpath, targetpath_len, user_path, NULL, folder_name); } /** @@ -357,8 +350,8 @@ static bool get_path_user(char *targetpath, * * \param targetpath: String to return path * \param folder_name: default name of folder within installation area - * \param subfolder_name: optional name of subfolder within folder - * \param ver: Blender version, used to construct a subdirectory name + * \param subfolder_name: optional name of sub-folder within folder + * \param ver: Blender version, used to construct a sub-directory name * \return true if it was able to construct such a path. */ static bool get_path_system(char *targetpath, @@ -401,10 +394,9 @@ static bool get_path_system(char *targetpath, /* try $BLENDERPATH/folder_name/subfolder_name */ return test_path(targetpath, targetpath_len, system_path, folder_name, subfolder_name); } - else { - /* try $BLENDERPATH/folder_name */ - return test_path(targetpath, targetpath_len, system_path, NULL, folder_name); - } + + /* try $BLENDERPATH/folder_name */ + return test_path(targetpath, targetpath_len, system_path, NULL, folder_name); } /** @@ -643,7 +635,7 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con * adds the correct extension (.com .exe etc) from * $PATHEXT if necessary. Also on Windows it translates * the name to its 8.3 version to prevent problems with - * spaces and stuff. Final result is returned in fullname. + * spaces and stuff. Final result is returned in \a fullname. * * \param fullname: The full path and full name of the executable * (must be FILE_MAX minimum) @@ -983,7 +975,7 @@ static void where_is_temp(char *fullname, char *basename, const size_t maxlen, c /** * Sets btempdir_base to userdir if specified and is a valid directory, otherwise * chooses a suitable OS-specific temporary directory. - * Sets btempdir_session to a mkdtemp-generated sub-dir of btempdir_base. + * Sets btempdir_session to a #mkdtemp generated sub-dir of btempdir_base. * * \note On Window userdir will be set to the temporary directory! */ @@ -1027,7 +1019,11 @@ void BKE_tempdir_session_purge(void) } /* Gets a good default directory for fonts */ -bool BKE_appdir_font_folder_default(char *dir) + +bool BKE_appdir_font_folder_default( + /* This parameter can only be `const` on non-windows platforms. + * NOLINTNEXTLINE: readability-non-const-parameter. */ + char *dir) { bool success = false; #ifdef WIN32 diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 007062abb5b..631ce4edd20 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -512,12 +512,10 @@ bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag) if (bone->flag & flag) { return true; } - else if (bone->parent) { + if (bone->parent) { return BKE_armature_bone_flag_test_recursive(bone->parent, flag); } - else { - return false; - } + return false; } /** \} */ @@ -687,10 +685,7 @@ int bone_autoside_name( return 1; } - - else { - return 0; - } + return 0; } /** \} */ @@ -1387,7 +1382,7 @@ void get_objectspace_bone_matrix(struct Bone *bone, } /* Convert World-Space Matrix to Pose-Space Matrix */ -void BKE_armature_mat_world_to_pose(Object *ob, float inmat[4][4], float outmat[4][4]) +void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float outmat[4][4]) { float obmat[4][4]; @@ -1679,7 +1674,9 @@ void BKE_bone_parent_transform_apply(const struct BoneParentTransform *bpt, /* Convert Pose-Space Matrix to Bone-Space Matrix. * NOTE: this cannot be used to convert to pose-space transforms of the supplied * pose-channel into its local space (i.e. 'visual'-keyframing) */ -void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]) +void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, + const float inmat[4][4], + float outmat[4][4]) { BoneParentTransform bpt; @@ -1689,7 +1686,9 @@ void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[4][4], float } /* Convert Bone-Space Matrix to Pose-Space Matrix. */ -void BKE_armature_mat_bone_to_pose(bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]) +void BKE_armature_mat_bone_to_pose(bPoseChannel *pchan, + const float inmat[4][4], + float outmat[4][4]) { BoneParentTransform bpt; @@ -1725,7 +1724,7 @@ void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], fl void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph, Object *ob, bPoseChannel *pchan, - float inmat[4][4], + const float inmat[4][4], float outmat[4][4]) { bPoseChannel work_pchan = *pchan; @@ -1746,7 +1745,7 @@ void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph, /** * Same as #BKE_object_mat3_to_rot(). */ -void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, float mat[3][3], bool use_compat) +void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat) { BLI_ASSERT_UNIT_M3(mat); @@ -1771,17 +1770,17 @@ void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, float mat[3][3], bool use_compat /** * Same as #BKE_object_rot_to_mat3(). */ -void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float mat[3][3]) +void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float r_mat[3][3]) { /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */ if (pchan->rotmode > 0) { /* euler rotations (will cause gimble lock, * but this can be alleviated a bit with rotation orders) */ - eulO_to_mat3(mat, pchan->eul, pchan->rotmode); + eulO_to_mat3(r_mat, pchan->eul, pchan->rotmode); } else if (pchan->rotmode == ROT_MODE_AXISANGLE) { /* axis-angle - not really that great for 3D-changing orientations */ - axis_angle_to_mat3(mat, pchan->rotAxis, pchan->rotAngle); + axis_angle_to_mat3(r_mat, pchan->rotAxis, pchan->rotAngle); } else { /* quats are normalized before use to eliminate scaling issues */ @@ -1791,7 +1790,7 @@ void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float mat[3][3]) * since this was kindof evil in some cases but if this proves to be too problematic, * switch back to the old system of operating directly on the stored copy. */ normalize_qt_qt(quat, pchan->quat); - quat_to_mat3(mat, quat); + quat_to_mat3(r_mat, quat); } } @@ -1799,7 +1798,7 @@ void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float mat[3][3]) * Apply a 4x4 matrix to the pose bone, * similar to #BKE_object_apply_mat4(). */ -void BKE_pchan_apply_mat4(bPoseChannel *pchan, float mat[4][4], bool use_compat) +void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat) { float rot[3][3]; mat4_to_loc_rot_size(pchan->loc, rot, pchan->size, mat); @@ -2003,7 +2002,7 @@ void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll) * └ -2 * x * z, x^2 - z^2 ┘ * </pre> */ -void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float mat[3][3]) +void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3]) { #define THETA_THRESHOLD_NEGY 1.0e-9f #define THETA_THRESHOLD_NEGY_CLOSE 1.0e-5f @@ -2057,18 +2056,18 @@ void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float mat axis_angle_normalized_to_mat3(rMatrix, nor, roll); /* Combine and output result */ - mul_m3_m3m3(mat, rMatrix, bMatrix); + mul_m3_m3m3(r_mat, rMatrix, bMatrix); #undef THETA_THRESHOLD_NEGY #undef THETA_THRESHOLD_NEGY_CLOSE } -void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]) +void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3]) { float nor[3]; normalize_v3_v3(nor, vec); - vec_roll_to_mat3_normalized(nor, roll, mat); + vec_roll_to_mat3_normalized(nor, roll, r_mat); } /** \} */ @@ -2169,7 +2168,7 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected) } /* clear all transformation values from library */ - BKE_pose_rest(frompose); + BKE_pose_rest(frompose, false); /* copy over all of the proxy's bone groups */ /* TODO for later @@ -2206,7 +2205,7 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected) pchan->mpath = NULL; /* Reset runtime data, we don't want to share that with the proxy. */ - BKE_pose_channel_runtime_reset(&pchanw.runtime); + BKE_pose_channel_runtime_reset_on_copy(&pchanw.runtime); /* this is freed so copy a copy, else undo crashes */ if (pchanw.prop) { @@ -2423,8 +2422,10 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_ /** \name Pose Solver * \{ */ -/* loc/rot/size to given mat4 */ -void BKE_pchan_to_mat4(const bPoseChannel *pchan, float chan_mat[4][4]) +/** + * Convert the loc/rot/size to \a r_chanmat (typically #bPoseChannel.chan_mat). + */ +void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4]) { float smat[3][3]; float rmat[3][3]; @@ -2438,12 +2439,12 @@ void BKE_pchan_to_mat4(const bPoseChannel *pchan, float chan_mat[4][4]) /* calculate matrix of bone (as 3x3 matrix, but then copy the 4x4) */ mul_m3_m3m3(tmat, rmat, smat); - copy_m4_m3(chan_mat, tmat); + copy_m4_m3(r_chanmat, tmat); /* prevent action channels breaking chains */ /* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */ if ((pchan->bone == NULL) || !(pchan->bone->flag & BONE_CONNECTED)) { - copy_v3_v3(chan_mat[3], pchan->loc); + copy_v3_v3(r_chanmat[3], pchan->loc); } } @@ -2581,7 +2582,7 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob) } /* 2a. construct the IK tree (standard IK) */ - BIK_initialize_tree(depsgraph, scene, ob, ctime); + BIK_init_tree(depsgraph, scene, ob, ctime); /* 2b. construct the Spline IK trees * - this is not integrated as an IK plugin, since it should be able diff --git a/source/blender/blenkernel/intern/armature_deform.c b/source/blender/blenkernel/intern/armature_deform.c index 44b50ab96d3..8711a001e32 100644 --- a/source/blender/blenkernel/intern/armature_deform.c +++ b/source/blender/blenkernel/intern/armature_deform.c @@ -163,17 +163,15 @@ float distfactor_to_bone( if (dist_sq < a) { return 1.0f; } - else { - l = rad + rdist; - l *= l; - if (rdist == 0.0f || dist_sq >= l) { - return 0.0f; - } - else { - a = sqrtf(dist_sq) - rad; - return 1.0f - (a * a) / (rdist * rdist); - } + + l = rad + rdist; + l *= l; + if (rdist == 0.0f || dist_sq >= l) { + return 0.0f; } + + a = sqrtf(dist_sq) - rad; + return 1.0f - (a * a) / (rdist * rdist); } static float dist_bone_deform( diff --git a/source/blender/blenkernel/intern/armature_test.cc b/source/blender/blenkernel/intern/armature_test.cc new file mode 100644 index 00000000000..cf17c37bc69 --- /dev/null +++ b/source/blender/blenkernel/intern/armature_test.cc @@ -0,0 +1,93 @@ +/* + * 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 Blender Foundation + * All rights reserved. + */ + +#include "BKE_armature.h" + +#include "BLI_math.h" + +#include "testing/testing.h" + +namespace blender::bke::tests { + +static const float FLOAT_EPSILON = 1.2e-7; + +TEST(mat3_vec_to_roll, UnitMatrix) +{ + float unit_matrix[3][3]; + float roll; + + unit_m3(unit_matrix); + + // Any vector with a unit matrix should return zero roll. + mat3_vec_to_roll(unit_matrix, unit_matrix[0], &roll); + EXPECT_FLOAT_EQ(0.0f, roll); + + mat3_vec_to_roll(unit_matrix, unit_matrix[1], &roll); + EXPECT_FLOAT_EQ(0.0f, roll); + + mat3_vec_to_roll(unit_matrix, unit_matrix[2], &roll); + EXPECT_FLOAT_EQ(0.0f, roll); + + { + // Non-unit vector. + float vector[3] = {1.0f, 1.0f, 1.0f}; + mat3_vec_to_roll(unit_matrix, vector, &roll); + EXPECT_NEAR(0.0f, roll, FLOAT_EPSILON); + + // Normalized version of the above vector. + normalize_v3(vector); + mat3_vec_to_roll(unit_matrix, vector, &roll); + EXPECT_NEAR(0.0f, roll, FLOAT_EPSILON); + } +} + +TEST(mat3_vec_to_roll, Rotationmatrix) +{ + float rotation_matrix[3][3]; + float roll; + + const float rot_around_x[3] = {1.234f, 0.0f, 0.0f}; + eul_to_mat3(rotation_matrix, rot_around_x); + + { + const float unit_axis_x[3] = {1.0f, 0.0f, 0.0f}; + mat3_vec_to_roll(rotation_matrix, unit_axis_x, &roll); + EXPECT_NEAR(1.234f, roll, FLOAT_EPSILON); + } + + { + const float unit_axis_y[3] = {0.0f, 1.0f, 0.0f}; + mat3_vec_to_roll(rotation_matrix, unit_axis_y, &roll); + EXPECT_NEAR(0, roll, FLOAT_EPSILON); + } + + { + const float unit_axis_z[3] = {0.0f, 0.0f, 1.0f}; + mat3_vec_to_roll(rotation_matrix, unit_axis_z, &roll); + EXPECT_NEAR(0, roll, FLOAT_EPSILON); + } + + { + const float between_x_and_y[3] = {1.0f, 1.0f, 0.0f}; + mat3_vec_to_roll(rotation_matrix, between_x_and_y, &roll); + EXPECT_NEAR(0.57158958f, roll, FLOAT_EPSILON); + } +} + +} // namespace blender::bke::tests diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index d0a5e4348b9..97c717572bc 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -119,9 +119,8 @@ static void splineik_init_tree_from_pchan(Scene *UNUSED(scene), if (segcount == 0) { return; } - else { - pchanRoot = pchanChain[segcount - 1]; - } + + pchanRoot = pchanChain[segcount - 1]; /* perform binding step if required */ if ((ikData->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) { @@ -659,7 +658,7 @@ void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, Scene *scene, Object *ob return; } /* construct the IK tree (standard IK) */ - BIK_initialize_tree(depsgraph, scene, object, ctime); + BIK_init_tree(depsgraph, scene, object, ctime); /* construct the Spline IK trees * - this is not integrated as an IK plugin, since it should be able * to function in conjunction with standard IK. */ @@ -717,7 +716,7 @@ void BKE_pose_constraints_evaluate(struct Depsgraph *depsgraph, if (armature->flag & ARM_RESTPOS) { return; } - else if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) { + if (pchan->flag & POSE_IKTREE || pchan->flag & POSE_IKSPLINE) { /* IK are being solved separately/ */ } else { diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index d5064629451..a0da1b1677d 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -872,91 +872,90 @@ static Object *boid_find_ground(BoidBrainData *bbd, return bpa->ground; } - else { - float zvec[3] = {0.0f, 0.0f, 2000.0f}; - ParticleCollision col; - ColliderCache *coll; - BVHTreeRayHit hit; - float radius = 0.0f, t, ray_dir[3]; - - if (!bbd->sim->colliders) { - return NULL; - } - - memset(&col, 0, sizeof(ParticleCollision)); - /* first try to find below boid */ - copy_v3_v3(col.co1, pa->state.co); - sub_v3_v3v3(col.co2, pa->state.co, zvec); - sub_v3_v3v3(ray_dir, col.co2, col.co1); - col.f = 0.0f; - hit.index = -1; - hit.dist = col.original_ray_length = normalize_v3(ray_dir); - col.pce.inside = 0; + float zvec[3] = {0.0f, 0.0f, 2000.0f}; + ParticleCollision col; + ColliderCache *coll; + BVHTreeRayHit hit; + float radius = 0.0f, t, ray_dir[3]; - for (coll = bbd->sim->colliders->first; coll; coll = coll->next) { - col.current = coll->ob; - col.md = coll->collmd; - col.fac1 = col.fac2 = 0.f; + if (!bbd->sim->colliders) { + return NULL; + } - if (col.md && col.md->bvhtree) { - BLI_bvhtree_ray_cast_ex(col.md->bvhtree, - col.co1, - ray_dir, - radius, - &hit, - BKE_psys_collision_neartest_cb, - &col, - raycast_flag); - } + memset(&col, 0, sizeof(ParticleCollision)); + + /* first try to find below boid */ + copy_v3_v3(col.co1, pa->state.co); + sub_v3_v3v3(col.co2, pa->state.co, zvec); + sub_v3_v3v3(ray_dir, col.co2, col.co1); + col.f = 0.0f; + hit.index = -1; + hit.dist = col.original_ray_length = normalize_v3(ray_dir); + col.pce.inside = 0; + + for (coll = bbd->sim->colliders->first; coll; coll = coll->next) { + col.current = coll->ob; + col.md = coll->collmd; + col.fac1 = col.fac2 = 0.f; + + if (col.md && col.md->bvhtree) { + BLI_bvhtree_ray_cast_ex(col.md->bvhtree, + col.co1, + ray_dir, + radius, + &hit, + BKE_psys_collision_neartest_cb, + &col, + raycast_flag); } - /* then use that object */ - if (hit.index >= 0) { - t = hit.dist / col.original_ray_length; - interp_v3_v3v3(ground_co, col.co1, col.co2, t); - normalize_v3_v3(ground_nor, col.pce.nor); - return col.hit; - } - - /* couldn't find below, so find upmost deflector object */ - add_v3_v3v3(col.co1, pa->state.co, zvec); - sub_v3_v3v3(col.co2, pa->state.co, zvec); - sub_v3_v3(col.co2, zvec); - sub_v3_v3v3(ray_dir, col.co2, col.co1); - col.f = 0.0f; - hit.index = -1; - hit.dist = col.original_ray_length = normalize_v3(ray_dir); - - for (coll = bbd->sim->colliders->first; coll; coll = coll->next) { - col.current = coll->ob; - col.md = coll->collmd; + } + /* then use that object */ + if (hit.index >= 0) { + t = hit.dist / col.original_ray_length; + interp_v3_v3v3(ground_co, col.co1, col.co2, t); + normalize_v3_v3(ground_nor, col.pce.nor); + return col.hit; + } - if (col.md && col.md->bvhtree) { - BLI_bvhtree_ray_cast_ex(col.md->bvhtree, - col.co1, - ray_dir, - radius, - &hit, - BKE_psys_collision_neartest_cb, - &col, - raycast_flag); - } + /* couldn't find below, so find upmost deflector object */ + add_v3_v3v3(col.co1, pa->state.co, zvec); + sub_v3_v3v3(col.co2, pa->state.co, zvec); + sub_v3_v3(col.co2, zvec); + sub_v3_v3v3(ray_dir, col.co2, col.co1); + col.f = 0.0f; + hit.index = -1; + hit.dist = col.original_ray_length = normalize_v3(ray_dir); + + for (coll = bbd->sim->colliders->first; coll; coll = coll->next) { + col.current = coll->ob; + col.md = coll->collmd; + + if (col.md && col.md->bvhtree) { + BLI_bvhtree_ray_cast_ex(col.md->bvhtree, + col.co1, + ray_dir, + radius, + &hit, + BKE_psys_collision_neartest_cb, + &col, + raycast_flag); } - /* then use that object */ - if (hit.index >= 0) { - t = hit.dist / col.original_ray_length; - interp_v3_v3v3(ground_co, col.co1, col.co2, t); - normalize_v3_v3(ground_nor, col.pce.nor); - return col.hit; - } - - /* default to z=0 */ - copy_v3_v3(ground_co, pa->state.co); - ground_co[2] = 0; - ground_nor[0] = ground_nor[1] = 0.0f; - ground_nor[2] = 1.0f; - return NULL; } + /* then use that object */ + if (hit.index >= 0) { + t = hit.dist / col.original_ray_length; + interp_v3_v3v3(ground_co, col.co1, col.co2, t); + normalize_v3_v3(ground_nor, col.pce.nor); + return col.hit; + } + + /* default to z=0 */ + copy_v3_v3(ground_co, pa->state.co); + ground_co[2] = 0; + ground_nor[0] = ground_nor[1] = 0.0f; + ground_nor[2] = 1.0f; + return NULL; } static int boid_rule_applies(ParticleData *pa, BoidSettings *UNUSED(boids), BoidRule *rule) { @@ -1046,9 +1045,7 @@ static int apply_boid_rule( fuzziness * len_v3(pa->prev_state.vel)) == 0) { return 1; } - else { - return 0; - } + return 0; } static BoidState *get_boid_state(BoidSettings *boids, ParticleData *pa) { diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 44873c54469..e2d17f34992 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -147,19 +147,16 @@ static bool bpath_relative_rebase_visit_cb(void *userdata, char *path_dst, const data->count_changed++; return true; } - else { - /* Failed to make relative path absolute. */ - BLI_assert(0); - BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src); - data->count_failed++; - return false; - } - return false; - } - else { - /* Absolute, leave this as-is. */ + + /* Failed to make relative path absolute. */ + BLI_assert(0); + BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src); + data->count_failed++; return false; } + + /* Absolute, leave this as-is. */ + return false; } void BKE_bpath_relative_rebase(Main *bmain, @@ -211,18 +208,17 @@ static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, cons if (BLI_path_is_rel(path_src)) { return false; /* already relative */ } + + strcpy(path_dst, path_src); + BLI_path_rel(path_dst, data->basedir); + if (BLI_path_is_rel(path_dst)) { + data->count_changed++; + } else { - strcpy(path_dst, path_src); - BLI_path_rel(path_dst, data->basedir); - if (BLI_path_is_rel(path_dst)) { - data->count_changed++; - } - else { - BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src); - data->count_failed++; - } - return true; + BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src); + data->count_failed++; } + return true; } void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports) @@ -263,18 +259,17 @@ static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, cons if (BLI_path_is_rel(path_src) == false) { return false; /* already absolute */ } + + strcpy(path_dst, path_src); + BLI_path_abs(path_dst, data->basedir); + if (BLI_path_is_rel(path_dst) == false) { + data->count_changed++; + } else { - strcpy(path_dst, path_src); - BLI_path_abs(path_dst, data->basedir); - if (BLI_path_is_rel(path_dst) == false) { - data->count_changed++; - } - else { - BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src); - data->count_failed++; - } - return true; + BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src); + data->count_failed++; } + return true; } /* similar to BKE_bpath_relative_convert - keep in sync! */ @@ -411,7 +406,7 @@ static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const c BLI_path_basename(data->searchdir)); return false; } - else if (found == false) { + if (found == false) { BKE_reportf(data->reports, RPT_WARNING, "Could not find '%s' in '%s'", @@ -419,18 +414,17 @@ static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const c data->searchdir); return false; } - else { - bool was_relative = BLI_path_is_rel(path_dst); - BLI_strncpy(path_dst, filename_new, FILE_MAX); + bool was_relative = BLI_path_is_rel(path_dst); - /* keep path relative if the previous one was relative */ - if (was_relative) { - BLI_path_rel(path_dst, data->basedir); - } + BLI_strncpy(path_dst, filename_new, FILE_MAX); - return true; + /* keep path relative if the previous one was relative */ + if (was_relative) { + BLI_path_rel(path_dst, data->basedir); } + + return true; } void BKE_bpath_missing_files_find(Main *bmain, @@ -483,9 +477,8 @@ static bool rewrite_path_fixed(char *path, BLI_strncpy(path, path_dst, FILE_MAX); return true; } - else { - return false; - } + + return false; } static bool rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], @@ -510,9 +503,8 @@ static bool rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], BLI_split_dirfile(path_dst, path_dir, path_file, FILE_MAXDIR, FILE_MAXFILE); return true; } - else { - return false; - } + + return false; } static bool rewrite_path_alloc(char **path, @@ -538,9 +530,8 @@ static bool rewrite_path_alloc(char **path, (*path) = BLI_strdup(path_dst); return true; } - else { - return false; - } + + return false; } /** @@ -827,10 +818,9 @@ bool BKE_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *pa BLI_strncpy(path_dst, filepath, FILE_MAX); return true; } - else { - /* Path was not relative to begin with. */ - return false; - } + + /* Path was not relative to begin with. */ + return false; } /** \} */ diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index a8f52593429..39fbea66637 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -372,8 +372,8 @@ bool BKE_brush_delete(Main *bmain, Brush *brush) if (brush->id.tag & LIB_TAG_INDIRECT) { return false; } - else if (BKE_library_ID_is_indirectly_used(bmain, brush) && ID_REAL_USERS(brush) <= 1 && - ID_EXTRA_USERS(brush) == 0) { + if (BKE_library_ID_is_indirectly_used(bmain, brush) && ID_REAL_USERS(brush) <= 1 && + ID_EXTRA_USERS(brush) == 0) { return false; } @@ -503,7 +503,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.4f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->input_samples = 10; brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH; @@ -557,7 +557,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) /* Curve. */ custom_curve = brush->gpencil_settings->curve_sensitivity; BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f); - BKE_curvemapping_initialize(custom_curve); + BKE_curvemapping_init(custom_curve); brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INK); brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INK; @@ -594,7 +594,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) /* Curve. */ custom_curve = brush->gpencil_settings->curve_sensitivity; BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f); - BKE_curvemapping_initialize(custom_curve); + BKE_curvemapping_init(custom_curve); brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_INKNOISE); brush->gpencil_settings->icon_id = GP_BRUSH_ICON_INKNOISE; @@ -631,7 +631,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) /* Curve. */ custom_curve = brush->gpencil_settings->curve_sensitivity; BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f); - BKE_curvemapping_initialize(custom_curve); + BKE_curvemapping_init(custom_curve); brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_MARKER); brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER; @@ -667,12 +667,12 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) /* Curve. */ custom_curve = brush->gpencil_settings->curve_sensitivity; BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f); - BKE_curvemapping_initialize(custom_curve); + BKE_curvemapping_init(custom_curve); brush_gpencil_curvemap_reset(custom_curve->cm, 3, GPCURVE_PRESET_CHISEL_SENSIVITY); custom_curve = brush->gpencil_settings->curve_strength; BKE_curvemapping_set_defaults(custom_curve, 0, 0.0f, 0.0f, 1.0f, 1.0f); - BKE_curvemapping_initialize(custom_curve); + BKE_curvemapping_init(custom_curve); brush_gpencil_curvemap_reset(custom_curve->cm, 4, GPCURVE_PRESET_CHISEL_STRENGTH); brush->gpencil_settings->icon_id = GP_BRUSH_ICON_CHISEL; @@ -686,7 +686,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag &= ~GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 1.0f; - brush->gpencil_settings->flag &= ~GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag &= ~GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->input_samples = 10; brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH; @@ -717,7 +717,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.4f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->input_samples = 10; brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH; @@ -760,7 +760,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.6f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->input_samples = 10; brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH; @@ -812,7 +812,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->draw_strength = 0.5f; brush->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER; brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT; brush->gpencil_tool = GPAINT_TOOL_ERASE; brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT; @@ -859,7 +859,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -872,7 +872,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -885,7 +885,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -898,7 +898,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -911,7 +911,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -924,7 +924,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -937,7 +937,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAG_SMOOTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; @@ -951,7 +951,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAG_SMOOTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; @@ -965,7 +965,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.5f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -978,7 +978,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->size = 25.0f; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -991,7 +991,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1004,7 +1004,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1017,7 +1017,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.5f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1030,7 +1030,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.5f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1043,7 +1043,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->size = 25.0f; brush->gpencil_settings->draw_strength = 1.0f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1056,7 +1056,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1484,6 +1484,7 @@ void BKE_brush_sculpt_reset(Brush *br) case SCULPT_TOOL_SLIDE_RELAX: br->spacing = 10; br->alpha = 1.0f; + br->slide_deform_type = BRUSH_SLIDE_DEFORM_DRAG; break; case SCULPT_TOOL_CLAY: br->flag |= BRUSH_SIZE_PRESSURE; @@ -1533,6 +1534,7 @@ void BKE_brush_sculpt_reset(Brush *br) break; case SCULPT_TOOL_SMOOTH: br->flag &= ~BRUSH_SPACE_ATTEN; + br->automasking_flags |= BRUSH_AUTOMASKING_BOUNDARY_EDGES; br->spacing = 5; br->alpha = 0.7f; br->surface_smooth_shape_preservation = 0.5f; @@ -2180,10 +2182,9 @@ float BKE_brush_curve_strength(const Brush *br, float p, const float len) if (p >= len) { return 0; } - else { - p = p / len; - p = 1.0f - p; - } + + p = p / len; + p = 1.0f - p; switch (br->curve_preset) { case BRUSH_CURVE_CUSTOM: @@ -2273,7 +2274,7 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary, bool int half = side / 2; int i, j; - BKE_curvemapping_initialize(br->curve); + BKE_curvemapping_init(br->curve); texcache = BKE_brush_gen_texture_cache(br, half, secondary); im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect"); im->x = im->y = side; diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 93794eb9709..bea8fdd5719 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -717,11 +717,14 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, /* printf("BVHTree built and saved on cache\n"); */ BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); - bvhcache_unlock(bvh_cache, lock_started); in_cache = true; } } + if (bvh_cache_p) { + bvhcache_unlock(*bvh_cache_p, lock_started); + } + /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_verts_setup_data(data, tree, in_cache, vert, vert_allocated); @@ -929,11 +932,14 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ bvhcache_insert(bvh_cache, tree, bvh_cache_type); - bvhcache_unlock(bvh_cache, lock_started); in_cache = true; } } + if (bvh_cache_p) { + bvhcache_unlock(*bvh_cache_p, lock_started); + } + /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_edges_setup_data( data, tree, in_cache, vert, vert_allocated, edge, edge_allocated); @@ -1058,11 +1064,14 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, /* printf("BVHTree built and saved on cache\n"); */ BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); - bvhcache_unlock(bvh_cache, lock_started); in_cache = true; } } + if (bvh_cache_p) { + bvhcache_unlock(*bvh_cache_p, lock_started); + } + /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_faces_setup_data( data, tree, in_cache, vert, vert_allocated, face, face_allocated); @@ -1298,11 +1307,14 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, if (bvh_cache_p) { BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); - bvhcache_unlock(bvh_cache, lock_started); in_cache = true; } } + if (bvh_cache_p) { + bvhcache_unlock(*bvh_cache_p, lock_started); + } + /* Setup BVHTreeFromMesh */ bvhtree_from_mesh_looptri_setup_data(data, tree, @@ -1428,8 +1440,6 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, mesh->medge, mesh->totedge, mesh->mvert, verts_len, &loose_vert_len); } - /* TODO: a global mutex lock held during the expensive operation of - * building the BVH tree is really bad for performance. */ tree = bvhtree_from_mesh_verts_ex(data, mesh->mvert, verts_len, diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index da9dab36044..9ad6ae84c5c 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -61,6 +61,8 @@ static void cache_file_init_data(ID *id) BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(cache_file, id)); cache_file->scale = 1.0f; + cache_file->velocity_unit = CACHEFILE_VELOCITY_UNIT_SECOND; + BLI_strncpy(cache_file->velocity_name, ".velocities", sizeof(cache_file->velocity_name)); } static void cache_file_copy_data(Main *UNUSED(bmain), diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 566954fd5fa..467bd68c631 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -30,7 +30,6 @@ #include "DNA_scene_types.h" #include "BLI_edgehash.h" -#include "BLI_ghash.h" #include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_rand.h" @@ -48,7 +47,7 @@ #include "BKE_modifier.h" #include "BKE_pointcache.h" -#include "BPH_mass_spring.h" +#include "SIM_mass_spring.h" // #include "PIL_time.h" /* timing for debug prints */ @@ -345,12 +344,12 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int return 0; } - BKE_cloth_solver_set_positions(clmd); + SIM_cloth_solver_set_positions(clmd); ClothSimSettings *parms = clmd->sim_parms; if (parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE && !(parms->flags & CLOTH_SIMSETTINGS_FLAG_PRESSURE_VOL)) { - BKE_cloth_solver_set_volume(clmd); + SIM_cloth_solver_set_volume(clmd); } clmd->clothObject->last_frame = MINFRAME - 1; @@ -405,7 +404,7 @@ static int do_step_cloth( // TIMEIT_START(cloth_step) /* call the solver. */ - ret = BPH_cloth_solve(depsgraph, ob, framenr, clmd, effectors); + ret = SIM_cloth_solve(depsgraph, ob, framenr, clmd, effectors); // TIMEIT_END(cloth_step) @@ -454,7 +453,7 @@ void clothModifier_do(ClothModifierData *clmd, BKE_ptcache_invalidate(cache); return; } - else if (framenr > endframe) { + if (framenr > endframe) { framenr = endframe; } @@ -480,7 +479,7 @@ void clothModifier_do(ClothModifierData *clmd, if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED || (!can_simulate && cache_result == PTCACHE_READ_OLD)) { - BKE_cloth_solver_set_positions(clmd); + SIM_cloth_solver_set_positions(clmd); cloth_to_object(ob, clmd, vertexCos); BKE_ptcache_validate(cache, framenr); @@ -493,8 +492,8 @@ void clothModifier_do(ClothModifierData *clmd, return; } - else if (cache_result == PTCACHE_READ_OLD) { - BKE_cloth_solver_set_positions(clmd); + if (cache_result == PTCACHE_READ_OLD) { + SIM_cloth_solver_set_positions(clmd); } else if ( /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ @@ -538,7 +537,7 @@ void cloth_free_modifier(ClothModifierData *clmd) cloth = clmd->clothObject; if (cloth) { - BPH_cloth_solver_free(clmd); + SIM_cloth_solver_free(clmd); // Free the verts. if (cloth->verts != NULL) { @@ -587,7 +586,7 @@ void cloth_free_modifier(ClothModifierData *clmd) } if (cloth->sew_edge_graph) { - BLI_ghash_free(cloth->sew_edge_graph, MEM_freeN, NULL); + BLI_edgeset_free(cloth->sew_edge_graph); cloth->sew_edge_graph = NULL; } @@ -620,7 +619,7 @@ void cloth_free_modifier_extern(ClothModifierData *clmd) printf("cloth_free_modifier_extern in\n"); } - BPH_cloth_solver_free(clmd); + SIM_cloth_solver_free(clmd); // Free the verts. if (cloth->verts != NULL) { @@ -669,7 +668,7 @@ void cloth_free_modifier_extern(ClothModifierData *clmd) } if (cloth->sew_edge_graph) { - BLI_ghash_free(cloth->sew_edge_graph, MEM_freeN, NULL); + BLI_edgeset_free(cloth->sew_edge_graph); cloth->sew_edge_graph = NULL; } @@ -920,10 +919,10 @@ static int cloth_from_object( } // init our solver - BPH_cloth_solver_init(ob, clmd); + SIM_cloth_solver_init(ob, clmd); if (!first) { - BKE_cloth_solver_set_positions(clmd); + SIM_cloth_solver_set_positions(clmd); } clmd->clothObject->bvhtree = bvhtree_build_from_cloth(clmd, clmd->coll_parms->epsilon); @@ -1038,7 +1037,7 @@ static void cloth_free_errorsprings(Cloth *cloth, } BLI_INLINE void cloth_bend_poly_dir( - ClothVertex *verts, int i, int j, int *inds, int len, float r_dir[3]) + ClothVertex *verts, int i, int j, const int *inds, int len, float r_dir[3]) { float cent[3] = {0}; float fact = 1.0f / len; @@ -1557,9 +1556,8 @@ static bool find_internal_spring_target_vertex(BVHTreeFromMesh *treedata, *r_tar_v_idx = vert_idx; return true; } - else { - return false; - } + + return false; } static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) @@ -1693,8 +1691,7 @@ static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW) { /* cloth->sew_edge_graph should not exist before this */ BLI_assert(cloth->sew_edge_graph == NULL); - cloth->sew_edge_graph = BLI_ghash_new( - BLI_ghashutil_inthash_v2_p, BLI_ghashutil_inthash_v2_cmp, "cloth_sewing_edges_graph"); + cloth->sew_edge_graph = BLI_edgeset_new("cloth_sewing_edges_graph"); } /* Structural springs. */ @@ -1709,18 +1706,7 @@ static int cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) spring->lin_stiffness = 1.0f; spring->type = CLOTH_SPRING_TYPE_SEWING; - /* set indices of verts of the sewing edge symmetrically in sew_edge_graph */ - unsigned int *vertex_index_pair = MEM_mallocN(sizeof(unsigned int) * 2, - "sewing_edge_index_pair_01"); - if (medge[i].v1 < medge[i].v2) { - vertex_index_pair[0] = medge[i].v1; - vertex_index_pair[1] = medge[i].v2; - } - else { - vertex_index_pair[0] = medge[i].v2; - vertex_index_pair[1] = medge[i].v1; - } - BLI_ghash_insert(cloth->sew_edge_graph, vertex_index_pair, NULL); + BLI_edgeset_insert(cloth->sew_edge_graph, medge[i].v1, medge[i].v2); } else { shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 080d61f1500..6118325c231 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -249,6 +249,34 @@ void BKE_collection_add_from_object(Main *bmain, BKE_main_collection_sync(bmain); } +/** + * Add \a collection_dst to all scene collections that reference collection \a collection_src is + * in. + * + * Logic is very similar to #BKE_collection_object_add_from(). + */ +void BKE_collection_add_from_collection(Main *bmain, + Scene *scene, + Collection *collection_src, + Collection *collection_dst) +{ + bool is_instantiated = false; + + FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { + if (!ID_IS_LINKED(collection) && BKE_collection_has_collection(collection, collection_src)) { + collection_child_add(collection, collection_dst, 0, true); + is_instantiated = true; + } + } + FOREACH_SCENE_COLLECTION_END; + + if (!is_instantiated) { + collection_child_add(scene->master_collection, collection_dst, 0, true); + } + + BKE_main_collection_sync(bmain); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -333,7 +361,6 @@ static Collection *collection_duplicate_recursive(Main *bmain, Collection *collection_new; bool do_full_process = false; const bool is_collection_master = (collection_old->flag & COLLECTION_IS_MASTER) != 0; - const bool is_collection_liboverride = ID_IS_OVERRIDE_LIBRARY(collection_old); const bool do_objects = (duplicate_flags & USER_DUP_OBJECT) != 0; @@ -346,7 +373,12 @@ static Collection *collection_duplicate_recursive(Main *bmain, } else if (collection_old->id.newid == NULL) { collection_new = (Collection *)BKE_id_copy_for_duplicate( - bmain, (ID *)collection_old, is_collection_liboverride, duplicate_flags); + bmain, (ID *)collection_old, duplicate_flags); + + if (collection_new == collection_old) { + return collection_new; + } + do_full_process = true; } else { @@ -382,17 +414,15 @@ static Collection *collection_duplicate_recursive(Main *bmain, Object *ob_old = cob->ob; Object *ob_new = (Object *)ob_old->id.newid; - /* If collection is an override, we do not want to duplicate any linked data-block, as that - * would generate a purely local data. */ - if (is_collection_liboverride && ID_IS_LINKED(ob_old)) { - continue; - } - if (ob_new == NULL) { ob_new = BKE_object_duplicate( bmain, ob_old, duplicate_flags, duplicate_options | LIB_ID_DUPLICATE_IS_SUBPROCESS); } + if (ob_new == ob_old) { + continue; + } + collection_object_add(bmain, collection_new, ob_new, 0, true); collection_object_remove(bmain, collection_new, ob_old, false); } @@ -403,13 +433,11 @@ static Collection *collection_duplicate_recursive(Main *bmain, LISTBASE_FOREACH_MUTABLE (CollectionChild *, child, &collection_old->children) { Collection *child_collection_old = child->collection; - if (is_collection_liboverride && ID_IS_LINKED(child_collection_old)) { - continue; - } - - collection_duplicate_recursive( + Collection *child_collection_new = collection_duplicate_recursive( bmain, collection_new, child_collection_old, duplicate_flags, duplicate_options); - collection_child_remove(collection_new, child_collection_old); + if (child_collection_new != child_collection_old) { + collection_child_remove(collection_new, child_collection_old); + } } return collection_new; @@ -434,6 +462,11 @@ Collection *BKE_collection_duplicate(Main *bmain, if (!is_subprocess) { BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false); BKE_main_id_clear_newpoins(bmain); + /* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate + * all expected linked data. */ + if (ID_IS_LINKED(collection)) { + duplicate_flags |= USER_DUP_LINKED_ID; + } } Collection *collection_new = collection_duplicate_recursive( @@ -1114,7 +1147,7 @@ void BKE_collections_after_lib_link(Main *bmain) /** \name Collection Children * \{ */ -static bool collection_find_instance_recursive(Collection *collection, +static bool collection_instance_find_recursive(Collection *collection, Collection *instance_collection) { LISTBASE_FOREACH (CollectionObject *, collection_object, &collection->gobject) { @@ -1126,7 +1159,7 @@ static bool collection_find_instance_recursive(Collection *collection, } LISTBASE_FOREACH (CollectionChild *, collection_child, &collection->children) { - if (collection_find_instance_recursive(collection_child->collection, instance_collection)) { + if (collection_instance_find_recursive(collection_child->collection, instance_collection)) { return true; } } @@ -1134,21 +1167,88 @@ static bool collection_find_instance_recursive(Collection *collection, return false; } -bool BKE_collection_find_cycle(Collection *new_ancestor, Collection *collection) +/** + * Find potential cycles in collections. + * + * \param new_ancestor the potential new owner of given \a collection, or the collection to check + * if the later is NULL. + * \param collection the collection we want to add to \a new_ancestor, may be NULL if we just want + * to ensure \a new_ancestor does not already have cycles. + * \return true if a cycle is found. + */ +bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection) { if (collection == new_ancestor) { return true; } + if (collection == NULL) { + collection = new_ancestor; + } + LISTBASE_FOREACH (CollectionParent *, parent, &new_ancestor->parents) { - if (BKE_collection_find_cycle(parent->collection, collection)) { + if (BKE_collection_cycle_find(parent->collection, collection)) { return true; } } /* Find possible objects in collection or its children, that would instantiate the given ancestor * collection (that would also make a fully invalid cycle of dependencies) .*/ - return collection_find_instance_recursive(collection, new_ancestor); + return collection_instance_find_recursive(collection, new_ancestor); +} + +static bool collection_instance_fix_recursive(Collection *parent_collection, + Collection *collection) +{ + bool cycles_found = false; + + LISTBASE_FOREACH (CollectionObject *, collection_object, &parent_collection->gobject) { + if (collection_object->ob != NULL && + collection_object->ob->instance_collection == collection) { + id_us_min(&collection->id); + collection_object->ob->instance_collection = NULL; + cycles_found = true; + } + } + + LISTBASE_FOREACH (CollectionChild *, collection_child, &parent_collection->children) { + if (collection_instance_fix_recursive(collection_child->collection, collection)) { + cycles_found = true; + } + } + + return cycles_found; +} + +static bool collection_cycle_fix_recursive(Main *bmain, + Collection *parent_collection, + Collection *collection) +{ + bool cycles_found = false; + + LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &parent_collection->parents) { + if (BKE_collection_cycle_find(parent->collection, collection)) { + BKE_collection_child_remove(bmain, parent->collection, parent_collection); + cycles_found = true; + } + else if (collection_cycle_fix_recursive(bmain, parent->collection, collection)) { + cycles_found = true; + } + } + + return cycles_found; +} + +/** + * Find and fix potential cycles in collections. + * + * \param collection the collection to check for existing cycles. + * \return true if cycles are found and fixed. + */ +bool BKE_collection_cycles_fix(Main *bmain, Collection *collection) +{ + return collection_cycle_fix_recursive(bmain, collection, collection) || + collection_instance_fix_recursive(collection, collection); } static CollectionChild *collection_find_child(Collection *parent, Collection *collection) @@ -1190,7 +1290,7 @@ static bool collection_child_add(Collection *parent, if (child) { return false; } - if (BKE_collection_find_cycle(parent, collection)) { + if (BKE_collection_cycle_find(parent, collection)) { return false; } @@ -1268,7 +1368,7 @@ void BKE_collection_parent_relations_rebuild(Collection *collection) child = child_next) { child_next = child->next; - if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) { + if (child->collection == NULL || BKE_collection_cycle_find(collection, child->collection)) { BLI_freelinkN(&collection->children, child); } else { @@ -1431,7 +1531,7 @@ bool BKE_collection_move(Main *bmain, if (collection->flag & COLLECTION_IS_MASTER) { return false; } - if (BKE_collection_find_cycle(to_parent, collection)) { + if (BKE_collection_cycle_find(to_parent, collection)) { return false; } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index daf1602319f..31d49dd4508 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -32,7 +32,7 @@ #include "DNA_scene_types.h" #include "BLI_blenlib.h" -#include "BLI_ghash.h" +#include "BLI_edgehash.h" #include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_task.h" @@ -1153,17 +1153,7 @@ static bool cloth_bvh_selfcollision_is_active(const Cloth *cloth, } if (sewing_active) { - unsigned int vertex_index_pair[2]; - /* The indices pair are ordered, thus must ensure the same here as well */ - if (tri_a->tri[i] < tri_b->tri[j]) { - vertex_index_pair[0] = tri_a->tri[i]; - vertex_index_pair[1] = tri_b->tri[j]; - } - else { - vertex_index_pair[0] = tri_b->tri[j]; - vertex_index_pair[1] = tri_a->tri[i]; - } - if (BLI_ghash_haskey(cloth->sew_edge_graph, vertex_index_pair)) { + if (BLI_edgeset_haskey(cloth->sew_edge_graph, tri_a->tri[i], tri_b->tri[j])) { return false; } } diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 4f4eb8f9f9d..fc326ffb390 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1202,7 +1202,7 @@ int BKE_curvemapping_RGBA_does_something(const CurveMapping *cumap) return 0; } -void BKE_curvemapping_initialize(CurveMapping *cumap) +void BKE_curvemapping_init(CurveMapping *cumap) { int a; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 06c28776840..2ef32895db9 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -53,6 +53,7 @@ #include "BKE_action.h" #include "BKE_anim_path.h" +#include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_bvhutils.h" #include "BKE_cachefile.h" @@ -2625,7 +2626,7 @@ static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy) } } -static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), +static void actcon_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, @@ -2679,6 +2680,8 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), s = (vec[axis] - data->min) / (data->max - data->min); CLAMP(s, 0, 1); t = (s * (data->end - data->start)) + data->start; + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + t); if (G.debug & G_DEBUG) { printf("do Action Constraint %s - Ob %s Pchan %s\n", @@ -2693,7 +2696,7 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), /* evaluate using workob */ /* FIXME: we don't have any consistent standards on limiting effects on object... */ - what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, t); + what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, &anim_eval_context); BKE_object_to_mat4(&workob, ct->matrix); } else if (cob->type == CONSTRAINT_OBTYPE_BONE) { @@ -2710,7 +2713,7 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph), tchan->rotmode = pchan->rotmode; /* evaluate action using workob (it will only set the PoseChannel in question) */ - what_does_obaction(cob->ob, &workob, &pose, data->act, pchan->name, t); + what_does_obaction(cob->ob, &workob, &pose, data->act, pchan->name, &anim_eval_context); /* convert animation to matrices for use here */ BKE_pchan_calc_mat(tchan); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 8de12139306..30f021b0e81 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -694,6 +694,11 @@ wmWindowManager *CTX_wm_manager(const bContext *C) return C->wm.manager; } +bool CTX_wm_interface_locked(const bContext *C) +{ + return (bool)C->wm.manager->is_interface_locked; +} + wmWindow *CTX_wm_window(const bContext *C) { return ctx_wm_python_context_get(C, "window", &RNA_Window, C->wm.window); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 6b28297622c..e126fb7f632 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -223,7 +223,7 @@ void BKE_curve_init(Curve *cu, const short curve_type) cu->vfont->id.us += 4; cu->str = MEM_malloc_arrayN(12, sizeof(unsigned char), "str"); BLI_strncpy(cu->str, "Text", 12); - cu->len = cu->len_wchar = cu->pos = 4; + cu->len = cu->len_char32 = cu->pos = 4; cu->strinfo = MEM_calloc_arrayN(12, sizeof(CharInfo), "strinfo new"); cu->totbox = cu->actbox = 1; cu->tb = MEM_calloc_arrayN(MAXTEXTBOX, sizeof(TextBox), "textbox"); @@ -1157,7 +1157,7 @@ void BKE_nurb_knot_calc_v(Nurb *nu) } static void basisNurb( - float t, short order, int pnts, float *knots, float *basis, int *start, int *end) + float t, short order, int pnts, const float *knots, float *basis, int *start, int *end) { float d, e; int i, i1 = 0, i2 = 0, j, orderpluspnts, opp2, o2; @@ -1190,9 +1190,8 @@ static void basisNurb( } break; } - else { - basis[i] = 0.0; - } + + basis[i] = 0.0; } basis[i] = 0.0; @@ -1727,205 +1726,6 @@ static void forward_diff_bezier_cotangent(const float p0[3], } } -/* ***************** BEVEL ****************** */ - -void BKE_curve_bevel_make(Object *ob, ListBase *disp) -{ - DispList *dl, *dlnew; - Curve *bevcu, *cu; - float *fp, facx, facy, angle, dangle; - int nr, a; - - cu = ob->data; - BLI_listbase_clear(disp); - - /* if a font object is being edited, then do nothing */ - // XXX if ( ob == obedit && ob->type == OB_FONT ) return; - - if (cu->bevobj) { - if (cu->bevobj->type != OB_CURVE) { - return; - } - - bevcu = cu->bevobj->data; - if (bevcu->ext1 == 0.0f && bevcu->ext2 == 0.0f) { - ListBase bevdisp = {NULL, NULL}; - facx = cu->bevobj->scale[0]; - facy = cu->bevobj->scale[1]; - - if (cu->bevobj->runtime.curve_cache) { - dl = cu->bevobj->runtime.curve_cache->disp.first; - } - else { - BLI_assert(cu->bevobj->runtime.curve_cache != NULL); - dl = NULL; - } - - while (dl) { - if (ELEM(dl->type, DL_POLY, DL_SEGM)) { - dlnew = MEM_mallocN(sizeof(DispList), "makebevelcurve1"); - *dlnew = *dl; - dlnew->verts = MEM_malloc_arrayN( - dl->parts * dl->nr, 3 * sizeof(float), "makebevelcurve1"); - memcpy(dlnew->verts, dl->verts, 3 * sizeof(float) * dl->parts * dl->nr); - - if (dlnew->type == DL_SEGM) { - dlnew->flag |= (DL_FRONT_CURVE | DL_BACK_CURVE); - } - - BLI_addtail(disp, dlnew); - fp = dlnew->verts; - nr = dlnew->parts * dlnew->nr; - while (nr--) { - fp[2] = fp[1] * facy; - fp[1] = -fp[0] * facx; - fp[0] = 0.0; - fp += 3; - } - } - dl = dl->next; - } - - BKE_displist_free(&bevdisp); - } - } - else if (cu->ext1 == 0.0f && cu->ext2 == 0.0f) { - /* pass */ - } - else if (cu->ext2 == 0.0f) { - dl = MEM_callocN(sizeof(DispList), "makebevelcurve2"); - dl->verts = MEM_malloc_arrayN(2, sizeof(float[3]), "makebevelcurve2"); - BLI_addtail(disp, dl); - dl->type = DL_SEGM; - dl->parts = 1; - dl->flag = DL_FRONT_CURVE | DL_BACK_CURVE; - dl->nr = 2; - - fp = dl->verts; - fp[0] = fp[1] = 0.0; - fp[2] = -cu->ext1; - fp[3] = fp[4] = 0.0; - fp[5] = cu->ext1; - } - else if ((cu->flag & (CU_FRONT | CU_BACK)) == 0 && cu->ext1 == 0.0f) { - /* We make a full round bevel in that case. */ - - nr = 4 + 2 * cu->bevresol; - - dl = MEM_callocN(sizeof(DispList), "makebevelcurve p1"); - dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve p1"); - BLI_addtail(disp, dl); - dl->type = DL_POLY; - dl->parts = 1; - dl->flag = DL_BACK_CURVE; - dl->nr = nr; - - /* a circle */ - fp = dl->verts; - dangle = (2.0f * (float)M_PI / (nr)); - angle = -(nr - 1) * dangle; - - for (a = 0; a < nr; a++) { - fp[0] = 0.0; - fp[1] = (cosf(angle) * (cu->ext2)); - fp[2] = (sinf(angle) * (cu->ext2)) - cu->ext1; - angle += dangle; - fp += 3; - } - } - else { - /* The general case for nonzero extrusion or an incomplete loop. */ - dl = MEM_callocN(sizeof(DispList), "makebevelcurve"); - if ((cu->flag & (CU_FRONT | CU_BACK)) == 0) { - /* The full loop. */ - nr = 4 * cu->bevresol + 6; - dl->flag = DL_FRONT_CURVE | DL_BACK_CURVE; - } - else if ((cu->flag & CU_FRONT) && (cu->flag & CU_BACK)) { - /* Half the loop. */ - nr = 2 * (cu->bevresol + 1) + ((cu->ext1 == 0.0f) ? 1 : 2); - dl->flag = DL_FRONT_CURVE | DL_BACK_CURVE; - } - else { - /* One quarter of the loop (just front or back). */ - nr = (cu->ext1 == 0.0f) ? cu->bevresol + 2 : cu->bevresol + 3; - dl->flag = (cu->flag & CU_FRONT) ? DL_FRONT_CURVE : DL_BACK_CURVE; - } - - dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), "makebevelcurve"); - BLI_addtail(disp, dl); - /* Use a different type depending on whether the loop is complete or not. */ - dl->type = ((cu->flag & (CU_FRONT | CU_BACK)) == 0) ? DL_POLY : DL_SEGM; - dl->parts = 1; - dl->nr = nr; - - fp = dl->verts; - dangle = (float)M_PI_2 / (cu->bevresol + 1); - angle = 0.0; - - /* Build the back section. */ - if (cu->flag & CU_BACK || !(cu->flag & CU_FRONT)) { - angle = (float)M_PI_2 * 3.0f; - for (a = 0; a < cu->bevresol + 2; a++) { - fp[0] = 0.0; - fp[1] = (float)(cosf(angle) * (cu->ext2)); - fp[2] = (float)(sinf(angle) * (cu->ext2)) - cu->ext1; - angle += dangle; - fp += 3; - } - if ((cu->ext1 != 0.0f) && !(cu->flag & CU_FRONT) && (cu->flag & CU_BACK)) { - /* Add the extrusion if we're only building the back. */ - fp[0] = 0.0; - fp[1] = cu->ext2; - fp[2] = cu->ext1; - } - } - - /* Build the front section. */ - if (cu->flag & CU_FRONT || !(cu->flag & CU_BACK)) { - if ((cu->ext1 != 0.0f) && !(cu->flag & CU_BACK) && (cu->flag & CU_FRONT)) { - /* Add the extrusion if we're only building the back. */ - fp[0] = 0.0; - fp[1] = cu->ext2; - fp[2] = -cu->ext1; - fp += 3; - } - /* Don't duplicate the last back vertex. */ - angle = (cu->ext1 == 0.0f && (cu->flag & CU_BACK)) ? dangle : 0; - int front_len = (cu->ext1 == 0.0f && ((cu->flag & CU_BACK) || !(cu->flag & CU_FRONT))) ? - cu->bevresol + 1 : - cu->bevresol + 2; - for (a = 0; a < front_len; a++) { - fp[0] = 0.0; - fp[1] = (float)(cosf(angle) * (cu->ext2)); - fp[2] = (float)(sinf(angle) * (cu->ext2)) + cu->ext1; - angle += dangle; - fp += 3; - } - } - - /* Build the other half only if we're building the full loop. */ - if (!(cu->flag & (CU_FRONT | CU_BACK))) { - for (a = 0; a < cu->bevresol + 1; a++) { - fp[0] = 0.0; - fp[1] = (float)(cosf(angle) * (cu->ext2)); - fp[2] = (float)(sinf(angle) * (cu->ext2)) + cu->ext1; - angle += dangle; - fp += 3; - } - - angle = (float)M_PI; - for (a = 0; a < cu->bevresol + 1; a++) { - fp[0] = 0.0; - fp[1] = (float)(cosf(angle) * (cu->ext2)); - fp[2] = (float)(sinf(angle) * (cu->ext2)) - cu->ext1; - angle += dangle; - fp += 3; - } - } - } -} - static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], @@ -2040,7 +1840,7 @@ static int vergxcobev(const void *a1, const void *a2) if (x1->left > x2->left) { return 1; } - else if (x1->left < x2->left) { + if (x1->left < x2->left) { return -1; } return 0; @@ -3113,8 +2913,9 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) if (bl->poly > 0) { BevPoint *bevp; - min = 300000.0; bevp = bl->bevpoints; + bevp1 = bl->bevpoints; + min = bevp1->vec[0]; nr = bl->nr; while (nr--) { if (min > bevp->vec[0]) { @@ -3561,8 +3362,13 @@ static void free_arrays(void *buffer) } /* computes in which direction to change h[i] to satisfy conditions better */ -static float bezier_relax_direction( - float *a, float *b, float *c, float *d, float *h, int i, int count) +static float bezier_relax_direction(const float *a, + const float *b, + const float *c, + const float *d, + const float *h, + int i, + int count) { /* current deviation between sides of the equation */ float state = a[i] * h[(i + count - 1) % count] + b[i] * h[i] + c[i] * h[(i + 1) % count] - d[i]; @@ -3578,8 +3384,15 @@ static void bezier_lock_unknown(float *a, float *b, float *c, float *d, int i, f d[i] = value; } -static void bezier_restore_equation( - float *a, float *b, float *c, float *d, float *a0, float *b0, float *c0, float *d0, int i) +static void bezier_restore_equation(float *a, + float *b, + float *c, + float *d, + const float *a0, + const float *b0, + const float *c0, + const float *d0, + int i) { a[i] = a0[i]; b[i] = b0[i]; @@ -3587,8 +3400,14 @@ static void bezier_restore_equation( d[i] = d0[i]; } -static bool tridiagonal_solve_with_limits( - float *a, float *b, float *c, float *d, float *h, float *hmin, float *hmax, int solve_count) +static bool tridiagonal_solve_with_limits(float *a, + float *b, + float *c, + float *d, + float *h, + const float *hmin, + const float *hmax, + int solve_count) { float *a0, *b0, *c0, *d0; float **arrays[] = {&a0, &b0, &c0, &d0, NULL}; @@ -3727,7 +3546,7 @@ static bool tridiagonal_solve_with_limits( /* clang-format on */ static void bezier_eq_continuous( - float *a, float *b, float *c, float *d, float *dy, float *l, int i) + float *a, float *b, float *c, float *d, const float *dy, const float *l, int i) { a[i] = l[i] * l[i]; b[i] = 2.0f * (l[i] + 1); @@ -3736,7 +3555,7 @@ static void bezier_eq_continuous( } static void bezier_eq_noaccel_right( - float *a, float *b, float *c, float *d, float *dy, float *l, int i) + float *a, float *b, float *c, float *d, const float *dy, const float *l, int i) { a[i] = 0.0f; b[i] = 2.0f; @@ -3745,7 +3564,7 @@ static void bezier_eq_noaccel_right( } static void bezier_eq_noaccel_left( - float *a, float *b, float *c, float *d, float *dy, float *l, int i) + float *a, float *b, float *c, float *d, const float *dy, const float *l, int i) { a[i] = l[i] * l[i]; b[i] = 2.0f * l[i]; @@ -4612,7 +4431,7 @@ void BKE_nurb_direction_switch(Nurb *nu) bp1++; bp2--; } - /* If there're odd number of points no need to touch coord of middle one, + /* If there are odd number of points no need to touch coord of middle one, * but still need to change it's tilt. */ if (nu->pntsu & 1) { @@ -4824,7 +4643,7 @@ float (*BKE_curve_nurbs_key_vert_coords_alloc(ListBase *lb, float *key, int *r_v return cos; } -void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, float *key) +void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, const float *key) { Nurb *nu; int i; @@ -5064,32 +4883,31 @@ bool BKE_nurb_type_convert(Nurb *nu, } return false; /* conversion impossible */ } - else { - bezt = MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2"); - nu->bezt = bezt; - a = nr; - bp = nu->bp; - while (a--) { - copy_v3_v3(bezt->vec[0], bp->vec); - bezt->f1 = bp->f1; - bp++; - copy_v3_v3(bezt->vec[1], bp->vec); - bezt->f2 = bp->f1; - bp++; - copy_v3_v3(bezt->vec[2], bp->vec); - bezt->f3 = bp->f1; - bezt->radius = bp->radius; - bezt->weight = bp->weight; - bp++; - bezt++; - } - MEM_freeN(nu->bp); - nu->bp = NULL; - MEM_freeN(nu->knotsu); - nu->knotsu = NULL; - nu->pntsu = nr; - nu->type = CU_BEZIER; + + bezt = MEM_calloc_arrayN(nr, sizeof(BezTriple), "setsplinetype2"); + nu->bezt = bezt; + a = nr; + bp = nu->bp; + while (a--) { + copy_v3_v3(bezt->vec[0], bp->vec); + bezt->f1 = bp->f1; + bp++; + copy_v3_v3(bezt->vec[1], bp->vec); + bezt->f2 = bp->f1; + bp++; + copy_v3_v3(bezt->vec[2], bp->vec); + bezt->f3 = bp->f1; + bezt->radius = bp->radius; + bezt->weight = bp->weight; + bp++; + bezt++; } + MEM_freeN(nu->bp); + nu->bp = NULL; + MEM_freeN(nu->knotsu); + nu->knotsu = NULL; + nu->pntsu = nr; + nu->type = CU_BEZIER; } } @@ -5140,10 +4958,9 @@ int BKE_curve_nurb_vert_index_get(const Nurb *nu, const void *vert) BLI_assert(ARRAY_HAS_ITEM((BezTriple *)vert, nu->bezt, nu->pntsu)); return (BezTriple *)vert - nu->bezt; } - else { - BLI_assert(ARRAY_HAS_ITEM((BPoint *)vert, nu->bp, nu->pntsu * nu->pntsv)); - return (BPoint *)vert - nu->bp; - } + + BLI_assert(ARRAY_HAS_ITEM((BPoint *)vert, nu->bp, nu->pntsu * nu->pntsv)); + return (BPoint *)vert - nu->bp; } /* Set active nurb and active vert for curve */ @@ -5293,8 +5110,11 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3]) return false; } -void BKE_curve_transform_ex( - Curve *cu, float mat[4][4], const bool do_keys, const bool do_props, const float unit_scale) +void BKE_curve_transform_ex(Curve *cu, + const float mat[4][4], + const bool do_keys, + const bool do_props, + const float unit_scale) { Nurb *nu; BPoint *bp; @@ -5357,13 +5177,13 @@ void BKE_curve_transform_ex( } } -void BKE_curve_transform(Curve *cu, float mat[4][4], const bool do_keys, const bool do_props) +void BKE_curve_transform(Curve *cu, const float mat[4][4], const bool do_keys, const bool do_props) { float unit_scale = mat4_to_scale(mat); BKE_curve_transform_ex(cu, mat, do_keys, do_props, unit_scale); } -void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys) +void BKE_curve_translate(Curve *cu, const float offset[3], const bool do_keys) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); Nurb *nu; @@ -5422,7 +5242,7 @@ void BKE_curve_material_index_remove(Curve *cu, int index) if (curvetype == OB_FONT) { struct CharInfo *info = cu->strinfo; int i; - for (i = cu->len_wchar - 1; i >= 0; i--, info++) { + for (i = cu->len_char32 - 1; i >= 0; i--, info++) { if (info->mat_nr && info->mat_nr >= index) { info->mat_nr--; } @@ -5446,7 +5266,7 @@ bool BKE_curve_material_index_used(Curve *cu, int index) if (curvetype == OB_FONT) { struct CharInfo *info = cu->strinfo; int i; - for (i = cu->len_wchar - 1; i >= 0; i--, info++) { + for (i = cu->len_char32 - 1; i >= 0; i--, info++) { if (info->mat_nr == index) { return true; } @@ -5472,7 +5292,7 @@ void BKE_curve_material_index_clear(Curve *cu) if (curvetype == OB_FONT) { struct CharInfo *info = cu->strinfo; int i; - for (i = cu->len_wchar - 1; i >= 0; i--, info++) { + for (i = cu->len_char32 - 1; i >= 0; i--, info++) { info->mat_nr = 0; } } @@ -5494,7 +5314,7 @@ bool BKE_curve_material_index_validate(Curve *cu) CharInfo *info = cu->strinfo; const int max_idx = max_ii(0, cu->totcol); /* OB_FONT use 1 as first mat index, not 0!!! */ int i; - for (i = cu->len_wchar - 1; i >= 0; i--, info++) { + for (i = cu->len_char32 - 1; i >= 0; i--, info++) { if (info->mat_nr > max_idx) { info->mat_nr = 0; is_valid = false; @@ -5516,9 +5336,7 @@ bool BKE_curve_material_index_validate(Curve *cu) DEG_id_tag_update(&cu->id, ID_RECALC_GEOMETRY); return true; } - else { - return false; - } + return false; } void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len) @@ -5544,7 +5362,7 @@ void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int } else { strinfo = cu->strinfo; - charinfo_len = cu->len_wchar; + charinfo_len = cu->len_char32; } for (i = 0; i <= charinfo_len; i++) { diff --git a/source/blender/blenkernel/intern/curve_bevel.c b/source/blender/blenkernel/intern/curve_bevel.c new file mode 100644 index 00000000000..7f23f0215cc --- /dev/null +++ b/source/blender/blenkernel/intern/curve_bevel.c @@ -0,0 +1,272 @@ +/* + * 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. + */ + +/** \file + * \ingroup bke + * + * Handle curve object data bevel options, + * both extruding + */ + +#include <string.h> + +#include "BLI_listbase.h" +#include "BLI_math_base.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_curve_types.h" +#include "DNA_object_types.h" + +#include "BKE_curve.h" +#include "BKE_displist.h" + +typedef enum CurveBevelFillType { + BACK = 0, + FRONT, + HALF, + FULL, +} CurveBevelFillType; + +static CurveBevelFillType curve_bevel_get_fill_type(const Curve *curve) +{ + if (!(curve->flag & (CU_FRONT | CU_BACK))) { + return FULL; + } + if ((curve->flag & CU_FRONT) && (curve->flag & CU_BACK)) { + return HALF; + } + + return (curve->flag & CU_FRONT) ? FRONT : BACK; +} + +static void curve_bevel_make_extrude_and_fill(Curve *cu, + ListBase *disp, + const bool use_extrude, + const CurveBevelFillType fill_type) +{ + DispList *dl = MEM_callocN(sizeof(DispList), __func__); + + int nr; + if (fill_type == FULL) { + /* The full loop. */ + nr = 4 * cu->bevresol + 6; + dl->flag = DL_FRONT_CURVE | DL_BACK_CURVE; + } + else if (fill_type == HALF) { + /* Half the loop. */ + nr = 2 * (cu->bevresol + 1) + (use_extrude ? 2 : 1); + dl->flag = DL_FRONT_CURVE | DL_BACK_CURVE; + } + else { + /* One quarter of the loop (just front or back). */ + nr = use_extrude ? cu->bevresol + 3 : cu->bevresol + 2; + dl->flag = (fill_type == FRONT) ? DL_FRONT_CURVE : DL_BACK_CURVE; + } + + dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), __func__); + BLI_addtail(disp, dl); + /* Use a different type depending on whether the loop is complete or not. */ + dl->type = (fill_type == FULL) ? DL_POLY : DL_SEGM; + dl->parts = 1; + dl->nr = nr; + + float *fp = dl->verts; + const float dangle = (float)M_PI_2 / (cu->bevresol + 1); + float angle = 0.0f; + + /* Build the back section. */ + if (ELEM(fill_type, BACK, HALF, FULL)) { + angle = (float)M_PI_2 * 3.0f; + for (int i = 0; i < cu->bevresol + 2; i++) { + fp[0] = 0.0f; + fp[1] = (float)(cosf(angle) * (cu->ext2)); + fp[2] = (float)(sinf(angle) * (cu->ext2)) - cu->ext1; + angle += dangle; + fp += 3; + } + if (use_extrude && fill_type == BACK) { + /* Add the extrusion if we're only building the back. */ + fp[0] = 0.0f; + fp[1] = cu->ext2; + fp[2] = cu->ext1; + } + } + + /* Build the front section. */ + if (ELEM(fill_type, FRONT, HALF, FULL)) { + if (use_extrude && fill_type == FRONT) { + /* Add the extrusion if we're only building the front. */ + fp[0] = 0.0f; + fp[1] = cu->ext2; + fp[2] = -cu->ext1; + fp += 3; + } + /* Don't duplicate the last back vertex. */ + angle = (!use_extrude && ELEM(fill_type, HALF, FULL)) ? dangle : 0; + int front_len = (!use_extrude && ELEM(fill_type, HALF, FULL)) ? cu->bevresol + 1 : + cu->bevresol + 2; + for (int i = 0; i < front_len; i++) { + fp[0] = 0.0f; + fp[1] = (float)(cosf(angle) * (cu->ext2)); + fp[2] = (float)(sinf(angle) * (cu->ext2)) + cu->ext1; + angle += dangle; + fp += 3; + } + } + + /* Build the other half only if we're building the full loop. */ + if (fill_type == FULL) { + for (int i = 0; i < cu->bevresol + 1; i++) { + fp[0] = 0.0f; + fp[1] = (float)(cosf(angle) * (cu->ext2)); + fp[2] = (float)(sinf(angle) * (cu->ext2)) + cu->ext1; + angle += dangle; + fp += 3; + } + + angle = (float)M_PI; + for (int i = 0; i < cu->bevresol + 1; i++) { + fp[0] = 0.0f; + fp[1] = (float)(cosf(angle) * (cu->ext2)); + fp[2] = (float)(sinf(angle) * (cu->ext2)) - cu->ext1; + angle += dangle; + fp += 3; + } + } +} + +static void curve_bevel_make_full_circle(Curve *cu, ListBase *disp) +{ + const int nr = 4 + 2 * cu->bevresol; + + DispList *dl = MEM_callocN(sizeof(DispList), __func__); + dl->verts = MEM_malloc_arrayN(nr, sizeof(float[3]), __func__); + BLI_addtail(disp, dl); + dl->type = DL_POLY; + dl->parts = 1; + dl->flag = DL_BACK_CURVE; + dl->nr = nr; + + float *fp = dl->verts; + const float dangle = (2.0f * (float)M_PI / (nr)); + float angle = -(nr - 1) * dangle; + + for (int i = 0; i < nr; i++) { + fp[0] = 0.0; + fp[1] = (cosf(angle) * (cu->ext2)); + fp[2] = (sinf(angle) * (cu->ext2)) - cu->ext1; + angle += dangle; + fp += 3; + } +} + +static void curve_bevel_make_only_extrude(Curve *cu, ListBase *disp) +{ + DispList *dl = MEM_callocN(sizeof(DispList), __func__); + dl->verts = MEM_malloc_arrayN(2, sizeof(float[3]), __func__); + BLI_addtail(disp, dl); + dl->type = DL_SEGM; + dl->parts = 1; + dl->flag = DL_FRONT_CURVE | DL_BACK_CURVE; + dl->nr = 2; + + float *fp = dl->verts; + fp[0] = fp[1] = 0.0; + fp[2] = -cu->ext1; + fp[3] = fp[4] = 0.0; + fp[5] = cu->ext1; +} + +static void curve_bevel_make_from_object(Curve *cu, ListBase *disp) +{ + if (cu->bevobj->type != OB_CURVE) { + return; + } + + Curve *bevcu = cu->bevobj->data; + if (bevcu->ext1 == 0.0f && bevcu->ext2 == 0.0f) { + ListBase bevdisp = {NULL, NULL}; + float facx = cu->bevobj->scale[0]; + float facy = cu->bevobj->scale[1]; + + DispList *dl; + if (cu->bevobj->runtime.curve_cache) { + dl = cu->bevobj->runtime.curve_cache->disp.first; + } + else { + BLI_assert(cu->bevobj->runtime.curve_cache != NULL); + dl = NULL; + } + + while (dl) { + if (ELEM(dl->type, DL_POLY, DL_SEGM)) { + DispList *dlnew = MEM_mallocN(sizeof(DispList), __func__); + *dlnew = *dl; + dlnew->verts = MEM_malloc_arrayN(dl->parts * dl->nr, 3 * sizeof(float), __func__); + memcpy(dlnew->verts, dl->verts, 3 * sizeof(float) * dl->parts * dl->nr); + + if (dlnew->type == DL_SEGM) { + dlnew->flag |= (DL_FRONT_CURVE | DL_BACK_CURVE); + } + + BLI_addtail(disp, dlnew); + float *fp = dlnew->verts; + int nr = dlnew->parts * dlnew->nr; + while (nr--) { + fp[2] = fp[1] * facy; + fp[1] = -fp[0] * facx; + fp[0] = 0.0; + fp += 3; + } + } + dl = dl->next; + } + + BKE_displist_free(&bevdisp); + } +} + +void BKE_curve_bevel_make(Object *ob, ListBase *disp) +{ + Curve *curve = ob->data; + + const bool use_extrude = curve->ext1 != 0.0f; + const bool use_bevel = curve->ext2 != 0.0f; + + BLI_listbase_clear(disp); + + if (curve->bevobj) { + curve_bevel_make_from_object(curve, disp); + } + else if (!(use_extrude || use_bevel)) { + /* Pass. */ + } + else if (use_extrude && !use_bevel) { + curve_bevel_make_only_extrude(curve, disp); + } + else { + CurveBevelFillType fill_type = curve_bevel_get_fill_type(curve); + + if (!use_extrude && fill_type == FULL) { + curve_bevel_make_full_circle(curve, disp); + } + else { + /* The general case for nonzero extrusion or an incomplete loop. */ + curve_bevel_make_extrude_and_fill(curve, disp, use_extrude, fill_type); + } + } +} diff --git a/source/blender/blenkernel/intern/curveprofile.c b/source/blender/blenkernel/intern/curveprofile.c index 6919d4fa10f..0a41529aac1 100644 --- a/source/blender/blenkernel/intern/curveprofile.c +++ b/source/blender/blenkernel/intern/curveprofile.c @@ -886,7 +886,7 @@ void BKE_curveprofile_create_samples(CurveProfile *profile, */ static void curveprofile_make_table(CurveProfile *profile) { - int n_samples = PROF_N_TABLE(profile->path_len); + int n_samples = PROF_TABLE_LEN(profile->path_len); CurveProfilePoint *new_table = MEM_callocN(sizeof(CurveProfilePoint) * (n_samples + 1), "high-res table"); @@ -1040,7 +1040,7 @@ void BKE_curveprofile_update(CurveProfile *profile, const int update_flags) * Also sets the number of segments used for the display preview of the locations * of the sampled points. */ -void BKE_curveprofile_initialize(CurveProfile *profile, short segments_len) +void BKE_curveprofile_init(CurveProfile *profile, short segments_len) { if (segments_len != profile->segments_len) { profile->flag |= PROF_DIRTY_PRESET; @@ -1055,11 +1055,11 @@ void BKE_curveprofile_initialize(CurveProfile *profile, short segments_len) * Gives the distance to the next point in the widgets sampled table, in other words the length * of the \a 'i' edge of the table. * - * \note Requires curveprofile_initialize or #BKE_curveprofile_update call before to fill table. + * \note Requires #BKE_curveprofile_init or #BKE_curveprofile_update call before to fill table. */ static float curveprofile_distance_to_next_table_point(const CurveProfile *profile, int i) { - BLI_assert(i < PROF_N_TABLE(profile->path_len)); + BLI_assert(i < PROF_TABLE_LEN(profile->path_len)); return len_v2v2(&profile->table[i].x, &profile->table[i + 1].x); } @@ -1067,12 +1067,12 @@ static float curveprofile_distance_to_next_table_point(const CurveProfile *profi /** * Calculates the total length of the profile from the curves sampled in the table. * - * \note Requires curveprofile_initialize or #BKE_curveprofile_update call before to fill table. + * \note Requires #BKE_curveprofile_init or #BKE_curveprofile_update call before to fill table. */ float BKE_curveprofile_total_length(const CurveProfile *profile) { float total_length = 0; - for (int i = 0; i < PROF_N_TABLE(profile->path_len) - 1; i++) { + for (int i = 0; i < PROF_TABLE_LEN(profile->path_len) - 1; i++) { total_length += len_v2v2(&profile->table[i].x, &profile->table[i + 1].x); } return total_length; @@ -1082,7 +1082,7 @@ float BKE_curveprofile_total_length(const CurveProfile *profile) * Samples evenly spaced positions along the curve profile's table (generated from path). Fills * an entire table at once for a speedup if all of the results are going to be used anyway. * - * \note Requires curveprofile_initialize or #BKE_curveprofile_update call before to fill table. + * \note Requires #BKE_curveprofile_init or #BKE_curveprofile_update call before to fill table. * \note Working, but would conflict with "Sample Straight Edges" option, so this is unused for * now. */ @@ -1145,7 +1145,7 @@ void BKE_curveprofile_create_samples_even_spacing(CurveProfile *profile, * Travels down (length_portion * path) length and returns the position at that point. * * \param length_portion: The portion (0 to 1) of the path's full length to sample at. - * \note Requires curveprofile_initialize or #BKE_curveprofile_update call before to fill table. + * \note Requires #BKE_curveprofile_init or #BKE_curveprofile_update call before to fill table. */ void BKE_curveprofile_evaluate_length_portion(const CurveProfile *profile, float length_portion, @@ -1160,7 +1160,7 @@ void BKE_curveprofile_evaluate_length_portion(const CurveProfile *profile, float length_travelled = 0.0f; while (length_travelled < requested_length) { /* Check if we reached the last point before the final one. */ - if (i == PROF_N_TABLE(profile->path_len) - 2) { + if (i == PROF_TABLE_LEN(profile->path_len) - 2) { break; } float new_length = curveprofile_distance_to_next_table_point(profile, i); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 2be61239ac6..7ddb0a6862d 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -300,7 +300,7 @@ static void layerInterp_mdeformvert(const void **sources, /* now we know how many unique deform weights there are, so realloc */ if (dvert->dw && (dvert->totweight == totweight)) { - /* pass (fastpath if we don't need to realloc) */ + /* pass (fast-path if we don't need to realloc). */ } else { if (dvert->dw) { @@ -1464,6 +1464,102 @@ static int layerMaxNum_propcol(void) return MAX_MCOL; } +static void layerInterp_propfloat3( + const void **sources, const float *weights, const float *sub_weights, int count, void *dest) +{ + vec3f result = {0.0f, 0.0f, 0.0f}; + for (int i = 0; i < count; i++) { + float weight = weights ? weights[i] : 1.0f; + const vec3f *src = sources[i]; + if (sub_weights) { + madd_v3_v3fl(&result.x, &src->x, sub_weights[i] * weight); + } + else { + madd_v3_v3fl(&result.x, &src->x, weight); + } + } + copy_v3_v3((float *)dest, &result.x); +} + +static void layerMultiply_propfloat3(void *data, float fac) +{ + vec3f *vec = data; + vec->x *= fac; + vec->y *= fac; + vec->z *= fac; +} + +static void layerAdd_propfloat3(void *data1, const void *data2) +{ + vec3f *vec1 = data1; + const vec3f *vec2 = data2; + vec1->x += vec2->x; + vec1->y += vec2->y; + vec1->z += vec2->z; +} + +static bool layerValidate_propfloat3(void *data, const uint totitems, const bool do_fixes) +{ + float *values = data; + bool has_errors = false; + for (int i = 0; i < totitems * 3; i++) { + if (!isfinite(values[i])) { + if (do_fixes) { + values[i] = 0.0f; + } + has_errors = true; + } + } + return has_errors; +} + +static void layerInterp_propfloat2( + const void **sources, const float *weights, const float *sub_weights, int count, void *dest) +{ + vec2f result = {0.0f, 0.0f}; + for (int i = 0; i < count; i++) { + float weight = weights ? weights[i] : 1.0f; + const vec2f *src = sources[i]; + if (sub_weights) { + madd_v2_v2fl(&result.x, &src->x, sub_weights[i] * weight); + } + else { + madd_v2_v2fl(&result.x, &src->x, weight); + } + } + copy_v2_v2((float *)dest, &result.x); +} + +static void layerMultiply_propfloat2(void *data, float fac) +{ + vec2f *vec = data; + vec->x *= fac; + vec->y *= fac; +} + +static void layerAdd_propfloat2(void *data1, const void *data2) +{ + vec2f *vec1 = data1; + const vec2f *vec2 = data2; + vec1->x += vec2->x; + vec1->y += vec2->y; +} + +static bool layerValidate_propfloat2(void *data, const uint totitems, const bool do_fixes) +{ + float *values = data; + bool has_errors = false; + for (int i = 0; i < totitems * 2; i++) { + if (!isfinite(values[i])) { + if (do_fixes) { + values[i] = 0.0f; + } + has_errors = true; + } + } + return has_errors; +} + static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 0: CD_MVERT */ {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, @@ -1799,7 +1895,38 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { NULL, NULL, NULL, - layerMaxNum_propcol}}; + layerMaxNum_propcol}, + /* 48: CD_PROP_FLOAT3 */ + {sizeof(float[3]), + "vec3f", + 1, + N_("Float3"), + NULL, + NULL, + layerInterp_propfloat3, + NULL, + NULL, + layerValidate_propfloat3, + NULL, + layerMultiply_propfloat3, + NULL, + layerAdd_propfloat3}, + /* 49: CD_PROP_FLOAT2 */ + {sizeof(float[2]), + "vec2f", + 1, + N_("Float2"), + NULL, + NULL, + layerInterp_propfloat2, + NULL, + NULL, + layerValidate_propfloat2, + NULL, + layerMultiply_propfloat2, + NULL, + layerAdd_propfloat2}, +}; static const char *LAYERTYPENAMES[CD_NUMTYPES] = { /* 0-4 */ "CDMVert", @@ -1852,6 +1979,8 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { "CDHairMapping", "CDPoint", "CDPropCol", + "CDPropFloat3", + "CDPropFloat2", }; const CustomData_MeshMasks CD_MASK_BAREMESH = { @@ -2514,11 +2643,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, } if (alloctype == CD_DUPLICATE && layerdata) { - if (typeInfo->copy) { - typeInfo->copy(layerdata, newlayerdata, totelem); - } - else { - memcpy(newlayerdata, layerdata, (size_t)totelem * typeInfo->size); + if (totelem > 0) { + if (typeInfo->copy) { + typeInfo->copy(layerdata, newlayerdata, totelem); + } + else { + memcpy(newlayerdata, layerdata, (size_t)totelem * typeInfo->size); + } } } else if (alloctype == CD_DEFAULT) { @@ -4440,6 +4571,32 @@ bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, cons return false; } +void CustomData_layers__print(CustomData *data) +{ + int i; + const CustomDataLayer *layer; + + printf("{\n"); + + for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) { + + const char *name = CustomData_layertype_name(layer->type); + const int size = CustomData_sizeof(layer->type); + const char *structname; + int structnum; + CustomData_file_write_info(layer->type, &structname, &structnum); + printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n", + name, + structname, + layer->type, + (const void *)layer->data, + size, + (int)(MEM_allocN_len(layer->data) / size)); + } + + printf("}\n"); +} + /****************************** External Files *******************************/ static void customdata_external_filename(char filename[FILE_MAX], diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 48e0ee50d43..7bf87d0e639 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -43,6 +43,7 @@ #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" #include "BKE_mesh_runtime.h" +#include "BKE_mesh_wrapper.h" #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_object_deform.h" @@ -562,7 +563,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map CustomData *cd_dst, const bool use_dupref_dst, const int tolayers, - bool *use_layers_src, + const bool *use_layers_src, const int num_layers_src, cd_datatransfer_interp interp, void *interp_data) @@ -1467,6 +1468,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph, if (!me_src) { return changed; } + BKE_mesh_wrapper_ensure_mdata(me_src); if (auto_transform) { if (space_transform == NULL) { diff --git a/source/blender/blenkernel/intern/data_transfer_intern.h b/source/blender/blenkernel/intern/data_transfer_intern.h index 68ded6e2bc4..c5d7dd42cb8 100644 --- a/source/blender/blenkernel/intern/data_transfer_intern.h +++ b/source/blender/blenkernel/intern/data_transfer_intern.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __DATA_TRANSFER_INTERN_H__ -#define __DATA_TRANSFER_INTERN_H__ +#pragma once #include "BKE_customdata.h" /* For cd_datatransfer_interp */ @@ -75,5 +74,3 @@ void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLaye const float *weights, const int count, const float mix_factor); - -#endif /* __DATA_TRANSFER_INTERN_H__ */ diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index b97935d57f2..98fc5f9a23a 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -249,7 +249,7 @@ void BKE_defvert_sync_mapped(MDeformVert *dvert_dst, /** * be sure all flip_map values are valid */ -void BKE_defvert_remap(MDeformVert *dvert, int *map, const int map_len) +void BKE_defvert_remap(MDeformVert *dvert, const int *map, const int map_len) { MDeformWeight *dw = dvert->dw; unsigned int i; @@ -1184,7 +1184,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, CustomData *cd_dst, const bool UNUSED(use_dupref_dst), const int tolayers, - bool *use_layers_src, + const bool *use_layers_src, const int num_layers_src) { int idx_src; diff --git a/source/blender/blenkernel/intern/derived_node_tree.cc b/source/blender/blenkernel/intern/derived_node_tree.cc deleted file mode 100644 index 01317eeb5ce..00000000000 --- a/source/blender/blenkernel/intern/derived_node_tree.cc +++ /dev/null @@ -1,441 +0,0 @@ -/* - * 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. - */ - -#include "BKE_derived_node_tree.hh" - -#include "BLI_dot_export.hh" - -#define UNINITIALIZED_ID UINT32_MAX - -namespace blender::bke { - -static const NodeTreeRef &get_tree_ref(NodeTreeRefMap &node_tree_refs, bNodeTree *btree) -{ - return *node_tree_refs.lookup_or_add_cb(btree, - [&]() { return std::make_unique<NodeTreeRef>(btree); }); -} - -DerivedNodeTree::DerivedNodeTree(bNodeTree *btree, NodeTreeRefMap &node_tree_refs) : btree_(btree) -{ - const NodeTreeRef &main_tree_ref = get_tree_ref(node_tree_refs, btree); - - Vector<DNode *> all_nodes; - Vector<DGroupInput *> all_group_inputs; - Vector<DParentNode *> all_parent_nodes; - - this->insert_nodes_and_links_in_id_order(main_tree_ref, nullptr, all_nodes); - this->expand_groups(all_nodes, all_group_inputs, all_parent_nodes, node_tree_refs); - this->remove_expanded_group_interfaces(all_nodes); - this->remove_unused_group_inputs(all_group_inputs); - this->store_in_this_and_init_ids( - std::move(all_nodes), std::move(all_group_inputs), std::move(all_parent_nodes)); -} - -BLI_NOINLINE void DerivedNodeTree::insert_nodes_and_links_in_id_order(const NodeTreeRef &tree_ref, - DParentNode *parent, - Vector<DNode *> &all_nodes) -{ - Array<DSocket *, 64> sockets_map(tree_ref.sockets().size()); - - /* Insert nodes. */ - for (const NodeRef *node_ref : tree_ref.nodes()) { - DNode &node = this->create_node(*node_ref, parent, sockets_map); - all_nodes.append(&node); - } - - /* Insert links. */ - for (const NodeRef *node_ref : tree_ref.nodes()) { - for (const InputSocketRef *to_socket_ref : node_ref->inputs()) { - DInputSocket *to_socket = (DInputSocket *)sockets_map[to_socket_ref->id()]; - for (const OutputSocketRef *from_socket_ref : to_socket_ref->linked_sockets()) { - DOutputSocket *from_socket = (DOutputSocket *)sockets_map[from_socket_ref->id()]; - to_socket->linked_sockets_.append(from_socket); - from_socket->linked_sockets_.append(to_socket); - } - } - } -} - -DNode &DerivedNodeTree::create_node(const NodeRef &node_ref, - DParentNode *parent, - MutableSpan<DSocket *> r_sockets_map) -{ - DNode &node = *allocator_.construct<DNode>(); - node.node_ref_ = &node_ref; - node.parent_ = parent; - node.id_ = UNINITIALIZED_ID; - - node.inputs_ = allocator_.construct_elements_and_pointer_array<DInputSocket>( - node_ref.inputs().size()); - node.outputs_ = allocator_.construct_elements_and_pointer_array<DOutputSocket>( - node_ref.outputs().size()); - - for (uint i : node.inputs_.index_range()) { - const InputSocketRef &socket_ref = node_ref.input(i); - DInputSocket &socket = *node.inputs_[i]; - - socket.id_ = UNINITIALIZED_ID; - socket.node_ = &node; - socket.socket_ref_ = &socket_ref; - - r_sockets_map[socket_ref.id()] = &socket; - } - - for (uint i : node.outputs_.index_range()) { - const OutputSocketRef &socket_ref = node_ref.output(i); - DOutputSocket &socket = *node.outputs_[i]; - - socket.id_ = UNINITIALIZED_ID; - socket.node_ = &node; - socket.socket_ref_ = &socket_ref; - - r_sockets_map[socket_ref.id()] = &socket; - } - - return node; -} - -BLI_NOINLINE void DerivedNodeTree::expand_groups(Vector<DNode *> &all_nodes, - Vector<DGroupInput *> &all_group_inputs, - Vector<DParentNode *> &all_parent_nodes, - NodeTreeRefMap &node_tree_refs) -{ - for (uint i = 0; i < all_nodes.size(); i++) { - DNode &node = *all_nodes[i]; - if (node.node_ref_->is_group_node()) { - this->expand_group_node(node, all_nodes, all_group_inputs, all_parent_nodes, node_tree_refs); - } - } -} - -BLI_NOINLINE void DerivedNodeTree::expand_group_node(DNode &group_node, - Vector<DNode *> &all_nodes, - Vector<DGroupInput *> &all_group_inputs, - Vector<DParentNode *> &all_parent_nodes, - NodeTreeRefMap &node_tree_refs) -{ - const NodeRef &group_node_ref = *group_node.node_ref_; - BLI_assert(group_node_ref.is_group_node()); - - bNodeTree *btree = (bNodeTree *)group_node_ref.bnode()->id; - if (btree == nullptr) { - return; - } - - const NodeTreeRef &group_ref = get_tree_ref(node_tree_refs, btree); - - DParentNode &parent = *allocator_.construct<DParentNode>(); - parent.id_ = all_parent_nodes.append_and_get_index(&parent); - parent.parent_ = group_node.parent_; - parent.node_ref_ = &group_node_ref; - - this->insert_nodes_and_links_in_id_order(group_ref, &parent, all_nodes); - Span<DNode *> new_nodes_by_id = all_nodes.as_span().take_back(group_ref.nodes().size()); - - this->create_group_inputs_for_unlinked_inputs(group_node, all_group_inputs); - this->relink_group_inputs(group_ref, new_nodes_by_id, group_node); - this->relink_group_outputs(group_ref, new_nodes_by_id, group_node); -} - -BLI_NOINLINE void DerivedNodeTree::create_group_inputs_for_unlinked_inputs( - DNode &node, Vector<DGroupInput *> &all_group_inputs) -{ - for (DInputSocket *input_socket : node.inputs_) { - if (input_socket->is_linked()) { - continue; - } - - DGroupInput &group_input = *allocator_.construct<DGroupInput>(); - group_input.id_ = UNINITIALIZED_ID; - group_input.socket_ref_ = &input_socket->socket_ref(); - group_input.parent_ = node.parent_; - - group_input.linked_sockets_.append(input_socket); - input_socket->linked_group_inputs_.append(&group_input); - all_group_inputs.append(&group_input); - } -} - -BLI_NOINLINE void DerivedNodeTree::relink_group_inputs(const NodeTreeRef &group_ref, - Span<DNode *> nodes_by_id, - DNode &group_node) -{ - Span<const NodeRef *> node_refs = group_ref.nodes_by_type("NodeGroupInput"); - if (node_refs.size() == 0) { - return; - } - /* TODO: Pick correct group input node if there are more than one. */ - const NodeRef &input_node_ref = *node_refs[0]; - DNode &input_node = *nodes_by_id[input_node_ref.id()]; - - uint input_amount = group_node.inputs().size(); - BLI_assert(input_amount == input_node_ref.outputs().size() - 1); - - for (uint input_index : IndexRange(input_amount)) { - DInputSocket *outside_group = group_node.inputs_[input_index]; - DOutputSocket *inside_group = input_node.outputs_[input_index]; - - for (DOutputSocket *outside_connected : outside_group->linked_sockets_) { - outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group); - } - - for (DGroupInput *outside_connected : outside_group->linked_group_inputs_) { - outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group); - } - - for (DInputSocket *inside_connected : inside_group->linked_sockets_) { - inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group); - - for (DOutputSocket *outside_connected : outside_group->linked_sockets_) { - inside_connected->linked_sockets_.append(outside_connected); - outside_connected->linked_sockets_.append(inside_connected); - } - - for (DGroupInput *outside_connected : outside_group->linked_group_inputs_) { - inside_connected->linked_group_inputs_.append(outside_connected); - outside_connected->linked_sockets_.append(inside_connected); - } - } - - inside_group->linked_sockets_.clear(); - outside_group->linked_sockets_.clear(); - outside_group->linked_group_inputs_.clear(); - } -} - -BLI_NOINLINE void DerivedNodeTree::relink_group_outputs(const NodeTreeRef &group_ref, - Span<DNode *> nodes_by_id, - DNode &group_node) -{ - Span<const NodeRef *> node_refs = group_ref.nodes_by_type("NodeGroupOutput"); - if (node_refs.size() == 0) { - return; - } - /* TODO: Pick correct group output node if there are more than one. */ - const NodeRef &output_node_ref = *node_refs[0]; - DNode &output_node = *nodes_by_id[output_node_ref.id()]; - - uint output_amount = group_node.outputs().size(); - BLI_assert(output_amount == output_node_ref.inputs().size() - 1); - - for (uint output_index : IndexRange(output_amount)) { - DOutputSocket *outside_group = group_node.outputs_[output_index]; - DInputSocket *inside_group = output_node.inputs_[output_index]; - - for (DInputSocket *outside_connected : outside_group->linked_sockets_) { - outside_connected->linked_sockets_.remove_first_occurrence_and_reorder(outside_group); - } - - for (DOutputSocket *inside_connected : inside_group->linked_sockets_) { - inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group); - - for (DInputSocket *outside_connected : outside_group->linked_sockets_) { - inside_connected->linked_sockets_.append(outside_connected); - outside_connected->linked_sockets_.append(inside_connected); - } - } - - for (DGroupInput *inside_connected : inside_group->linked_group_inputs_) { - inside_connected->linked_sockets_.remove_first_occurrence_and_reorder(inside_group); - - for (DInputSocket *outside_connected : outside_group->linked_sockets_) { - inside_connected->linked_sockets_.append(outside_connected); - outside_connected->linked_group_inputs_.append(inside_connected); - } - } - - outside_group->linked_sockets_.clear(); - inside_group->linked_sockets_.clear(); - } -} - -BLI_NOINLINE void DerivedNodeTree::remove_expanded_group_interfaces(Vector<DNode *> &all_nodes) -{ - int index = 0; - while (index < all_nodes.size()) { - DNode &node = *all_nodes[index]; - const NodeRef &node_ref = *node.node_ref_; - if (node_ref.is_group_node() || - (node.parent_ != nullptr && - (node_ref.is_group_input_node() || node_ref.is_group_output_node()))) { - all_nodes.remove_and_reorder(index); - node.destruct_with_sockets(); - } - else { - index++; - } - } -} - -BLI_NOINLINE void DerivedNodeTree::remove_unused_group_inputs( - Vector<DGroupInput *> &all_group_inputs) -{ - int index = 0; - while (index < all_group_inputs.size()) { - DGroupInput &group_input = *all_group_inputs[index]; - if (group_input.linked_sockets_.is_empty()) { - all_group_inputs.remove_and_reorder(index); - group_input.~DGroupInput(); - } - else { - index++; - } - } -} - -void DNode::destruct_with_sockets() -{ - for (DInputSocket *socket : inputs_) { - socket->~DInputSocket(); - } - for (DOutputSocket *socket : outputs_) { - socket->~DOutputSocket(); - } - this->~DNode(); -} - -BLI_NOINLINE void DerivedNodeTree::store_in_this_and_init_ids( - Vector<DNode *> &&all_nodes, - Vector<DGroupInput *> &&all_group_inputs, - Vector<DParentNode *> &&all_parent_nodes) -{ - nodes_by_id_ = std::move(all_nodes); - group_inputs_ = std::move(all_group_inputs); - parent_nodes_ = std::move(all_parent_nodes); - - for (uint node_index : nodes_by_id_.index_range()) { - DNode *node = nodes_by_id_[node_index]; - node->id_ = node_index; - - const bNodeType *nodetype = node->node_ref_->bnode()->typeinfo; - nodes_by_type_.lookup_or_add_default(nodetype).append(node); - - for (DInputSocket *socket : node->inputs_) { - socket->id_ = sockets_by_id_.append_and_get_index(socket); - input_sockets_.append(socket); - } - for (DOutputSocket *socket : node->outputs_) { - socket->id_ = sockets_by_id_.append_and_get_index(socket); - output_sockets_.append(socket); - } - } - - for (uint i : group_inputs_.index_range()) { - group_inputs_[i]->id_ = i; - } -} - -DerivedNodeTree::~DerivedNodeTree() -{ - for (DInputSocket *socket : input_sockets_) { - socket->~DInputSocket(); - } - for (DOutputSocket *socket : output_sockets_) { - socket->~DOutputSocket(); - } - for (DNode *node : nodes_by_id_) { - node->~DNode(); - } - for (DGroupInput *group_input : group_inputs_) { - group_input->~DGroupInput(); - } - for (DParentNode *parent : parent_nodes_) { - parent->~DParentNode(); - } -} - -static dot::Cluster *get_cluster_for_parent(dot::DirectedGraph &graph, - Map<const DParentNode *, dot::Cluster *> &clusters, - const DParentNode *parent) -{ - if (parent == nullptr) { - return nullptr; - } - return clusters.lookup_or_add_cb(parent, [&]() { - dot::Cluster *parent_cluster = get_cluster_for_parent(graph, clusters, parent->parent()); - bNodeTree *btree = (bNodeTree *)parent->node_ref().bnode()->id; - dot::Cluster *new_cluster = &graph.new_cluster(parent->node_ref().name() + " / " + - StringRef(btree->id.name + 2)); - new_cluster->set_parent_cluster(parent_cluster); - return new_cluster; - }); -} - -std::string DerivedNodeTree::to_dot() const -{ - dot::DirectedGraph digraph; - digraph.set_rankdir(dot::Attr_rankdir::LeftToRight); - - Map<const DNode *, dot::NodeWithSocketsRef> dot_nodes; - Map<const DGroupInput *, dot::NodeWithSocketsRef> dot_group_inputs; - Map<const DParentNode *, dot::Cluster *> dot_clusters; - - for (const DNode *node : nodes_by_id_) { - dot::Node &dot_node = digraph.new_node(""); - dot_node.set_background_color("white"); - - Vector<std::string> input_names; - for (const DInputSocket *socket : node->inputs()) { - input_names.append(socket->name()); - } - Vector<std::string> output_names; - for (const DOutputSocket *socket : node->outputs()) { - output_names.append(socket->name()); - } - - dot_nodes.add_new(node, - dot::NodeWithSocketsRef(dot_node, node->name(), input_names, output_names)); - - dot::Cluster *cluster = get_cluster_for_parent(digraph, dot_clusters, node->parent()); - dot_node.set_parent_cluster(cluster); - } - - for (const DGroupInput *group_input : group_inputs_) { - dot::Node &dot_node = digraph.new_node(""); - dot_node.set_background_color("white"); - - std::string group_input_name = group_input->name(); - dot_group_inputs.add_new( - group_input, dot::NodeWithSocketsRef(dot_node, "Group Input", {}, {group_input_name})); - - dot::Cluster *cluster = get_cluster_for_parent(digraph, dot_clusters, group_input->parent()); - dot_node.set_parent_cluster(cluster); - } - - for (const DNode *to_node : nodes_by_id_) { - dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(to_node); - - for (const DInputSocket *to_socket : to_node->inputs()) { - for (const DOutputSocket *from_socket : to_socket->linked_sockets()) { - const DNode *from_node = &from_socket->node(); - dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(from_node); - - digraph.new_edge(from_dot_node.output(from_socket->index()), - to_dot_node.input(to_socket->index())); - } - for (const DGroupInput *group_input : to_socket->linked_group_inputs()) { - dot::NodeWithSocketsRef &from_dot_node = dot_group_inputs.lookup(group_input); - - digraph.new_edge(from_dot_node.output(0), to_dot_node.input(to_socket->index())); - } - } - } - - digraph.set_random_cluster_bgcolors(); - return digraph.to_dot_string(); -} - -} // namespace blender::bke diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 2e1fa519284..7b7b7ceb84b 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -588,7 +588,7 @@ static bool boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, const float dist) } /* check whether bounds intersects a point with given radius */ -static bool boundIntersectPoint(Bounds3D *b, float point[3], const float radius) +static bool boundIntersectPoint(Bounds3D *b, const float point[3], const float radius) { if (!b->valid) { return false; @@ -4203,7 +4203,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( brushVelocity[v3].v, weights); - /* substract canvas point velocity */ + /* subtract canvas point velocity */ if (bData->velocity) { sub_v3_v3v3(velocity, brushPointVelocity, bData->velocity[index].v); } @@ -4548,7 +4548,7 @@ static void dynamic_paint_paint_particle_cell_point_cb_ex( ParticleData *pa = psys->particles + part_index; mul_v3_v3fl(velocity, pa->state.vel, particle_timestep); - /* substract canvas point velocity */ + /* subtract canvas point velocity */ if (bData->velocity) { sub_v3_v3(velocity, bData->velocity[index].v); } @@ -4739,7 +4739,7 @@ static void dynamic_paint_paint_single_point_cb_ex(void *__restrict userdata, if (brush->flags & MOD_DPAINT_USES_VELOCITY) { float velocity[3]; - /* substract canvas point velocity */ + /* subtract canvas point velocity */ if (bData->velocity) { sub_v3_v3v3(velocity, brushVelocity->v, bData->velocity[index].v); } @@ -4780,13 +4780,16 @@ static void dynamic_paint_paint_single_point_cb_ex(void *__restrict userdata, } } -static int dynamicPaint_paintSinglePoint(Depsgraph *depsgraph, - DynamicPaintSurface *surface, - float *pointCoord, - DynamicPaintBrushSettings *brush, - Object *brushOb, - Scene *scene, - float timescale) +static int dynamicPaint_paintSinglePoint( + Depsgraph *depsgraph, + DynamicPaintSurface *surface, + /* Cannot be const, because it is assigned to non-const variable. + * NOLINTNEXTLINE: readability-non-const-parameter. */ + float *pointCoord, + DynamicPaintBrushSettings *brush, + Object *brushOb, + Scene *scene, + float timescale) { PaintSurfaceData *sData = surface->data; float brush_radius = brush->paint_distance * surface->radius_scale; @@ -5456,11 +5459,14 @@ static void dynamic_paint_effect_drip_cb(void *__restrict userdata, } } -static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, - float *force, - PaintPoint *prevPoint, - float timescale, - float steps) +static void dynamicPaint_doEffectStep( + DynamicPaintSurface *surface, + /* Cannot be const, because it is assigned to non-const variable. + * NOLINTNEXTLINE: readability-non-const-parameter. */ + float *force, + PaintPoint *prevPoint, + float timescale, + float steps) { PaintSurfaceData *sData = surface->data; diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c index 6fcaf84d4ca..897fc7e692b 100644 --- a/source/blender/blenkernel/intern/editmesh_tangent.c +++ b/source/blender/blenkernel/intern/editmesh_tangent.c @@ -274,8 +274,8 @@ static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), vo /** * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data. * - * \note This function is not so normal, its using `bm->ldata` as input, - * but output's to `dm->loopData`. + * \note This function is not so normal, its using #BMesh.ldata as input, + * but output's to #Mesh.ldata. * This is done because #CD_TANGENT is cache data used only for drawing. */ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em, diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 235c834fde9..a43553ee89f 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -1094,11 +1094,11 @@ void BKE_effectors_apply(ListBase *effectors, * Modifies the force on a particle according to its * relation with the effector object * Different kind of effectors include: - * Forcefields: Gravity-like attractor + * Force-fields: Gravity-like attractor * (force power is related to the inverse of distance to the power of a falloff value) * Vortex fields: swirling effectors * (particles rotate around Z-axis of the object. otherwise, same relation as) - * (Forcefields, but this is not done through a force/acceleration) + * (Force-fields, but this is not done through a force/acceleration) * Guide: particles on a path * (particles are guided along a curve bezier or old nurbs) * (is independent of other effectors) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index bc14f525c2c..acbbf50701a 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1277,7 +1277,7 @@ short test_time_fcurve(FCurve *fcu) * than the horizontal distance between (v1-v4). * This is to prevent curve loops. */ -void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]) +void correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2]) { float h1[2], h2[2], len1, len2, len, fac; @@ -1872,17 +1872,18 @@ float evaluate_fcurve_only_curve(FCurve *fcu, float evaltime) float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, ChannelDriver *driver_orig, - float evaltime) + const AnimationEvalContext *anim_eval_context) { BLI_assert(fcu->driver != NULL); float cvalue = 0.0f; + float evaltime = anim_eval_context->eval_time; /* If there is a driver (only if this F-Curve is acting as 'driver'), * evaluate it to find value to use as "evaltime" since drivers essentially act as alternative * input (i.e. in place of 'time') for F-Curves. */ if (fcu->driver) { /* evaltime now serves as input for the curve */ - evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, evaltime); + evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, anim_eval_context); /* only do a default 1-1 mapping if it's unlikely that anything else will set a value... */ if (fcu->totvert == 0) { @@ -1924,7 +1925,9 @@ bool BKE_fcurve_is_empty(FCurve *fcu) } /* Calculate the value of the given F-Curve at the given frame, and set its curval */ -float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime) +float calculate_fcurve(PathResolvedRNA *anim_rna, + FCurve *fcu, + const AnimationEvalContext *anim_eval_context) { /* only calculate + set curval (overriding the existing value) if curve has * any data which warrants this... @@ -1936,10 +1939,10 @@ float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime) /* calculate and set curval (evaluates driver too if necessary) */ float curval; if (fcu->driver) { - curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, evaltime); + curval = evaluate_fcurve_driver(anim_rna, fcu, fcu->driver, anim_eval_context); } else { - curval = evaluate_fcurve(fcu, evaltime); + curval = evaluate_fcurve(fcu, anim_eval_context->eval_time); } fcu->curval = curval; /* debug display only, not thread safe! */ return curval; diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c index a0625918a62..87cb77930f5 100644 --- a/source/blender/blenkernel/intern/fcurve_driver.c +++ b/source/blender/blenkernel/intern/fcurve_driver.c @@ -21,12 +21,6 @@ * \ingroup bke */ -// #include <float.h> -// #include <math.h> -// #include <stddef.h> -// #include <stdio.h> -// #include <string.h> - #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" @@ -43,6 +37,7 @@ #include "BLT_translation.h" #include "BKE_action.h" +#include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_constraint.h" #include "BKE_fcurve_driver.h" @@ -65,17 +60,19 @@ static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER; static CLG_LogRef LOG = {"bke.fcurve"}; -/* Driver Variables --------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Driver Variables + * \{ */ /* TypeInfo for Driver Variables (dvti) */ typedef struct DriverVarTypeInfo { - /* evaluation callback */ + /* Evaluation callback. */ float (*get_value)(ChannelDriver *driver, DriverVar *dvar); - /* allocation of target slots */ - int num_targets; /* number of target slots required */ - const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */ - short target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */ + /* Allocation of target slots. */ + int num_targets; /* Number of target slots required. */ + const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots. */ + short target_flags[MAX_DRIVER_TARGETS]; /* Flags defining the requirements for each slot. */ } DriverVarTypeInfo; /* Macro to begin definitions */ @@ -84,7 +81,11 @@ typedef struct DriverVarTypeInfo { /* Macro to end definitions */ #define END_DVAR_TYPEDEF } -/* ......... */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Target Utilities + * \{ */ static ID *dtar_id_ensure_proxy_from(ID *id) { @@ -106,14 +107,14 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) int index = -1; float value = 0.0f; - /* sanity check */ + /* Sanity check. */ if (ELEM(NULL, driver, dtar)) { return 0.0f; } id = dtar_id_ensure_proxy_from(dtar->id); - /* error check for missing pointer... */ + /* Error check for missing pointer. */ if (id == NULL) { if (G.debug & G_DEBUG) { CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); @@ -124,12 +125,12 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) return 0.0f; } - /* get RNA-pointer for the ID-block given in target */ + /* Get RNA-pointer for the ID-block given in target. */ RNA_id_pointer_create(id, &id_ptr); - /* get property to read from, and get value as appropriate */ + /* Get property to read from, and get value as appropriate. */ if (!RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { - /* path couldn't be resolved */ + /* Path couldn't be resolved. */ if (G.debug & G_DEBUG) { CLOG_ERROR(&LOG, "Driver Evaluation Error: cannot resolve target for %s -> %s", @@ -143,9 +144,9 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) } if (RNA_property_array_check(prop)) { - /* array */ + /* Array. */ if (index < 0 || index >= RNA_property_array_length(&ptr, prop)) { - /* out of bounds */ + /* Out of bounds. */ if (G.debug & G_DEBUG) { CLOG_ERROR(&LOG, "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)", @@ -174,7 +175,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) } } else { - /* not an array */ + /* Not an array. */ switch (RNA_property_type(prop)) { case PROP_BOOLEAN: value = (float)RNA_property_boolean_get(&ptr, prop); @@ -193,7 +194,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) } } - /* if we're still here, we should be ok... */ + /* If we're still here, we should be ok. */ dtar->flag &= ~DTAR_FLAG_INVALID; return value; } @@ -213,14 +214,14 @@ bool driver_get_variable_property(ChannelDriver *driver, ID *id; int index = -1; - /* sanity check */ + /* Sanity check. */ if (ELEM(NULL, driver, dtar)) { return false; } id = dtar_id_ensure_proxy_from(dtar->id); - /* error check for missing pointer... */ + /* Error check for missing pointer. */ if (id == NULL) { if (G.debug & G_DEBUG) { CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); @@ -231,19 +232,19 @@ bool driver_get_variable_property(ChannelDriver *driver, return false; } - /* get RNA-pointer for the ID-block given in target */ + /* Get RNA-pointer for the ID-block given in target. */ RNA_id_pointer_create(id, &id_ptr); - /* get property to read from, and get value as appropriate */ + /* Get property to read from, and get value as appropriate. */ if (dtar->rna_path == NULL || dtar->rna_path[0] == '\0') { ptr = PointerRNA_NULL; - prop = NULL; /* ok */ + prop = NULL; /* OK. */ } else if (RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { - /* ok */ + /* OK. */ } else { - /* path couldn't be resolved */ + /* Path couldn't be resolved. */ if (G.debug & G_DEBUG) { CLOG_ERROR(&LOG, "Driver Evaluation Error: cannot resolve target for %s -> %s", @@ -264,7 +265,7 @@ bool driver_get_variable_property(ChannelDriver *driver, *r_prop = prop; *r_index = index; - /* if we're still here, we should be ok... */ + /* If we're still here, we should be ok. */ dtar->flag &= ~DTAR_FLAG_INVALID; return true; } @@ -276,14 +277,14 @@ static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar) DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - /* check if this target has valid data */ + /* Check if this target has valid data. */ if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { - /* invalid target, so will not have enough targets */ + /* Invalid target, so will not have enough targets. */ driver->flag |= DRIVER_FLAG_INVALID; dtar->flag |= DTAR_FLAG_INVALID; } else { - /* target seems to be OK now... */ + /* Target seems to be OK now. */ dtar->flag &= ~DTAR_FLAG_INVALID; valid_targets++; } @@ -293,21 +294,25 @@ static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar) return valid_targets; } -/* ......... */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Variable Utilities + * \{ */ -/* evaluate 'single prop' driver variable */ +/* Evaluate 'single prop' driver variable. */ static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar) { - /* just evaluate the first target slot */ + /* Just evaluate the first target slot. */ return dtar_get_prop_val(driver, &dvar->targets[0]); } -/* evaluate 'rotation difference' driver variable */ +/* Evaluate 'rotation difference' driver variable. */ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) { short valid_targets = driver_check_valid_targets(driver, dvar); - /* make sure we have enough valid targets to use - all or nothing for now... */ + /* Make sure we have enough valid targets to use - all or nothing for now. */ if (driver_check_valid_targets(driver, dvar) != 2) { if (G.debug & G_DEBUG) { CLOG_WARN(&LOG, @@ -323,31 +328,31 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) /* NOTE: for now, these are all just worldspace */ for (int i = 0; i < 2; i++) { - /* get pointer to loc values to store in */ + /* Get pointer to loc values to store in. */ DriverTarget *dtar = &dvar->targets[i]; Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); bPoseChannel *pchan; - /* after the checks above, the targets should be valid here... */ + /* After the checks above, the targets should be valid here. */ BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); - /* try to get posechannel */ + /* Try to get pose-channel. */ pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); - /* check if object or bone */ + /* Check if object or bone. */ if (pchan) { - /* bone */ + /* Bone. */ mat[i] = pchan->pose_mat; } else { - /* object */ + /* Object. */ mat[i] = ob->obmat; } } float q1[4], q2[4], quat[4], angle; - /* use the final posed locations */ + /* Use the final posed locations. */ mat4_to_quat(q1, mat[0]); mat4_to_quat(q2, mat[1]); @@ -359,15 +364,18 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle); } -/* evaluate 'location difference' driver variable */ -/* TODO: this needs to take into account space conversions... */ +/** + * Evaluate 'location difference' driver variable. + * + * TODO: this needs to take into account space conversions. + */ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) { float loc1[3] = {0.0f, 0.0f, 0.0f}; float loc2[3] = {0.0f, 0.0f, 0.0f}; short valid_targets = driver_check_valid_targets(driver, dvar); - /* make sure we have enough valid targets to use - all or nothing for now... */ + /* Make sure we have enough valid targets to use - all or nothing for now. */ if (valid_targets < dvar->num_targets) { if (G.debug & G_DEBUG) { CLOG_WARN(&LOG, @@ -380,72 +388,72 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) } /* SECOND PASS: get two location values */ - /* NOTE: for now, these are all just worldspace */ + /* NOTE: for now, these are all just world-space */ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - /* get pointer to loc values to store in */ + /* Get pointer to loc values to store in. */ Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); bPoseChannel *pchan; float tmp_loc[3]; - /* after the checks above, the targets should be valid here... */ + /* After the checks above, the targets should be valid here. */ BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); - /* try to get posechannel */ + /* Try to get pose-channel. */ pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); - /* check if object or bone */ + /* Check if object or bone. */ if (pchan) { - /* bone */ + /* Bone. */ if (dtar->flag & DTAR_FLAG_LOCALSPACE) { if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { float mat[4][4]; - /* extract transform just like how the constraints do it! */ + /* Extract transform just like how the constraints do it! */ copy_m4_m4(mat, pchan->pose_mat); BKE_constraint_mat_convertspace( ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); - /* ... and from that, we get our transform */ + /* ... and from that, we get our transform. */ copy_v3_v3(tmp_loc, mat[3]); } else { - /* transform space (use transform values directly) */ + /* Transform space (use transform values directly). */ copy_v3_v3(tmp_loc, pchan->loc); } } else { - /* convert to worldspace */ + /* Convert to worldspace. */ copy_v3_v3(tmp_loc, pchan->pose_head); mul_m4_v3(ob->obmat, tmp_loc); } } else { - /* object */ + /* Object. */ if (dtar->flag & DTAR_FLAG_LOCALSPACE) { if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* XXX: this should practically be the same as transform space... */ + /* XXX: this should practically be the same as transform space. */ float mat[4][4]; - /* extract transform just like how the constraints do it! */ + /* Extract transform just like how the constraints do it! */ copy_m4_m4(mat, ob->obmat); BKE_constraint_mat_convertspace( ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); - /* ... and from that, we get our transform */ + /* ... and from that, we get our transform. */ copy_v3_v3(tmp_loc, mat[3]); } else { - /* transform space (use transform values directly) */ + /* Transform space (use transform values directly). */ copy_v3_v3(tmp_loc, ob->loc); } } else { - /* worldspace */ + /* World-space. */ copy_v3_v3(tmp_loc, ob->obmat[3]); } } - /* copy the location to the right place */ + /* Copy the location to the right place. */ if (tarIndex) { copy_v3_v3(loc2, tmp_loc); } @@ -455,13 +463,14 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) } DRIVER_TARGETS_LOOPER_END; - /* if we're still here, there should now be two targets to use, - * so just take the length of the vector between these points - */ + /* If we're still here, there should now be two targets to use, + * so just take the length of the vector between these points. */ return len_v3v3(loc1, loc2); } -/* evaluate 'transform channel' driver variable */ +/** + * Evaluate 'transform channel' driver variable. + */ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) { DriverTarget *dtar = &dvar->targets[0]; @@ -472,15 +481,15 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) bool use_eulers = false; short rot_order = ROT_MODE_EUL; - /* check if this target has valid data */ + /* Check if this target has valid data. */ if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { - /* invalid target, so will not have enough targets */ + /* Invalid target, so will not have enough targets. */ driver->flag |= DRIVER_FLAG_INVALID; dtar->flag |= DTAR_FLAG_INVALID; return 0.0f; } else { - /* target should be valid now */ + /* Target should be valid now. */ dtar->flag &= ~DTAR_FLAG_INVALID; } @@ -494,7 +503,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) * but #DTAR_FLAG_LOCAL_CONSTS is for all the common "corrective-shapes-for-limbs" situations. */ if (pchan) { - /* bone */ + /* Bone. */ if (pchan->rotmode > 0) { copy_v3_v3(oldEul, pchan->eul); rot_order = pchan->rotmode; @@ -503,16 +512,15 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) if (dtar->flag & DTAR_FLAG_LOCALSPACE) { if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* just like how the constraints do it! */ + /* Just like how the constraints do it! */ copy_m4_m4(mat, pchan->pose_mat); BKE_constraint_mat_convertspace( ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); } else { - /* specially calculate local matrix, since chan_mat is not valid + /* Specially calculate local matrix, since chan_mat is not valid * since it stores delta transform of pose_mat so that deforms work - * so it cannot be used here for "transform" space - */ + * so it cannot be used here for "transform" space. */ BKE_pchan_to_mat4(pchan, mat); } } @@ -522,7 +530,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) } } else { - /* object */ + /* Object. */ if (ob->rotmode > 0) { copy_v3_v3(oldEul, ob->rot); rot_order = ob->rotmode; @@ -531,25 +539,25 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) if (dtar->flag & DTAR_FLAG_LOCALSPACE) { if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* just like how the constraints do it! */ + /* Just like how the constraints do it! */ copy_m4_m4(mat, ob->obmat); BKE_constraint_mat_convertspace( ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); } else { - /* transforms to matrix */ + /* Transforms to matrix. */ BKE_object_to_mat4(ob, mat); } } else { - /* worldspace matrix - just the good-old one */ + /* World-space matrix - just the good-old one. */ copy_m4_m4(mat, ob->obmat); } } - /* check which transform */ + /* Check which transform. */ if (dtar->transChan >= MAX_DTAR_TRANSCHAN_TYPES) { - /* not valid channel */ + /* Not valid channel. */ return 0.0f; } else if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) { @@ -566,7 +574,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]); } else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) { - /* extract rotation as eulers (if needed) + /* Extract rotation as eulers (if needed) * - definitely if rotation order isn't eulers already * - if eulers, then we have 2 options: * a) decompose transform matrix as required, then try to make eulers from @@ -595,7 +603,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) return quat[channel]; } else { - /* extract location and choose right axis */ + /* Extract location and choose right axis. */ return mat[3][dtar->transChan]; } } @@ -665,41 +673,45 @@ void BKE_driver_target_matrix_to_rot_channels( } } -/* ......... */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Variable Type Info + * \{ */ /* Table of Driver Variable Type Info Data */ static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP) dvar_eval_singleProp, /* eval callback */ - 1, /* number of targets used */ + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP) dvar_eval_singleProp, /* Eval callback. */ + 1, /* Number of targets used. */ {"Property"}, /* UI names for targets */ - {0} /* flags */ + {0} /* Flags. */ END_DVAR_TYPEDEF, - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF) dvar_eval_rotDiff, /* eval callback */ - 2, /* number of targets used */ + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF) dvar_eval_rotDiff, /* Eval callback. */ + 2, /* Number of targets used. */ {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, - DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* Flags. */ END_DVAR_TYPEDEF, - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_LOC_DIFF) dvar_eval_locDiff, /* eval callback */ - 2, /* number of targets used */ + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_LOC_DIFF) dvar_eval_locDiff, /* Eval callback. */ + 2, /* Number of targets used. */ {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, - DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* Flags. */ END_DVAR_TYPEDEF, - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_TRANSFORM_CHAN) dvar_eval_transChan, /* eval callback */ - 1, /* number of targets used */ + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_TRANSFORM_CHAN) dvar_eval_transChan, /* Eval callback. */ + 1, /* Number of targets used. */ {"Object/Bone"}, /* UI names for targets */ - {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* Flags. */ END_DVAR_TYPEDEF, }; /* Get driver variable typeinfo */ static const DriverVarTypeInfo *get_dvar_typeinfo(int type) { - /* check if valid type */ + /* Check if valid type. */ if ((type >= 0) && (type < MAX_DVAR_TYPES)) { return &dvar_types[type]; } @@ -708,40 +720,44 @@ static const DriverVarTypeInfo *get_dvar_typeinfo(int type) } } -/* Driver API --------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver API + * \{ */ /* Perform actual freeing driver variable and remove it from the given list */ void driver_free_variable(ListBase *variables, DriverVar *dvar) { - /* sanity checks */ + /* Sanity checks. */ if (dvar == NULL) { return; } - /* free target vars + /* Free target vars: * - need to go over all of them, not just up to the ones that are used * currently, since there may be some lingering RNA paths from * previous users needing freeing */ DRIVER_TARGETS_LOOPER_BEGIN (dvar) { - /* free RNA path if applicable */ + /* Free RNA path if applicable. */ if (dtar->rna_path) { MEM_freeN(dtar->rna_path); } } DRIVER_TARGETS_LOOPER_END; - /* remove the variable from the driver */ + /* Remove the variable from the driver. */ BLI_freelinkN(variables, dvar); } /* Free the driver variable and do extra updates */ void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar) { - /* remove and free the driver variable */ + /* Remove and free the driver variable. */ driver_free_variable(&driver->variables, dvar); - /* since driver variables are cached, the expression needs re-compiling too */ + /* Since driver variables are cached, the expression needs re-compiling too. */ BKE_driver_invalidate_expression(driver, false, true); } @@ -752,9 +768,9 @@ void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars) BLI_duplicatelist(dst_vars, src_vars); LISTBASE_FOREACH (DriverVar *, dvar, dst_vars) { - /* need to go over all targets so that we don't leave any dangling paths */ + /* Need to go over all targets so that we don't leave any dangling paths. */ DRIVER_TARGETS_LOOPER_BEGIN (dvar) { - /* make a copy of target's rna path if available */ + /* Make a copy of target's rna path if available. */ if (dtar->rna_path) { dtar->rna_path = MEM_dupallocN(dtar->rna_path); } @@ -768,25 +784,24 @@ void driver_change_variable_type(DriverVar *dvar, int type) { const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type); - /* sanity check */ + /* Sanity check. */ if (ELEM(NULL, dvar, dvti)) { return; } - /* set the new settings */ + /* Set the new settings. */ dvar->type = type; dvar->num_targets = dvti->num_targets; - /* make changes to the targets based on the defines for these types - * NOTE: only need to make sure the ones we're using here are valid... - */ + /* Make changes to the targets based on the defines for these types. + * NOTE: only need to make sure the ones we're using here are valid. */ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { short flags = dvti->target_flags[tarIndex]; - /* store the flags */ + /* Store the flags. */ dtar->flag = flags; - /* object ID types only, or idtype not yet initialized */ + /* Object ID types only, or idtype not yet initialized. */ if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0)) { dtar->idtype = ID_OB; } @@ -803,12 +818,12 @@ void driver_variable_name_validate(DriverVar *dvar) '?', ':', ';', '<', '>', '{', '}', '[', ']', '|', ' ', '.', '\t', '\n', '\r', }; - /* sanity checks */ + /* Sanity checks. */ if (dvar == NULL) { return; } - /* clear all invalid-name flags */ + /* Clear all invalid-name flags. */ dvar->flag &= ~DVAR_ALL_INVALID_FLAGS; /* 0) Zero-length identifiers are not allowed */ @@ -869,16 +884,16 @@ DriverVar *driver_add_new_variable(ChannelDriver *driver) { DriverVar *dvar; - /* sanity checks */ + /* Sanity checks. */ if (driver == NULL) { return NULL; } - /* make a new variable */ + /* Make a new variable. */ dvar = MEM_callocN(sizeof(DriverVar), "DriverVar"); BLI_addtail(&driver->variables, dvar); - /* give the variable a 'unique' name */ + /* Give the variable a 'unique' name. */ strcpy(dvar->name, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var")); BLI_uniquename(&driver->variables, dvar, @@ -887,13 +902,13 @@ DriverVar *driver_add_new_variable(ChannelDriver *driver) offsetof(DriverVar, name), sizeof(dvar->name)); - /* set the default type to 'single prop' */ + /* Set the default type to 'single prop'. */ driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP); - /* since driver variables are cached, the expression needs re-compiling too */ + /* Since driver variables are cached, the expression needs re-compiling too. */ BKE_driver_invalidate_expression(driver, false, true); - /* return the target */ + /* Return the target. */ return dvar; } @@ -903,20 +918,20 @@ void fcurve_free_driver(FCurve *fcu) ChannelDriver *driver; DriverVar *dvar, *dvarn; - /* sanity checks */ + /* Sanity checks. */ if (ELEM(NULL, fcu, fcu->driver)) { return; } driver = fcu->driver; - /* free driver targets */ + /* Free driver targets. */ for (dvar = driver->variables.first; dvar; dvar = dvarn) { dvarn = dvar->next; driver_free_variable_ex(driver, dvar); } #ifdef WITH_PYTHON - /* free compiled driver expression */ + /* Free compiled driver expression. */ if (driver->expr_comp) { BPY_DECREF(driver->expr_comp); } @@ -935,27 +950,31 @@ ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver) { ChannelDriver *ndriver; - /* sanity checks */ + /* Sanity checks. */ if (driver == NULL) { return NULL; } - /* copy all data */ + /* Copy all data. */ ndriver = MEM_dupallocN(driver); ndriver->expr_comp = NULL; ndriver->expr_simple = NULL; - /* copy variables */ + /* Copy variables. */ - /* to get rid of refs to non-copied data (that's still used on original) */ + /* To get rid of refs to non-copied data (that's still used on original). */ BLI_listbase_clear(&ndriver->variables); driver_variables_copy(&ndriver->variables, &driver->variables); - /* return the new driver */ + /* Return the new driver. */ return ndriver; } -/* Driver Expression Evaluation --------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Expression Evaluation + * \{ */ /* Index constants for the expression parameter array. */ enum { @@ -1025,7 +1044,7 @@ static bool driver_evaluate_simple_expr(ChannelDriver *driver, return true; default: - /* arriving here means a bug, not user error */ + /* Arriving here means a bug, not user error. */ CLOG_ERROR(&LOG, "simple driver expression evaluation failed: '%s'", driver->expression); return false; } @@ -1134,22 +1153,25 @@ void BKE_driver_invalidate_expression(ChannelDriver *driver, #endif } -/* Driver Evaluation -------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Evaluation + * \{ */ /* Evaluate a Driver Variable to get a value that contributes to the final */ float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar) { const DriverVarTypeInfo *dvti; - /* sanity check */ + /* Sanity check. */ if (ELEM(NULL, driver, dvar)) { return 0.0f; } - /* call the relevant callbacks to get the variable value + /* Call the relevant callbacks to get the variable value * using the variable type info, storing the obtained value - * in dvar->curval so that drivers can be debugged - */ + * in `dvar->curval` so that drivers can be debugged. */ dvti = get_dvar_typeinfo(dvar->type); if (dvti && dvti->get_value) { @@ -1166,25 +1188,25 @@ static void evaluate_driver_sum(ChannelDriver *driver) { DriverVar *dvar; - /* check how many variables there are first (i.e. just one?) */ + /* Check how many variables there are first (i.e. just one?). */ if (BLI_listbase_is_single(&driver->variables)) { - /* just one target, so just use that */ + /* Just one target, so just use that. */ dvar = driver->variables.first; driver->curval = driver_get_variable_value(driver, dvar); return; } - /* more than one target, so average the values of the targets */ + /* More than one target, so average the values of the targets. */ float value = 0.0f; int tot = 0; - /* loop through targets, adding (hopefully we don't get any overflow!) */ + /* Loop through targets, adding (hopefully we don't get any overflow!). */ for (dvar = driver->variables.first; dvar; dvar = dvar->next) { value += driver_get_variable_value(driver, dvar); tot++; } - /* perform operations on the total if appropriate */ + /* Perform operations on the total if appropriate. */ if (driver->type == DRIVER_TYPE_AVERAGE) { driver->curval = tot ? (value / (float)tot) : 0.0f; } @@ -1198,97 +1220,99 @@ static void evaluate_driver_min_max(ChannelDriver *driver) DriverVar *dvar; float value = 0.0f; - /* loop through the variables, getting the values and comparing them to existing ones */ + /* Loop through the variables, getting the values and comparing them to existing ones. */ for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - /* get value */ + /* Get value. */ float tmp_val = driver_get_variable_value(driver, dvar); - /* store this value if appropriate */ + /* Store this value if appropriate. */ if (dvar->prev) { - /* check if greater/smaller than the baseline */ + /* Check if greater/smaller than the baseline. */ if (driver->type == DRIVER_TYPE_MAX) { - /* max? */ + /* Max? */ if (tmp_val > value) { value = tmp_val; } } else { - /* min? */ + /* Min? */ if (tmp_val < value) { value = tmp_val; } } } else { - /* first item - make this the baseline for comparisons */ + /* First item - make this the baseline for comparisons. */ value = tmp_val; } } - /* store value in driver */ + /* Store value in driver. */ driver->curval = value; } static void evaluate_driver_python(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, - const float evaltime) + const AnimationEvalContext *anim_eval_context) { - /* check for empty or invalid expression */ + /* Check for empty or invalid expression. */ if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) { driver->curval = 0.0f; } - else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) { + else if (!driver_try_evaluate_simple_expr( + driver, driver_orig, &driver->curval, anim_eval_context->eval_time)) { #ifdef WITH_PYTHON - /* this evaluates the expression using Python, and returns its result: - * - on errors it reports, then returns 0.0f - */ + /* This evaluates the expression using Python, and returns its result: + * - on errors it reports, then returns 0.0f. */ BLI_mutex_lock(&python_driver_lock); - driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime); + driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, anim_eval_context); BLI_mutex_unlock(&python_driver_lock); -#else /* WITH_PYTHON*/ - UNUSED_VARS(anim_rna, evaltime); -#endif /* WITH_PYTHON*/ +#else /* WITH_PYTHON */ + UNUSED_VARS(anim_rna, anim_eval_context); +#endif /* WITH_PYTHON */ } } -/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime" - * - "evaltime" is the frame at which F-Curve is being evaluated - * - has to return a float value - * - driver_orig is where we cache Python expressions, in case of COW +/** + * Evaluate an Channel-Driver to get a 'time' value to use + * instead of `anim_eval_context->eval_time`. + * + * - `anim_eval_context->eval_time` is the frame at which F-Curve is being evaluated. + * - Has to return a float value. + * - \a driver_orig is where we cache Python expressions, in case of COW */ float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, ChannelDriver *driver_orig, - const float evaltime) + const AnimationEvalContext *anim_eval_context) { - /* check if driver can be evaluated */ + /* Check if driver can be evaluated. */ if (driver_orig->flag & DRIVER_FLAG_INVALID) { return 0.0f; } switch (driver->type) { - case DRIVER_TYPE_AVERAGE: /* average values of driver targets */ - case DRIVER_TYPE_SUM: /* sum values of driver targets */ + case DRIVER_TYPE_AVERAGE: /* Average values of driver targets. */ + case DRIVER_TYPE_SUM: /* Sum values of driver targets. */ evaluate_driver_sum(driver); break; - case DRIVER_TYPE_MIN: /* smallest value */ - case DRIVER_TYPE_MAX: /* largest value */ + case DRIVER_TYPE_MIN: /* Smallest value. */ + case DRIVER_TYPE_MAX: /* Largest value. */ evaluate_driver_min_max(driver); break; - case DRIVER_TYPE_PYTHON: /* expression */ - evaluate_driver_python(anim_rna, driver, driver_orig, evaltime); + case DRIVER_TYPE_PYTHON: /* Expression. */ + evaluate_driver_python(anim_rna, driver, driver_orig, anim_eval_context); break; default: - /* special 'hack' - just use stored value + /* Special 'hack' - just use stored value * This is currently used as the mechanism which allows animated settings to be able - * to be changed via the UI. - */ + * to be changed via the UI. */ break; } - /* return value for driver */ + /* Return value for driver. */ return driver->curval; } diff --git a/source/blender/blenkernel/intern/fcurve_test.cc b/source/blender/blenkernel/intern/fcurve_test.cc new file mode 100644 index 00000000000..a6f65a7c9b3 --- /dev/null +++ b/source/blender/blenkernel/intern/fcurve_test.cc @@ -0,0 +1,213 @@ +/* + * 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. + */ +#include "testing/testing.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_fcurve.h" + +#include "ED_keyframing.h" + +#include "DNA_anim_types.h" + +namespace blender::bke::tests { + +// Epsilon for floating point comparisons. +static const float EPSILON = 1e-7f; + +TEST(evaluate_fcurve, EmptyFCurve) +{ + FCurve *fcu = BKE_fcurve_create(); + EXPECT_EQ(evaluate_fcurve(fcu, 47.0f), 0.0f); + BKE_fcurve_free(fcu); +} + +TEST(evaluate_fcurve, OnKeys) +{ + FCurve *fcu = BKE_fcurve_create(); + + insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF); + insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF); + insert_vert_fcurve(fcu, 3.0f, 19.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF); + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.0f), 7.0f, EPSILON); // hits 'on or before first' function + EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f), 13.0f, EPSILON); // hits 'between' function + EXPECT_NEAR(evaluate_fcurve(fcu, 3.0f), 19.0f, EPSILON); // hits 'on or after last' function + + /* Also test within a specific time epsilon of the keys, as this was an issue in T39207. + * This epsilon is just slightly smaller than the epsilon given to binarysearch_bezt_index_ex() + * in fcurve_eval_between_keyframes(), so it should hit the "exact" code path. */ + float time_epsilon = 0.00008f; + EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f - time_epsilon), 13.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f + time_epsilon), 13.0f, EPSILON); + + BKE_fcurve_free(fcu); +} + +TEST(evaluate_fcurve, InterpolationConstant) +{ + FCurve *fcu = BKE_fcurve_create(); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].ipo = BEZT_IPO_CONST; + fcu->bezt[1].ipo = BEZT_IPO_CONST; + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 7.0f, EPSILON); + + BKE_fcurve_free(fcu); +} + +TEST(evaluate_fcurve, InterpolationLinear) +{ + FCurve *fcu = BKE_fcurve_create(); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].ipo = BEZT_IPO_LIN; + fcu->bezt[1].ipo = BEZT_IPO_LIN; + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 8.5f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 10.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 11.5f, EPSILON); + + BKE_fcurve_free(fcu); +} + +TEST(evaluate_fcurve, InterpolationBezier) +{ + FCurve *fcu = BKE_fcurve_create(); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + EXPECT_EQ(fcu->bezt[0].ipo, BEZT_IPO_BEZ); + EXPECT_EQ(fcu->bezt[1].ipo, BEZT_IPO_BEZ); + + // Test with default handles. + EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.8297067f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 10.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 12.170294f, EPSILON); + + // Test with modified handles. + fcu->bezt[0].vec[0][0] = 0.71855f; // left handle X + fcu->bezt[0].vec[0][1] = 6.22482f; // left handle Y + fcu->bezt[0].vec[2][0] = 1.35148f; // right handle X + fcu->bezt[0].vec[2][1] = 7.96806f; // right handle Y + + fcu->bezt[1].vec[0][0] = 1.66667f; // left handle X + fcu->bezt[1].vec[0][1] = 10.4136f; // left handle Y + fcu->bezt[1].vec[2][0] = 2.33333f; // right handle X + fcu->bezt[1].vec[2][1] = 15.5864f; // right handle Y + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.945497f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 9.3495407f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 11.088551f, EPSILON); + + BKE_fcurve_free(fcu); +} + +TEST(evaluate_fcurve, InterpolationBounce) +{ + FCurve *fcu = BKE_fcurve_create(); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].ipo = BEZT_IPO_BOUNCE; + fcu->bezt[1].ipo = BEZT_IPO_BOUNCE; + + fcu->bezt[0].easing = BEZT_IPO_EASE_IN; + fcu->bezt[1].easing = BEZT_IPO_EASE_AUTO; + + EXPECT_NEAR(evaluate_fcurve(fcu, 1.4f), 8.3649998f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.5f), 8.4062500f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 1.8f), 11.184999f, EPSILON); + + BKE_fcurve_free(fcu); +} + +TEST(evaluate_fcurve, ExtrapolationLinearKeys) +{ + FCurve *fcu = BKE_fcurve_create(); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + fcu->bezt[0].ipo = BEZT_IPO_LIN; + fcu->bezt[1].ipo = BEZT_IPO_LIN; + + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + // Before first keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 5.5f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 0.50f), 4.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), -8.0f, EPSILON); + // After last keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 17.5f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 22.0f, EPSILON); + + fcu->extend = FCURVE_EXTRAPOLATE_CONSTANT; + // Before first keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 7.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), 7.0f, EPSILON); + // After last keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 13.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 13.0f, EPSILON); + + BKE_fcurve_free(fcu); +} + +TEST(evaluate_fcurve, ExtrapolationBezierKeys) +{ + FCurve *fcu = BKE_fcurve_create(); + + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].vec[0][0] = 0.71855f; // left handle X + fcu->bezt[0].vec[0][1] = 6.22482f; // left handle Y + fcu->bezt[0].vec[2][0] = 1.35148f; // right handle X + fcu->bezt[0].vec[2][1] = 7.96806f; // right handle Y + + fcu->bezt[1].vec[0][0] = 1.66667f; // left handle X + fcu->bezt[1].vec[0][1] = 10.4136f; // left handle Y + fcu->bezt[1].vec[2][0] = 2.33333f; // right handle X + fcu->bezt[1].vec[2][1] = 15.5864f; // right handle Y + + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + // Before first keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 6.3114409f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, -0.50f), 2.8686447f, EPSILON); + // After last keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 18.81946f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 24.63892f, EPSILON); + + fcu->extend = FCURVE_EXTRAPOLATE_CONSTANT; + // Before first keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 7.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), 7.0f, EPSILON); + // After last keyframe. + EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 13.0f, EPSILON); + EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 13.0f, EPSILON); + + BKE_fcurve_free(fcu); +} + +} // namespace blender::bke::tests diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 1f748487841..2245af31f0d 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -137,109 +137,84 @@ bool BKE_fluid_reallocate_fluid(FluidDomainSettings *fds, int res[3], int free_o void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds, int o_res[3], int n_res[3], - int o_min[3], - int n_min[3], - int o_max[3], + const int o_min[3], + const int n_min[3], + const int o_max[3], int o_shift[3], int n_shift[3]) { - int x, y, z; struct MANTA *fluid_old = fds->fluid; const int block_size = fds->noise_scale; int new_shift[3] = {0}; sub_v3_v3v3_int(new_shift, n_shift, o_shift); - /* allocate new fluid data */ + /* Allocate new fluid data. */ BKE_fluid_reallocate_fluid(fds, n_res, 0); int o_total_cells = o_res[0] * o_res[1] * o_res[2]; int n_total_cells = n_res[0] * n_res[1] * n_res[2]; - /* boundary cells will be skipped when copying data */ - int bwidth = fds->boundary_width; - - /* copy values from old fluid to new */ + /* Copy values from old fluid to new fluid object. */ if (o_total_cells > 1 && n_total_cells > 1) { - /* base smoke */ - float *o_dens, *o_react, *o_flame, *o_fuel, *o_heat, *o_vx, *o_vy, *o_vz, *o_r, *o_g, *o_b; - float *n_dens, *n_react, *n_flame, *n_fuel, *n_heat, *n_vx, *n_vy, *n_vz, *n_r, *n_g, *n_b; - float dummy, *dummy_s; - int *dummy_p; - /* noise smoke */ + float *o_dens = manta_smoke_get_density(fluid_old); + float *o_react = manta_smoke_get_react(fluid_old); + float *o_flame = manta_smoke_get_flame(fluid_old); + float *o_fuel = manta_smoke_get_fuel(fluid_old); + float *o_heat = manta_smoke_get_heat(fluid_old); + float *o_vx = manta_get_velocity_x(fluid_old); + float *o_vy = manta_get_velocity_y(fluid_old); + float *o_vz = manta_get_velocity_z(fluid_old); + float *o_r = manta_smoke_get_color_r(fluid_old); + float *o_g = manta_smoke_get_color_g(fluid_old); + float *o_b = manta_smoke_get_color_b(fluid_old); + + float *n_dens = manta_smoke_get_density(fds->fluid); + float *n_react = manta_smoke_get_react(fds->fluid); + float *n_flame = manta_smoke_get_flame(fds->fluid); + float *n_fuel = manta_smoke_get_fuel(fds->fluid); + float *n_heat = manta_smoke_get_heat(fds->fluid); + float *n_vx = manta_get_velocity_x(fds->fluid); + float *n_vy = manta_get_velocity_y(fds->fluid); + float *n_vz = manta_get_velocity_z(fds->fluid); + float *n_r = manta_smoke_get_color_r(fds->fluid); + float *n_g = manta_smoke_get_color_g(fds->fluid); + float *n_b = manta_smoke_get_color_b(fds->fluid); + + /* Noise smoke fields. */ int wt_res_old[3]; - float *o_wt_dens, *o_wt_react, *o_wt_flame, *o_wt_fuel, *o_wt_tcu, *o_wt_tcv, *o_wt_tcw, - *o_wt_tcu2, *o_wt_tcv2, *o_wt_tcw2, *o_wt_r, *o_wt_g, *o_wt_b; - float *n_wt_dens, *n_wt_react, *n_wt_flame, *n_wt_fuel, *n_wt_tcu, *n_wt_tcv, *n_wt_tcw, - *n_wt_tcu2, *n_wt_tcv2, *n_wt_tcw2, *n_wt_r, *n_wt_g, *n_wt_b; - - if (fds->flags & FLUID_DOMAIN_USE_NOISE) { - manta_smoke_turbulence_export(fluid_old, - &o_wt_dens, - &o_wt_react, - &o_wt_flame, - &o_wt_fuel, - &o_wt_r, - &o_wt_g, - &o_wt_b, - &o_wt_tcu, - &o_wt_tcv, - &o_wt_tcw, - &o_wt_tcu2, - &o_wt_tcv2, - &o_wt_tcw2); - manta_smoke_turbulence_get_res(fluid_old, wt_res_old); - manta_smoke_turbulence_export(fds->fluid, - &n_wt_dens, - &n_wt_react, - &n_wt_flame, - &n_wt_fuel, - &n_wt_r, - &n_wt_g, - &n_wt_b, - &n_wt_tcu, - &n_wt_tcv, - &n_wt_tcw, - &n_wt_tcu2, - &n_wt_tcv2, - &n_wt_tcw2); - } - - manta_smoke_export(fluid_old, - &dummy, - &dummy, - &o_dens, - &o_react, - &o_flame, - &o_fuel, - &o_heat, - &o_vx, - &o_vy, - &o_vz, - &o_r, - &o_g, - &o_b, - &dummy_p, - &dummy_s); - manta_smoke_export(fds->fluid, - &dummy, - &dummy, - &n_dens, - &n_react, - &n_flame, - &n_fuel, - &n_heat, - &n_vx, - &n_vy, - &n_vz, - &n_r, - &n_g, - &n_b, - &dummy_p, - &dummy_s); - - for (x = o_min[0]; x < o_max[0]; x++) { - for (y = o_min[1]; y < o_max[1]; y++) { - for (z = o_min[2]; z < o_max[2]; z++) { + float *o_wt_dens = manta_noise_get_density(fluid_old); + float *o_wt_react = manta_noise_get_react(fluid_old); + float *o_wt_flame = manta_noise_get_flame(fluid_old); + float *o_wt_fuel = manta_noise_get_fuel(fluid_old); + float *o_wt_r = manta_noise_get_color_r(fluid_old); + float *o_wt_g = manta_noise_get_color_g(fluid_old); + float *o_wt_b = manta_noise_get_color_b(fluid_old); + float *o_wt_tcu = manta_noise_get_texture_u(fluid_old); + float *o_wt_tcv = manta_noise_get_texture_v(fluid_old); + float *o_wt_tcw = manta_noise_get_texture_w(fluid_old); + float *o_wt_tcu2 = manta_noise_get_texture_u2(fluid_old); + float *o_wt_tcv2 = manta_noise_get_texture_v2(fluid_old); + float *o_wt_tcw2 = manta_noise_get_texture_w2(fluid_old); + + float *n_wt_dens = manta_noise_get_density(fds->fluid); + float *n_wt_react = manta_noise_get_react(fds->fluid); + float *n_wt_flame = manta_noise_get_flame(fds->fluid); + float *n_wt_fuel = manta_noise_get_fuel(fds->fluid); + float *n_wt_r = manta_noise_get_color_r(fds->fluid); + float *n_wt_g = manta_noise_get_color_g(fds->fluid); + float *n_wt_b = manta_noise_get_color_b(fds->fluid); + float *n_wt_tcu = manta_noise_get_texture_u(fds->fluid); + float *n_wt_tcv = manta_noise_get_texture_v(fds->fluid); + float *n_wt_tcw = manta_noise_get_texture_w(fds->fluid); + float *n_wt_tcu2 = manta_noise_get_texture_u2(fds->fluid); + float *n_wt_tcv2 = manta_noise_get_texture_v2(fds->fluid); + float *n_wt_tcw2 = manta_noise_get_texture_w2(fds->fluid); + + manta_noise_get_res(fluid_old, wt_res_old); + + for (int z = o_min[2]; z < o_max[2]; z++) { + for (int y = o_min[1]; y < o_max[1]; y++) { + for (int x = o_min[0]; x < o_max[0]; x++) { /* old grid index */ int xo = x - o_min[0]; int yo = y - o_min[1]; @@ -251,20 +226,31 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds, int zn = z - n_min[2] - new_shift[2]; int index_new = manta_get_index(xn, n_res[0], yn, n_res[1], zn); - /* skip if outside new domain */ + /* Skip if outside new domain. */ if (xn < 0 || xn >= n_res[0] || yn < 0 || yn >= n_res[1] || zn < 0 || zn >= n_res[2]) { continue; } - /* skip if trying to copy from old boundary cell */ +# if 0 + /* Note (sebbas): + * Disabling this "skip section" as not copying borders results in weird cut-off effects. + * It is possible that this cutting off is the reason for line effects as seen in T74559. + * Since domain borders will be handled on the simulation side anyways, + * copying border values should not be an issue. */ + + /* boundary cells will be skipped when copying data */ + int bwidth = fds->boundary_width; + + /* Skip if trying to copy from old boundary cell. */ if (xo < bwidth || yo < bwidth || zo < bwidth || xo >= o_res[0] - bwidth || yo >= o_res[1] - bwidth || zo >= o_res[2] - bwidth) { continue; } - /* skip if trying to copy into new boundary cell */ + /* Skip if trying to copy into new boundary cell. */ if (xn < bwidth || yn < bwidth || zn < bwidth || xn >= n_res[0] - bwidth || yn >= n_res[1] - bwidth || zn >= n_res[2] - bwidth) { continue; } +# endif /* copy data */ if (fds->flags & FLUID_DOMAIN_USE_NOISE) { @@ -491,6 +477,17 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *fds, fds->cell_size[2] /= (float)fds->base_res[2]; } +static void update_final_gravity(FluidDomainSettings *fds, Scene *scene) +{ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(fds->gravity_final, scene->physics_settings.gravity); + } + else { + copy_v3_v3(fds->gravity_final, fds->gravity); + } + mul_v3_fl(fds->gravity_final, fds->effector_weights->global_gravity); +} + static bool BKE_fluid_modifier_init( FluidModifierData *fmd, Depsgraph *depsgraph, Object *ob, Scene *scene, Mesh *me) { @@ -502,10 +499,7 @@ static bool BKE_fluid_modifier_init( /* Set domain dimensions from mesh. */ manta_set_domain_from_mesh(fds, ob, me, true); /* Set domain gravity, use global gravity if enabled. */ - if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { - copy_v3_v3(fds->gravity, scene->physics_settings.gravity); - } - mul_v3_fl(fds->gravity, fds->effector_weights->global_gravity); + update_final_gravity(fds, scene); /* Reset domain values. */ zero_v3_int(fds->shift); zero_v3(fds->shift_f); @@ -559,7 +553,7 @@ static bool BKE_fluid_modifier_init( // forward declaration static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *view_layer); static float calc_voxel_transp( - float *result, float *input, int res[3], int *pixel, float *t_ray, float correct); + float *result, const float *input, int res[3], int *pixel, float *t_ray, float correct); static void update_distances(int index, float *fesh_distances, BVHTreeFromMesh *tree_data, @@ -594,8 +588,8 @@ static int get_light(ViewLayer *view_layer, float *light) static void clamp_bounds_in_domain(FluidDomainSettings *fds, int min[3], int max[3], - float *min_vel, - float *max_vel, + const float *min_vel, + const float *max_vel, int margin, float dt) { @@ -1125,6 +1119,7 @@ static void ensure_obstaclefields(FluidDomainSettings *fds) if (fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE) { manta_ensure_guiding(fds->fluid, fds->fmd); } + manta_update_pointers(fds->fluid, fds->fmd, false); } static void update_obstacleflags(FluidDomainSettings *fds, @@ -1398,8 +1393,7 @@ static void update_obstacles(Depsgraph *depsgraph, /* Cannot use static mode with adaptive domain. * The adaptive domain might expand and only later in the simulations discover the static * object. */ - bool is_static = is_static_object(effecobj) && - ((fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) == 0); + bool is_static = is_static_object(effecobj) && !use_adaptivedomain; /* Check for initialized effector object. */ if ((fmd2->type & MOD_FLUID_TYPE_EFFEC) && fmd2->effector) { @@ -1830,7 +1824,7 @@ static void sample_mesh(FluidFlowSettings *ffs, float *velocity_map, int index, const int base_res[3], - float flow_center[3], + const float flow_center[3], BVHTreeFromMesh *tree_data, const float ray_start[3], const float *vert_vel, @@ -2256,15 +2250,15 @@ static void adaptive_domain_adjust( int x, y, z; float *density = manta_smoke_get_density(fds->fluid); float *fuel = manta_smoke_get_fuel(fds->fluid); - float *bigdensity = manta_smoke_turbulence_get_density(fds->fluid); - float *bigfuel = manta_smoke_turbulence_get_fuel(fds->fluid); + float *bigdensity = manta_noise_get_density(fds->fluid); + float *bigfuel = manta_noise_get_fuel(fds->fluid); float *vx = manta_get_velocity_x(fds->fluid); float *vy = manta_get_velocity_y(fds->fluid); float *vz = manta_get_velocity_z(fds->fluid); int wt_res[3]; if (fds->flags & FLUID_DOMAIN_USE_NOISE && fds->fluid) { - manta_smoke_turbulence_get_res(fds->fluid, wt_res); + manta_noise_get_res(fds->fluid, wt_res); } INIT_MINMAX(min_vel, max_vel); @@ -2603,7 +2597,7 @@ static void ensure_flowsfields(FluidDomainSettings *fds) manta_smoke_ensure_fire(fds->fluid, fds->fmd); } if (fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS) { - /* initialize all smoke with "active_color" */ + /* Initialize all smoke with "active_color". */ manta_smoke_ensure_colors(fds->fluid, fds->fmd); } if (fds->type == FLUID_DOMAIN_TYPE_LIQUID && @@ -2612,6 +2606,7 @@ static void ensure_flowsfields(FluidDomainSettings *fds) fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)) { manta_liquid_ensure_sndparts(fds->fluid, fds->fmd); } + manta_update_pointers(fds->fluid, fds->fmd, false); } static void update_flowsflags(FluidDomainSettings *fds, Object **flowobjs, int numflowobj) @@ -2624,7 +2619,7 @@ static void update_flowsflags(FluidDomainSettings *fds, Object **flowobjs, int n FLUID_DOMAIN_ACTIVE_HEAT | FLUID_DOMAIN_ACTIVE_FIRE); active_fields &= ~prev_flags; - /* Monitor active fields based on flow settings */ + /* Monitor active fields based on flow settings. */ for (flow_index = 0; flow_index < numflowobj; flow_index++) { Object *flow_ob = flowobjs[flow_index]; FluidModifierData *fmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flow_ob, @@ -2635,6 +2630,7 @@ static void update_flowsflags(FluidDomainSettings *fds, Object **flowobjs, int n continue; } + /* Activate specific grids if at least one flow object requires this grid. */ if ((fmd2->type & MOD_FLUID_TYPE_FLOW) && fmd2->flow) { FluidFlowSettings *ffs = fmd2->flow; if (!ffs) { @@ -2655,17 +2651,17 @@ static void update_flowsflags(FluidDomainSettings *fds, Object **flowobjs, int n continue; } - /* activate heat field if flow produces any heat */ - if (ffs->temperature) { + /* Activate heat field if a flow object produces any heat. */ + if (ffs->temperature != 0.0) { active_fields |= FLUID_DOMAIN_ACTIVE_HEAT; } - /* activate fuel field if flow adds any fuel */ - if (ffs->fuel_amount && - (ffs->type == FLUID_FLOW_TYPE_FIRE || ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE)) { + /* Activate fuel field if a flow object is of fire type. */ + if (ffs->fuel_amount != 0.0 || ffs->type == FLUID_FLOW_TYPE_FIRE || + ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE) { active_fields |= FLUID_DOMAIN_ACTIVE_FIRE; } - /* activate color field if flows add smoke with varying colors */ - if (ffs->density && + /* Activate color field if flows add smoke with varying colors. */ + if (ffs->density != 0.0 && (ffs->type == FLUID_FLOW_TYPE_SMOKE || ffs->type == FLUID_FLOW_TYPE_SMOKEFIRE)) { if (!(active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET)) { copy_v3_v3(fds->active_color, ffs->color); @@ -2678,11 +2674,11 @@ static void update_flowsflags(FluidDomainSettings *fds, Object **flowobjs, int n } } } - /* Monitor active fields based on domain settings */ + /* Monitor active fields based on domain settings. */ if (fds->type == FLUID_DOMAIN_TYPE_GAS && active_fields & FLUID_DOMAIN_ACTIVE_FIRE) { - /* heat is always needed for fire */ + /* Heat is always needed for fire. */ active_fields |= FLUID_DOMAIN_ACTIVE_HEAT; - /* also activate colors if domain smoke color differs from active color */ + /* Also activate colors if domain smoke color differs from active color. */ if (!(active_fields & FLUID_DOMAIN_ACTIVE_COLOR_SET)) { copy_v3_v3(fds->active_color, fds->flame_smoke_color); active_fields |= FLUID_DOMAIN_ACTIVE_COLOR_SET; @@ -2931,8 +2927,21 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, float *velx_initial = manta_get_in_velocity_x(fds->fluid); float *vely_initial = manta_get_in_velocity_y(fds->fluid); float *velz_initial = manta_get_in_velocity_z(fds->fluid); - uint z; + float *forcex = manta_get_force_x(fds->fluid); + float *forcey = manta_get_force_y(fds->fluid); + float *forcez = manta_get_force_z(fds->fluid); + + BLI_assert(forcex && forcey && forcez); + + /* Either all or no components have to exist. */ + BLI_assert((color_r && color_g && color_b) || (!color_r && !color_g && !color_b)); + BLI_assert((color_r_in && color_g_in && color_b_in) || + (!color_r_in && !color_g_in && !color_b_in)); + BLI_assert((velx_initial && vely_initial && velz_initial) || + (!velx_initial && !vely_initial && !velz_initial)); + + uint z; /* Grid reset before writing again. */ for (z = 0; z < fds->res[0] * fds->res[1] * fds->res[2]; z++) { /* Only reset static phi on first frame, dynamic phi gets reset every time. */ @@ -2956,7 +2965,7 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, if (heat_in) { heat_in[z] = heat[z]; } - if (color_r_in) { + if (color_r_in && color_g_in && color_b_in) { color_r_in[z] = color_r[z]; color_g_in[z] = color_b[z]; color_b_in[z] = color_g[z]; @@ -2968,11 +2977,15 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, if (emission_in) { emission_in[z] = 0.0f; } - if (velx_initial) { + if (velx_initial && vely_initial && velz_initial) { velx_initial[z] = 0.0f; vely_initial[z] = 0.0f; velz_initial[z] = 0.0f; } + /* Reset forces here as update_effectors() is skipped when no external forces are present. */ + forcex[z] = 0.0f; + forcey[z] = 0.0f; + forcez[z] = 0.0f; } /* Apply emission data for every flow object. */ @@ -3156,13 +3169,13 @@ static void update_effectors_task_cb(void *__restrict userdata, continue; } - /* get velocities from manta grid space and convert to blender units */ + /* Get velocities from manta grid space and convert to blender units. */ vel[0] = data->velocity_x[index]; vel[1] = data->velocity_y[index]; vel[2] = data->velocity_z[index]; mul_v3_fl(vel, fds->dx); - /* convert vel to global space */ + /* Convert vel to global space. */ mag = len_v3(vel); mul_mat3_m4_v3(fds->obmat, vel); normalize_v3(vel); @@ -3173,18 +3186,18 @@ static void update_effectors_task_cb(void *__restrict userdata, voxel_center[2] = fds->p0[2] + fds->cell_size[2] * ((float)(z + fds->res_min[2]) + 0.5f); mul_m4_v3(fds->obmat, voxel_center); - /* do effectors */ + /* Do effectors. */ pd_point_from_loc(data->scene, voxel_center, vel, index, &epoint); BKE_effectors_apply( data->effectors, NULL, fds->effector_weights, &epoint, retvel, NULL, NULL); - /* convert retvel to local space */ + /* Convert retvel to local space. */ mag = len_v3(retvel); mul_mat3_m4_v3(fds->imat, retvel); normalize_v3(retvel); mul_v3_fl(retvel, mag); - /* constrain forces to interval -1 to 1 */ + /* Constrain forces to interval -1 to 1. */ data->force_x[index] = min_ff(max_ff(-1.0f, retvel[0] * 0.2f), 1.0f); data->force_y[index] = min_ff(max_ff(-1.0f, retvel[1] * 0.2f), 1.0f); data->force_z[index] = min_ff(max_ff(-1.0f, retvel[2] * 0.2f), 1.0f); @@ -3328,17 +3341,13 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obj mverts->co[1] = manta_liquid_get_vertex_y_at(fds->fluid, i); mverts->co[2] = manta_liquid_get_vertex_z_at(fds->fluid, i); - /* If reading raw data directly from manta, normalize now (e.g. during replay mode). - * If reading data from files from disk, omit this normalization. */ - if (!manta_liquid_mesh_from_file(fds->fluid)) { - // normalize to unit cube around 0 - mverts->co[0] -= ((float)fds->res[0] * fds->mesh_scale) * 0.5f; - mverts->co[1] -= ((float)fds->res[1] * fds->mesh_scale) * 0.5f; - mverts->co[2] -= ((float)fds->res[2] * fds->mesh_scale) * 0.5f; - mverts->co[0] *= fds->dx / fds->mesh_scale; - mverts->co[1] *= fds->dx / fds->mesh_scale; - mverts->co[2] *= fds->dx / fds->mesh_scale; - } + /* Adjust coordinates from Mantaflow to match viewport scaling. */ + float tmp[3] = {(float)fds->res[0], (float)fds->res[1], (float)fds->res[2]}; + /* Scale to unit cube around 0. */ + mul_v3_fl(tmp, fds->mesh_scale * 0.5f); + sub_v3_v3(mverts->co, tmp); + /* Apply scaling of domain object. */ + mul_v3_fl(mverts->co, fds->dx / fds->mesh_scale); mul_v3_v3(mverts->co, co_scale); add_v3_v3(mverts->co, co_offset); @@ -3628,14 +3637,16 @@ static int manta_step( fds->time_per_frame = time_per_frame; fds->time_total = time_total; } + /* Total time must not exceed framecount times framelength. Correct tiny errors here. */ CLAMP(fds->time_total, fds->time_total, time_total_old + fds->frame_length); + /* Compute shadow grid for gas simulations. Make sure to skip if bake job was canceled early. */ if (fds->type == FLUID_DOMAIN_TYPE_GAS && result) { manta_smoke_calc_transparency(fds, DEG_get_evaluated_view_layer(depsgraph)); } - BLI_mutex_unlock(&object_update_lock); + BLI_mutex_unlock(&object_update_lock); return result; } @@ -3727,29 +3738,35 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, int mode = fds->cache_type; /* Do not process modifier if current frame is out of cache range. */ + bool escape = false; switch (mode) { case FLUID_DOMAIN_CACHE_ALL: case FLUID_DOMAIN_CACHE_MODULAR: if (fds->cache_frame_offset > 0) { if (scene_framenr < fds->cache_frame_start || scene_framenr > fds->cache_frame_end + fds->cache_frame_offset) { - return; + escape = true; } } else { if (scene_framenr < fds->cache_frame_start + fds->cache_frame_offset || scene_framenr > fds->cache_frame_end) { - return; + escape = true; } } break; case FLUID_DOMAIN_CACHE_REPLAY: default: if (scene_framenr < fds->cache_frame_start || scene_framenr > fds->cache_frame_end) { - return; + escape = true; } break; } + /* If modifier will not be processed, update/flush pointers from (old) fluid object once more. */ + if (escape && fds->fluid) { + manta_update_pointers(fds->fluid, fmd, true); + return; + } /* Reset fluid if no fluid present. Also resets active fields. */ if (!fds->fluid) { @@ -3808,10 +3825,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, fds->time_per_frame = 0; /* Ensure that gravity is copied over every frame (could be keyframed). */ - if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { - copy_v3_v3(fds->gravity, scene->physics_settings.gravity); - mul_v3_fl(fds->gravity, fds->effector_weights->global_gravity); - } + update_final_gravity(fds, scene); int next_frame = scene_framenr + 1; int prev_frame = scene_framenr - 1; @@ -3831,9 +3845,8 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, floater = fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; bool with_resumable_cache = fds->flags & FLUID_DOMAIN_USE_RESUMABLE_CACHE; - bool with_script, with_adaptive, with_noise, with_mesh, with_particles, with_guide; + bool with_script, with_noise, with_mesh, with_particles, with_guide; with_script = fds->flags & FLUID_DOMAIN_EXPORT_MANTA_SCRIPT; - with_adaptive = fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN; with_noise = fds->flags & FLUID_DOMAIN_USE_NOISE; with_mesh = fds->flags & FLUID_DOMAIN_USE_MESH; with_guide = fds->flags & FLUID_DOMAIN_USE_GUIDE; @@ -3845,7 +3858,15 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, has_mesh = manta_has_mesh(fds->fluid, fmd, scene_framenr); has_particles = manta_has_particles(fds->fluid, fmd, scene_framenr); has_guide = manta_has_guiding(fds->fluid, fmd, scene_framenr, guide_parent); - has_config = false; + has_config = manta_read_config(fds->fluid, fmd, scene_framenr); + + /* When reading data from cache (has_config == true) ensure that active fields are allocated. + * update_flowsflags() and update_obstacleflags() will not find flow sources hidden from renders. + * See also: T72192. */ + if (has_config) { + ensure_flowsfields(fds); + ensure_obstaclefields(fds); + } bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide; baking_data = fds->cache_flag & FLUID_DOMAIN_BAKING_DATA; @@ -3950,13 +3971,21 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, break; } + /* Adaptive domain needs to know about current state, so save it here. */ + copy_v3_v3_int(o_res, fds->res); + copy_v3_v3_int(o_min, fds->res_min); + copy_v3_v3_int(o_max, fds->res_max); + copy_v3_v3_int(o_shift, fds->shift); + bool read_partial = false, read_all = false; /* Try to read from cache and keep track of read success. */ if (read_cache) { /* Read mesh cache. */ if (with_liquid && with_mesh) { - has_config = manta_read_config(fds->fluid, fmd, mesh_frame); + if (mesh_frame != scene_framenr) { + has_config = manta_read_config(fds->fluid, fmd, mesh_frame); + } /* Update mesh data from file is faster than via Python (manta_read_mesh()). */ has_mesh = manta_read_mesh(fds->fluid, fmd, mesh_frame); @@ -3964,7 +3993,9 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, /* Read particles cache. */ if (with_liquid && with_particles) { - has_config = manta_read_config(fds->fluid, fmd, particles_frame); + if (particles_frame != scene_framenr) { + has_config = manta_read_config(fds->fluid, fmd, particles_frame); + } read_partial = !baking_data && !baking_particles && next_particles; read_all = !read_partial && with_resumable_cache; @@ -3979,38 +4010,29 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, /* Read noise and data cache */ if (with_smoke && with_noise) { - has_config = manta_read_config(fds->fluid, fmd, noise_frame); + if (noise_frame != scene_framenr) { + has_config = manta_read_config(fds->fluid, fmd, noise_frame); + } /* Only reallocate when just reading cache or when resuming during bake. */ - if ((!baking_noise || (baking_noise && resume_noise)) && has_config && - manta_needs_realloc(fds->fluid, fmd)) { - BKE_fluid_reallocate_fluid(fds, fds->res, 1); + if (has_data && has_config && manta_needs_realloc(fds->fluid, fmd)) { + BKE_fluid_reallocate_copy_fluid( + fds, o_res, fds->res, o_min, fds->res_min, o_max, o_shift, fds->shift); } read_partial = !baking_data && !baking_noise && next_noise; read_all = !read_partial && with_resumable_cache; has_noise = manta_read_noise(fds->fluid, fmd, noise_frame, read_all); - /* When using the adaptive domain, copy all data that was read to a new fluid object. */ - if (with_adaptive && baking_noise) { - /* Adaptive domain needs to know about current state, so save it, then copy. */ - copy_v3_v3_int(o_res, fds->res); - copy_v3_v3_int(o_min, fds->res_min); - copy_v3_v3_int(o_max, fds->res_max); - copy_v3_v3_int(o_shift, fds->shift); - if (has_config && manta_needs_realloc(fds->fluid, fmd)) { - BKE_fluid_reallocate_copy_fluid( - fds, o_res, fds->res, o_min, fds->res_min, o_max, o_shift, fds->shift); - } - } - read_partial = !baking_data && !baking_noise && next_data && next_noise; read_all = !read_partial && with_resumable_cache; has_data = manta_read_data(fds->fluid, fmd, data_frame, read_all); } /* Read data cache only */ else { - has_config = manta_read_config(fds->fluid, fmd, data_frame); + if (data_frame != scene_framenr) { + has_config = manta_read_config(fds->fluid, fmd, data_frame); + } if (with_smoke) { /* Read config and realloc fluid object if needed. */ @@ -4095,6 +4117,9 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, } } + /* Ensure that fluid pointers are always up to date at the end of modifier processing. */ + manta_update_pointers(fds->fluid, fmd, false); + fds->flags &= ~FLUID_DOMAIN_FILE_LOAD; fmd->time = scene_framenr; } @@ -4118,43 +4143,47 @@ static void BKE_fluid_modifier_process( struct Mesh *BKE_fluid_modifier_do( FluidModifierData *fmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me) { - /* Lock so preview render does not read smoke data while it gets modified. */ - if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { - BLI_rw_mutex_lock(fmd->domain->fluid_mutex, THREAD_LOCK_WRITE); - } - - BKE_fluid_modifier_process(fmd, depsgraph, scene, ob, me); - - if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { - BLI_rw_mutex_unlock(fmd->domain->fluid_mutex); - } - /* Optimization: Do not update viewport during bakes (except in replay mode) * Reason: UI is locked and updated liquid / smoke geometry is not visible anyways. */ bool needs_viewport_update = false; - if (fmd->domain) { - FluidDomainSettings *fds = fmd->domain; - /* Always update viewport in cache replay mode. */ - if (fds->cache_type == FLUID_DOMAIN_CACHE_REPLAY || - fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) { - needs_viewport_update = true; + /* Optimization: Only process modifier if object is not being altered. */ + if (!G.moving) { + /* Lock so preview render does not read smoke data while it gets modified. */ + if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { + BLI_rw_mutex_lock(fmd->domain->fluid_mutex, THREAD_LOCK_WRITE); } - /* In other cache modes, only update the viewport when no bake is going on. */ - else { - bool with_mesh; - with_mesh = fds->flags & FLUID_DOMAIN_USE_MESH; - bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide; - baking_data = fds->cache_flag & FLUID_DOMAIN_BAKING_DATA; - baking_noise = fds->cache_flag & FLUID_DOMAIN_BAKING_NOISE; - baking_mesh = fds->cache_flag & FLUID_DOMAIN_BAKING_MESH; - baking_particles = fds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES; - baking_guide = fds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE; - - if (with_mesh && !baking_data && !baking_noise && !baking_mesh && !baking_particles && - !baking_guide) { + + BKE_fluid_modifier_process(fmd, depsgraph, scene, ob, me); + + if ((fmd->type & MOD_FLUID_TYPE_DOMAIN) && fmd->domain) { + BLI_rw_mutex_unlock(fmd->domain->fluid_mutex); + } + + if (fmd->domain) { + FluidDomainSettings *fds = fmd->domain; + + /* Always update viewport in cache replay mode. */ + if (fds->cache_type == FLUID_DOMAIN_CACHE_REPLAY || + fds->flags & FLUID_DOMAIN_USE_ADAPTIVE_DOMAIN) { needs_viewport_update = true; } + /* In other cache modes, only update the viewport when no bake is going on. */ + else { + bool with_mesh; + with_mesh = fds->flags & FLUID_DOMAIN_USE_MESH; + bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide; + baking_data = fds->cache_flag & FLUID_DOMAIN_BAKING_DATA; + baking_noise = fds->cache_flag & FLUID_DOMAIN_BAKING_NOISE; + baking_mesh = fds->cache_flag & FLUID_DOMAIN_BAKING_MESH; + baking_particles = fds->cache_flag & FLUID_DOMAIN_BAKING_PARTICLES; + baking_guide = fds->cache_flag & FLUID_DOMAIN_BAKING_GUIDE; + + if (with_mesh && !baking_data && !baking_noise && !baking_mesh && !baking_particles && + !baking_guide) { + needs_viewport_update = true; + } + } } } @@ -4196,7 +4225,7 @@ struct Mesh *BKE_fluid_modifier_do( } static float calc_voxel_transp( - float *result, float *input, int res[3], int *pixel, float *t_ray, float correct) + float *result, const float *input, int res[3], int *pixel, float *t_ray, float correct) { const size_t index = manta_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]); @@ -4311,7 +4340,7 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *v { float bv[6] = {0}; float light[3]; - int a, z, slabsize = fds->res[0] * fds->res[1], size = fds->res[0] * fds->res[1] * fds->res[2]; + int slabsize = fds->res[0] * fds->res[1]; float *density = manta_smoke_get_density(fds->fluid); float *shadow = manta_smoke_get_shadow(fds->fluid); float correct = -7.0f * fds->dx; @@ -4320,54 +4349,49 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *v return; } - /* convert light pos to sim cell space */ + /* Convert light pos to sim cell space. */ mul_m4_v3(fds->imat, light); light[0] = (light[0] - fds->p0[0]) / fds->cell_size[0] - 0.5f - (float)fds->res_min[0]; light[1] = (light[1] - fds->p0[1]) / fds->cell_size[1] - 0.5f - (float)fds->res_min[1]; light[2] = (light[2] - fds->p0[2]) / fds->cell_size[2] - 0.5f - (float)fds->res_min[2]; - for (a = 0; a < size; a++) { - shadow[a] = -1.0f; - } - - /* calculate domain bounds in sim cell space */ + /* Calculate domain bounds in sim cell space. */ // 0,2,4 = 0.0f bv[1] = (float)fds->res[0]; // x bv[3] = (float)fds->res[1]; // y bv[5] = (float)fds->res[2]; // z - for (z = 0; z < fds->res[2]; z++) { + for (int z = 0; z < fds->res[2]; z++) { size_t index = z * slabsize; - int x, y; - for (y = 0; y < fds->res[1]; y++) { - for (x = 0; x < fds->res[0]; x++, index++) { + for (int y = 0; y < fds->res[1]; y++) { + for (int x = 0; x < fds->res[0]; x++, index++) { float voxel_center[3]; float pos[3]; int cell[3]; float t_ray = 1.0; - if (shadow[index] >= 0.0f) { - continue; - } + /* Reset shadow value.*/ + shadow[index] = -1.0f; + voxel_center[0] = (float)x; voxel_center[1] = (float)y; voxel_center[2] = (float)z; - // get starting cell (light pos) + /* Get starting cell (light pos). */ if (BLI_bvhtree_bb_raycast(bv, light, voxel_center, pos) > FLT_EPSILON) { - // we're outside -> use point on side of domain + /* We're outside -> use point on side of domain. */ cell[0] = (int)floor(pos[0]); cell[1] = (int)floor(pos[1]); cell[2] = (int)floor(pos[2]); } else { - // we're inside -> use light itself + /* We're inside -> use light itself. */ cell[0] = (int)floor(light[0]); cell[1] = (int)floor(light[1]); cell[2] = (int)floor(light[2]); } - /* clamp within grid bounds */ + /* Clamp within grid bounds */ CLAMP(cell[0], 0, fds->res[0] - 1); CLAMP(cell[1], 0, fds->res[1] - 1); CLAMP(cell[2], 0, fds->res[2] - 1); @@ -4385,7 +4409,7 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *fds, ViewLayer *v fds->res, correct); - // convention -> from a RGBA float array, use G value for t_ray + /* Convention -> from a RGBA float array, use G value for t_ray. */ shadow[index] = t_ray; } } @@ -4879,6 +4903,7 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *fmd) fmd->domain->particle_radius = 1.0f; fmd->domain->particle_band_width = 3.0f; fmd->domain->fractions_threshold = 0.05f; + fmd->domain->sys_particle_maximum = 0; /* diffusion options*/ fmd->domain->surface_tension = 0.0f; @@ -5123,6 +5148,7 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd, tfds->particle_radius = fds->particle_radius; tfds->particle_band_width = fds->particle_band_width; tfds->fractions_threshold = fds->fractions_threshold; + tfds->sys_particle_maximum = fds->sys_particle_maximum; /* diffusion options*/ tfds->surface_tension = fds->surface_tension; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index dfa5ff6975f..958acf0589b 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -797,7 +797,7 @@ static bool vfont_to_curve(Object *ob, } else { char32_t *mem_tmp; - slen = cu->len_wchar; + slen = cu->len_char32; /* Create unicode string */ mem_tmp = MEM_malloc_arrayN((slen + 1), sizeof(*mem_tmp), "convertedmem"); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 6a9511d8275..eeb55c44d6e 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -681,10 +681,10 @@ void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_d } /** - * Make a copy of a given gpencil stroke. - * \param gps_src: Source grease pencil strokeyes - * \param dup_points: Duplicate points data - * \return Pointer to new stroke + * Make a copy of a given grease-pencil stroke. + * \param gps_src: Source grease pencil strokes. + * \param dup_points: Duplicate points data. + * \return Pointer to new stroke. */ bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_points) { @@ -1512,12 +1512,12 @@ int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *materi } /** - * Creates a new gpencil material and assigns it to object. + * Creates a new grease-pencil material and assigns it to object. * \param bmain: Main pointer * \param ob: Grease pencil object * \param name: Material name * \param r_index: value is set to zero based index of the new material if \a r_index is not NULL. - * \return Materil pointer + * \return Material pointer. */ Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index) { @@ -1555,7 +1555,7 @@ Material *BKE_gpencil_object_material_from_brush_get(Object *ob, Brush *brush) * Returns the material index for a brush with respect to its pinned state. * \param ob: Grease pencil object * \param brush: Brush - * \return Materil index + * \return Material index. */ int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush) { @@ -1571,8 +1571,7 @@ int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush) * Guaranteed to return a material assigned to object. Returns never NULL. * \param bmain: Main pointer * \param ob: Grease pencil object - * \param ts: Toolsettings - * \return Material pointer + * \return Material pointer. */ Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main *bmain, Object *ob, @@ -1590,7 +1589,7 @@ Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main /** * Guaranteed to return a material assigned to object. Returns never NULL. * \param bmain: Main pointer - * \param ob: Grease pencil obejct + * \param ob: Grease pencil object. * \param brush: Brush * \return Material pointer */ @@ -1783,7 +1782,8 @@ float BKE_gpencil_multiframe_falloff_calc( value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f); } else { - value = 1.0f; + /* Center of the curve. */ + value = BKE_curvemapping_evaluateF(cur_falloff, 0, 0.5f); } return value; @@ -2330,8 +2330,8 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, /** * Update original pointers in evaluated frame. - * \param gpf_orig: Original greas epencil frame - * \param gpf_eval: Evaluated grease pencil frame + * \param gpf_orig: Original grease-pencil frame. + * \param gpf_eval: Evaluated grease pencil frame. */ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig, const struct bGPDframe *gpf_eval) diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c index 66e9e2184c1..a7adbed6c4b 100644 --- a/source/blender/blenkernel/intern/gpencil_curve.c +++ b/source/blender/blenkernel/intern/gpencil_curve.c @@ -363,7 +363,7 @@ static void gpencil_convert_spline(Main *bmain, BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3])); /* Allocate memory for storage points. */ - gps->totpoints = nurb_points - 1; + gps->totpoints = nurb_points; gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); /* Add points. */ diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 49940c2d466..14eb6bb4f4c 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -33,6 +33,7 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" +#include "BLI_hash.h" #include "BLI_math_vector.h" #include "BLI_polyfill_2d.h" @@ -989,7 +990,7 @@ bool BKE_gpencil_stroke_smooth_uv(bGPDstroke *gps, int point_index, float influe * \param points: Array of grease pencil points (3D) * \param totpoints: Total of points * \param points2d: Result array of 2D points - * \param r_direction: Return Concave (-1), Convex (1), or Autodetect (0) + * \param r_direction: Return Concave (-1), Convex (1), or Auto-detect (0) */ void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, @@ -1043,7 +1044,7 @@ void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points, points2d[i][1] = dot_v3v3(loc, locy); } - /* Concave (-1), Convex (1), or Autodetect (0)? */ + /* Concave (-1), Convex (1), or Auto-detect (0)? */ *r_direction = (int)locy[2]; } @@ -1056,7 +1057,7 @@ void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points, * \param totpoints: Total points * \param points2d: Result array of 2D points * \param scale: Scale factor - * \param r_direction: Return Concave (-1), Convex (1), or Autodetect (0) + * \param r_direction: Return Concave (-1), Convex (1), or Auto-detect (0) */ void BKE_gpencil_stroke_2d_flat_ref(const bGPDspoint *ref_points, int ref_totpoints, @@ -1138,7 +1139,7 @@ void BKE_gpencil_stroke_2d_flat_ref(const bGPDspoint *ref_points, points2d[i][1] = dot_v3v3(loc, locy); } - /* Concave (-1), Convex (1), or Autodetect (0)? */ + /* Concave (-1), Convex (1), or Auto-detect (0)? */ *r_direction = (int)locy[2]; } @@ -1146,7 +1147,7 @@ void BKE_gpencil_stroke_2d_flat_ref(const bGPDspoint *ref_points, static void gpencil_calc_stroke_fill_uv(const float (*points2d)[2], bGPDstroke *gps, const float minv[2], - float maxv[2], + const float maxv[2], float (*r_uv)[2]) { const float s = sin(gps->uv_rotation); @@ -1289,9 +1290,9 @@ void BKE_gpencil_stroke_geometry_update(bGPDstroke *gps) /** * Calculate grease pencil stroke length. - * @param gps Grease pencil stroke - * @param use_3d Set to true to use 3D points - * @return Length of the stroke + * \param gps: Grease pencil stroke + * \param use_3d: Set to true to use 3D points + * \return Length of the stroke */ float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d) { @@ -2088,6 +2089,7 @@ static int gpencil_walk_edge(GHash *v_table, static void gpencil_generate_edgeloops(Object *ob, bGPDframe *gpf_stroke, + int stroke_mat_index, const float angle, const int thickness, const float offset, @@ -2175,7 +2177,7 @@ static void gpencil_generate_edgeloops(Object *ob, /* Create Stroke. */ bGPDstroke *gps_stroke = BKE_gpencil_stroke_add( - gpf_stroke, 0, array_len + 1, thickness * thickness, false); + gpf_stroke, MAX2(stroke_mat_index, 0), array_len + 1, thickness * thickness, false); /* Create first segment. */ float fpt[3]; @@ -2258,6 +2260,19 @@ static Material *gpencil_add_material(Main *bmain, return mat_gp; } +static int gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_prefix) +{ + const int name_prefix_len = strlen(name_prefix); + for (int i = 0; i < ob->totcol; i++) { + Material *ma = BKE_object_material_get(ob, i + 1); + if ((ma != NULL) && (ma->gp_style != NULL) && + (STREQLEN(ma->id.name + 2, name_prefix, name_prefix_len))) { + return i; + } + } + + return -1; +} /** * Convert a mesh object to grease pencil stroke. * @@ -2273,6 +2288,7 @@ static Material *gpencil_add_material(Main *bmain, * \param frame_offset: Destination frame number offset. * \param use_seams: Only export seam edges. * \param use_faces: Export faces as filled strokes. + * \simple_material: Create only 2 materials (stroke and fill) */ void BKE_gpencil_convert_mesh(Main *bmain, Depsgraph *depsgraph, @@ -2285,7 +2301,8 @@ void BKE_gpencil_convert_mesh(Main *bmain, const float matrix[4][4], const int frame_offset, const bool use_seams, - const bool use_faces) + const bool use_faces, + const bool simple_material) { if (ELEM(NULL, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) { return; @@ -2300,6 +2317,8 @@ void BKE_gpencil_convert_mesh(Main *bmain, MLoop *mloop = me_eval->mloop; int mpoly_len = me_eval->totpoly; int i; + int stroke_mat_index = gpencil_material_find_index_by_name_prefix(ob_gp, "Stroke"); + int fill_mat_index = gpencil_material_find_index_by_name_prefix(ob_gp, "Fill"); /* If the object has enough materials means it was created in a previous step. */ const bool create_mat = ((ob_gp->totcol > 0) && (ob_gp->totcol >= ob_mesh->totcol)) ? false : @@ -2314,12 +2333,15 @@ void BKE_gpencil_convert_mesh(Main *bmain, const float default_colors[2][4] = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.7f, 0.7f, 0.7f, 1.0f}}; /* Create stroke material. */ if (create_mat) { - gpencil_add_material(bmain, ob_gp, "Stroke", default_colors[0], true, false, &r_idx); + if (stroke_mat_index == -1) { + gpencil_add_material(bmain, ob_gp, "Stroke", default_colors[0], true, false, &r_idx); + stroke_mat_index = ob_gp->totcol - 1; + } } /* Export faces as filled strokes. */ if (use_faces) { if (create_mat) { - /* Find a material slot with material assigned */ + /* Find a material slot with material assigned. */ bool material_found = false; for (i = 0; i < ob_mesh->totcol; i++) { Material *ma = BKE_object_material_get(ob_mesh, i + 1); @@ -2329,9 +2351,12 @@ void BKE_gpencil_convert_mesh(Main *bmain, } } - /* If no materials, create a simple fill. */ - if (!material_found) { - gpencil_add_material(bmain, ob_gp, "Fill", default_colors[1], false, true, &r_idx); + /* If no materials or use simple materials, create a simple fill. */ + if ((!material_found) || (simple_material)) { + if (fill_mat_index == -1) { + gpencil_add_material(bmain, ob_gp, "Fill", default_colors[1], false, true, &r_idx); + fill_mat_index = ob_gp->totcol - 1; + } } else { /* Create all materials for fill. */ @@ -2359,8 +2384,11 @@ void BKE_gpencil_convert_mesh(Main *bmain, for (i = 0, mp = mpoly; i < mpoly_len; i++, mp++) { MLoop *ml = &mloop[mp->loopstart]; /* Create fill stroke. */ - bGPDstroke *gps_fill = BKE_gpencil_stroke_add( - gpf_fill, mp->mat_nr + 1, mp->totloop, 10, false); + int mat_idx = (simple_material) || (mp->mat_nr + 1 > ob_gp->totcol - 1) ? + MAX2(fill_mat_index, 0) : + mp->mat_nr + 1; + + bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, mp->totloop, 10, false); gps_fill->flag |= GP_STROKE_CYCLIC; /* Add points to strokes. */ @@ -2387,7 +2415,8 @@ void BKE_gpencil_convert_mesh(Main *bmain, } bGPDframe *gpf_stroke = BKE_gpencil_layer_frame_get( gpl_stroke, CFRA + frame_offset, GP_GETFRAME_ADD_NEW); - gpencil_generate_edgeloops(ob_eval, gpf_stroke, angle, thickness, offset, matrix, use_seams); + gpencil_generate_edgeloops( + ob_eval, gpf_stroke, stroke_mat_index, angle, thickness, offset, matrix, use_seams); /* Tag for recalculation */ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); @@ -2395,10 +2424,10 @@ void BKE_gpencil_convert_mesh(Main *bmain, /** * Apply grease pencil Transforms. - * @param gpd Grease pencil data-block - * @param mat Transformation matrix + * \param gpd: Grease pencil data-block + * \param mat: Transformation matrix */ -void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4]) +void BKE_gpencil_transform(bGPdata *gpd, const float mat[4][4]) { if (gpd == NULL) { return; @@ -2430,4 +2459,152 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4]) } } } + +/* Used for "move only origins" in object_data_transform.c */ +int BKE_gpencil_stroke_point_count(bGPdata *gpd) +{ + int total_points = 0; + + if (gpd == NULL) { + return 0; + } + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* FIXME: For now, we just skip parented layers. + * Otherwise, we have to update each frame to find + * the current parent position/effects. + */ + if (gpl->parent) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + total_points += gps->totpoints; + } + } + } + return total_points; +} + +/* Used for "move only origins" in object_data_transform.c */ +void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_data) +{ + if (gpd == NULL) { + return; + } + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* FIXME: For now, we just skip parented layers. + * Otherwise, we have to update each frame to find + * the current parent position/effects. + */ + if (gpl->parent) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + + for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) { + copy_v3_v3(elem_data->co, &pt->x); + elem_data->pressure = pt->pressure; + elem_data++; + } + } + } + } +} + +/* Used for "move only origins" in object_data_transform.c */ +void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates *elem_data) +{ + if (gpd == NULL) { + return; + } + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* FIXME: For now, we just skip parented layers. + * Otherwise, we have to update each frame to find + * the current parent position/effects. + */ + if (gpl->parent) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + + for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) { + copy_v3_v3(&pt->x, elem_data->co); + pt->pressure = elem_data->pressure; + elem_data++; + } + + /* Distortion may mean we need to re-triangulate. */ + BKE_gpencil_stroke_geometry_update(gps); + } + } + } +} + +/* Used for "move only origins" in object_data_transform.c */ +void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd, + const GPencilPointCoordinates *elem_data, + const float mat[4][4]) +{ + if (gpd == NULL) { + return; + } + + const float scalef = mat4_to_scale(mat); + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* FIXME: For now, we just skip parented layers. + * Otherwise, we have to update each frame to find + * the current parent position/effects. + */ + if (gpl->parent) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + + for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) { + mul_v3_m4v3(&pt->x, mat, elem_data->co); + pt->pressure = elem_data->pressure * scalef; + elem_data++; + } + + /* Distortion may mean we need to re-triangulate. */ + BKE_gpencil_stroke_geometry_update(gps); + } + } + } +} + +/** + * Set a random color to stroke using vertex color. + * \param gps: Stroke + */ +void BKE_gpencil_stroke_set_random_color(bGPDstroke *gps) +{ + BLI_assert(gps->totpoints > 0); + + float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + bGPDspoint *pt = &gps->points[0]; + color[0] *= BLI_hash_int_01(BLI_hash_int_2d(gps->totpoints / 5, pt->x + pt->z)); + color[1] *= BLI_hash_int_01(BLI_hash_int_2d(gps->totpoints + pt->x, pt->y * pt->z + pt->x)); + color[2] *= BLI_hash_int_01(BLI_hash_int_2d(gps->totpoints - pt->x, pt->z * pt->x + pt->y)); + for (int i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + copy_v4_v4(pt->vert_color, color); + } +} /** \} */ diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 24cfc65a8fe..e92bf5a4502 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -197,7 +197,7 @@ static int gpencil_time_modifier( /** * Set current grease pencil active frame. * \param depsgraph: Current depsgraph - * \param gpd: Grease pencil data-block + * \param gpd: Grease pencil data-block. */ void BKE_gpencil_frame_active_set(Depsgraph *depsgraph, bGPdata *gpd) { @@ -223,8 +223,7 @@ void BKE_gpencil_frame_active_set(Depsgraph *depsgraph, bGPdata *gpd) } /** - * Init grease pencil modifier. - * \param void + * Initialize grease pencil modifier. */ void BKE_gpencil_modifier_init(void) { @@ -460,7 +459,6 @@ GpencilModifierData *BKE_gpencil_modifiers_findby_type(Object *ob, GpencilModifi * Set grease pencil modifier error. * \param md: Modifier data * \param _format: Format - * \param */ void BKE_gpencil_modifier_set_error(GpencilModifierData *md, const char *_format, ...) { @@ -560,8 +558,8 @@ static int gpencil_remap_time_get(Depsgraph *depsgraph, Scene *scene, Object *ob return remap_cfra; } -/** Get the current frame retimed with time modifiers. - * \param depsgraph: Current depsgraph +/** Get the current frame re-timed with time modifiers. + * \param depsgraph: Current depsgraph. * \param scene: Current scene * \param ob: Grease pencil object * \param gpl: Grease pencil layer diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c index 2684e964eb1..1166ad9ad2f 100644 --- a/source/blender/blenkernel/intern/idtype.c +++ b/source/blender/blenkernel/intern/idtype.c @@ -36,8 +36,11 @@ #include "BLT_translation.h" #include "DNA_ID.h" +#include "DNA_node_types.h" +#include "DNA_scene_types.h" #include "BKE_main.h" +#include "BKE_node.h" #include "BKE_idtype.h" @@ -470,3 +473,33 @@ short BKE_idtype_idcode_iter_step(int *index) { return (*index < ARRAY_SIZE(id_types)) ? BKE_idtype_idcode_from_index((*index)++) : 0; } + +/** Wrapper around IDTypeInfo foreach_cache that also handles embedded IDs. */ +void BKE_idtype_id_foreach_cache(struct ID *id, + IDTypeForeachCacheFunctionCallback function_callback, + void *user_data) +{ + const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(id); + if (type_info->foreach_cache != NULL) { + type_info->foreach_cache(id, function_callback, user_data); + } + + /* Handle 'private IDs'. */ + bNodeTree *nodetree = ntreeFromID(id); + if (nodetree != NULL) { + type_info = BKE_idtype_get_info_from_id(&nodetree->id); + if (type_info->foreach_cache != NULL) { + type_info->foreach_cache(&nodetree->id, function_callback, user_data); + } + } + + if (GS(id->name) == ID_SCE) { + Scene *scene = (Scene *)id; + if (scene->master_collection != NULL) { + type_info = BKE_idtype_get_info_from_id(&scene->master_collection->id); + if (type_info->foreach_cache != NULL) { + type_info->foreach_cache(&scene->master_collection->id, function_callback, user_data); + } + } + } +} diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 41ef5dc00ef..e331e5ae1dd 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -57,6 +57,7 @@ #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_world_types.h" #include "BLI_blenlib.h" @@ -64,7 +65,7 @@ #include "BLI_mempool.h" #include "BLI_system.h" #include "BLI_threads.h" -#include "BLI_timecode.h" /* for stamp timecode format */ +#include "BLI_timecode.h" /* For stamp time-code format. */ #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -89,7 +90,6 @@ #include "RE_pipeline.h" -#include "GPU_draw.h" #include "GPU_texture.h" #include "BLI_sys_types.h" // for intptr_t support @@ -195,24 +195,24 @@ static void image_foreach_cache(ID *id, .offset_in_ID = offsetof(Image, cache), .cache_v = image->cache, }; - function_callback(id, &key, (void **)&image->cache, user_data); + function_callback(id, &key, (void **)&image->cache, 0, user_data); for (int eye = 0; eye < 2; eye++) { for (int a = 0; a < TEXTARGET_COUNT; a++) { key.offset_in_ID = offsetof(Image, gputexture[a][eye]); key.cache_v = image->gputexture[a][eye]; - function_callback(id, &key, (void **)&image->gputexture[a][eye], user_data); + function_callback(id, &key, (void **)&image->gputexture[a][eye], 0, user_data); } } key.offset_in_ID = offsetof(Image, rr); key.cache_v = image->rr; - function_callback(id, &key, (void **)&image->rr, user_data); + function_callback(id, &key, (void **)&image->rr, 0, user_data); LISTBASE_FOREACH (RenderSlot *, slot, &image->renderslots) { key.offset_in_ID = (size_t)BLI_ghashutil_strhash_p(slot->name); key.cache_v = slot->render; - function_callback(id, &key, (void **)&slot->render, user_data); + function_callback(id, &key, (void **)&slot->render, 0, user_data); } } @@ -392,7 +392,7 @@ void BKE_image_free_buffers_ex(Image *ima, bool do_lock) ima->rr = NULL; } - GPU_free_image(ima); + BKE_image_free_gputextures(ima); LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { tile->ok = IMA_OK; @@ -3240,6 +3240,12 @@ static void image_walk_id_all_users( if (scene->nodetree && scene->use_nodes && !skip_nested_nodes) { image_walk_ntree_all_users(scene->nodetree, &scene->id, customdata, callback); } + break; + } + case ID_SIM: { + Simulation *simulation = (Simulation *)id; + image_walk_ntree_all_users(simulation->nodetree, &simulation->id, customdata, callback); + break; } default: break; @@ -3344,8 +3350,7 @@ static void image_free_tile(Image *ima, ImageTile *tile) for (int i = 0; i < TEXTARGET_COUNT; i++) { /* Only two textures depends on all tiles, so if this is a secondary tile we can keep the other * two. */ - if (tile != ima->tiles.first && - !(ELEM(i, TEXTARGET_TEXTURE_2D_ARRAY, TEXTARGET_TEXTURE_TILE_MAPPING))) { + if (tile != ima->tiles.first && !(ELEM(i, TEXTARGET_2D_ARRAY, TEXTARGET_TILE_MAPPING))) { continue; } @@ -3622,13 +3627,13 @@ ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *la for (int eye = 0; eye < 2; eye++) { /* Reallocate GPU tile array. */ - if (ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][eye] != NULL) { - GPU_texture_free(ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][eye]); - ima->gputexture[TEXTARGET_TEXTURE_2D_ARRAY][eye] = NULL; + if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != NULL) { + GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye]); + ima->gputexture[TEXTARGET_2D_ARRAY][eye] = NULL; } - if (ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING][eye] != NULL) { - GPU_texture_free(ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING][eye]); - ima->gputexture[TEXTARGET_TEXTURE_TILE_MAPPING][eye] = NULL; + if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != NULL) { + GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye]); + ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = NULL; } } @@ -3937,7 +3942,7 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) #endif /* WITH_OPENEXR */ /* common stuff to do with images after loading */ -static void image_initialize_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ibuf)) +static void image_init_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ibuf)) { /* Preview is NULL when it has never been used as an icon before. * Never handle previews/icons outside of main thread. */ @@ -4040,11 +4045,11 @@ static ImBuf *load_sequence_single( } } else { - image_initialize_after_load(ima, iuser, ibuf); + image_init_after_load(ima, iuser, ibuf); *r_assign = true; } #else - image_initialize_after_load(ima, iuser, ibuf); + image_init_after_load(ima, iuser, ibuf); *r_assign = true; #endif } @@ -4149,7 +4154,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e BKE_imbuf_stamp_info(ima->rr, ibuf); - image_initialize_after_load(ima, iuser, ibuf); + image_init_after_load(ima, iuser, ibuf); image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : 0, entry); } // else printf("pass not found\n"); @@ -4213,7 +4218,7 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i ibuf = IMB_makeSingleUser(IMB_anim_absolute(ia->anim, fra, IMB_TC_RECORD_RUN, IMB_PROXY_NONE)); if (ibuf) { - image_initialize_after_load(ima, iuser, ibuf); + image_init_after_load(ima, iuser, ibuf); } else { tile->ok = 0; @@ -4358,12 +4363,12 @@ static ImBuf *load_image_single(Image *ima, else #endif { - image_initialize_after_load(ima, iuser, ibuf); + image_init_after_load(ima, iuser, ibuf); *r_assign = true; /* make packed file for autopack */ if ((has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) { - ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Packefile"); + ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file"); BLI_addtail(&ima->packedfiles, imapf); STRNCPY(imapf->filepath, filepath); @@ -4472,7 +4477,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) if (rpass) { ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0); - image_initialize_after_load(ima, iuser, ibuf); + image_init_after_load(ima, iuser, ibuf); ibuf->rect_float = rpass->rect; ibuf->flags |= IB_rectfloat; @@ -5213,24 +5218,32 @@ int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, bool *r_is_in_ran void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra) { if (iuser) { - bool is_in_range; - const int framenr = BKE_image_user_frame_get(iuser, cfra, &is_in_range); + if (ima && BKE_image_is_animated(ima)) { + /* Compute current frame for animated image. */ + bool is_in_range; + const int framenr = BKE_image_user_frame_get(iuser, cfra, &is_in_range); - if (is_in_range) { - iuser->flag |= IMA_USER_FRAME_IN_RANGE; + if (is_in_range) { + iuser->flag |= IMA_USER_FRAME_IN_RANGE; + } + else { + iuser->flag &= ~IMA_USER_FRAME_IN_RANGE; + } + + iuser->framenr = framenr; } else { - iuser->flag &= ~IMA_USER_FRAME_IN_RANGE; + /* Set fixed frame number for still image. */ + iuser->framenr = 0; + iuser->flag |= IMA_USER_FRAME_IN_RANGE; } - iuser->framenr = framenr; - - if (ima && BKE_image_is_animated(ima) && ima->gpuframenr != framenr) { + if (ima && ima->gpuframenr != iuser->framenr) { /* Note: a single texture and refresh doesn't really work when * multiple image users may use different frames, this is to * be improved with perhaps a GPU texture cache. */ ima->gpuflag |= IMA_GPU_REFRESH; - ima->gpuframenr = framenr; + ima->gpuframenr = iuser->framenr; } if (iuser->ok == 0) { diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c new file mode 100644 index 00000000000..22fb6dfd02a --- /dev/null +++ b/source/blender/blenkernel/intern/image_gpu.c @@ -0,0 +1,774 @@ +/* + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_boxpack_2d.h" +#include "BLI_linklist.h" +#include "BLI_listbase.h" +#include "BLI_threads.h" + +#include "DNA_image_types.h" +#include "DNA_userdef_types.h" + +#include "IMB_colormanagement.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" + +#include "GPU_extensions.h" +#include "GPU_state.h" +#include "GPU_texture.h" + +#include "PIL_time.h" + +/* Prototypes. */ +static void gpu_free_unused_buffers(void); +static void image_free_gpu(Image *ima, const bool immediate); + +/* -------------------------------------------------------------------- */ +/** \name UDIM gpu texture + * \{ */ + +static bool is_over_resolution_limit(int w, int h) +{ + return (w > GPU_texture_size_with_limit(w) || h > GPU_texture_size_with_limit(h)); +} + +static int smaller_power_of_2_limit(int num) +{ + return power_of_2_min_i(GPU_texture_size_with_limit(num)); +} + +static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multiview_eye) +{ + GPUTexture *tilearray = ima->gputexture[TEXTARGET_2D_ARRAY][multiview_eye]; + + if (tilearray == NULL) { + return 0; + } + + float array_w = GPU_texture_width(tilearray); + float array_h = GPU_texture_height(tilearray); + + ImageTile *last_tile = (ImageTile *)ima->tiles.last; + /* Tiles are sorted by number. */ + int max_tile = last_tile->tile_number - 1001; + + /* create image */ + int width = max_tile + 1; + float *data = (float *)MEM_callocN(width * 8 * sizeof(float), __func__); + for (int i = 0; i < width; i++) { + data[4 * i] = -1.0f; + } + LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { + int i = tile->tile_number - 1001; + data[4 * i] = tile->runtime.tilearray_layer; + + float *tile_info = &data[4 * width + 4 * i]; + tile_info[0] = tile->runtime.tilearray_offset[0] / array_w; + tile_info[1] = tile->runtime.tilearray_offset[1] / array_h; + tile_info[2] = tile->runtime.tilearray_size[0] / array_w; + tile_info[3] = tile->runtime.tilearray_size[1] / array_h; + } + + GPUTexture *tex = GPU_texture_create_1d_array(width, 2, GPU_RGBA32F, data, NULL); + GPU_texture_mipmap_mode(tex, false, false); + + MEM_freeN(data); + + return tex; +} + +typedef struct PackTile { + FixedSizeBoxPack boxpack; + ImageTile *tile; + float pack_score; +} PackTile; + +static int compare_packtile(const void *a, const void *b) +{ + const PackTile *tile_a = (const PackTile *)a; + const PackTile *tile_b = (const PackTile *)b; + + return tile_a->pack_score < tile_b->pack_score; +} + +static GPUTexture *gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf) +{ + int arraywidth = 0, arrayheight = 0; + ListBase boxes = {NULL}; + + LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { + ImageUser iuser; + BKE_imageuser_default(&iuser); + iuser.tile = tile->tile_number; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + + if (ibuf) { + PackTile *packtile = (PackTile *)MEM_callocN(sizeof(PackTile), __func__); + packtile->tile = tile; + packtile->boxpack.w = ibuf->x; + packtile->boxpack.h = ibuf->y; + + if (is_over_resolution_limit(packtile->boxpack.w, packtile->boxpack.h)) { + packtile->boxpack.w = smaller_power_of_2_limit(packtile->boxpack.w); + packtile->boxpack.h = smaller_power_of_2_limit(packtile->boxpack.h); + } + arraywidth = max_ii(arraywidth, packtile->boxpack.w); + arrayheight = max_ii(arrayheight, packtile->boxpack.h); + + /* We sort the tiles by decreasing size, with an additional penalty term + * for high aspect ratios. This improves packing efficiency. */ + float w = packtile->boxpack.w, h = packtile->boxpack.h; + packtile->pack_score = max_ff(w, h) / min_ff(w, h) * w * h; + + BKE_image_release_ibuf(ima, ibuf, NULL); + BLI_addtail(&boxes, packtile); + } + } + + BLI_assert(arraywidth > 0 && arrayheight > 0); + + BLI_listbase_sort(&boxes, compare_packtile); + int arraylayers = 0; + /* Keep adding layers until all tiles are packed. */ + while (boxes.first != NULL) { + ListBase packed = {NULL}; + BLI_box_pack_2d_fixedarea(&boxes, arraywidth, arrayheight, &packed); + BLI_assert(packed.first != NULL); + + LISTBASE_FOREACH (PackTile *, packtile, &packed) { + ImageTile *tile = packtile->tile; + int *tileoffset = tile->runtime.tilearray_offset; + int *tilesize = tile->runtime.tilearray_size; + + tileoffset[0] = packtile->boxpack.x; + tileoffset[1] = packtile->boxpack.y; + tilesize[0] = packtile->boxpack.w; + tilesize[1] = packtile->boxpack.h; + tile->runtime.tilearray_layer = arraylayers; + } + + BLI_freelistN(&packed); + arraylayers++; + } + + const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH); + /* Create Texture without content. */ + GPUTexture *tex = IMB_touch_gpu_texture( + main_ibuf, arraywidth, arrayheight, arraylayers, use_high_bitdepth); + + GPU_texture_bind(tex, 0); + + /* Upload each tile one by one. */ + LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { + int tilelayer = tile->runtime.tilearray_layer; + int *tileoffset = tile->runtime.tilearray_offset; + int *tilesize = tile->runtime.tilearray_size; + + if (tilesize[0] == 0 || tilesize[1] == 0) { + continue; + } + + ImageUser iuser; + BKE_imageuser_default(&iuser); + iuser.tile = tile->tile_number; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + + if (ibuf) { + const bool store_premultiplied = ibuf->rect_float ? (ima->alpha_mode != IMA_ALPHA_STRAIGHT) : + (ima->alpha_mode == IMA_ALPHA_PREMUL); + IMB_update_gpu_texture_sub(tex, + ibuf, + UNPACK2(tileoffset), + tilelayer, + UNPACK2(tilesize), + use_high_bitdepth, + store_premultiplied); + } + + BKE_image_release_ibuf(ima, ibuf, NULL); + } + + if (GPU_mipmap_enabled()) { + GPU_texture_generate_mipmap(tex); + GPU_texture_mipmap_mode(tex, true, true); + if (ima) { + ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; + } + } + else { + GPU_texture_mipmap_mode(tex, false, true); + } + + GPU_texture_unbind(tex); + + return tex; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Regular gpu texture + * \{ */ + +static GPUTexture **get_image_gpu_texture_ptr(Image *ima, + eGPUTextureTarget textarget, + const int multiview_eye) +{ + const bool in_range = (textarget >= 0) && (textarget < TEXTARGET_COUNT); + BLI_assert(in_range); + + if (in_range) { + return &(ima->gputexture[textarget][multiview_eye]); + } + return NULL; +} + +static GPUTexture *image_gpu_texture_error_create(eGPUTextureTarget textarget) +{ + switch (textarget) { + case TEXTARGET_2D_ARRAY: + return GPU_texture_create_error(2, true); + case TEXTARGET_TILE_MAPPING: + return GPU_texture_create_error(1, true); + case TEXTARGET_2D: + default: + return GPU_texture_create_error(2, false); + } +} + +static GPUTexture *image_get_gpu_texture(Image *ima, + ImageUser *iuser, + ImBuf *ibuf, + eGPUTextureTarget textarget) +{ + if (ima == NULL) { + return NULL; + } + + /* Free any unused GPU textures, since we know we are in a thread with OpenGL + * context and might as well ensure we have as much space free as possible. */ + gpu_free_unused_buffers(); + + /* currently, gpu refresh tagging is used by ima sequences */ + if (ima->gpuflag & IMA_GPU_REFRESH) { + image_free_gpu(ima, true); + ima->gpuflag &= ~IMA_GPU_REFRESH; + } + + /* Tag as in active use for garbage collector. */ + BKE_image_tag_time(ima); + + /* Test if we already have a texture. */ + GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, iuser ? iuser->multiview_eye : 0); + if (*tex) { + return *tex; + } + + /* Check if we have a valid image. If not, we return a dummy + * texture with zero bind-code so we don't keep trying. */ + ImageTile *tile = BKE_image_get_tile(ima, 0); + if (tile == NULL || tile->ok == 0) { + *tex = image_gpu_texture_error_create(textarget); + return *tex; + } + + /* check if we have a valid image buffer */ + ImBuf *ibuf_intern = ibuf; + if (ibuf_intern == NULL) { + ibuf_intern = BKE_image_acquire_ibuf(ima, iuser, NULL); + if (ibuf_intern == NULL) { + *tex = image_gpu_texture_error_create(textarget); + return *tex; + } + } + + if (textarget == TEXTARGET_2D_ARRAY) { + *tex = gpu_texture_create_tile_array(ima, ibuf_intern); + } + else if (textarget == TEXTARGET_TILE_MAPPING) { + *tex = gpu_texture_create_tile_mapping(ima, iuser ? iuser->multiview_eye : 0); + } + else { + const bool use_high_bitdepth = (ima->flag & IMA_HIGH_BITDEPTH); + const bool store_premultiplied = ibuf_intern->rect_float ? + (ima ? (ima->alpha_mode != IMA_ALPHA_STRAIGHT) : false) : + (ima ? (ima->alpha_mode == IMA_ALPHA_PREMUL) : true); + + *tex = IMB_create_gpu_texture(ibuf_intern, use_high_bitdepth, store_premultiplied); + + if (GPU_mipmap_enabled()) { + GPU_texture_bind(*tex, 0); + GPU_texture_generate_mipmap(*tex); + GPU_texture_unbind(*tex); + if (ima) { + ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; + } + GPU_texture_mipmap_mode(*tex, true, true); + } + else { + GPU_texture_mipmap_mode(*tex, false, true); + } + } + + /* if `ibuf` was given, we don't own the `ibuf_intern` */ + if (ibuf == NULL) { + BKE_image_release_ibuf(ima, ibuf_intern, NULL); + } + + GPU_texture_orig_size_set(*tex, ibuf_intern->x, ibuf_intern->y); + + return *tex; +} + +GPUTexture *BKE_image_get_gpu_texture(Image *image, ImageUser *iuser, ImBuf *ibuf) +{ + return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_2D); +} + +GPUTexture *BKE_image_get_gpu_tiles(Image *image, ImageUser *iuser, ImBuf *ibuf) +{ + return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_2D_ARRAY); +} + +GPUTexture *BKE_image_get_gpu_tilemap(Image *image, ImageUser *iuser, ImBuf *ibuf) +{ + return image_get_gpu_texture(image, iuser, ibuf, TEXTARGET_TILE_MAPPING); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delayed GPU texture free + * + * Image datablocks can be deleted by any thread, but there may not be any active OpenGL context. + * In that case we push them into a queue and free the buffers later. + * \{ */ + +static LinkNode *gpu_texture_free_queue = NULL; +static ThreadMutex gpu_texture_queue_mutex = BLI_MUTEX_INITIALIZER; + +static void gpu_free_unused_buffers(void) +{ + if (gpu_texture_free_queue == NULL) { + return; + } + + BLI_mutex_lock(&gpu_texture_queue_mutex); + + while (gpu_texture_free_queue != NULL) { + GPUTexture *tex = BLI_linklist_pop(&gpu_texture_free_queue); + GPU_texture_free(tex); + } + + BLI_mutex_unlock(&gpu_texture_queue_mutex); +} + +void BKE_image_free_unused_gpu_textures() +{ + if (BLI_thread_is_main()) { + gpu_free_unused_buffers(); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Deletion + * \{ */ + +static void image_free_gpu(Image *ima, const bool immediate) +{ + for (int eye = 0; eye < 2; eye++) { + for (int i = 0; i < TEXTARGET_COUNT; i++) { + if (ima->gputexture[i][eye] != NULL) { + if (immediate) { + GPU_texture_free(ima->gputexture[i][eye]); + } + else { + BLI_mutex_lock(&gpu_texture_queue_mutex); + BLI_linklist_prepend(&gpu_texture_free_queue, ima->gputexture[i][eye]); + BLI_mutex_unlock(&gpu_texture_queue_mutex); + } + + ima->gputexture[i][eye] = NULL; + } + } + } + + ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; +} + +void BKE_image_free_gputextures(Image *ima) +{ + image_free_gpu(ima, BLI_thread_is_main()); +} + +void BKE_image_free_all_gputextures(Main *bmain) +{ + if (bmain) { + LISTBASE_FOREACH (Image *, ima, &bmain->images) { + BKE_image_free_gputextures(ima); + } + } +} + +/* same as above but only free animated images */ +void BKE_image_free_anim_gputextures(Main *bmain) +{ + if (bmain) { + LISTBASE_FOREACH (Image *, ima, &bmain->images) { + if (BKE_image_is_animated(ima)) { + BKE_image_free_gputextures(ima); + } + } + } +} + +void BKE_image_free_old_gputextures(Main *bmain) +{ + static int lasttime = 0; + int ctime = (int)PIL_check_seconds_timer(); + + /* + * Run garbage collector once for every collecting period of time + * if textimeout is 0, that's the option to NOT run the collector + */ + if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime) { + return; + } + + /* of course not! */ + if (G.is_rendering) { + return; + } + + lasttime = ctime; + + LISTBASE_FOREACH (Image *, ima, &bmain->images) { + if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) { + /* If it's in GL memory, deallocate and set time tag to current time + * This gives textures a "second chance" to be used before dying. */ + if (BKE_image_has_opengl_texture(ima)) { + BKE_image_free_gputextures(ima); + ima->lastused = ctime; + } + /* Otherwise, just kill the buffers */ + else { + BKE_image_free_buffers(ima); + } + } + } +} +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paint Update + * \{ */ + +static ImBuf *update_do_scale(uchar *rect, + float *rect_float, + int *x, + int *y, + int *w, + int *h, + int limit_w, + int limit_h, + int full_w, + int full_h) +{ + /* Partial update with scaling. */ + float xratio = limit_w / (float)full_w; + float yratio = limit_h / (float)full_h; + + int part_w = *w, part_h = *h; + + /* Find sub coordinates in scaled image. Take ceiling because we will be + * losing 1 pixel due to rounding errors in x,y. */ + *x *= xratio; + *y *= yratio; + *w = (int)ceil(xratio * (*w)); + *h = (int)ceil(yratio * (*h)); + + /* ...but take back if we are over the limit! */ + if (*x + *w > limit_w) { + (*w)--; + } + if (*y + *h > limit_h) { + (*h)--; + } + + /* Scale pixels. */ + ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, part_w, part_h, 4); + IMB_scaleImBuf(ibuf, *w, *h); + + return ibuf; +} + +static void gpu_texture_update_scaled(GPUTexture *tex, + uchar *rect, + float *rect_float, + int full_w, + int full_h, + int x, + int y, + int layer, + const int *tile_offset, + const int *tile_size, + int w, + int h) +{ + ImBuf *ibuf; + if (layer > -1) { + ibuf = update_do_scale( + rect, rect_float, &x, &y, &w, &h, tile_size[0], tile_size[1], full_w, full_h); + + /* Shift to account for tile packing. */ + x += tile_offset[0]; + y += tile_offset[1]; + } + else { + /* Partial update with scaling. */ + int limit_w = smaller_power_of_2_limit(full_w); + int limit_h = smaller_power_of_2_limit(full_h); + + ibuf = update_do_scale(rect, rect_float, &x, &y, &w, &h, limit_w, limit_h, full_w, full_h); + } + + void *data = (ibuf->rect_float) ? (void *)(ibuf->rect_float) : (void *)(ibuf->rect); + eGPUDataFormat data_format = (ibuf->rect_float) ? GPU_DATA_FLOAT : GPU_DATA_UNSIGNED_BYTE; + + GPU_texture_update_sub(tex, data_format, data, x, y, layer, w, h, 1); + + IMB_freeImBuf(ibuf); +} + +static void gpu_texture_update_unscaled(GPUTexture *tex, + uchar *rect, + float *rect_float, + int x, + int y, + int layer, + const int tile_offset[2], + int w, + int h, + int tex_stride, + int tex_offset) +{ + if (layer > -1) { + /* Shift to account for tile packing. */ + x += tile_offset[0]; + y += tile_offset[1]; + } + + void *data = (rect_float) ? (void *)(rect_float + tex_offset) : (void *)(rect + tex_offset); + eGPUDataFormat data_format = (rect_float) ? GPU_DATA_FLOAT : GPU_DATA_UNSIGNED_BYTE; + + /* Partial update without scaling. Stride and offset are used to copy only a + * subset of a possible larger buffer than what we are updating. */ + GPU_unpack_row_length_set(tex_stride); + + GPU_texture_update_sub(tex, data_format, data, x, y, layer, w, h, 1); + /* Restore default. */ + GPU_unpack_row_length_set(0); +} + +static void gpu_texture_update_from_ibuf( + GPUTexture *tex, Image *ima, ImBuf *ibuf, ImageTile *tile, int x, int y, int w, int h) +{ + bool scaled; + if (tile != NULL) { + int *tilesize = tile->runtime.tilearray_size; + scaled = (ibuf->x != tilesize[0]) || (ibuf->y != tilesize[1]); + } + else { + scaled = is_over_resolution_limit(ibuf->x, ibuf->y); + } + + if (scaled) { + /* Extra padding to account for bleed from neighboring pixels. */ + const int padding = 4; + const int xmax = min_ii(x + w + padding, ibuf->x); + const int ymax = min_ii(y + h + padding, ibuf->y); + x = max_ii(x - padding, 0); + y = max_ii(y - padding, 0); + w = xmax - x; + h = ymax - y; + } + + /* Get texture data pointers. */ + float *rect_float = ibuf->rect_float; + uchar *rect = (uchar *)ibuf->rect; + int tex_stride = ibuf->x; + int tex_offset = ibuf->channels * (y * ibuf->x + x); + + if (rect_float == NULL) { + /* Byte pixels. */ + if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) { + const bool compress_as_srgb = !IMB_colormanagement_space_is_scene_linear( + ibuf->rect_colorspace); + + rect = (uchar *)MEM_mallocN(sizeof(uchar) * 4 * w * h, __func__); + if (rect == NULL) { + return; + } + + tex_stride = w; + tex_offset = 0; + + /* Convert to scene linear with sRGB compression, and premultiplied for + * correct texture interpolation. */ + const bool store_premultiplied = (ima->alpha_mode == IMA_ALPHA_PREMUL); + IMB_colormanagement_imbuf_to_byte_texture( + rect, x, y, w, h, ibuf, compress_as_srgb, store_premultiplied); + } + } + else { + /* Float pixels. */ + const bool store_premultiplied = (ima->alpha_mode != IMA_ALPHA_STRAIGHT); + + if (ibuf->channels != 4 || scaled || !store_premultiplied) { + rect_float = (float *)MEM_mallocN(sizeof(float) * 4 * w * h, __func__); + if (rect_float == NULL) { + return; + } + + tex_stride = w; + tex_offset = 0; + + IMB_colormanagement_imbuf_to_float_texture( + rect_float, x, y, w, h, ibuf, store_premultiplied); + } + } + + GPU_texture_bind(tex, 0); + + if (scaled) { + /* Slower update where we first have to scale the input pixels. */ + if (tile != NULL) { + int *tileoffset = tile->runtime.tilearray_offset; + int *tilesize = tile->runtime.tilearray_size; + int tilelayer = tile->runtime.tilearray_layer; + gpu_texture_update_scaled( + tex, rect, rect_float, ibuf->x, ibuf->y, x, y, tilelayer, tileoffset, tilesize, w, h); + } + else { + gpu_texture_update_scaled( + tex, rect, rect_float, ibuf->x, ibuf->y, x, y, -1, NULL, NULL, w, h); + } + } + else { + /* Fast update at same resolution. */ + if (tile != NULL) { + int *tileoffset = tile->runtime.tilearray_offset; + int tilelayer = tile->runtime.tilearray_layer; + gpu_texture_update_unscaled( + tex, rect, rect_float, x, y, tilelayer, tileoffset, w, h, tex_stride, tex_offset); + } + else { + gpu_texture_update_unscaled( + tex, rect, rect_float, x, y, -1, NULL, w, h, tex_stride, tex_offset); + } + } + + /* Free buffers if needed. */ + if (rect && rect != (uchar *)ibuf->rect) { + MEM_freeN(rect); + } + if (rect_float && rect_float != ibuf->rect_float) { + MEM_freeN(rect_float); + } + + if (GPU_mipmap_enabled()) { + GPU_texture_generate_mipmap(tex); + } + else { + ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; + } + + GPU_texture_unbind(tex); +} + +/* Partial update of texture for texture painting. This is often much + * quicker than fully updating the texture for high resolution images. */ +void BKE_image_update_gputexture(Image *ima, ImageUser *iuser, int x, int y, int w, int h) +{ + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser); + + if ((ibuf == NULL) || (w == 0) || (h == 0)) { + /* Full reload of texture. */ + BKE_image_free_gputextures(ima); + } + + GPUTexture *tex = ima->gputexture[TEXTARGET_2D][0]; + /* Check if we need to update the main gputexture. */ + if (tex != NULL && tile == ima->tiles.first) { + gpu_texture_update_from_ibuf(tex, ima, ibuf, NULL, x, y, w, h); + } + + /* Check if we need to update the array gputexture. */ + tex = ima->gputexture[TEXTARGET_2D_ARRAY][0]; + if (tex != NULL) { + gpu_texture_update_from_ibuf(tex, ima, ibuf, tile, x, y, w, h); + } + + BKE_image_release_ibuf(ima, ibuf, NULL); +} + +/* these two functions are called on entering and exiting texture paint mode, + * temporary disabling/enabling mipmapping on all images for quick texture + * updates with glTexSubImage2D. images that didn't change don't have to be + * re-uploaded to OpenGL */ +void BKE_image_paint_set_mipmap(Main *bmain, bool mipmap) +{ + LISTBASE_FOREACH (Image *, ima, &bmain->images) { + if (BKE_image_has_opengl_texture(ima)) { + if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) { + for (int eye = 0; eye < 2; eye++) { + for (int a = 0; a < TEXTARGET_COUNT; a++) { + if (ELEM(a, TEXTARGET_2D, TEXTARGET_2D_ARRAY)) { + GPUTexture *tex = ima->gputexture[a][eye]; + if (tex != NULL) { + GPU_texture_mipmap_mode(tex, mipmap, true); + } + } + } + } + } + else { + BKE_image_free_gputextures(ima); + } + } + else { + ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; + } + } +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index af8ab22e14b..a71b9cc2a1d 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -529,7 +529,13 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float t[4], int cycl) return 0; } -static void flerp(int tot, float *in, float *f0, float *f1, float *f2, float *f3, float *t) +static void flerp(int tot, + float *in, + const float *f0, + const float *f1, + const float *f2, + const float *f3, + const float *t) { int a; @@ -538,7 +544,7 @@ static void flerp(int tot, float *in, float *f0, float *f1, float *f2, float *f3 } } -static void rel_flerp(int tot, float *in, float *ref, float *out, float fac) +static void rel_flerp(int tot, float *in, const float *ref, const float *out, float fac) { int a; @@ -1541,6 +1547,134 @@ float *BKE_key_evaluate_object(Object *ob, int *r_totelem) return BKE_key_evaluate_object_ex(ob, r_totelem, NULL, 0); } +/** + * \param shape_index: The index to use or all (when -1). + */ +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)) { + result += kb->totelem; + } + } + return result; +} + +int BKE_keyblock_element_count(const Key *key) +{ + return BKE_keyblock_element_count_from_shape(key, -1); +} + +/** + * \param shape_index: The index to use or all (when -1). + */ +size_t BKE_keyblock_element_calc_size_from_shape(const Key *key, const int shape_index) +{ + return (size_t)BKE_keyblock_element_count_from_shape(key, shape_index) * key->elemsize; +} + +size_t BKE_keyblock_element_calc_size(const Key *key) +{ + return BKE_keyblock_element_calc_size_from_shape(key, -1); +} + +/* -------------------------------------------------------------------- */ +/** \name Key-Block Data Access + * + * Utilities for getting/setting key data as a single array, + * use #BKE_keyblock_element_calc_size to allocate the size of the data needed. + * \{ */ + +/** + * \param shape_index: The index to use or all (when -1). + */ +void BKE_keyblock_data_get_from_shape(const Key *key, float (*arr)[3], const int shape_index) +{ + 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)) { + const int block_elem_len = kb->totelem * key->elemsize; + memcpy(elements, kb->data, block_elem_len); + elements += block_elem_len; + } + } +} + +void BKE_keyblock_data_get(const Key *key, float (*arr)[3]) +{ + BKE_keyblock_data_get_from_shape(key, arr, -1); +} + +/** + * Set the data to all key-blocks (or shape_index if != -1). + */ +void BKE_keyblock_data_set_with_mat4(Key *key, + const int shape_index, + const float (*coords)[3], + const float mat[4][4]) +{ + if (key->elemsize != sizeof(float[3])) { + BLI_assert(!"Invalid elemsize"); + return; + } + + const float(*elements)[3] = coords; + + int index = 0; + for (KeyBlock *kb = key->block.first; kb; kb = kb->next, index++) { + if ((shape_index == -1) || (index == shape_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) { + const float *src_data = (const float *)(elements + data_offset); + float *dst_data = (float *)(block_data + data_offset); + mul_v3_m4v3(dst_data, mat, src_data); + } + elements += block_elem_len; + } + } +} + +/** + * Set the data for all key-blocks (or shape_index if != -1), + * transforming by \a mat. + */ +void BKE_keyblock_curve_data_set_with_mat4( + Key *key, const ListBase *nurb, const int shape_index, const void *data, const float mat[4][4]) +{ + 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)) { + const int block_elem_size = kb->totelem * key->elemsize; + BKE_keyblock_curve_data_transform(nurb, mat, elements, kb->data); + elements += block_elem_size; + } + } +} + +/** + * Set the data for all key-blocks (or shape_index if != -1). + */ +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)) { + const int block_elem_size = kb->totelem * key->elemsize; + memcpy(kb->data, elements, block_elem_size); + elements += block_elem_size; + } + } +} + +/** \} */ + bool BKE_key_idtype_support(const short id_type) { switch (id_type) { @@ -1897,6 +2031,37 @@ void BKE_keyblock_update_from_curve(Curve *UNUSED(cu), KeyBlock *kb, ListBase *n } } +void BKE_keyblock_curve_data_transform(const ListBase *nurb, + const float mat[4][4], + const void *src_data, + void *dst_data) +{ + const float *src = src_data; + float *dst = dst_data; + for (Nurb *nu = nurb->first; nu; nu = nu->next) { + if (nu->bezt) { + for (int a = nu->pntsu; a; a--) { + for (int i = 0; i < 3; i++) { + mul_v3_m4v3(&dst[i * 3], mat, &src[i * 3]); + } + dst[9] = src[9]; + dst[10] = src[10]; + src += KEYELEM_FLOAT_LEN_BEZTRIPLE; + dst += KEYELEM_FLOAT_LEN_BEZTRIPLE; + } + } + else { + for (int a = nu->pntsu * nu->pntsv; a; a--) { + mul_v3_m4v3(dst, mat, src); + dst[3] = src[3]; + dst[4] = src[4]; + src += KEYELEM_FLOAT_LEN_BPOINT; + dst += KEYELEM_FLOAT_LEN_BPOINT; + } + } + } +} + void BKE_keyblock_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb) { int tot; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 8820434cbcf..4d523ffa2e0 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -672,7 +672,7 @@ void BKE_lattice_center_bounds(Lattice *lt, float cent[3]) mid_v3_v3v3(cent, min, max); } -void BKE_lattice_transform(Lattice *lt, float mat[4][4], bool do_keys) +void BKE_lattice_transform(Lattice *lt, const float mat[4][4], bool do_keys) { BPoint *bp = lt->def; int i = lt->pntsu * lt->pntsv * lt->pntsw; @@ -694,7 +694,7 @@ void BKE_lattice_transform(Lattice *lt, float mat[4][4], bool do_keys) } } -void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys) +void BKE_lattice_translate(Lattice *lt, const float offset[3], bool do_keys) { int i, numVerts; diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c index 2b3349d4d9a..674ee9ed2c5 100644 --- a/source/blender/blenkernel/intern/lattice_deform.c +++ b/source/blender/blenkernel/intern/lattice_deform.c @@ -418,8 +418,8 @@ static void lattice_deform_coords_impl(const Object *ob_lattice, void BKE_lattice_deform_coords(const Object *ob_lattice, const Object *ob_target, float (*vert_coords)[3], - int vert_coords_len, - short flag, + const int vert_coords_len, + const short flag, const char *defgrp_name, float fac) { diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index f03bf60817f..83071fd5dd3 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -221,7 +221,7 @@ ViewLayer *BKE_view_layer_add(Scene *scene, view_layer_new = view_layer_add(name); BLI_addtail(&scene->view_layers, view_layer_new); - /* Initialise layercollections */ + /* Initialize layer-collections. */ BKE_layer_collection_sync(scene, view_layer_new); layer_collection_exclude_all(view_layer_new->layer_collections.first); @@ -695,8 +695,8 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection * stores state like selection. */ static void layer_collection_sync(ViewLayer *view_layer, - const ListBase *lb_scene, - ListBase *lb_layer, + const ListBase *lb_collections, + ListBase *lb_layer_collections, ListBase *new_object_bases, short parent_exclude, short parent_restrict, @@ -708,11 +708,10 @@ static void layer_collection_sync(ViewLayer *view_layer, * linking we can only sync after the fact. */ /* Remove layer collections that no longer have a corresponding scene collection. */ - for (LayerCollection *lc = lb_layer->first; lc;) { - /* Note ID remap can set lc->collection to NULL when deleting collections. */ - LayerCollection *lc_next = lc->next; + LISTBASE_FOREACH_MUTABLE (LayerCollection *, lc, lb_layer_collections) { + /* Note that ID remap can set lc->collection to NULL when deleting collections. */ Collection *collection = (lc->collection) ? - BLI_findptr(lb_scene, + BLI_findptr(lb_collections, lc->collection, offsetof(CollectionChild, collection)) : NULL; @@ -724,21 +723,20 @@ static void layer_collection_sync(ViewLayer *view_layer, /* Free recursively. */ layer_collection_free(view_layer, lc); - BLI_freelinkN(lb_layer, lc); + BLI_freelinkN(lb_layer_collections, lc); } - - lc = lc_next; } /* Add layer collections for any new scene collections, and ensure order is the same. */ ListBase new_lb_layer = {NULL, NULL}; - LISTBASE_FOREACH (const CollectionChild *, child, lb_scene) { + LISTBASE_FOREACH (const CollectionChild *, child, lb_collections) { Collection *collection = child->collection; - LayerCollection *lc = BLI_findptr(lb_layer, collection, offsetof(LayerCollection, collection)); + LayerCollection *lc = BLI_findptr( + lb_layer_collections, collection, offsetof(LayerCollection, collection)); if (lc) { - BLI_remlink(lb_layer, lc); + BLI_remlink(lb_layer_collections, lc); BLI_addtail(&new_lb_layer, lc); } else { @@ -845,8 +843,8 @@ static void layer_collection_sync(ViewLayer *view_layer, } /* Replace layer collection list with new one. */ - *lb_layer = new_lb_layer; - BLI_assert(BLI_listbase_count(lb_scene) == BLI_listbase_count(lb_layer)); + *lb_layer_collections = new_lb_layer; + BLI_assert(BLI_listbase_count(lb_collections) == BLI_listbase_count(lb_layer_collections)); } /** @@ -876,9 +874,9 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer) } /* Generate new layer connections and object bases when collections changed. */ - CollectionChild child = {NULL, NULL, scene->master_collection}; - const ListBase collections = {&child, &child}; - ListBase new_object_bases = {NULL, NULL}; + CollectionChild child = {.next = NULL, .prev = NULL, .collection = scene->master_collection}; + const ListBase collections = {.first = &child, .last = &child}; + ListBase new_object_bases = {.first = NULL, .last = NULL}; const short parent_exclude = 0, parent_restrict = 0, parent_layer_restrict = 0; layer_collection_sync(view_layer, diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 7c09ae51344..a64e550579d 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -611,41 +611,39 @@ bool BKE_id_copy(Main *bmain, const ID *id, ID **newid) * Invokes the appropriate copy method for the block and returns the result in * newid, unless test. Returns true if the block can be copied. */ -ID *BKE_id_copy_for_duplicate(Main *bmain, - ID *id, - const bool is_owner_id_liboverride, - const eDupli_ID_Flags duplicate_flags) +ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplicate_flags) { if (id == NULL) { - return NULL; + return id; } if (id->newid == NULL) { - if (!is_owner_id_liboverride || !ID_IS_LINKED(id)) { - ID *id_new; - BKE_id_copy(bmain, id, &id_new); - /* Copying add one user by default, need to get rid of that one. */ - id_us_min(id_new); - ID_NEW_SET(id, id_new); - - /* Shape keys are always copied with their owner ID, by default. */ - ID *key_new = (ID *)BKE_key_from_id(id_new); - ID *key = (ID *)BKE_key_from_id(id); - if (key != NULL) { - ID_NEW_SET(key, key_new); - } + const bool do_linked_id = (duplicate_flags & USER_DUP_LINKED_ID) != 0; + if (!(do_linked_id || !ID_IS_LINKED(id))) { + return id; + } - /* Note: embedded data (root nodetrees and master collections) should never be referenced by - * anything else, so we do not need to set their newid pointer and flag. */ + ID *id_new; + BKE_id_copy(bmain, id, &id_new); + /* Copying add one user by default, need to get rid of that one. */ + id_us_min(id_new); + ID_NEW_SET(id, id_new); - if (duplicate_flags & USER_DUP_ACT) { - BKE_animdata_copy_id_action(bmain, id_new, true); - if (key_new != NULL) { - BKE_animdata_copy_id_action(bmain, key_new, true); - } - /* Note that actions of embedded data (root nodetrees and master collections) are handled - * by `BKE_animdata_copy_id_action` as well. */ - } + /* Shape keys are always copied with their owner ID, by default. */ + ID *key_new = (ID *)BKE_key_from_id(id_new); + ID *key = (ID *)BKE_key_from_id(id); + if (key != NULL) { + ID_NEW_SET(key, key_new); } + + /* Note: embedded data (root nodetrees and master collections) should never be referenced by + * anything else, so we do not need to set their newid pointer and flag. */ + + BKE_animdata_duplicate_id_action(bmain, id_new, duplicate_flags); + if (key_new != NULL) { + BKE_animdata_duplicate_id_action(bmain, id_new, duplicate_flags); + } + /* Note that actions of embedded data (root nodetrees and master collections) are handled + * by `BKE_animdata_duplicate_id_action` as well. */ } return id->newid; } @@ -2163,7 +2161,7 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separa /** * Generate full name of the data-block (without ID code, but with library if any), - * with a 3-character prefix prepended indicating whether it comes from a library, + * with a 2 to 3 character prefix prepended indicating whether it comes from a library, * is overriding, has a fake or no user, etc. * * \note Result is unique to a given ID type in a given Main database. @@ -2172,11 +2170,13 @@ void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separa * will be filled with generated string. * \param separator_char: Character to use for separating name and library name. Can be 0 to use * default (' '). + * \param r_prefix_len: The length of the prefix added. */ void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const ID *id, const bool add_lib_hint, - char separator_char) + char separator_char, + int *r_prefix_len) { int i = 0; @@ -2187,6 +2187,10 @@ void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], name[i++] = ' '; BKE_id_full_name_get(name + i, id, separator_char); + + if (r_prefix_len) { + *r_prefix_len = i; + } } /** diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index b4f2caac861..561db7d62c2 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -144,15 +144,14 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i } #endif + Key *key = ((flag & LIB_ID_FREE_NO_MAIN) == 0) ? BKE_key_from_id(id) : NULL; + if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) { BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0); } - if ((flag & LIB_ID_FREE_NO_MAIN) == 0) { - Key *key = BKE_key_from_id(id); - if (key != NULL) { - BKE_id_free_ex(bmain, &key->id, flag, use_flag_from_idtag); - } + if ((flag & LIB_ID_FREE_NO_MAIN) == 0 && key != NULL) { + BKE_id_free_ex(bmain, &key->id, flag, use_flag_from_idtag); } BKE_libblock_free_datablock(id, flag); diff --git a/source/blender/blenkernel/intern/lib_intern.h b/source/blender/blenkernel/intern/lib_intern.h index 9cc5db64d17..7305785573b 100644 --- a/source/blender/blenkernel/intern/lib_intern.h +++ b/source/blender/blenkernel/intern/lib_intern.h @@ -21,11 +21,8 @@ * \ingroup bke */ -#ifndef __LIB_INTERN_H__ -#define __LIB_INTERN_H__ +#pragma once extern BKE_library_free_notifier_reference_cb free_notifier_reference_cb; extern BKE_library_remap_editor_id_reference_cb remap_editor_id_reference_cb; - -#endif /* __LIB_INTERN_H__ */ diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 457d096f983..8b0517a77fb 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -27,19 +27,25 @@ #include "MEM_guardedalloc.h" #include "DNA_ID.h" +#include "DNA_collection_types.h" #include "DNA_key_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "BKE_armature.h" +#include "BKE_collection.h" #include "BKE_idtype.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" +#include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" +#include "BKE_scene.h" #include "BLI_ghash.h" #include "BLI_listbase.h" @@ -66,20 +72,6 @@ static void lib_override_library_property_clear(IDOverrideLibraryProperty *op); static void lib_override_library_property_operation_clear( IDOverrideLibraryPropertyOperation *opop); -/* Temp, for until library override is ready and tested enough to go 'public', - * we hide it by default in UI and such. */ -static bool _lib_override_library_enabled = true; - -void BKE_lib_override_library_enable(const bool do_enable) -{ - _lib_override_library_enabled = do_enable; -} - -bool BKE_lib_override_library_is_enabled() -{ - return _lib_override_library_enabled; -} - /** Initialize empty overriding of \a reference_id by \a local_id. */ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) { @@ -163,8 +155,8 @@ void BKE_lib_override_library_clear(IDOverrideLibrary *override, const bool do_i { BLI_assert(override != NULL); - if (override->runtime != NULL) { - BLI_ghash_clear(override->runtime, NULL, NULL); + if (!ELEM(NULL, override->runtime, override->runtime->rna_path_to_override_properties)) { + BLI_ghash_clear(override->runtime->rna_path_to_override_properties, NULL, NULL); } LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &override->properties) { @@ -184,8 +176,10 @@ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bo BLI_assert(*override != NULL); if ((*override)->runtime != NULL) { - BLI_ghash_free((*override)->runtime, NULL, NULL); - (*override)->runtime = NULL; + if ((*override)->runtime->rna_path_to_override_properties != NULL) { + BLI_ghash_free((*override)->runtime->rna_path_to_override_properties, NULL, NULL); + } + MEM_SAFE_FREE((*override)->runtime); } BKE_lib_override_library_clear(*override, do_id_user); @@ -368,19 +362,284 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain) return success; } -/* We only build override GHash on request. */ -BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_mapping_ensure( +static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint tag) +{ + void **entry_vp = BLI_ghash_lookup_p(bmain->relations->id_user_to_used, id); + if (entry_vp == NULL) { + /* Already processed. */ + return (id->tag & tag) != 0; + } + + /* This way we won't process again that ID should we encounter it again through another + * relationship hierarchy. + * Note that this does not free any memory from relations, so we can still use the entries. + */ + BKE_main_relations_ID_remove(bmain, id); + + for (MainIDRelationsEntry *entry = *entry_vp; entry != NULL; entry = entry->next) { + if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) { + /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as + * actual dependencies. */ + continue; + } + /* We only consider IDs from the same library. */ + if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { + if (lib_override_hierarchy_recursive_tag(bmain, *entry->id_pointer, tag)) { + id->tag |= tag; + } + } + } + + return (id->tag & tag) != 0; +} + +/** + * Tag all IDs in given \a bmain that are being used by given \a id_root ID or its dependencies, + * recursively. + * + * This will include all local IDs, and all IDs from the same library as the \a id_root. + * + * \param id_root The root of the hierarchy of dependencies to be tagged. + * \param do_create_main_relashionships Whether main relations needs to be created or already exist + * (in any case, they will be freed by this function). + */ +void BKE_lib_override_library_dependencies_tag(struct Main *bmain, + struct ID *id_root, + const uint tag, + const bool do_create_main_relashionships) +{ + if (do_create_main_relashionships) { + BKE_main_relations_create(bmain, 0); + } + + /* Then we tag all intermediary data-blocks in-between two overridden ones (e.g. if a shapekey + * has a driver using an armature object's bone, we need to override the shapekey/obdata, the + * objects using them, etc.) */ + lib_override_hierarchy_recursive_tag(bmain, id_root, tag); + + BKE_main_relations_free(bmain); +} + +static int lib_override_library_make_tag_ids_cb(LibraryIDLinkCallbackData *cb_data) +{ + if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) { + return IDWALK_RET_STOP_RECURSION; + } + + ID *id_root = cb_data->user_data; + Library *library_root = id_root->lib; + ID *id = *cb_data->id_pointer; + ID *id_owner = cb_data->id_owner; + + BLI_assert(id_owner == cb_data->id_self); + + if (ELEM(id, NULL, id_owner)) { + return IDWALK_RET_NOP; + } + + BLI_assert(id->lib != NULL); + BLI_assert(id_owner->lib == library_root); + + if (id->tag & LIB_TAG_DOIT) { + /* Already processed, but maybe not with the same chain of dependency, so we need to check that + * one nonetheless. */ + return IDWALK_RET_STOP_RECURSION; + } + + if (id->lib != library_root) { + /* We do not override data-blocks from other libraries, nor do we process them. */ + return IDWALK_RET_STOP_RECURSION; + } + + /* We tag all collections and objects for override. And we also tag all other data-blocks which + * would user one of those. */ + if (ELEM(GS(id->name), ID_OB, ID_GR)) { + id->tag |= LIB_TAG_DOIT; + } + + return IDWALK_RET_NOP; +} + +/** + * Advanced 'smart' function to create fully functional overrides. + * + * \note Currently it only does special things if given \a id_root is an object of collection, more + * specific behaviors may be added in the future for other ID types. + * + * \note It will overrides all IDs tagged with \a LIB_TAG_DOIT, and it does not clear that tag at + * its beginning, so caller code can add extra data-blocks to be overridden as well. + * + * \note In the future that same function may be extended to support 'refresh' of overrides + * (rebuilding overrides from linked data, trying to preserve local overrides already defined). + * + * \param id_root The root ID to create an override from. + * \param id_reference some reference ID used to do some post-processing after overrides have been + * created, may be NULL. Typically, the Empty object instantiating the linked + * collection we override, currently. + * \return true if override was successfully created. + */ +bool BKE_lib_override_library_create( + Main *bmain, Scene *scene, ViewLayer *view_layer, ID *id_root, ID *id_reference) +{ + /* Tag all collections and objects, as well as other IDs using them. */ + id_root->tag |= LIB_TAG_DOIT; + + BKE_main_relations_create(bmain, 0); + + if (ELEM(GS(id_root->name), ID_OB, ID_GR)) { + BKE_library_foreach_ID_link(bmain, + id_root, + lib_override_library_make_tag_ids_cb, + id_root, + IDWALK_READONLY | IDWALK_RECURSE); + + /* Then, we remove (untag) bone shape objects, you shall never want to override those + * (hopefully)... */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & LIB_TAG_DOIT)) { + for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) { + if (pchan->custom != NULL) { + pchan->custom->id.tag &= ~LIB_TAG_DOIT; + } + } + } + } + } + + /* Note that this call will also free the main relations data we created above. */ + BKE_lib_override_library_dependencies_tag(bmain, id_root, LIB_TAG_DOIT, false); + + const bool success = BKE_lib_override_library_create_from_tag(bmain); + + if (success) { + BKE_main_collection_sync(bmain); + + switch (GS(id_root->name)) { + case ID_GR: { + Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ? + (Object *)id_reference : + NULL; + Collection *collection_new = ((Collection *)id_root->newid); + if (ob_reference != NULL) { + BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new); + } + else { + BKE_collection_add_from_collection( + bmain, scene, ((Collection *)id_root), collection_new); + } + + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection_new, ob_new) { + if (ob_new != NULL && ob_new->id.override_library != NULL) { + if (ob_reference != NULL) { + Base *base; + if ((base = BKE_view_layer_base_find(view_layer, ob_new)) == NULL) { + BKE_collection_object_add_from(bmain, scene, ob_reference, ob_new); + base = BKE_view_layer_base_find(view_layer, ob_new); + DEG_id_tag_update_ex( + bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + } + + if (ob_new == (Object *)ob_reference->id.newid) { + /* TODO: is setting active needed? */ + BKE_view_layer_base_select_and_set_active(view_layer, base); + } + } + else if (BKE_view_layer_base_find(view_layer, ob_new) == NULL) { + BKE_collection_object_add(bmain, collection_new, ob_new); + DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + } + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + break; + } + case ID_OB: { + BKE_collection_object_add_from( + bmain, scene, (Object *)id_root, ((Object *)id_root->newid)); + break; + } + default: + break; + } + + /* We need to ensure all new overrides of objects are properly instantiated. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + Object *ob_new = (Object *)ob->id.newid; + if (ob_new != NULL) { + BLI_assert(ob_new->id.override_library != NULL && + ob_new->id.override_library->reference == &ob->id); + + Collection *default_instantiating_collection = NULL; + if (BKE_view_layer_base_find(view_layer, ob_new) == NULL) { + if (default_instantiating_collection == NULL) { + switch (GS(id_root->name)) { + case ID_GR: { + default_instantiating_collection = BKE_collection_add( + bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); + break; + } + case ID_OB: { + /* Add the new container collection to one of the collections instantiating the + * root object, or scene's master collection if none found. */ + Object *ob_root = (Object *)id_root; + LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { + if (BKE_collection_has_object(collection, ob_root) && + BKE_view_layer_has_collection(view_layer, collection) && + !ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection)) { + default_instantiating_collection = BKE_collection_add( + bmain, collection, "OVERRIDE_HIDDEN"); + } + } + if (default_instantiating_collection == NULL) { + default_instantiating_collection = BKE_collection_add( + bmain, scene->master_collection, "OVERRIDE_HIDDEN"); + } + break; + } + default: + BLI_assert(0); + } + /* Hide the collection from viewport and render. */ + default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | + COLLECTION_RESTRICT_RENDER; + } + + BKE_collection_object_add(bmain, default_instantiating_collection, ob_new); + DEG_id_tag_update_ex(bmain, &ob_new->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); + } + } + } + } + + /* Cleanup. */ + BKE_main_id_clear_newpoins(bmain); + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + + return success; +} + +BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_runtime_ensure( IDOverrideLibrary *override) { if (override->runtime == NULL) { - override->runtime = BLI_ghash_new( + override->runtime = MEM_callocN(sizeof(*override->runtime), __func__); + } + return override->runtime; +} + +/* We only build override GHash on request. */ +BLI_INLINE GHash *override_library_rna_path_mapping_ensure(IDOverrideLibrary *override) +{ + IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_runtime_ensure(override); + if (override_runtime->rna_path_to_override_properties == NULL) { + override_runtime->rna_path_to_override_properties = BLI_ghash_new( BLI_ghashutil_strhash_p_murmur, BLI_ghashutil_strcmp, __func__); for (IDOverrideLibraryProperty *op = override->properties.first; op != NULL; op = op->next) { - BLI_ghash_insert(override->runtime, op->rna_path, op); + BLI_ghash_insert(override_runtime->rna_path_to_override_properties, op->rna_path, op); } } - return override->runtime; + return override_runtime->rna_path_to_override_properties; } /** @@ -389,7 +648,7 @@ BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_mapping_ensure( IDOverrideLibraryProperty *BKE_lib_override_library_property_find(IDOverrideLibrary *override, const char *rna_path) { - IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_mapping_ensure(override); + GHash *override_runtime = override_library_rna_path_mapping_ensure(override); return BLI_ghash_lookup(override_runtime, rna_path); } @@ -407,8 +666,7 @@ IDOverrideLibraryProperty *BKE_lib_override_library_property_get(IDOverrideLibra op->rna_path = BLI_strdup(rna_path); BLI_addtail(&override->properties, op); - IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_mapping_ensure( - override); + GHash *override_runtime = override_library_rna_path_mapping_ensure(override); BLI_ghash_insert(override_runtime, op->rna_path, op); if (r_created) { @@ -454,8 +712,11 @@ void lib_override_library_property_clear(IDOverrideLibraryProperty *op) void BKE_lib_override_library_property_delete(IDOverrideLibrary *override, IDOverrideLibraryProperty *override_property) { - if (override->runtime != NULL) { - BLI_ghash_remove(override->runtime, override_property->rna_path, NULL, NULL); + if (!ELEM(NULL, override->runtime, override->runtime->rna_path_to_override_properties)) { + BLI_ghash_remove(override->runtime->rna_path_to_override_properties, + override_property->rna_path, + NULL, + NULL); } lib_override_library_property_clear(override_property); BLI_freelinkN(&override->properties, override_property); @@ -884,11 +1145,11 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for TaskPool *task_pool = BLI_task_pool_create(bmain, TASK_PRIORITY_HIGH); FOREACH_MAIN_ID_BEGIN (bmain, id) { - if ((ID_IS_OVERRIDE_LIBRARY_REAL(id) && force_auto) || - (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH)) { + if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && + (force_auto || (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) { BLI_task_pool_push(task_pool, lib_override_library_operations_create_cb, id, false, NULL); - id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH; } + id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH; } FOREACH_MAIN_ID_END; @@ -905,6 +1166,137 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for #endif } +static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root) +{ + bool was_op_deleted = false; + + LISTBASE_FOREACH_MUTABLE ( + IDOverrideLibraryProperty *, op, &id_root->override_library->properties) { + bool do_op_delete = true; + const bool is_collection = op->rna_prop_type == PROP_COLLECTION; + if (is_collection || op->rna_prop_type == PROP_POINTER) { + PointerRNA ptr_root, ptr_root_lib, ptr, ptr_lib; + PropertyRNA *prop, *prop_lib; + + RNA_pointer_create(id_root, &RNA_ID, id_root, &ptr_root); + RNA_pointer_create(id_root->override_library->reference, + &RNA_ID, + id_root->override_library->reference, + &ptr_root_lib); + + bool prop_exists = RNA_path_resolve_property(&ptr_root, op->rna_path, &ptr, &prop); + BLI_assert(prop_exists); + prop_exists = RNA_path_resolve_property(&ptr_root_lib, op->rna_path, &ptr_lib, &prop_lib); + + if (prop_exists) { + BLI_assert(ELEM(RNA_property_type(prop), PROP_POINTER, PROP_COLLECTION)); + BLI_assert(RNA_property_type(prop) == RNA_property_type(prop_lib)); + if (is_collection) { + ptr.type = RNA_property_pointer_type(&ptr, prop); + ptr_lib.type = RNA_property_pointer_type(&ptr_lib, prop_lib); + } + else { + ptr = RNA_property_pointer_get(&ptr, prop); + ptr_lib = RNA_property_pointer_get(&ptr_lib, prop_lib); + } + if (ptr.owner_id != NULL && ptr_lib.owner_id != NULL) { + BLI_assert(ptr.type == ptr_lib.type); + do_op_delete = !(RNA_struct_is_ID(ptr.type) && ptr.owner_id->override_library != NULL && + ptr.owner_id->override_library->reference == ptr_lib.owner_id); + } + } + } + + if (do_op_delete) { + BKE_lib_override_library_property_delete(id_root->override_library, op); + was_op_deleted = true; + } + } + + if (was_op_deleted) { + DEG_id_tag_update_ex(bmain, id_root, ID_RECALC_COPY_ON_WRITE); + IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_runtime_ensure( + id_root->override_library); + override_runtime->tag |= IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD; + } + + return was_op_deleted; +} + +/** Reset all overrides in given \a id_root, while preserving ID relations. */ +void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { + return; + } + + if (lib_override_library_id_reset_do(bmain, id_root)) { + if (id_root->override_library->runtime != NULL && + (id_root->override_library->runtime->tag & IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD) != + 0) { + BKE_lib_override_library_update(bmain, id_root); + id_root->override_library->runtime->tag &= ~IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD; + } + } +} + +static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *id_root) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) { + return; + } + + void **entry_pp = BLI_ghash_lookup(bmain->relations->id_user_to_used, id_root); + if (entry_pp == NULL) { + /* Already processed. */ + return; + } + + lib_override_library_id_reset_do(bmain, id_root); + + /* This way we won't process again that ID should we encounter it again through another + * relationship hierarchy. + * Note that this does not free any memory from relations, so we can still use the entries. + */ + BKE_main_relations_ID_remove(bmain, id_root); + + for (MainIDRelationsEntry *entry = *entry_pp; entry != NULL; entry = entry->next) { + if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) { + /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as + * actual dependencies. */ + continue; + } + /* We only consider IDs from the same library. */ + if (entry->id_pointer != NULL) { + ID *id_entry = *entry->id_pointer; + if (id_entry->override_library != NULL) { + lib_override_library_id_hierarchy_recursive_reset(bmain, id_entry); + } + } + } +} + +/** Reset all overrides in given \a id_root and its dependencies, while preserving ID relations. */ +void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, ID *id_root) +{ + BKE_main_relations_create(bmain, 0); + + lib_override_library_id_hierarchy_recursive_reset(bmain, id_root); + + BKE_main_relations_free(bmain); + + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || id->override_library->runtime == NULL || + (id->override_library->runtime->tag & IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD) == 0) { + continue; + } + BKE_lib_override_library_update(bmain, id); + id->override_library->runtime->tag &= ~IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD; + } + FOREACH_MAIN_ID_END; +} + /** Set or clear given tag in all operations as unused in that override property data. */ void BKE_lib_override_library_operations_tag(struct IDOverrideLibraryProperty *override_property, const short tag, @@ -1040,8 +1432,6 @@ void BKE_lib_override_library_update(Main *bmain, ID *local) Key *local_key = BKE_key_from_id(local); Key *tmp_key = BKE_key_from_id(tmp_id); if (local_key != NULL && tmp_key != NULL) { - /* This is some kind of hard-coded 'always enforced override'... */ - tmp_key->from = local_key->from; tmp_key->id.flag |= (local_key->id.flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE); } @@ -1060,6 +1450,18 @@ void BKE_lib_override_library_update(Main *bmain, ID *local) * So when we'll free tmp_id, we'll actually free old, outdated data from local. */ BKE_lib_id_swap(bmain, local, tmp_id); + if (local_key != NULL && tmp_key != NULL) { + /* This is some kind of hard-coded 'always enforced override'... */ + BKE_lib_id_swap(bmain, &local_key->id, &tmp_key->id); + tmp_key->id.flag |= (local_key->id.flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE); + /* The swap of local and tmp_id inverted those pointers, we need to redefine proper + * relationships. */ + *BKE_key_from_id_p(local) = local_key; + *BKE_key_from_id_p(tmp_id) = tmp_key; + local_key->from = local; + tmp_key->from = tmp_id; + } + /* Again, horribly inn-efficient in our case, we need something off-Main * (aka more generic nolib copy/free stuff)! */ /* XXX And crashing in complex cases (e.g. because depsgraph uses same data...). */ @@ -1078,6 +1480,7 @@ void BKE_lib_override_library_update(Main *bmain, ID *local) /* Full rebuild of Depsgraph! */ /* Note: this is really brute force, in theory updates from RNA should have handle this already, * but for now let's play it safe. */ + DEG_id_tag_update_ex(bmain, local, ID_RECALC_ALL); DEG_relations_tag_update(bmain); } @@ -1112,7 +1515,7 @@ void BKE_lib_override_library_main_update(Main *bmain) */ /** Initialize an override storage. */ -OverrideLibraryStorage *BKE_lib_override_library_operations_store_initialize(void) +OverrideLibraryStorage *BKE_lib_override_library_operations_store_init(void) { return BKE_main_new(); } diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index 00a42b12e07..0f81d45c10f 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -412,6 +412,8 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) return ELEM(id_type_used, ID_MA); case ID_VO: return ELEM(id_type_used, ID_MA); + case ID_SIM: + return ELEM(id_type_used, ID_OB, ID_IM); case ID_IM: case ID_VF: case ID_TXT: @@ -422,7 +424,6 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) case ID_PAL: case ID_PC: case ID_CF: - case ID_SIM: /* Those types never use/reference other IDs... */ return false; case ID_IP: diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index aa1005c663f..f42df6765c4 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -58,7 +58,7 @@ static void light_init_data(ID *id) MEMCPY_STRUCT_AFTER(la, DNA_struct_default_get(Light), id); la->curfalloff = BKE_curvemapping_add(1, 0.0f, 1.0f, 1.0f, 0.0f); - BKE_curvemapping_initialize(la->curfalloff); + BKE_curvemapping_init(la->curfalloff); } /** diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 49c909850de..7e859799a4e 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -624,7 +624,7 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float co, bezt->vec[1], bezt->vec[2], bezt_next->vec[0], bezt_next->vec[1], u); } -BLI_INLINE void orthogonal_direction_get(float vec[2], float result[2]) +BLI_INLINE void orthogonal_direction_get(const float vec[2], float result[2]) { result[0] = -vec[1]; result[1] = vec[0]; diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 412ccd3ab39..01d44d070b3 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -769,8 +769,8 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, BLI_assert(tot_diff_feather_points == tot_diff_point); - /* note: only added for convenience, we don't infact use these to scanfill, - * only to create feather faces after scanfill */ + /* Note: only added for convenience, we don't in fact use these to scan-fill, + * only to create feather faces after scan-fill. */ for (j = 0; j < tot_diff_feather_points; j++) { copy_v2_v2(co_feather, diff_feather_points[j]); sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather); @@ -1256,7 +1256,7 @@ static float maskrasterize_layer_z_depth_quad( return w[2] + w[3]; /* we can make this assumption for small speedup */ } -static float maskrasterize_layer_isect(unsigned int *face, +static float maskrasterize_layer_isect(const unsigned int *face, float (*cos)[3], const float dist_orig, const float xy[2]) @@ -1489,6 +1489,8 @@ static void maskrasterize_buffer_cb(void *__restrict userdata, void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle, const unsigned int width, const unsigned int height, + /* Cannot be const, because it is assigned to non-const variable. + * NOLINTNEXTLINE: readability-non-const-parameter. */ float *buffer) { const float x_inv = 1.0f / (float)width; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index d4de04a9e98..e878a894b27 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -955,18 +955,26 @@ void BKE_object_material_remap_calc(Object *ob_dst, Object *ob_src, short *remap void BKE_object_material_array_assign(Main *bmain, struct Object *ob, struct Material ***matar, - short totcol) + int totcol, + const bool to_object_only) { int actcol_orig = ob->actcol; - short i; while ((ob->totcol > totcol) && BKE_object_material_slot_remove(bmain, ob)) { /* pass */ } /* now we have the right number of slots */ - for (i = 0; i < totcol; i++) { - BKE_object_material_assign(bmain, ob, (*matar)[i], i + 1, BKE_MAT_ASSIGN_USERPREF); + for (int i = 0; i < totcol; i++) { + if (to_object_only && ob->matbits[i] == 0) { + /* If we only assign to object, and that slot uses obdata material, do nothing. */ + continue; + } + BKE_object_material_assign(bmain, + ob, + (*matar)[i], + i + 1, + to_object_only ? BKE_MAT_ASSIGN_OBJECT : BKE_MAT_ASSIGN_USERPREF); } if (actcol_orig > ob->totcol) { @@ -1272,8 +1280,6 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) if (ma->paint_clone_slot >= count) { ma->paint_clone_slot = count - 1; } - - return; } void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob) @@ -1712,6 +1718,29 @@ static void material_default_volume_init(Material *ma) nodeSetActive(ntree, output); } +static void material_default_holdout_init(Material *ma) +{ + bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); + ma->nodetree = ntree; + ma->use_nodes = true; + + bNode *holdout = nodeAddStaticNode(NULL, ntree, SH_NODE_HOLDOUT); + bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); + + nodeAddLink(ntree, + holdout, + nodeFindSocket(holdout, SOCK_OUT, "Holdout"), + output, + nodeFindSocket(output, SOCK_IN, "Surface")); + + holdout->locx = 10.0f; + holdout->locy = 300.0f; + output->locx = 300.0f; + output->locy = 300.0f; + + nodeSetActive(ntree, output); +} + Material *BKE_material_default_empty(void) { return &default_material_empty; @@ -1757,6 +1786,7 @@ void BKE_materials_init(void) material_default_surface_init(&default_material_surface); material_default_volume_init(&default_material_volume); + material_default_holdout_init(&default_material_holdout); material_default_gpencil_init(&default_material_gpencil); } diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index ad178e76ef6..72b99bea0f4 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -315,7 +315,7 @@ static float densfunc(const MetaElem *ball, float x, float y, float z) float dist2; float dvec[3] = {x, y, z}; - mul_m4_v3((float(*)[4])ball->imat, dvec); + mul_m4_v3((const float(*)[4])ball->imat, dvec); switch (ball->type) { case MB_BALL: diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 48baedadd73..048af022adb 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1305,7 +1305,7 @@ bool BKE_mesh_minmax(const Mesh *me, float r_min[3], float r_max[3]) return (me->totvert != 0); } -void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys) +void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys) { int i; MVert *mvert = me->mvert; diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 9e5565d744a..a0f3bc9e74d 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -286,12 +286,14 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, } } else if (dl->type == DL_SURF) { - int tot; - totvert += dl->parts * dl->nr; - tot = (dl->parts - 1 + ((dl->flag & DL_CYCL_V) == 2)) * - (dl->nr - 1 + (dl->flag & DL_CYCL_U)); - totpoly += tot; - totloop += tot * 4; + if (dl->parts != 0) { + int tot; + totvert += dl->parts * dl->nr; + tot = (((dl->flag & DL_CYCL_U) ? 1 : 0) + (dl->nr - 1)) * + (((dl->flag & DL_CYCL_V) ? 1 : 0) + (dl->parts - 1)); + totpoly += tot; + totloop += tot * 4; + } } else if (dl->type == DL_INDEX3) { int tot; diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index b298a6a2787..49957b584ad 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -2888,7 +2888,7 @@ void BKE_mesh_loops_to_mface_corners( void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface, - int *polyindices, + const int *polyindices, unsigned int (*loopindices)[4], const int num_faces) { @@ -2981,7 +2981,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, void BKE_mesh_tangent_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface, - int *polyindices, + const int *polyindices, unsigned int (*loopindices)[4], const int num_faces, const char *layer_name) diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 4ed9b31dbb5..686f58a0ceb 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -953,7 +953,7 @@ void BKE_mesh_loop_islands_free(MeshIslandStore *island_store) void BKE_mesh_loop_islands_add(MeshIslandStore *island_store, const int item_num, - int *items_indices, + const int *items_indices, const int num_island_items, int *island_item_indices, const int num_innercut_items, diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index 404d6a581ae..a4991675d2d 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -1071,7 +1071,7 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, BLI_bitmap *done_edges, MeshElemMap *edge_to_poly_map, const bool is_edge_innercut, - int *poly_island_index_map, + const int *poly_island_index_map, float (*poly_centers)[3], unsigned char *poly_status) { diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c index 932423bc445..b9eb3876dde 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.c +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -43,8 +43,6 @@ /** \name Mesh Runtime Struct Utils * \{ */ -static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; - /** * Default values defined at read time. */ @@ -159,23 +157,21 @@ const MLoopTri *BKE_mesh_runtime_looptri_ensure(Mesh *mesh) { MLoopTri *looptri; - BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_READ); + ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex; + BLI_mutex_lock(mesh_eval_mutex); + looptri = mesh->runtime.looptris.array; - BLI_rw_mutex_unlock(&loops_cache_lock); if (looptri != NULL) { BLI_assert(BKE_mesh_runtime_looptri_len(mesh) == mesh->runtime.looptris.len); } else { - BLI_rw_mutex_lock(&loops_cache_lock, THREAD_LOCK_WRITE); - /* We need to ensure array is still NULL inside mutex-protected code, - * some other thread might have already recomputed those looptris. */ - if (mesh->runtime.looptris.array == NULL) { - BKE_mesh_runtime_looptri_recalc(mesh); - } + BKE_mesh_runtime_looptri_recalc(mesh); looptri = mesh->runtime.looptris.array; - BLI_rw_mutex_unlock(&loops_cache_lock); } + + BLI_mutex_unlock(mesh_eval_mutex); + return looptri; } diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index f64ed609d18..4d8c0568eb6 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -547,6 +547,16 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, for (i = 0, mp = mpolys; i < totpoly; i++, mp++, sp++) { sp->index = i; + /* Material index, isolated from other tests here. While large indices are clamped, + * negative indices aren't supported by drawing, exporters etc. + * To check the indices are in range, use #BKE_mesh_validate_material_indices */ + if (mp->mat_nr < 0) { + PRINT_ERR("\tPoly %u has invalid material (%d)", sp->index, mp->mat_nr); + if (do_fixes) { + mp->mat_nr = 0; + } + } + if (mp->loopstart < 0 || mp->totloop < 3) { /* Invalid loop data. */ PRINT_ERR("\tPoly %u is invalid (loopstart: %d, totloop: %d)", @@ -1133,14 +1143,15 @@ bool BKE_mesh_is_valid(Mesh *me) */ bool BKE_mesh_validate_material_indices(Mesh *me) { + /* Cast to unsigned to catch negative indices too. */ + const uint16_t mat_nr_max = max_ii(0, me->totcol - 1); MPoly *mp; - const int max_idx = max_ii(0, me->totcol - 1); const int totpoly = me->totpoly; int i; bool is_valid = true; for (mp = me->mpoly, i = 0; i < totpoly; i++, mp++) { - if (mp->mat_nr > max_idx) { + if ((uint16_t)mp->mat_nr > mat_nr_max) { mp->mat_nr = 0; is_valid = false; } diff --git a/source/blender/blenkernel/intern/mesh_wrapper.c b/source/blender/blenkernel/intern/mesh_wrapper.c index 6a8bc698b11..acd272ac305 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.c +++ b/source/blender/blenkernel/intern/mesh_wrapper.c @@ -40,6 +40,7 @@ #include "BLI_ghash.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BKE_editmesh.h" @@ -96,9 +97,14 @@ Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em, void BKE_mesh_wrapper_ensure_mdata(Mesh *me) { + ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime.eval_mutex; + BLI_mutex_lock(mesh_eval_mutex); + if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) { + BLI_mutex_unlock(mesh_eval_mutex); return; } + const eMeshWrapperType geom_type_orig = me->runtime.wrapper_type; me->runtime.wrapper_type = ME_WRAPPER_TYPE_MDATA; @@ -130,6 +136,8 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me) if (me->runtime.wrapper_type_finalize) { BKE_mesh_wrapper_deferred_finalize(me, &me->runtime.cd_mask_extra); } + + BLI_mutex_unlock(mesh_eval_mutex); } bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3]) diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index f0efc9b8c50..a5bd2ecf68a 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -129,6 +129,23 @@ static void movie_clip_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void movie_clip_foreach_cache(ID *id, + IDTypeForeachCacheFunctionCallback function_callback, + void *user_data) +{ + MovieClip *movie_clip = (MovieClip *)id; + IDCacheKey key = { + .id_session_uuid = id->session_uuid, + .offset_in_ID = offsetof(MovieClip, cache), + .cache_v = movie_clip->cache, + }; + function_callback(id, &key, (void **)&movie_clip->cache, 0, user_data); + + key.offset_in_ID = offsetof(MovieClip, tracking.camera.intrinsics); + key.cache_v = movie_clip->tracking.camera.intrinsics; + function_callback(id, &key, (void **)&movie_clip->tracking.camera.intrinsics, 0, user_data); +} + IDTypeInfo IDType_ID_MC = { .id_code = ID_MC, .id_filter = FILTER_ID_MC, @@ -144,6 +161,7 @@ IDTypeInfo IDType_ID_MC = { .free_data = movie_clip_free_data, .make_local = NULL, .foreach_id = movie_clip_foreach_id, + .foreach_cache = movie_clip_foreach_cache, }; /*********************** movieclip buffer loaders *************************/ @@ -1848,3 +1866,88 @@ void BKE_movieclip_eval_selection_update(struct Depsgraph *depsgraph, MovieClip DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip); movieclip_selection_sync(clip, (MovieClip *)clip->id.orig_id); } + +/* -------------------------------------------------------------------- */ +/** \name GPU textures + * \{ */ + +static GPUTexture **movieclip_get_gputexture_ptr(MovieClip *clip, + MovieClipUser *cuser, + eGPUTextureTarget textarget) +{ + /* Check if we have an existing entry for that clip user. */ + MovieClip_RuntimeGPUTexture *tex; + for (tex = clip->runtime.gputextures.first; tex; tex = tex->next) { + if (memcmp(&tex->user, cuser, sizeof(MovieClipUser)) == 0) { + break; + } + } + + /* If not, allocate a new one. */ + if (tex == NULL) { + tex = (MovieClip_RuntimeGPUTexture *)MEM_mallocN(sizeof(MovieClip_RuntimeGPUTexture), + __func__); + + for (int i = 0; i < TEXTARGET_COUNT; i++) { + tex->gputexture[i] = NULL; + } + + memcpy(&tex->user, cuser, sizeof(MovieClipUser)); + BLI_addtail(&clip->runtime.gputextures, tex); + } + + return &tex->gputexture[textarget]; +} + +GPUTexture *BKE_movieclip_get_gpu_texture(MovieClip *clip, MovieClipUser *cuser) +{ + if (clip == NULL) { + return NULL; + } + + GPUTexture **tex = movieclip_get_gputexture_ptr(clip, cuser, TEXTARGET_2D); + if (*tex) { + return *tex; + } + + /* check if we have a valid image buffer */ + ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, cuser); + if (ibuf == NULL) { + *tex = GPU_texture_create_error(2, false); + return *tex; + } + + /* This only means RGBA16F instead of RGBA32F. */ + const bool high_bitdepth = false; + const bool store_premultiplied = ibuf->rect_float ? false : true; + *tex = IMB_create_gpu_texture(ibuf, high_bitdepth, store_premultiplied); + + /* Do not generate mips for movieclips... too slow. */ + GPU_texture_mipmap_mode(*tex, false, true); + + IMB_freeImBuf(ibuf); + + return *tex; +} + +void BKE_movieclip_free_gputexture(struct MovieClip *clip) +{ + /* number of gpu textures to keep around as cache + * We don't want to keep too many GPU textures for + * movie clips around, as they can be large.*/ + const int MOVIECLIP_NUM_GPUTEXTURES = 1; + + while (BLI_listbase_count(&clip->runtime.gputextures) > MOVIECLIP_NUM_GPUTEXTURES) { + MovieClip_RuntimeGPUTexture *tex = (MovieClip_RuntimeGPUTexture *)BLI_pophead( + &clip->runtime.gputextures); + for (int i = 0; i < TEXTARGET_COUNT; i++) { + /* free glsl image binding */ + if (tex->gputexture[i]) { + GPU_texture_free(tex->gputexture[i]); + tex->gputexture[i] = NULL; + } + } + MEM_freeN(tex); + } +} +/** \} */ diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 7e78be6d66e..6c10f6de855 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -175,7 +175,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, return subd; } -static BLI_bitmap *multires_mdisps_downsample_hidden(BLI_bitmap *old_hidden, +static BLI_bitmap *multires_mdisps_downsample_hidden(const BLI_bitmap *old_hidden, int old_level, int new_level) { @@ -241,7 +241,7 @@ static void multires_mdisps_subdivide_hidden(MDisps *md, int new_level) md->hidden = subd; } -static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level) +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); @@ -868,7 +868,7 @@ static void multires_subdivide_legacy( mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); if (!mdisps) { - mdisps = multires_mdisps_initialize_hidden(me, totlvl); + mdisps = multires_mdisps_init_hidden(me, totlvl); } if (mdisps->disps && !updateblock && lvl != 0) { diff --git a/source/blender/blenkernel/intern/multires_inline.h b/source/blender/blenkernel/intern/multires_inline.h index 3d00101ec29..49329698b3a 100644 --- a/source/blender/blenkernel/intern/multires_inline.h +++ b/source/blender/blenkernel/intern/multires_inline.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __MULTIRES_INLINE_H__ -#define __MULTIRES_INLINE_H__ +#pragma once #include "BKE_multires.h" #include "BLI_math_vector.h" @@ -57,5 +56,3 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3] normalize_v3(tangent_matrix[1]); normalize_v3(tangent_matrix[2]); } - -#endif /* __MULTIRES_INLINE_H__ */ diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h index 12816a455ee..d6c1d79dfd7 100644 --- a/source/blender/blenkernel/intern/multires_reshape.h +++ b/source/blender/blenkernel/intern/multires_reshape.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_INTERN_MULTIRES_RESHAPE_H__ -#define __BKE_INTERN_MULTIRES_RESHAPE_H__ +#pragma once #include "BLI_sys_types.h" @@ -331,4 +330,3 @@ void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshap * * NOTE: Will re-evaluate all leading modifiers, so it's not cheap. */ void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context); -#endif /* __BKE_INTERN_MULTIRES_RESHAPE_H__ */ diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c index 3564ae80d24..e12e692ea23 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.c +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c @@ -271,7 +271,7 @@ static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_sm for (int grid_index = 0; grid_index < num_grids; ++grid_index) { surface_grid[grid_index].points = MEM_calloc_arrayN( - sizeof(SurfacePoint), grid_area, "delta grid dispalcement"); + sizeof(SurfacePoint), grid_area, "delta grid displacement"); } reshape_smooth_context->base_surface_grids = surface_grid; diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c index 6bd7b6b6a98..fa1a53f946e 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.c +++ b/source/blender/blenkernel/intern/multires_unsubdivide.c @@ -80,7 +80,7 @@ /** * Used to check if a vertex is in a disconnected element ID. */ -static bool is_vertex_in_id(BMVert *v, int *elem_id, int elem) +static bool is_vertex_in_id(BMVert *v, const int *elem_id, int elem) { const int v_index = BM_elem_index_get(v); return elem_id[v_index] == elem; diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.h b/source/blender/blenkernel/intern/multires_unsubdivide.h index e00a1ae6d8b..39c6da0b6c8 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.h +++ b/source/blender/blenkernel/intern/multires_unsubdivide.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ -#define __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ +#pragma once #include "BLI_sys_types.h" @@ -90,5 +89,3 @@ void multires_unsubdivide_context_free(MultiresUnsubdivideContext *context); /* Rebuilds all subdivision to the level 0 base mesh. */ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context); - -#endif /* __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index b73f957535c..91693abd1cf 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -61,6 +61,7 @@ #include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_simulation.h" #include "BLI_ghash.h" #include "BLI_threads.h" @@ -315,6 +316,33 @@ static void node_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void node_foreach_cache(ID *id, + IDTypeForeachCacheFunctionCallback function_callback, + void *user_data) +{ + bNodeTree *nodetree = (bNodeTree *)id; + IDCacheKey key = { + .id_session_uuid = id->session_uuid, + .offset_in_ID = offsetof(bNodeTree, previews), + .cache_v = nodetree->previews, + }; + + /* TODO, see also `direct_link_nodetree()` in readfile.c. */ +#if 0 + function_callback(id, &key, (void **)&nodetree->previews, 0, user_data); +#endif + + if (nodetree->type == NTREE_COMPOSIT) { + for (bNode *node = nodetree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_MOVIEDISTORTION) { + key.offset_in_ID = (size_t)BLI_ghashutil_strhash_p(node->name); + key.cache_v = node->storage; + function_callback(id, &key, (void **)&node->storage, 0, user_data); + } + } + } +} + IDTypeInfo IDType_ID_NT = { .id_code = ID_NT, .id_filter = FILTER_ID_NT, @@ -330,6 +358,7 @@ IDTypeInfo IDType_ID_NT = { .free_data = ntree_free_data, .make_local = NULL, .foreach_id = node_foreach_id, + .foreach_cache = node_foreach_cache, }; static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) @@ -817,12 +846,12 @@ static void socket_id_user_increment(bNodeSocket *sock) switch ((eNodeSocketDatatype)sock->type) { case SOCK_OBJECT: { bNodeSocketValueObject *default_value = sock->default_value; - id_us_plus(&default_value->value->id); + id_us_plus((ID *)default_value->value); break; } case SOCK_IMAGE: { bNodeSocketValueImage *default_value = sock->default_value; - id_us_plus(&default_value->value->id); + id_us_plus((ID *)default_value->value); break; } case SOCK_FLOAT: @@ -2465,6 +2494,7 @@ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree) &bmain->textures, &bmain->scenes, &bmain->linestyles, + &bmain->simulations, NULL}; for (int i = 0; lists[i] != NULL; i++) { @@ -3609,6 +3639,16 @@ void ntreeUpdateAllUsers(Main *main, ID *ngroup) FOREACH_NODETREE_END; } +static void ntreeUpdateSimulationDependencies(Main *main, bNodeTree *simulation_ntree) +{ + FOREACH_NODETREE_BEGIN (main, ntree, owner_id) { + if (GS(owner_id->name) == ID_SIM && ntree == simulation_ntree) { + BKE_simulation_update_dependencies((Simulation *)owner_id, main); + } + } + FOREACH_NODETREE_END; +} + void ntreeUpdateTree(Main *bmain, bNodeTree *ntree) { bNode *node; @@ -3651,7 +3691,6 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree) ntreeInterfaceTypeUpdate(ntree); } - /* XXX hack, should be done by depsgraph!! */ if (bmain) { ntreeUpdateAllUsers(bmain, &ntree->id); } @@ -3667,6 +3706,11 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree) ntree_validate_links(ntree); } + if (bmain != NULL && ntree->typeinfo == ntreeType_Simulation && + (ntree->id.flag & LIB_EMBEDDED_DATA)) { + ntreeUpdateSimulationDependencies(bmain, ntree); + } + /* clear update flags */ for (node = ntree->nodes.first; node; node = node->next) { node->update = 0; @@ -4308,6 +4352,8 @@ static void registerSimulationNodes(void) register_node_type_sim_emit_particles(); register_node_type_sim_time(); register_node_type_sim_particle_attribute(); + register_node_type_sim_age_reached_event(); + register_node_type_sim_kill_particle(); } static void registerFunctionNodes(void) @@ -4317,6 +4363,8 @@ static void registerFunctionNodes(void) register_node_type_fn_switch(); register_node_type_fn_group_instance_id(); register_node_type_fn_combine_strings(); + register_node_type_fn_object_transforms(); + register_node_type_fn_random_float(); } void init_nodesystem(void) diff --git a/source/blender/blenkernel/intern/node_tree_ref.cc b/source/blender/blenkernel/intern/node_tree_ref.cc deleted file mode 100644 index 54ea2d338db..00000000000 --- a/source/blender/blenkernel/intern/node_tree_ref.cc +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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. - */ - -#include "BKE_node_tree_ref.hh" - -#include "BLI_dot_export.hh" - -namespace blender::bke { - -NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree) -{ - Map<bNode *, NodeRef *> node_mapping; - - LISTBASE_FOREACH (bNode *, bnode, &btree->nodes) { - NodeRef &node = *allocator_.construct<NodeRef>(); - - node.tree_ = this; - node.bnode_ = bnode; - node.id_ = nodes_by_id_.append_and_get_index(&node); - RNA_pointer_create(&btree->id, &RNA_Node, bnode, &node.rna_); - - LISTBASE_FOREACH (bNodeSocket *, bsocket, &bnode->inputs) { - InputSocketRef &socket = *allocator_.construct<InputSocketRef>(); - socket.node_ = &node; - socket.index_ = node.inputs_.append_and_get_index(&socket); - socket.is_input_ = true; - socket.bsocket_ = bsocket; - socket.id_ = sockets_by_id_.append_and_get_index(&socket); - RNA_pointer_create(&btree->id, &RNA_NodeSocket, bsocket, &socket.rna_); - } - - LISTBASE_FOREACH (bNodeSocket *, bsocket, &bnode->outputs) { - OutputSocketRef &socket = *allocator_.construct<OutputSocketRef>(); - socket.node_ = &node; - socket.index_ = node.outputs_.append_and_get_index(&socket); - socket.is_input_ = false; - socket.bsocket_ = bsocket; - socket.id_ = sockets_by_id_.append_and_get_index(&socket); - RNA_pointer_create(&btree->id, &RNA_NodeSocket, bsocket, &socket.rna_); - } - - input_sockets_.extend(node.inputs_); - output_sockets_.extend(node.outputs_); - - node_mapping.add_new(bnode, &node); - } - - LISTBASE_FOREACH (bNodeLink *, blink, &btree->links) { - OutputSocketRef &from_socket = this->find_output_socket( - node_mapping, blink->fromnode, blink->fromsock); - InputSocketRef &to_socket = this->find_input_socket( - node_mapping, blink->tonode, blink->tosock); - - from_socket.directly_linked_sockets_.append(&to_socket); - to_socket.directly_linked_sockets_.append(&from_socket); - } - - for (OutputSocketRef *socket : output_sockets_) { - if (!socket->node_->is_reroute_node()) { - this->find_targets_skipping_reroutes(*socket, socket->linked_sockets_); - for (SocketRef *target : socket->linked_sockets_) { - target->linked_sockets_.append(socket); - } - } - } - - for (NodeRef *node : nodes_by_id_) { - const bNodeType *nodetype = node->bnode_->typeinfo; - nodes_by_type_.lookup_or_add_default(nodetype).append(node); - } -} - -NodeTreeRef::~NodeTreeRef() -{ - for (NodeRef *node : nodes_by_id_) { - node->~NodeRef(); - } - for (InputSocketRef *socket : input_sockets_) { - socket->~InputSocketRef(); - } - for (OutputSocketRef *socket : output_sockets_) { - socket->~OutputSocketRef(); - } -} - -InputSocketRef &NodeTreeRef::find_input_socket(Map<bNode *, NodeRef *> &node_mapping, - bNode *bnode, - bNodeSocket *bsocket) -{ - NodeRef *node = node_mapping.lookup(bnode); - for (SocketRef *socket : node->inputs_) { - if (socket->bsocket_ == bsocket) { - return *(InputSocketRef *)socket; - } - } - BLI_assert(false); - return *node->inputs_[0]; -} - -OutputSocketRef &NodeTreeRef::find_output_socket(Map<bNode *, NodeRef *> &node_mapping, - bNode *bnode, - bNodeSocket *bsocket) -{ - NodeRef *node = node_mapping.lookup(bnode); - for (SocketRef *socket : node->outputs_) { - if (socket->bsocket_ == bsocket) { - return *(OutputSocketRef *)socket; - } - } - BLI_assert(false); - return *node->outputs_[0]; -} - -void NodeTreeRef::find_targets_skipping_reroutes(OutputSocketRef &socket, - Vector<SocketRef *> &r_targets) -{ - for (SocketRef *direct_target : socket.directly_linked_sockets_) { - if (direct_target->node_->is_reroute_node()) { - this->find_targets_skipping_reroutes(*direct_target->node_->outputs_[0], r_targets); - } - else { - r_targets.append_non_duplicates(direct_target); - } - } -} - -std::string NodeTreeRef::to_dot() const -{ - dot::DirectedGraph digraph; - digraph.set_rankdir(dot::Attr_rankdir::LeftToRight); - - Map<const NodeRef *, dot::NodeWithSocketsRef> dot_nodes; - - for (const NodeRef *node : nodes_by_id_) { - dot::Node &dot_node = digraph.new_node(""); - dot_node.set_background_color("white"); - - Vector<std::string> input_names; - Vector<std::string> output_names; - for (const InputSocketRef *socket : node->inputs()) { - input_names.append(socket->name()); - } - for (const OutputSocketRef *socket : node->outputs()) { - output_names.append(socket->name()); - } - - dot_nodes.add_new(node, - dot::NodeWithSocketsRef(dot_node, node->name(), input_names, output_names)); - } - - for (const OutputSocketRef *from_socket : output_sockets_) { - for (const InputSocketRef *to_socket : from_socket->directly_linked_sockets()) { - dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(&from_socket->node()); - dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(&to_socket->node()); - - digraph.new_edge(from_dot_node.output(from_socket->index()), - to_dot_node.input(to_socket->index())); - } - } - - return digraph.to_dot_string(); -} - -} // namespace blender::bke diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6331f87f09f..fe559d2a44e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1760,7 +1760,7 @@ Object *BKE_object_copy(Main *bmain, const Object *ob) */ Object *BKE_object_duplicate(Main *bmain, Object *ob, - const eDupli_ID_Flags dupflag, + eDupli_ID_Flags dupflag, const eLibIDDuplicateFlags duplicate_options) { const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0; @@ -1768,10 +1768,14 @@ Object *BKE_object_duplicate(Main *bmain, if (!is_subprocess) { BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false); BKE_main_id_clear_newpoins(bmain); + /* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate + * all expected linked data. */ + if (ID_IS_LINKED(ob)) { + dupflag |= USER_DUP_LINKED_ID; + } } Material ***matarar; - const bool is_object_liboverride = ID_IS_OVERRIDE_LIBRARY(ob); Object *obn; BKE_id_copy(bmain, &ob->id, (ID **)&obn); @@ -1785,112 +1789,109 @@ Object *BKE_object_duplicate(Main *bmain, return obn; } - /* duplicates using userflags */ - if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action(bmain, &obn->id, true); - } + BKE_animdata_duplicate_id_action(bmain, &obn->id, dupflag); if (dupflag & USER_DUP_MAT) { for (int i = 0; i < obn->totcol; i++) { - BKE_id_copy_for_duplicate(bmain, (ID *)obn->mat[i], is_object_liboverride, dupflag); + BKE_id_copy_for_duplicate(bmain, (ID *)obn->mat[i], dupflag); } } if (dupflag & USER_DUP_PSYS) { ParticleSystem *psys; for (psys = obn->particlesystem.first; psys; psys = psys->next) { - BKE_id_copy_for_duplicate(bmain, (ID *)psys->part, is_object_liboverride, dupflag); + BKE_id_copy_for_duplicate(bmain, (ID *)psys->part, dupflag); } } - ID *id = obn->data; + ID *id_old = obn->data; ID *id_new = NULL; - const bool need_to_duplicate_obdata = (id != NULL) && (id->newid == NULL); + const bool need_to_duplicate_obdata = (id_old != NULL) && (id_old->newid == NULL); switch (obn->type) { case OB_MESH: if (dupflag & USER_DUP_MESH) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_CURVE: if (dupflag & USER_DUP_CURVE) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_SURF: if (dupflag & USER_DUP_SURF) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_FONT: if (dupflag & USER_DUP_FONT) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_MBALL: if (dupflag & USER_DUP_MBALL) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_LAMP: if (dupflag & USER_DUP_LAMP) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_ARMATURE: if (dupflag & USER_DUP_ARM) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_LATTICE: if (dupflag != 0) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_CAMERA: if (dupflag != 0) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_LIGHTPROBE: if (dupflag & USER_DUP_LIGHTPROBE) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_SPEAKER: if (dupflag != 0) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_GPENCIL: if (dupflag & USER_DUP_GPENCIL) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_HAIR: if (dupflag & USER_DUP_HAIR) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_POINTCLOUD: if (dupflag & USER_DUP_POINTCLOUD) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_VOLUME: if (dupflag & USER_DUP_VOLUME) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; } /* If obdata has been copied, we may also have to duplicate the materials assigned to it. */ - if (need_to_duplicate_obdata && id_new != NULL) { + if (need_to_duplicate_obdata && !ELEM(id_new, NULL, id_old)) { if (dupflag & USER_DUP_MAT) { matarar = BKE_object_material_array_p(obn); if (matarar) { for (int i = 0; i < obn->totcol; i++) { - BKE_id_copy_for_duplicate(bmain, (ID *)(*matarar)[i], is_object_liboverride, dupflag); + BKE_id_copy_for_duplicate(bmain, (ID *)(*matarar)[i], dupflag); } } } @@ -2087,7 +2088,7 @@ void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob) /* type conversions */ if (target->type == OB_ARMATURE) { copy_object_pose(ob, target, 0); /* data copy, object pointers in constraints */ - BKE_pose_rest(ob->pose); /* clear all transforms in channels */ + BKE_pose_rest(ob->pose, false); /* clear all transforms in channels */ BKE_pose_rebuild(bmain, ob, ob->data, true); /* set all internal links */ armature_set_id_extern(ob); @@ -2343,7 +2344,7 @@ void BKE_object_tfm_copy(Object *object_dst, const Object *object_src) #undef TFMCPY4D } -void BKE_object_to_mat3(Object *ob, float mat[3][3]) /* no parent */ +void BKE_object_to_mat3(Object *ob, float r_mat[3][3]) /* no parent */ { float smat[3][3]; float rmat[3][3]; @@ -2354,38 +2355,38 @@ void BKE_object_to_mat3(Object *ob, float mat[3][3]) /* no parent */ /* rot */ BKE_object_rot_to_mat3(ob, rmat, true); - mul_m3_m3m3(mat, rmat, smat); + mul_m3_m3m3(r_mat, rmat, smat); } -void BKE_object_to_mat4(Object *ob, float mat[4][4]) +void BKE_object_to_mat4(Object *ob, float r_mat[4][4]) { float tmat[3][3]; BKE_object_to_mat3(ob, tmat); - copy_m4_m3(mat, tmat); + copy_m4_m3(r_mat, tmat); - add_v3_v3v3(mat[3], ob->loc, ob->dloc); + add_v3_v3v3(r_mat[3], ob->loc, ob->dloc); } -void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]) +void BKE_object_matrix_local_get(struct Object *ob, float r_mat[4][4]) { if (ob->parent) { float par_imat[4][4]; BKE_object_get_parent_matrix(ob, ob->parent, par_imat); invert_m4(par_imat); - mul_m4_m4m4(mat, par_imat, ob->obmat); + mul_m4_m4m4(r_mat, par_imat, ob->obmat); } else { - copy_m4_m4(mat, ob->obmat); + copy_m4_m4(r_mat, ob->obmat); } } /** * \return success if \a mat is set. */ -static bool ob_parcurve(Object *ob, Object *par, float mat[4][4]) +static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4]) { Curve *cu = par->data; float vec[4], dir[3], quat[4], radius, ctime; @@ -2408,7 +2409,7 @@ static bool ob_parcurve(Object *ob, Object *par, float mat[4][4]) /* ctime is now a proper var setting of Curve which gets set by Animato like any other var * that's animated, but this will only work if it actually is animated. * - * We divide the curvetime calculated in the previous step by the length of the path, + * We divide the curve-time calculated in the previous step by the length of the path, * to get a time factor, which then gets clamped to lie within 0.0 - 1.0 range. */ if (cu->pathlen) { @@ -2419,34 +2420,34 @@ static bool ob_parcurve(Object *ob, Object *par, float mat[4][4]) } CLAMP(ctime, 0.0f, 1.0f); - unit_m4(mat); + unit_m4(r_mat); /* vec: 4 items! */ if (where_on_path(par, ctime, vec, dir, (cu->flag & CU_FOLLOW) ? quat : NULL, &radius, NULL)) { if (cu->flag & CU_FOLLOW) { quat_apply_track(quat, ob->trackflag, ob->upflag); normalize_qt(quat); - quat_to_mat4(mat, quat); + quat_to_mat4(r_mat, quat); } if (cu->flag & CU_PATH_RADIUS) { float tmat[4][4], rmat[4][4]; scale_m4_fl(tmat, radius); - mul_m4_m4m4(rmat, tmat, mat); - copy_m4_m4(mat, rmat); + mul_m4_m4m4(rmat, tmat, r_mat); + copy_m4_m4(r_mat, rmat); } - copy_v3_v3(mat[3], vec); + copy_v3_v3(r_mat[3], vec); } return true; } -static void ob_parbone(Object *ob, Object *par, float mat[4][4]) +static void ob_parbone(Object *ob, Object *par, float r_mat[4][4]) { bPoseChannel *pchan; float vec[3]; if (par->type != OB_ARMATURE) { - unit_m4(mat); + unit_m4(r_mat); return; } @@ -2455,7 +2456,7 @@ static void ob_parbone(Object *ob, Object *par, float mat[4][4]) if (!pchan || !pchan->bone) { CLOG_ERROR( &LOG, "Object %s with Bone parent: bone %s doesn't exist", ob->id.name + 2, ob->parsubstr); - unit_m4(mat); + unit_m4(r_mat); return; } @@ -2463,15 +2464,15 @@ static void ob_parbone(Object *ob, Object *par, float mat[4][4]) if (pchan->bone->flag & BONE_RELATIVE_PARENTING) { /* the new option uses the root - expected behavior, but differs from old... */ /* XXX check on version patching? */ - copy_m4_m4(mat, pchan->chan_mat); + copy_m4_m4(r_mat, pchan->chan_mat); } else { - copy_m4_m4(mat, pchan->pose_mat); + copy_m4_m4(r_mat, pchan->pose_mat); /* but for backwards compatibility, the child has to move to the tail */ - copy_v3_v3(vec, mat[1]); + copy_v3_v3(vec, r_mat[1]); mul_v3_fl(vec, pchan->bone->length); - add_v3_v3(mat[3], vec); + add_v3_v3(r_mat[3], vec); } } @@ -2593,7 +2594,7 @@ static void give_parvert(Object *par, int nr, float vec[3]) } } -static void ob_parvert3(Object *ob, Object *par, float mat[4][4]) +static void ob_parvert3(Object *ob, Object *par, float r_mat[4][4]) { /* in local ob space */ @@ -2606,16 +2607,16 @@ static void ob_parvert3(Object *ob, Object *par, float mat[4][4]) tri_to_quat(q, v1, v2, v3); quat_to_mat3(cmat, q); - copy_m4_m3(mat, cmat); + copy_m4_m3(r_mat, cmat); - mid_v3_v3v3v3(mat[3], v1, v2, v3); + mid_v3_v3v3v3(r_mat[3], v1, v2, v3); } else { - unit_m4(mat); + unit_m4(r_mat); } } -void BKE_object_get_parent_matrix(Object *ob, Object *par, float parentmat[4][4]) +void BKE_object_get_parent_matrix(Object *ob, Object *par, float r_parentmat[4][4]) { float tmat[4][4]; float vec[3]; @@ -2631,31 +2632,31 @@ void BKE_object_get_parent_matrix(Object *ob, Object *par, float parentmat[4][4] } if (ok) { - mul_m4_m4m4(parentmat, par->obmat, tmat); + mul_m4_m4m4(r_parentmat, par->obmat, tmat); } else { - copy_m4_m4(parentmat, par->obmat); + copy_m4_m4(r_parentmat, par->obmat); } break; case PARBONE: ob_parbone(ob, par, tmat); - mul_m4_m4m4(parentmat, par->obmat, tmat); + mul_m4_m4m4(r_parentmat, par->obmat, tmat); break; case PARVERT1: - unit_m4(parentmat); + unit_m4(r_parentmat); give_parvert(par, ob->par1, vec); - mul_v3_m4v3(parentmat[3], par->obmat, vec); + mul_v3_m4v3(r_parentmat[3], par->obmat, vec); break; case PARVERT3: ob_parvert3(ob, par, tmat); - mul_m4_m4m4(parentmat, par->obmat, tmat); + mul_m4_m4m4(r_parentmat, par->obmat, tmat); break; case PARSKEL: - copy_m4_m4(parentmat, par->obmat); + copy_m4_m4(r_parentmat, par->obmat); break; } } @@ -2671,7 +2672,7 @@ void BKE_object_get_parent_matrix(Object *ob, Object *par, float parentmat[4][4] * (without its own matrix applied) */ static void solve_parenting( - Object *ob, Object *par, float obmat[4][4], float r_originmat[3][3], const bool set_origin) + Object *ob, Object *par, const bool set_origin, float r_obmat[4][4], float r_originmat[3][3]) { float totmat[4][4]; float tmat[4][4]; @@ -2683,7 +2684,7 @@ static void solve_parenting( /* total */ mul_m4_m4m4(tmat, totmat, ob->parentinv); - mul_m4_m4m4(obmat, tmat, locmat); + mul_m4_m4m4(r_obmat, tmat, locmat); if (r_originmat) { /* usable originmat */ @@ -2713,7 +2714,7 @@ static void object_where_is_calc_ex(Depsgraph *depsgraph, Object *par = ob->parent; /* calculate parent matrix */ - solve_parenting(ob, par, ob->obmat, r_originmat, true); + solve_parenting(ob, par, true, ob->obmat, r_originmat); } else { BKE_object_to_mat4(ob, ob->obmat); @@ -2745,7 +2746,10 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o { /* Execute drivers and animation. */ const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + ctime); + BKE_animsys_evaluate_animdata( + &ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ALL, flush_to_original); object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL); } @@ -2753,14 +2757,14 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o * constraints -- assume dependencies are already solved by depsgraph. * no changes to object and it's parent would be done. * used for bundles orientation in 3d space relative to parented blender camera */ -void BKE_object_where_is_calc_mat4(Object *ob, float obmat[4][4]) +void BKE_object_where_is_calc_mat4(Object *ob, float r_obmat[4][4]) { if (ob->parent) { Object *par = ob->parent; - solve_parenting(ob, par, obmat, NULL, false); + solve_parenting(ob, par, false, r_obmat, NULL); } else { - BKE_object_to_mat4(ob, obmat); + BKE_object_to_mat4(ob, r_obmat); } } @@ -2821,8 +2825,11 @@ void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *o * \param use_compat: true to ensure that rotations are set using the * min difference between the old and new orientation. */ -void BKE_object_apply_mat4_ex( - Object *ob, float mat[4][4], Object *parent, float parentinv[4][4], const bool use_compat) +void BKE_object_apply_mat4_ex(Object *ob, + const float mat[4][4], + Object *parent, + const float parentinv[4][4], + const bool use_compat) { /* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */ @@ -2863,7 +2870,7 @@ void BKE_object_apply_mat4_ex( /* XXX: should be removed after COW operators port to use BKE_object_apply_mat4_ex directly */ void BKE_object_apply_mat4(Object *ob, - float mat[4][4], + const float mat[4][4], const bool use_compat, const bool use_parent) { @@ -2913,7 +2920,10 @@ void BKE_boundbox_calc_size_aabb(const BoundBox *bb, float r_size[3]) r_size[2] = 0.5f * fabsf(bb->vec[0][2] - bb->vec[1][2]); } -void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]) +void BKE_boundbox_minmax(const BoundBox *bb, + const float obmat[4][4], + float r_min[3], + float r_max[3]) { int i; for (i = 0; i < 8; i++) { @@ -3005,7 +3015,7 @@ void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval) * \warning Setting dimensions is prone to feedback loops in evaluation. * \{ */ -void BKE_object_dimensions_get(Object *ob, float vec[3]) +void BKE_object_dimensions_get(Object *ob, float r_vec[3]) { BoundBox *bb = NULL; @@ -3015,12 +3025,12 @@ void BKE_object_dimensions_get(Object *ob, float vec[3]) mat4_to_size(scale, ob->obmat); - vec[0] = fabsf(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]); - vec[1] = fabsf(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]); - vec[2] = fabsf(scale[2]) * (bb->vec[1][2] - bb->vec[0][2]); + r_vec[0] = fabsf(scale[0]) * (bb->vec[4][0] - bb->vec[0][0]); + r_vec[1] = fabsf(scale[1]) * (bb->vec[2][1] - bb->vec[0][1]); + r_vec[2] = fabsf(scale[2]) * (bb->vec[1][2] - bb->vec[0][2]); } else { - zero_v3(vec); + zero_v3(r_vec); } } @@ -3058,9 +3068,9 @@ void BKE_object_dimensions_set_ex(Object *ob, } } - if (len[i] > 0.0f) { - - ob->scale[i] = copysignf(value[i] / len[i], ob->scale[i]); + const float scale = copysignf(value[i] / len[i], ob->scale[i]); + if (isfinite(scale)) { + ob->scale[i] = scale; } } } @@ -3289,7 +3299,7 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph, } void BKE_object_foreach_display_point(Object *ob, - float obmat[4][4], + const float obmat[4][4], void (*func_cb)(const float[3], void *), void *user_data) { @@ -3960,15 +3970,20 @@ int BKE_object_is_modified(Scene *scene, Object *ob) return flag; } -/* Check of objects moves in time. */ -/* NOTE: This function is currently optimized for usage in combination - * with mti->canDeform, so modifiers can quickly check if their target - * objects moves (causing deformation motion blur) or not. +/** + * Check of objects moves in time. + * + * \note This function is currently optimized for usage in combination + * with modifier deformation checks (#eModifierTypeType_OnlyDeform), + * so modifiers can quickly check if their target objects moves + * (causing deformation motion blur) or not. * * This makes it possible to give some degree of false-positives here, * but it's currently an acceptable tradeoff between complexity and check * speed. In combination with checks of modifier stack and real life usage - * percentage of false-positives shouldn't be that height. + * percentage of false-positives shouldn't be that high. + * + * \note This function does not consider physics systems. */ bool BKE_object_moves_in_time(const Object *object, bool recurse_parent) { @@ -4642,9 +4657,13 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* was originally ID_RECALC_ALL - TODO - which flags are really needed??? */ /* TODO(sergey): What about animation? */ + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, + frame); + ob->id.recalc |= ID_RECALC_ALL; if (update_mesh) { - BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata( + &ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); /* ignore cache clear during subframe updates * to not mess up cache validity */ object_cacheIgnoreClear(ob, 1); @@ -4658,12 +4677,14 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* for curve following objects, parented curve has to be updated too */ if (ob->type == OB_CURVE) { Curve *cu = ob->data; - BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata( + &cu->id, cu->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); } /* and armatures... */ if (ob->type == OB_ARMATURE) { bArmature *arm = ob->data; - BKE_animsys_evaluate_animdata(&arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata( + &arm->id, arm->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original); BKE_pose_where_is(depsgraph, scene, ob); } diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index 6ca1442497a..51ec89cf77d 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -68,7 +68,7 @@ static Lattice *object_defgroup_lattice_get(ID *id) * * \param map: an array mapping old indices to new indices. */ -void BKE_object_defgroup_remap_update_users(Object *ob, int *map) +void BKE_object_defgroup_remap_update_users(Object *ob, const int *map) { ModifierData *md; ParticleSystem *psys; diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 4c6354f12a1..e0aea3a2910 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -37,6 +37,7 @@ #include "DNA_collection_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_vfont_types.h" @@ -186,7 +187,7 @@ static DupliObject *make_dupli(const DupliContext *ctx, Object *ob, float mat[4] dob->random_id = BLI_hash_string(dob->ob->id.name + 2); if (dob->persistent_id[0] != INT_MAX) { - for (i = 0; i < MAX_DUPLI_RECUR * 2; i++) { + for (i = 0; i < MAX_DUPLI_RECUR; i++) { dob->random_id = BLI_hash_int_2d(dob->random_id, (unsigned int)dob->persistent_id[i]); } } @@ -367,17 +368,13 @@ static void vertex_dupli(const VertexDupliData *vdd, DupliObject *dob; float obmat[4][4], space_mat[4][4]; - /* obmat is transform to vertex */ - get_duplivert_transform(co, no, vdd->use_rotation, inst_ob->trackflag, inst_ob->upflag, obmat); + /* space_mat is transform to vertex */ + get_duplivert_transform( + co, no, vdd->use_rotation, inst_ob->trackflag, inst_ob->upflag, space_mat); /* make offset relative to inst_ob using relative child transform */ - mul_mat3_m4_v3((float(*)[4])vdd->child_imat, obmat[3]); + mul_mat3_m4_v3((float(*)[4])vdd->child_imat, space_mat[3]); /* apply obmat _after_ the local vertex transform */ - mul_m4_m4m4(obmat, inst_ob->obmat, obmat); - - /* space matrix is constructed by removing obmat transform, - * this yields the worldspace transform for recursive duplis - */ - mul_m4_m4m4(space_mat, obmat, inst_ob->imat); + mul_m4_m4m4(obmat, inst_ob->obmat, space_mat); dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index); @@ -523,7 +520,7 @@ static void make_duplis_font(const DupliContext *ctx) /* Safety check even if it might fail badly when called for original object. */ const bool is_eval_curve = DEG_is_evaluated_id(&cu->id); - /* advance matching BLI_strncpy_wchar_from_utf8 */ + /* Advance matching BLI_str_utf8_as_utf32. */ for (a = 0; a < text_len; a++, ct++) { /* XXX That G.main is *really* ugly, but not sure what to do here... @@ -573,6 +570,63 @@ static const DupliGenerator gen_dupli_verts_font = { make_duplis_font /* make_duplis */ }; +/* OB_DUPLIVERTS - PointCloud */ +static void make_child_duplis_pointcloud(const DupliContext *ctx, + void *UNUSED(userdata), + Object *child) +{ + const Object *parent = ctx->object; + const PointCloud *pointcloud = parent->data; + const float(*co)[3] = pointcloud->co; + const float *radius = pointcloud->radius; + const float(*rotation)[4] = NULL; /* TODO: add optional rotation attribute. */ + const float(*orco)[3] = NULL; /* TODO: add optional texture coordinate attribute. */ + + /* Relative transform from parent to child space. */ + float child_imat[4][4]; + mul_m4_m4m4(child_imat, child->imat, parent->obmat); + + for (int i = 0; i < pointcloud->totpoint; i++) { + /* Transform matrix from point position, radius and rotation. */ + float quat[4] = {1.0f, 0.0f, 0.0f, 0.0f}; + float size[3] = {1.0f, 1.0f, 1.0f}; + if (radius) { + copy_v3_fl(size, radius[i]); + } + if (rotation) { + copy_v4_v4(quat, rotation[i]); + } + + float space_mat[4][4]; + loc_quat_size_to_mat4(space_mat, co[i], quat, size); + + /* Make offset relative to child object using relative child transform, + * and apply object matrix after local vertex transform. */ + mul_mat3_m4_v3(child_imat, space_mat[3]); + + /* Create dupli object. */ + float obmat[4][4]; + mul_m4_m4m4(obmat, child->obmat, space_mat); + DupliObject *dob = make_dupli(ctx, child, obmat, i); + if (orco) { + copy_v3_v3(dob->orco, orco[i]); + } + + /* Recursion. */ + make_recursive_duplis(ctx, child, space_mat, i); + } +} + +static void make_duplis_pointcloud(const DupliContext *ctx) +{ + make_child_duplis(ctx, NULL, make_child_duplis_pointcloud); +} + +static const DupliGenerator gen_dupli_verts_pointcloud = { + OB_DUPLIVERTS, /* type */ + make_duplis_pointcloud /* make_duplis */ +}; + /* OB_DUPLIFACES */ typedef struct FaceDupliData { Mesh *me_eval; @@ -1105,6 +1159,9 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) else if (ctx->object->type == OB_FONT) { return &gen_dupli_verts_font; } + else if (ctx->object->type == OB_POINTCLOUD) { + return &gen_dupli_verts_pointcloud; + } } else if (transflag & OB_DUPLIFACES) { if (ctx->object->type == OB_MESH) { diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 8957628c76a..198ff5a0540 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -147,19 +147,19 @@ static void init_complex(fftw_complex cmpl, float real, float image) cmpl[1] = image; } -static void add_comlex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) +static void add_comlex_c(fftw_complex res, const fftw_complex cmpl1, const fftw_complex cmpl2) { res[0] = cmpl1[0] + cmpl2[0]; res[1] = cmpl1[1] + cmpl2[1]; } -static void mul_complex_f(fftw_complex res, fftw_complex cmpl, float f) +static void mul_complex_f(fftw_complex res, const fftw_complex cmpl, float f) { res[0] = cmpl[0] * (double)f; res[1] = cmpl[1] * (double)f; } -static void mul_complex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) +static void mul_complex_c(fftw_complex res, const fftw_complex cmpl1, const fftw_complex cmpl2) { fftwf_complex temp; temp[0] = cmpl1[0] * cmpl2[0] - cmpl1[1] * cmpl2[1]; @@ -178,7 +178,7 @@ static float image_c(fftw_complex cmpl) return cmpl[1]; } -static void conj_complex(fftw_complex res, fftw_complex cmpl1) +static void conj_complex(fftw_complex res, const fftw_complex cmpl1) { res[0] = cmpl1[0]; res[1] = -cmpl1[1]; @@ -753,18 +753,26 @@ struct Ocean *BKE_ocean_add(void) return oc; } -bool BKE_ocean_ensure(struct OceanModifierData *omd) +bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution) { if (omd->ocean) { - return false; + /* Check that the ocean has the same resolution than we want now. */ + if (omd->ocean->_M == resolution * resolution) { + return false; + } + else { + BKE_ocean_free(omd->ocean); + } } omd->ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(omd->ocean, omd); + BKE_ocean_init_from_modifier(omd->ocean, omd, resolution); return true; } -void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd) +void BKE_ocean_init_from_modifier(struct Ocean *ocean, + struct OceanModifierData const *omd, + const int resolution) { short do_heightfield, do_chop, do_normals, do_jacobian; @@ -774,9 +782,10 @@ void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM); BKE_ocean_free_data(ocean); + BKE_ocean_init(ocean, - omd->resolution * omd->resolution, - omd->resolution * omd->resolution, + resolution * resolution, + resolution * resolution, omd->spatial_size, omd->spatial_size, omd->wind_velocity, @@ -831,7 +840,7 @@ void BKE_ocean_init(struct Ocean *o, o->_A = A; o->_w = w; o->_damp_reflections = 1.0f - damp; - o->_wind_alignment = alignment; + o->_wind_alignment = alignment * 10.0f; o->_depth = depth; o->_Lx = Lx; o->_Lz = Lz; @@ -845,7 +854,7 @@ void BKE_ocean_init(struct Ocean *o, /* Common JONSWAP parameters. */ o->_fetch_jonswap = fetch_jonswap; - o->_sharpen_peak_jonswap = sharpen_peak_jonswap; + o->_sharpen_peak_jonswap = sharpen_peak_jonswap * 10.0f; o->_do_disp_y = do_height_field; o->_do_normals = do_normals; @@ -1607,7 +1616,8 @@ void BKE_ocean_bake(struct Ocean *UNUSED(o), } void BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean), - struct OceanModifierData const *UNUSED(omd)) + struct OceanModifierData const *UNUSED(omd), + int UNUSED(resolution)) { } diff --git a/source/blender/blenkernel/intern/ocean_intern.h b/source/blender/blenkernel/intern/ocean_intern.h index 7da88419219..39ce0db09d6 100644 --- a/source/blender/blenkernel/intern/ocean_intern.h +++ b/source/blender/blenkernel/intern/ocean_intern.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BKE_OCEAN_INTERN_H__ -#define __BKE_OCEAN_INTERN_H__ +#pragma once /** \file * \ingroup bli @@ -133,5 +132,3 @@ typedef struct Ocean { #ifdef __cplusplus } #endif - -#endif diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index b3ab856468c..e7ff53f27b6 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -1314,6 +1314,13 @@ static void sculptsession_free_pbvh(Object *object) MEM_SAFE_FREE(ss->preview_vert_index_list); ss->preview_vert_index_count = 0; + + MEM_SAFE_FREE(ss->preview_vert_index_list); + + MEM_SAFE_FREE(ss->vertex_info.connected_component); + MEM_SAFE_FREE(ss->vertex_info.boundary); + + MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index); } void BKE_sculptsession_bm_to_me_for_render(Object *object) @@ -1366,11 +1373,6 @@ void BKE_sculptsession_free(Object *ob) MEM_SAFE_FREE(ss->deform_cos); MEM_SAFE_FREE(ss->deform_imats); - MEM_SAFE_FREE(ss->preview_vert_index_list); - - MEM_SAFE_FREE(ss->vertex_info.connected_component); - MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index); - if (ss->pose_ik_chain_preview) { for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) { MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments[i].weights); @@ -1482,7 +1484,7 @@ static void sculpt_update_object(Depsgraph *depsgraph, Mesh *me_eval, bool need_pmap, bool need_mask, - bool need_colors) + bool UNUSED(need_colors)) { Scene *scene = DEG_get_input_scene(depsgraph); Sculpt *sd = scene->toolsettings->sculpt; @@ -1491,6 +1493,8 @@ static void sculpt_update_object(Depsgraph *depsgraph, MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); const bool use_face_sets = (ob->mode & OB_MODE_SCULPT) != 0; + ss->depsgraph = depsgraph; + ss->deform_modifiers_active = sculpt_modifiers_active(scene, sd, ob); ss->show_mask = (sd->flags & SCULPT_HIDE_MASK) == 0; ss->show_face_sets = (sd->flags & SCULPT_HIDE_FACE_SETS) == 0; @@ -1512,16 +1516,6 @@ static void sculpt_update_object(Depsgraph *depsgraph, } } - /* Add a color layer if a color tool is used. */ - Mesh *orig_me = BKE_object_get_original_mesh(ob); - if (need_colors) { - if (!CustomData_has_layer(&orig_me->vdata, CD_PROP_COLOR)) { - CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert); - BKE_mesh_update_customdata_pointers(orig_me, true); - DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY); - } - } - /* tessfaces aren't used and will become invalid */ BKE_mesh_tessface_clear(me); @@ -1682,10 +1676,25 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval) Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); BLI_assert(me_eval != NULL); - sculpt_update_object(depsgraph, ob_orig, me_eval, false, false, false); } +void BKE_sculpt_color_layer_create_if_needed(struct Object *object) +{ + Mesh *orig_me = BKE_object_get_original_mesh(object); + if (!U.experimental.use_sculpt_vertex_colors) { + return; + } + + if (CustomData_has_layer(&orig_me->vdata, CD_PROP_COLOR)) { + return; + } + + CustomData_add_layer(&orig_me->vdata, CD_PROP_COLOR, CD_DEFAULT, NULL, orig_me->totvert); + BKE_mesh_update_customdata_pointers(orig_me, true); + DEG_id_tag_update(&orig_me->id, ID_RECALC_GEOMETRY); +} + void BKE_sculpt_update_object_for_edit( Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool need_mask, bool need_colors) { @@ -1817,6 +1826,64 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc return deformed; } +static void sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh) +{ + int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + if (!face_sets) { + return; + } + + for (int i = 0; i < mesh->totvert; i++) { + mesh->mvert[i].flag |= ME_HIDE; + } + + for (int i = 0; i < mesh->totpoly; i++) { + if (face_sets[i] >= 0) { + for (int l = 0; l < mesh->mpoly[i].totloop; l++) { + MLoop *loop = &mesh->mloop[mesh->mpoly[i].loopstart + l]; + mesh->mvert[loop->v].flag &= ~ME_HIDE; + } + } + } +} + +static void sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg) +{ + int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS); + if (!face_sets) { + return; + } + + if (!subdiv_ccg) { + return; + } + + CCGKey key; + BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); + for (int i = 0; i < mesh->totloop; i++) { + const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, i); + const bool is_hidden = (face_sets[face_index] < 0); + + /* Avoid creating and modifying the grid_hidden bitmap if the base mesh face is visible and + * there is not bitmap for the grid. This is because missing grid_hidden implies grid is fully + * visible. */ + if (is_hidden) { + BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg, i); + } + + BLI_bitmap *gh = subdiv_ccg->grid_hidden[i]; + if (gh) { + BLI_bitmap_set_all(gh, is_hidden, key.grid_area); + } + } +} + +void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *subdiv_ccg) +{ + sculpt_sync_face_sets_visibility_to_base_mesh(mesh); + sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg); +} + static PBVH *build_pbvh_for_dynamic_topology(Object *ob) { PBVH *pbvh = BKE_pbvh_new(); @@ -1842,6 +1909,8 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri); + BKE_sculpt_sync_face_set_visibility(me, NULL); + BKE_pbvh_build_mesh(pbvh, me, me->mpoly, @@ -1874,6 +1943,10 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); PBVH *pbvh = BKE_pbvh_new(); BKE_pbvh_respect_hide_set(pbvh, respect_hide); + + Mesh *base_mesh = BKE_mesh_from_object(ob); + BKE_sculpt_sync_face_set_visibility(base_mesh, subdiv_ccg); + BKE_pbvh_build_grids(pbvh, subdiv_ccg->grids, subdiv_ccg->num_grids, diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 942f3e0ca2b..1df5cda0ce5 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -283,8 +283,8 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur) } return tot; } -/* we allocate path cache memory in chunks instead of a big contiguous - * chunk, windows' memory allocater fails to find big blocks of memory often */ +/* We allocate path cache memory in chunks instead of a big contiguous + * chunk, windows' memory allocator fails to find big blocks of memory often. */ #define PATH_CACHE_BUF_SIZE 1024 @@ -1297,7 +1297,7 @@ static void do_particle_interpolation(ParticleSystem *psys, dfra = keys[2].time - keys[1].time; keytime = (real_t - keys[1].time) / dfra; - /* convert velocity to timestep size */ + /* Convert velocity to time-step size. */ if (pind->keyed || pind->cache || point_vel) { invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.f); mul_v3_fl(keys[1].vel, invdt); @@ -1305,8 +1305,8 @@ static void do_particle_interpolation(ParticleSystem *psys, interp_qt_qtqt(result->rot, keys[1].rot, keys[2].rot, keytime); } - /* Now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between - * [0, 1]->[k2, k3] (k1 & k4 used for cardinal & bspline interpolation). */ + /* Now we should have in chronological order k1<=k2<=t<=k3<=k4 with key-time between + * [0, 1]->[k2, k3] (k1 & k4 used for cardinal & b-spline interpolation). */ psys_interpolate_particle((pind->keyed || pind->cache || point_vel) ? -1 /* signal for cubic interpolation */ : @@ -3611,7 +3611,8 @@ void psys_mat_hair_to_global( /************************************************/ /* ParticleSettings handling */ /************************************************/ -ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, const char *name) +static ModifierData *object_add_or_copy_particle_system( + Main *bmain, Scene *scene, Object *ob, const char *name, const ParticleSystem *psys_orig) { ParticleSystem *psys; ModifierData *md; @@ -3622,7 +3623,7 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, } if (name == NULL) { - name = DATA_("ParticleSettings"); + name = (psys_orig != NULL) ? psys_orig->name : DATA_("ParticleSettings"); } psys = ob->particlesystem.first; @@ -3635,8 +3636,13 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, BLI_addtail(&ob->particlesystem, psys); psys_unique_name(ob, psys, name); - psys->part = BKE_particlesettings_add(bmain, psys->name); - + if (psys_orig != NULL) { + psys->part = psys_orig->part; + id_us_plus(&psys->part->id); + } + else { + psys->part = BKE_particlesettings_add(bmain, psys->name); + } md = BKE_modifier_new(eModifierType_ParticleSystem); BLI_strncpy(md->name, psys->name, sizeof(md->name)); BKE_modifier_unique_name(&ob->modifiers, md); @@ -3656,6 +3662,20 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, return md; } + +ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, const char *name) +{ + return object_add_or_copy_particle_system(bmain, scene, ob, name, NULL); +} + +ModifierData *object_copy_particle_system(Main *bmain, + Scene *scene, + Object *ob, + const ParticleSystem *psys_orig) +{ + return object_add_or_copy_particle_system(bmain, scene, ob, NULL, psys_orig); +} + void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob) { ParticleSystem *psys = psys_get_current(ob); @@ -3851,7 +3871,7 @@ void BKE_particlesettings_clump_curve_init(ParticleSettings *part) cumap->cm[0].curve[1].x = 1.0f; cumap->cm[0].curve[1].y = 1.0f; - BKE_curvemapping_initialize(cumap); + BKE_curvemapping_init(cumap); part->clumpcurve = cumap; } @@ -3865,7 +3885,7 @@ void BKE_particlesettings_rough_curve_init(ParticleSettings *part) cumap->cm[0].curve[1].x = 1.0f; cumap->cm[0].curve[1].y = 1.0f; - BKE_curvemapping_initialize(cumap); + BKE_curvemapping_init(cumap); part->roughcurve = cumap; } @@ -3879,7 +3899,7 @@ void BKE_particlesettings_twist_curve_init(ParticleSettings *part) cumap->cm[0].curve[1].x = 1.0f; cumap->cm[0].curve[1].y = 1.0f; - BKE_curvemapping_initialize(cumap); + BKE_curvemapping_init(cumap); part->twistcurve = cumap; } diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 7b9b2484dbe..e0dccd4d14a 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -433,7 +433,7 @@ static void psys_uv_to_w(float u, float v, int quad, float *w) } /* Find the index in "sum" array before "value" is crossed. */ -static int distribute_binary_search(float *sum, int n, float value) +static int distribute_binary_search(const float *sum, int n, float value) { int mid, low = 0, high = n - 1; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 4dc4aea04a7..6bfbb4b9d00 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -570,7 +570,7 @@ void psys_thread_context_free(ParticleThreadContext *ctx) } } -static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p) +static void init_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p) { ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; @@ -595,7 +595,7 @@ static void initialize_particle_texture(ParticleSimulationData *sim, ParticleDat } /* set particle parameters that don't change during particle's life */ -void initialize_particle(ParticleSimulationData *sim, ParticleData *pa) +void init_particle(ParticleSimulationData *sim, ParticleData *pa) { ParticleSettings *part = sim->psys->part; float birth_time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart; @@ -629,7 +629,7 @@ static void initialize_all_particles(ParticleSimulationData *sim) LOOP_PARTICLES { if (!(emit_from_volume_grid && (pa->flag & PARS_UNEXIST) != 0)) { - initialize_particle(sim, pa); + init_particle(sim, pa); } } } @@ -1092,7 +1092,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, * We could only do it now because we'll need to know coordinate * before sampling the texture. */ - initialize_particle_texture(sim, pa, p); + init_particle_texture(sim, pa, p); if (part->phystype == PART_PHYS_BOIDS && pa->boid) { BoidParticle *bpa = pa->boid; @@ -1939,7 +1939,7 @@ static void sphclassical_density_accum_cb(void *userdata, return; } - /* Smoothing factor. Utilise the Wendland kernel. gnuplot: + /* Smoothing factor. Utilize the Wendland kernel. gnuplot: * q1(x) = (2.0 - x)**4 * ( 1.0 + 2.0 * x) * plot [0:2] q1(x) */ q = qfac / pow3f(pfr->h) * pow4f(2.0f - rij_h) * (1.0f + 2.0f * rij_h); @@ -2054,7 +2054,7 @@ static void sphclassical_force_cb(void *sphdata_v, npressure = stiffness * (pow7f(npa->sphdensity / rest_density) - 1.0f); - /* First derivative of smoothing factor. Utilise the Wendland kernel. + /* First derivative of smoothing factor. Utilize the Wendland kernel. * gnuplot: * q2(x) = 2.0 * (2.0 - x)**4 - 4.0 * (2.0 - x)**3 * (1.0 + 2.0 * x) * plot [0:2] q2(x) @@ -2947,7 +2947,7 @@ static int collision_response(ParticleSimulationData *sim, /* get exact velocity right before collision */ madd_v3_v3v3fl(v0, col->ve1, col->acc, dt1); - /* Convert collider velocity from 1/framestep to 1/s TODO: + /* Convert collider velocity from `1/frame_step` to `1/s` TODO: * here we assume 1 frame step for collision modifier. */ mul_v3_fl(pce->vel, col->inv_timestep); @@ -4584,7 +4584,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ psys->dt_frac = get_base_time_step(part); } else if ((int)cfra == startframe) { - /* Variable time step; initialise to subframes */ + /* Variable time step; initialize to sub-frames. */ psys->dt_frac = get_base_time_step(part); } else if (psys->dt_frac < MIN_TIMESTEP) { @@ -4854,8 +4854,10 @@ void particle_system_update(struct Depsgraph *depsgraph, for (i = 0; i <= part->hair_step; i++) { hcfra = 100.0f * (float)i / (float)psys->part->hair_step; if ((part->flag & PART_HAIR_REGROW) == 0) { + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + depsgraph, hcfra); BKE_animsys_evaluate_animdata( - &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false); + &part_local->id, part_local->adt, &anim_eval_context, ADT_RECALC_ANIM, false); } system_step(&sim, hcfra, use_render_params); psys->cfra = hcfra; @@ -4966,6 +4968,7 @@ void particle_system_update(struct Depsgraph *depsgraph, psys_orig->flag = (psys->flag & ~PSYS_SHARED_CACHES); psys_orig->cfra = psys->cfra; psys_orig->recalc = psys->recalc; + psys_orig->part->totpart = part->totpart; } } diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 8d7dabf9859..92a47f24240 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -358,7 +358,7 @@ static void update_vb(PBVH *pbvh, PBVHNode *node, BBC *prim_bbc, int offset, int /* Returns the number of visible quads in the nodes' grids. */ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden, - int *grid_indices, + const int *grid_indices, int totgrid, int gridsize) { @@ -644,7 +644,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh, pbvh->totgrid = totgrid; pbvh->gridkey = *key; pbvh->grid_hidden = grid_hidden; - pbvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1); + pbvh->leaf_limit = max_ii(LEAF_LIMIT / (gridsize * gridsize), 1); BB cb; BB_reset(&cb); @@ -1542,7 +1542,7 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata, PBVHUpdateData *data = userdata; PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; - if (node->flag & PBVH_UpdateMask) { + if (node->flag & PBVH_UpdateVisibility) { switch (BKE_pbvh_type(pbvh)) { case PBVH_FACES: pbvh_faces_node_visibility_update(pbvh, node); @@ -1554,7 +1554,7 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata, pbvh_bmesh_node_visibility_update(node); break; } - node->flag &= ~PBVH_UpdateMask; + node->flag &= ~PBVH_UpdateVisibility; } } @@ -1772,6 +1772,11 @@ void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden) } } +bool BKE_pbvh_node_fully_hidden_get(PBVHNode *node) +{ + return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyHidden); +} + void BKE_pbvh_node_fully_masked_set(PBVHNode *node, int fully_masked) { BLI_assert(node->flag & PBVH_Leaf); diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index 6f8bae822ea..63bc8753fc7 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -14,8 +14,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __PBVH_INTERN_H__ -#define __PBVH_INTERN_H__ +#pragma once /** \file * \ingroup bli @@ -235,5 +234,3 @@ bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node, bool use_original); void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode); - -#endif diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 61308810191..c2c5b42dbb0 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -206,7 +206,7 @@ static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNUS return 1; } static void ptcache_softbody_read( - int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data) + int index, void *soft_v, void **data, float UNUSED(cfra), const float *old_data) { SoftBody *soft = soft_v; BodyPoint *bp = soft->bpoint + index; @@ -220,8 +220,13 @@ static void ptcache_softbody_read( PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec); } } -static void ptcache_softbody_interpolate( - int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_softbody_interpolate(int index, + void *soft_v, + void **data, + float cfra, + float cfra1, + float cfra2, + const float *old_data) { SoftBody *soft = soft_v; BodyPoint *bp = soft->bpoint + index; @@ -316,7 +321,7 @@ static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time); } static void ptcache_particle_read( - int index, void *psys_v, void **data, float cfra, float *old_data) + int index, void *psys_v, void **data, float cfra, const float *old_data) { ParticleSystem *psys = psys_v; ParticleData *pa; @@ -383,8 +388,13 @@ static void ptcache_particle_read( unit_qt(pa->state.rot); } } -static void ptcache_particle_interpolate( - int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_particle_interpolate(int index, + void *psys_v, + void **data, + float cfra, + float cfra1, + float cfra2, + const float *old_data) { ParticleSystem *psys = psys_v; ParticleData *pa; @@ -528,7 +538,7 @@ static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSED return 1; } static void ptcache_cloth_read( - int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data) + int index, void *cloth_v, void **data, float UNUSED(cfra), const float *old_data) { ClothModifierData *clmd = cloth_v; Cloth *cloth = clmd->clothObject; @@ -545,8 +555,13 @@ static void ptcache_cloth_read( PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst); } } -static void ptcache_cloth_interpolate( - int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_cloth_interpolate(int index, + void *cloth_v, + void **data, + float cfra, + float cfra1, + float cfra2, + const float *old_data) { ClothModifierData *clmd = cloth_v; Cloth *cloth = clmd->clothObject; @@ -1496,7 +1511,7 @@ static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSE if (ob && ob->rigidbody_object) { RigidBodyOb *rbo = ob->rigidbody_object; - if (rbo->type == RBO_TYPE_ACTIVE) { + if (rbo->type == RBO_TYPE_ACTIVE && rbo->shared->physics_object != NULL) { #ifdef WITH_BULLET RB_body_get_position(rbo->shared->physics_object, rbo->pos); RB_body_get_orientation(rbo->shared->physics_object, rbo->orn); @@ -1509,7 +1524,7 @@ static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSE return 1; } static void ptcache_rigidbody_read( - int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data) + int index, void *rb_v, void **data, float UNUSED(cfra), const float *old_data) { RigidBodyWorld *rbw = rb_v; Object *ob = NULL; @@ -1534,8 +1549,13 @@ static void ptcache_rigidbody_read( } } } -static void ptcache_rigidbody_interpolate( - int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_rigidbody_interpolate(int index, + void *rb_v, + void **data, + float cfra, + float cfra1, + float cfra2, + const float *old_data) { RigidBodyWorld *rbw = rb_v; Object *ob = NULL; @@ -1865,87 +1885,6 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r pid->file_type = PTCACHE_FILE_PTCACHE; } -static int ptcache_sim_particle_totpoint(void *state_v, int UNUSED(cfra)) -{ - ParticleSimulationState *state = (ParticleSimulationState *)state_v; - return state->tot_particles; -} - -static void ptcache_sim_particle_error(void *UNUSED(state_v), const char *UNUSED(message)) -{ -} - -static int ptcache_sim_particle_write(int index, void *state_v, void **data, int UNUSED(cfra)) -{ - ParticleSimulationState *state = (ParticleSimulationState *)state_v; - - const float *positions = (const float *)CustomData_get_layer_named( - &state->attributes, CD_LOCATION, "Position"); - - PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, positions + (index * 3)); - - return 1; -} -static void ptcache_sim_particle_read( - int index, void *state_v, void **data, float UNUSED(cfra), float *UNUSED(old_data)) -{ - ParticleSimulationState *state = (ParticleSimulationState *)state_v; - - BLI_assert(index < state->tot_particles); - float *positions = (float *)CustomData_get_layer_named( - &state->attributes, CD_LOCATION, "Position"); - - PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, positions + (index * 3)); -} - -void BKE_ptcache_id_from_sim_particles(PTCacheID *pid, ParticleSimulationState *state) -{ - memset(pid, 0, sizeof(PTCacheID)); - - ParticleSimulationState *state_orig; - if (state->head.orig_state != NULL) { - state_orig = (ParticleSimulationState *)state->head.orig_state; - } - else { - state_orig = state; - } - - pid->calldata = state; - pid->type = PTCACHE_TYPE_SIM_PARTICLES; - pid->cache = state_orig->point_cache; - pid->cache_ptr = &state_orig->point_cache; - pid->ptcaches = &state_orig->ptcaches; - pid->totpoint = ptcache_sim_particle_totpoint; - pid->totwrite = ptcache_sim_particle_totpoint; - pid->error = ptcache_sim_particle_error; - - pid->write_point = ptcache_sim_particle_write; - pid->read_point = ptcache_sim_particle_read; - pid->interpolate_point = NULL; - - pid->write_stream = NULL; - pid->read_stream = NULL; - - pid->write_openvdb_stream = NULL; - pid->read_openvdb_stream = NULL; - - pid->write_extra_data = NULL; - pid->read_extra_data = NULL; - pid->interpolate_extra_data = NULL; - - pid->write_header = NULL; - pid->read_header = NULL; - - pid->data_types = 1 << BPHYS_DATA_LOCATION; - pid->info_types = 0; - - pid->stack_index = 0; - - pid->default_step = 1; - pid->max_step = 1; - pid->file_type = PTCACHE_FILE_PTCACHE; -} - /** * \param ob: Optional, may be NULL. * \param scene: Optional may be NULL. @@ -2045,21 +1984,7 @@ static bool foreach_object_modifier_ptcache(Object *object, } } else if (md->type == eModifierType_Simulation) { - SimulationModifierData *smd = (SimulationModifierData *)md; - if (smd->simulation) { - LISTBASE_FOREACH (SimulationState *, state, &smd->simulation->states) { - switch ((eSimulationStateType)state->type) { - case SIM_STATE_TYPE_PARTICLES: { - ParticleSimulationState *particle_state = (ParticleSimulationState *)state; - BKE_ptcache_id_from_sim_particles(&pid, particle_state); - if (!callback(&pid, callback_user_data)) { - return false; - } - break; - } - } - } - } + /* TODO(jacques) */ } } return true; @@ -2289,7 +2214,9 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p return len; /* make sure the above string is always 16 chars */ } -/* youll need to close yourself after! */ +/** + * Caller must close after! + */ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) { PTCacheFile *pf; diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 4752782eaeb..7c335a8e98c 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -466,10 +466,10 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) return shape; } -/* Create new physics sim collision shape for object and store it, - * or remove the existing one first and replace... +/* Helper function to create physics collision shape for object. + * Returns a new collision shape. */ -static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) +static rbCollisionShape *rigidbody_validate_sim_shape_helper(RigidBodyWorld *rbw, Object *ob) { RigidBodyOb *rbo = ob->rigidbody_object; rbCollisionShape *new_shape = NULL; @@ -484,12 +484,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) /* sanity check */ if (rbo == NULL) { - return; - } - - /* don't create a new shape if we already have one and don't want to rebuild it */ - if (rbo->shared->physics_shape && !rebuild) { - return; + return NULL; } /* if automatically determining dimensions, use the Object's boundbox @@ -539,7 +534,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) break; case RB_SHAPE_CONVEXH: - /* try to emged collision margin */ + /* try to embed collision margin */ has_volume = (MIN3(size[0], size[1], size[2]) > 0.0f); if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && has_volume) { @@ -555,18 +550,69 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) case RB_SHAPE_TRIMESH: new_shape = rigidbody_get_shape_trimesh_from_mesh(ob); break; + case RB_SHAPE_COMPOUND: + new_shape = RB_shape_new_compound(); + rbCollisionShape *childShape = NULL; + float loc[3], rot[4]; + float mat[4][4]; + /* Add children to the compound shape */ + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, childObject) { + if (childObject->parent == ob) { + childShape = rigidbody_validate_sim_shape_helper(rbw, childObject); + if (childShape) { + BKE_object_matrix_local_get(childObject, mat); + mat4_to_loc_quat(loc, rot, mat); + RB_compound_add_child_shape(new_shape, childShape, loc, rot); + } + } + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + + break; } - /* use box shape if we can't fall back to old shape */ - if (new_shape == NULL && rbo->shared->physics_shape == NULL) { + /* use box shape if it failed to create new shape */ + if (new_shape == NULL) { new_shape = RB_shape_new_box(size[0], size[1], size[2]); } + if (new_shape) { + RB_shape_set_margin(new_shape, RBO_GET_MARGIN(rbo)); + } + + return new_shape; +} + +/* Create new physics sim collision shape for object and store it, + * or remove the existing one first and replace... + */ +static void rigidbody_validate_sim_shape(RigidBodyWorld *rbw, Object *ob, bool rebuild) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + rbCollisionShape *new_shape = NULL; + + /* sanity check */ + if (rbo == NULL) { + return; + } + + /* don't create a new shape if we already have one and don't want to rebuild it */ + if (rbo->shared->physics_shape && !rebuild) { + return; + } + + /* Also don't create a shape if this object is parent of a compound shape */ + if (ob->parent != NULL && ob->parent->rigidbody_object != NULL && + ob->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND) { + return; + } + + new_shape = rigidbody_validate_sim_shape_helper(rbw, ob); + /* assign new collision shape if creation was successful */ if (new_shape) { if (rbo->shared->physics_shape) { RB_shape_delete(rbo->shared->physics_shape); } rbo->shared->physics_shape = new_shape; - RB_shape_set_margin(rbo->shared->physics_shape, RBO_GET_MARGIN(rbo)); } } @@ -750,7 +796,7 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool /* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, * but it's needed for constraints to update correctly. */ if (rbo->shared->physics_shape == NULL || rebuild) { - rigidbody_validate_sim_shape(ob, true); + rigidbody_validate_sim_shape(rbw, ob, true); } if (rbo->shared->physics_object) { @@ -760,6 +806,12 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool /* remove rigid body if it already exists before creating a new one */ if (rbo->shared->physics_object) { RB_body_delete(rbo->shared->physics_object); + rbo->shared->physics_object = NULL; + } + /* Don't create rigid body object if the parent is a compound shape */ + if (ob->parent != NULL && ob->parent->rigidbody_object != NULL && + ob->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND) { + return; } mat4_to_loc_quat(loc, rot, ob->obmat); @@ -793,7 +845,7 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); } - if (rbw && rbw->shared->physics_world) { + if (rbw && rbw->shared->physics_world && rbo->shared->physics_object) { RB_dworld_add_body(rbw->shared->physics_world, rbo->shared->physics_object, rbo->col_groups); } } @@ -1179,9 +1231,12 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) * - object must exist * - cannot add rigid body if it already exists */ - if (ob == NULL || (ob->rigidbody_object != NULL)) { + if (ob == NULL) { return NULL; } + if (ob->rigidbody_object != NULL) { + return ob->rigidbody_object; + } /* create new settings data, and link it up */ rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb"); @@ -1530,7 +1585,11 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw) int n = 0; FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) { (void)object; - n++; + /* Ignore if this object is the direct child of an object with a compound shape */ + if (object->parent == NULL || object->parent->rigidbody_object == NULL || + object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND) { + n++; + } } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; @@ -1541,8 +1600,12 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw) int i = 0; FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) { - rbw->objects[i] = object; - i++; + /* Ignore if this object is the direct child of an object with a compound shape */ + if (object->parent == NULL || object->parent->rigidbody_object == NULL || + object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND) { + rbw->objects[i] = object; + i++; + } } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } @@ -1754,11 +1817,13 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, /* refresh shape... */ if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) { /* mesh/shape data changed, so force shape refresh */ - rigidbody_validate_sim_shape(ob, true); + rigidbody_validate_sim_shape(rbw, ob, true); /* now tell RB sim about it */ /* XXX: we assume that this can only get applied for active/passive shapes * that will be included as rigidbodies. */ - RB_body_set_collision_shape(rbo->shared->physics_object, rbo->shared->physics_shape); + if (rbo->shared->physics_object != NULL && rbo->shared->physics_shape != NULL) { + RB_body_set_collision_shape(rbo->shared->physics_object, rbo->shared->physics_shape); + } } } rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE); @@ -1817,7 +1882,8 @@ static void rigidbody_update_simulation_post_step(Depsgraph *depsgraph, RigidBod Base *base = BKE_view_layer_base_find(view_layer, ob); RigidBodyOb *rbo = ob->rigidbody_object; /* Reset kinematic state for transformed objects. */ - if (rbo && base && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) { + if (rbo && base && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ) && + rbo->shared->physics_object) { RB_body_set_kinematic_state(rbo->shared->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); RB_body_set_mass(rbo->shared->physics_object, RBO_GET_MASS(rbo)); @@ -1840,8 +1906,13 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) { RigidBodyOb *rbo = ob->rigidbody_object; + /* True if the shape of this object's parent is of type compound */ + bool obCompoundParent = (ob->parent != NULL && ob->parent->rigidbody_object != NULL && + ob->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND); + /* keep original transform for kinematic and passive objects */ - if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE) { + if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE || + obCompoundParent) { return; } @@ -1963,7 +2034,11 @@ void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime int n = 0; FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) { (void)object; - n++; + /* Ignore if this object is the direct child of an object with a compound shape */ + if (object->parent == NULL || object->parent->rigidbody_object == NULL || + object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND) { + n++; + } } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b0faa555f29..fdec29dd43e 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -127,7 +127,7 @@ static void scene_init_data(ID *id) mblur_shutter_curve = &scene->r.mblur_shutter_curve; BKE_curvemapping_set_defaults(mblur_shutter_curve, 1, 0.0f, 0.0f, 1.0f, 1.0f); - BKE_curvemapping_initialize(mblur_shutter_curve); + BKE_curvemapping_init(mblur_shutter_curve); BKE_curvemap_reset(mblur_shutter_curve->cm, &mblur_shutter_curve->clipr, CURVE_PRESET_MAX, @@ -140,13 +140,13 @@ static void scene_init_data(ID *id) /* grease pencil multiframe falloff curve */ scene->toolsettings->gp_sculpt.cur_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); CurveMapping *gp_falloff_curve = scene->toolsettings->gp_sculpt.cur_falloff; - BKE_curvemapping_initialize(gp_falloff_curve); + BKE_curvemapping_init(gp_falloff_curve); BKE_curvemap_reset( gp_falloff_curve->cm, &gp_falloff_curve->clipr, CURVE_PRESET_GAUSS, CURVEMAP_SLOPE_POSITIVE); scene->toolsettings->gp_sculpt.cur_primitive = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); CurveMapping *gp_primitive_curve = scene->toolsettings->gp_sculpt.cur_primitive; - BKE_curvemapping_initialize(gp_primitive_curve); + BKE_curvemapping_init(gp_primitive_curve); BKE_curvemap_reset(gp_primitive_curve->cm, &gp_primitive_curve->clipr, CURVE_PRESET_BELL, @@ -570,6 +570,24 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void scene_foreach_cache(ID *id, + IDTypeForeachCacheFunctionCallback function_callback, + void *user_data) +{ + Scene *scene = (Scene *)id; + IDCacheKey key = { + .id_session_uuid = id->session_uuid, + .offset_in_ID = offsetof(Scene, eevee.light_cache_data), + .cache_v = scene->eevee.light_cache_data, + }; + + function_callback(id, + &key, + (void **)&scene->eevee.light_cache_data, + IDTYPE_CACHE_CB_FLAGS_PERSISTENT, + user_data); +} + IDTypeInfo IDType_ID_SCE = { .id_code = ID_SCE, .id_filter = FILTER_ID_SCE, @@ -587,6 +605,7 @@ IDTypeInfo IDType_ID_SCE = { * support all possible corner cases. */ .make_local = NULL, .foreach_id = scene_foreach_id, + .foreach_cache = scene_foreach_cache, }; const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE"; @@ -751,7 +770,6 @@ void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src) Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) { - const bool is_scene_liboverride = ID_IS_OVERRIDE_LIBRARY(sce); Scene *sce_copy; /* TODO this should/could most likely be replaced by call to more generic code at some point... @@ -822,15 +840,13 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) return sce_copy; } else { - const eDupli_ID_Flags duplicate_flags = U.dupflag | USER_DUP_OBJECT; + eDupli_ID_Flags duplicate_flags = U.dupflag | USER_DUP_OBJECT; BKE_id_copy(bmain, (ID *)sce, (ID **)&sce_copy); id_us_min(&sce_copy->id); id_us_ensure_real(&sce_copy->id); - if (duplicate_flags & USER_DUP_ACT) { - BKE_animdata_copy_id_action(bmain, &sce_copy->id, true); - } + BKE_animdata_duplicate_id_action(bmain, &sce_copy->id, duplicate_flags); /* Extra actions, most notably SCE_FULL_COPY also duplicates several 'children' datablocks. */ @@ -841,22 +857,26 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) if (!is_subprocess) { BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false); BKE_main_id_clear_newpoins(bmain); + /* In case root duplicated ID is linked, assume we want to get a local copy of it and + * duplicate all expected linked data. */ + if (ID_IS_LINKED(sce)) { + duplicate_flags |= USER_DUP_LINKED_ID; + } } /* Copy Freestyle LineStyle datablocks. */ LISTBASE_FOREACH (ViewLayer *, view_layer_dst, &sce_copy->view_layers) { LISTBASE_FOREACH ( FreestyleLineSet *, lineset, &view_layer_dst->freestyle_config.linesets) { - BKE_id_copy_for_duplicate( - bmain, &lineset->linestyle->id, is_scene_liboverride, duplicate_flags); + BKE_id_copy_for_duplicate(bmain, (ID *)lineset->linestyle, duplicate_flags); } } /* Full copy of world (included animations) */ - BKE_id_copy_for_duplicate(bmain, &sce->world->id, is_scene_liboverride, duplicate_flags); + BKE_id_copy_for_duplicate(bmain, (ID *)sce->world, duplicate_flags); /* Full copy of GreasePencil. */ - BKE_id_copy_for_duplicate(bmain, &sce->gpd->id, is_scene_liboverride, duplicate_flags); + BKE_id_copy_for_duplicate(bmain, (ID *)sce->gpd, duplicate_flags); /* Deep-duplicate collections and objects (using preferences' settings for which sub-data to * duplicate along the object itself). */ diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index de233a8d473..4a2ad88bb28 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2668,7 +2668,7 @@ static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int heig } static void RVIsolateHighlights_float( - float *in, float *out, int width, int height, float threshold, float boost, float clamp) + const float *in, float *out, int width, int height, float threshold, float boost, float clamp) { int x, y, index; float intensity; @@ -3423,7 +3423,7 @@ static void do_gaussian_blur_effect_byte_x(Sequence *seq, int y, int frame_width, int UNUSED(frame_height), - unsigned char *rect, + const unsigned char *rect, unsigned char *out) { #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4) @@ -3473,7 +3473,7 @@ static void do_gaussian_blur_effect_byte_y(Sequence *seq, int y, int UNUSED(frame_width), int frame_height, - unsigned char *rect, + const unsigned char *rect, unsigned char *out) { #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4) diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 604cbf476a8..0bf7fffb833 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -57,7 +57,7 @@ typedef void (*modifier_apply_threaded_cb)(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v); typedef struct ModifierInitData { @@ -223,7 +223,7 @@ static void whiteBalance_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { int x, y; @@ -331,7 +331,7 @@ static void curves_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *)data_v; @@ -396,7 +396,7 @@ static void curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *m float black[3] = {0.0f, 0.0f, 0.0f}; float white[3] = {1.0f, 1.0f, 1.0f}; - BKE_curvemapping_initialize(&cmd->curve_mapping); + BKE_curvemapping_init(&cmd->curve_mapping); BKE_curvemapping_premultiply(&cmd->curve_mapping, 0); BKE_curvemapping_set_black_white(&cmd->curve_mapping, black, white); @@ -461,7 +461,7 @@ static void hue_correct_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { CurveMapping *curve_mapping = (CurveMapping *)data_v; @@ -525,7 +525,7 @@ static void hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImB { HueCorrectModifierData *hcmd = (HueCorrectModifierData *)smd; - BKE_curvemapping_initialize(&hcmd->curve_mapping); + BKE_curvemapping_init(&hcmd->curve_mapping); modifier_apply_threaded(ibuf, mask, hue_correct_apply_threaded, &hcmd->curve_mapping); } @@ -556,7 +556,7 @@ static void brightcontrast_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { BrightContrastThreadData *data = (BrightContrastThreadData *)data_v; @@ -658,7 +658,7 @@ static void maskmodifier_apply_threaded(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *UNUSED(data_v)) { int x, y; @@ -755,7 +755,7 @@ static void tonemapmodifier_apply_threaded_simple(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { AvgLogLum *avg = (AvgLogLum *)data_v; @@ -814,7 +814,7 @@ static void tonemapmodifier_apply_threaded_photoreceptor(int width, unsigned char *rect, float *rect_float, unsigned char *mask_rect, - float *mask_rect_float, + const float *mask_rect_float, void *data_v) { AvgLogLum *avg = (AvgLogLum *)data_v; diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c index 30a371b5b28..ff3829bdebb 100644 --- a/source/blender/blenkernel/intern/seqprefetch.c +++ b/source/blender/blenkernel/intern/seqprefetch.c @@ -183,6 +183,10 @@ static float seq_prefetch_cfra(PrefetchJob *pfjob) { return pfjob->cfra + pfjob->num_frames_prefetched; } +static AnimationEvalContext seq_prefetch_anim_eval_context(PrefetchJob *pfjob) +{ + return BKE_animsys_eval_context_construct(pfjob->depsgraph, seq_prefetch_cfra(pfjob)); +} void BKE_sequencer_prefetch_get_time_range(Scene *scene, int *start, int *end) { @@ -435,8 +439,9 @@ static void *seq_prefetch_frames(void *job) seq_prefetch_update_depsgraph(pfjob); AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id); + AnimationEvalContext anim_eval_context = seq_prefetch_anim_eval_context(pfjob); BKE_animsys_evaluate_animdata( - &pfjob->context_cpy.scene->id, adt, seq_prefetch_cfra(pfjob), ADT_RECALC_ALL, false); + &pfjob->context_cpy.scene->id, adt, &anim_eval_context, ADT_RECALC_ALL, false); /* This is quite hacky solution: * We need cross-reference original scene with copy for cache. diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 297d60e5976..b0a8f709399 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -46,6 +46,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_path_util.h" +#include "BLI_session_uuid.h" #include "BLI_string.h" #include "BLI_string_utf8.h" #include "BLI_threads.h" @@ -114,8 +115,7 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context, float cfra, clock_t begin, bool use_preprocess, - const bool is_proxy_image, - const bool is_preprocessed); + const bool is_proxy_image); static ImBuf *seq_render_strip(const SeqRenderData *context, SeqRenderState *state, Sequence *seq, @@ -1091,6 +1091,64 @@ void BKE_sequence_reload_new_file(Main *bmain, Scene *scene, Sequence *seq, cons BKE_sequence_calc(scene, seq); } +void BKE_sequence_movie_reload_if_needed(struct Main *bmain, + struct Scene *scene, + struct Sequence *seq, + bool *r_was_reloaded, + bool *r_can_produce_frames) +{ + BLI_assert(seq->type == SEQ_TYPE_MOVIE || + !"This function is only implemented for movie strips."); + + bool must_reload = false; + + /* The Sequence struct allows for multiple anim structs to be associated with one strip. This + * function will return true only if there is at least one 'anim' AND all anims can produce + * frames. */ + + if (BLI_listbase_is_empty(&seq->anims)) { + /* No anim present, so reloading is always necessary. */ + must_reload = true; + } + else { + LISTBASE_FOREACH (StripAnim *, sanim, &seq->anims) { + if (!IMB_anim_can_produce_frames(sanim->anim)) { + /* Anim cannot produce frames, try reloading. */ + must_reload = true; + break; + } + }; + } + + if (!must_reload) { + /* There are one or more anims, and all can produce frames. */ + *r_was_reloaded = false; + *r_can_produce_frames = true; + return; + } + + BKE_sequence_reload_new_file(bmain, scene, seq, true); + *r_was_reloaded = true; + + if (BLI_listbase_is_empty(&seq->anims)) { + /* No anims present after reloading => no frames can be produced. */ + *r_can_produce_frames = false; + return; + } + + /* Check if there are still anims that cannot produce frames. */ + LISTBASE_FOREACH (StripAnim *, sanim, &seq->anims) { + if (!IMB_anim_can_produce_frames(sanim->anim)) { + /* There still is an anim that cannot produce frames. */ + *r_can_produce_frames = false; + return; + } + }; + + /* There are one or more anims, and all can produce frames. */ + *r_can_produce_frames = true; +} + void BKE_sequencer_sort(Scene *scene) { /* all strips together per kind, and in order of y location ("machine") */ @@ -1332,30 +1390,6 @@ ListBase *BKE_sequence_seqbase_get(Sequence *seq, int *r_offset) /*********************** DO THE SEQUENCE *************************/ -static void make_black_ibuf(ImBuf *ibuf) -{ - unsigned int *rect; - float *rect_float; - int tot; - - if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { - return; - } - - tot = ibuf->x * ibuf->y; - - rect = ibuf->rect; - rect_float = ibuf->rect_float; - - if (rect) { - memset(rect, 0, tot * sizeof(char) * 4); - } - - if (rect_float) { - memset(rect_float, 0, tot * sizeof(float) * 4); - } -} - static void multibuf(ImBuf *ibuf, const float fmul) { char *rt; @@ -2415,7 +2449,7 @@ static void color_balance_byte_float(StripColorBalance *cb_, static void color_balance_float_float(StripColorBalance *cb_, float *rect_float, - float *mask_rect_float, + const float *mask_rect_float, int width, int height, float mul) @@ -2657,8 +2691,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, float cfra, ImBuf *ibuf, - const bool is_proxy_image, - const bool is_preprocessed) + const bool is_proxy_image) { Scene *scene = context->scene; float mul; @@ -2672,15 +2705,6 @@ static ImBuf *input_preprocess(const SeqRenderData *context, if (seq->flag & (SEQ_USE_CROP | SEQ_USE_TRANSFORM)) { StripCrop c = {0}; StripTransform t = {0}; - int sx, sy, dx, dy; - - if (is_proxy_image) { - double f = BKE_sequencer_rendersize_to_scale_factor(context->preview_render_size); - - if (f != 1.0) { - IMB_scalefastImBuf(ibuf, ibuf->x * f, ibuf->y * f); - } - } if (seq->flag & SEQ_USE_CROP && seq->strip->crop) { c = *seq->strip->crop; @@ -2689,33 +2713,41 @@ static ImBuf *input_preprocess(const SeqRenderData *context, t = *seq->strip->transform; } - if (is_preprocessed) { - double xscale = scene->r.xsch ? ((double)context->rectx / (double)scene->r.xsch) : 1.0; - double yscale = scene->r.ysch ? ((double)context->recty / (double)scene->r.ysch) : 1.0; - if (seq->flag & SEQ_USE_TRANSFORM) { - t.xofs *= xscale; - t.yofs *= yscale; + /* Calculate scale factor for current image if needed. */ + double scale_factor, image_scale_factor = 1.0; + if (context->preview_render_size == SEQ_PROXY_RENDER_SIZE_SCENE) { + scale_factor = image_scale_factor = (double)scene->r.size / 100; + } + else { + scale_factor = BKE_sequencer_rendersize_to_scale_factor(context->preview_render_size); + if (!is_proxy_image) { + image_scale_factor = scale_factor; } - if (seq->flag & SEQ_USE_CROP) { - c.left *= xscale; - c.right *= xscale; - c.top *= yscale; - c.bottom *= yscale; + } + + if (image_scale_factor != 1.0) { + if (context->for_render) { + IMB_scaleImBuf(ibuf, ibuf->x * image_scale_factor, ibuf->y * image_scale_factor); + } + else { + IMB_scalefastImBuf(ibuf, ibuf->x * image_scale_factor, ibuf->y * image_scale_factor); } } + t.xofs *= scale_factor; + t.yofs *= scale_factor; + c.left *= scale_factor; + c.right *= scale_factor; + c.top *= scale_factor; + c.bottom *= scale_factor; + + int sx, sy, dx, dy; sx = ibuf->x - c.left - c.right; sy = ibuf->y - c.top - c.bottom; if (seq->flag & SEQ_USE_TRANSFORM) { - if (is_preprocessed) { - dx = context->rectx; - dy = context->recty; - } - else { - dx = scene->r.xsch; - dy = scene->r.ysch; - } + dx = context->rectx; + dy = context->recty; } else { dx = sx; @@ -2724,19 +2756,15 @@ static ImBuf *input_preprocess(const SeqRenderData *context, if (c.top + c.bottom >= ibuf->y || c.left + c.right >= ibuf->x || t.xofs >= dx || t.yofs >= dy) { - make_black_ibuf(ibuf); + return NULL; } - else { - ImBuf *i = IMB_allocImBuf(dx, dy, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); - - IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); - sequencer_imbuf_assign_spaces(scene, i); - - IMB_metadata_copy(i, ibuf); - IMB_freeImBuf(ibuf); - ibuf = i; - } + ImBuf *i = IMB_allocImBuf(dx, dy, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); + IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); + sequencer_imbuf_assign_spaces(scene, i); + IMB_metadata_copy(i, ibuf); + IMB_freeImBuf(ibuf); + ibuf = i; } if (seq->flag & SEQ_FLIPX) { @@ -3097,7 +3125,7 @@ static ImBuf *seq_render_image_strip(const SeqRenderData *context, if (view_id != context->view_id) { ibufs_arr[view_id] = seq_render_preprocess_ibuf( - &localcontext, seq, ibufs_arr[view_id], cfra, clock(), true, false, false); + &localcontext, seq, ibufs_arr[view_id], cfra, clock(), true, false); } } @@ -3214,7 +3242,7 @@ static ImBuf *seq_render_movie_strip( if (view_id != context->view_id) { ibuf_arr[view_id] = seq_render_preprocess_ibuf( - &localcontext, seq, ibuf_arr[view_id], cfra, clock(), true, false, false); + &localcontext, seq, ibuf_arr[view_id], cfra, clock(), true, false); } } @@ -3334,7 +3362,9 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr /* anim-data */ adt = BKE_animdata_from_id(&mask->id); - BKE_animsys_evaluate_animdata(&mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false); + const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( + context->depsgraph, mask->sfra + nr); + BKE_animsys_evaluate_animdata(&mask_temp->id, adt, &anim_eval_context, ADT_RECALC_ANIM, false); maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__); @@ -3804,8 +3834,7 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context, float cfra, clock_t begin, bool use_preprocess, - const bool is_proxy_image, - const bool is_preprocessed) + const bool is_proxy_image) { if (context->is_proxy_render == false && (ibuf->x != context->rectx || ibuf->y != context->recty)) { @@ -3814,11 +3843,17 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context, if (use_preprocess) { float cost = seq_estimate_render_cost_end(context->scene, begin); - BKE_sequencer_cache_put(context, seq, cfra, SEQ_CACHE_STORE_RAW, ibuf, cost, false); + + /* TODO (Richard): It should be possible to store in cache if image is proxy, + * but it adds quite a bit of complexity. Since proxies are fast to read, I would + * rather simplify existing code a bit. */ + if (!is_proxy_image) { + BKE_sequencer_cache_put(context, seq, cfra, SEQ_CACHE_STORE_RAW, ibuf, cost, false); + } /* Reset timer so we can get partial render time. */ begin = seq_estimate_render_cost_begin(); - ibuf = input_preprocess(context, seq, cfra, ibuf, is_proxy_image, is_preprocessed); + ibuf = input_preprocess(context, seq, cfra, ibuf, is_proxy_image); } float cost = seq_estimate_render_cost_end(context->scene, begin); @@ -3834,11 +3869,6 @@ static ImBuf *seq_render_strip(const SeqRenderData *context, ImBuf *ibuf = NULL; bool use_preprocess = false; bool is_proxy_image = false; - /* all effects are handled similarly with the exception of speed effect */ - int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : - seq->type; - bool is_preprocessed = !ELEM( - type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP); clock_t begin = seq_estimate_render_cost_begin(); @@ -3855,7 +3885,7 @@ static ImBuf *seq_render_strip(const SeqRenderData *context, if (ibuf) { use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); ibuf = seq_render_preprocess_ibuf( - context, seq, ibuf, cfra, begin, use_preprocess, is_proxy_image, is_preprocessed); + context, seq, ibuf, cfra, begin, use_preprocess, is_proxy_image); } if (ibuf == NULL) { @@ -4272,6 +4302,10 @@ void BKE_sequence_invalidate_movieclip_strips(Main *bmain, MovieClip *clip_targe void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render) { + if (scene->ed == NULL) { + return; + } + Sequence *seq; BKE_sequencer_cache_cleanup(scene); @@ -5319,9 +5353,16 @@ Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine, int type) seq->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Sequence Stereo Format"); seq->cache_flag = SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED | SEQ_CACHE_STORE_COMPOSITE; + BKE_sequence_session_uuid_generate(seq); + return seq; } +void BKE_sequence_session_uuid_generate(struct Sequence *sequence) +{ + sequence->runtime.session_uuid = BLI_session_uuid_generate(); +} + void BKE_sequence_alpha_mode_from_extension(Sequence *seq) { if (seq->strip && seq->strip->stripdata) { @@ -5551,6 +5592,9 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad } } + if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { + seq_load->channel++; + } seq = BKE_sequence_alloc(seqbasep, seq_load->start_frame, seq_load->channel, SEQ_TYPE_MOVIE); /* multiview settings */ @@ -5607,11 +5651,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) { int start_frame_back = seq_load->start_frame; seq_load->channel--; - seq_load->seq_sound = BKE_sequencer_add_sound_strip(C, seqbasep, seq_load); - seq_load->start_frame = start_frame_back; - seq_load->channel++; } /* can be NULL */ @@ -5631,6 +5672,10 @@ static Sequence *seq_dupli(const Scene *scene_src, { Sequence *seqn = MEM_dupallocN(seq); + if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) { + BKE_sequence_session_uuid_generate(seq); + } + seq->tmp = seqn; seqn->strip = MEM_dupallocN(seq->strip); @@ -5698,7 +5743,7 @@ static Sequence *seq_dupli(const Scene *scene_src, struct SeqEffectHandle sh; sh = BKE_sequence_get_effect(seq); if (sh.copy) { - sh.copy(seq, seqn, flag); + sh.copy(seqn, seq, flag); } seqn->strip->stripdata = NULL; @@ -6013,3 +6058,113 @@ bool BKE_sequencer_check_scene_recursion(Scene *scene, ReportList *reports) return false; } + +/* Check if "seq_main" (indirectly) uses strip "seq". */ +bool BKE_sequencer_render_loop_check(Sequence *seq_main, Sequence *seq) +{ + if (seq_main == seq) { + return true; + } + + if ((seq_main->seq1 && BKE_sequencer_render_loop_check(seq_main->seq1, seq)) || + (seq_main->seq2 && BKE_sequencer_render_loop_check(seq_main->seq2, seq)) || + (seq_main->seq3 && BKE_sequencer_render_loop_check(seq_main->seq3, seq))) { + return true; + } + + SequenceModifierData *smd; + for (smd = seq_main->modifiers.first; smd; smd = smd->next) { + if (smd->mask_sequence && BKE_sequencer_render_loop_check(smd->mask_sequence, seq)) { + return true; + } + } + + return false; +} + +static void sequencer_flag_users_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq) +{ + LISTBASE_FOREACH (Sequence *, user_seq, seqbase) { + /* Look in metas for usage of seq. */ + if (user_seq->type == SEQ_TYPE_META) { + sequencer_flag_users_for_removal(scene, &user_seq->seqbase, seq); + } + + /* Clear seq from modifiers. */ + SequenceModifierData *smd; + for (smd = user_seq->modifiers.first; smd; smd = smd->next) { + if (smd->mask_sequence == seq) { + smd->mask_sequence = NULL; + } + } + + /* Remove effects, that use seq. */ + if ((user_seq->seq1 && user_seq->seq1 == seq) || (user_seq->seq2 && user_seq->seq2 == seq) || + (user_seq->seq3 && user_seq->seq3 == seq)) { + user_seq->flag |= SEQ_FLAG_DELETE; + /* Strips can be used as mask even if not in same seqbase. */ + sequencer_flag_users_for_removal(scene, &scene->ed->seqbase, user_seq); + } + } +} + +/* Flag seq and its users (effects) for removal. */ +void BKE_sequencer_flag_for_removal(Scene *scene, ListBase *seqbase, Sequence *seq) +{ + if (seq == NULL || (seq->flag & SEQ_FLAG_DELETE) != 0) { + return; + } + + /* Flag and remove meta children. */ + if (seq->type == SEQ_TYPE_META) { + LISTBASE_FOREACH (Sequence *, meta_child, &seq->seqbase) { + BKE_sequencer_flag_for_removal(scene, &seq->seqbase, meta_child); + } + } + + seq->flag |= SEQ_FLAG_DELETE; + sequencer_flag_users_for_removal(scene, seqbase, seq); +} + +/* Remove all flagged sequences, return true if sequence is removed. */ +void BKE_sequencer_remove_flagged_sequences(Scene *scene, ListBase *seqbase) +{ + LISTBASE_FOREACH_MUTABLE (Sequence *, seq, seqbase) { + if (seq->flag & SEQ_FLAG_DELETE) { + if (seq->type == SEQ_TYPE_META) { + BKE_sequencer_remove_flagged_sequences(scene, &seq->seqbase); + } + BLI_remlink(seqbase, seq); + BKE_sequence_free(scene, seq, true); + } + } +} + +void BKE_sequencer_check_uuids_unique_and_report(const Scene *scene) +{ + if (scene->ed == NULL) { + return; + } + + struct GSet *used_uuids = BLI_gset_new( + BLI_session_uuid_ghash_hash, BLI_session_uuid_ghash_compare, "sequencer used uuids"); + + const Sequence *sequence; + SEQ_BEGIN (scene->ed, sequence) { + const SessionUUID *session_uuid = &sequence->runtime.session_uuid; + if (!BLI_session_uuid_is_generated(session_uuid)) { + printf("Sequence %s does not have UUID generated.\n", sequence->name); + continue; + } + + if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) { + printf("Sequence %s has duplicate UUID generated.\n", sequence->name); + continue; + } + + BLI_gset_insert(used_uuids, (void *)session_uuid); + } + SEQ_END; + + BLI_gset_free(used_uuids, NULL); +} diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index c4a35141b0d..c0fc8fcb464 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -31,6 +31,7 @@ #include "BLI_float3.hh" #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_rand.h" #include "BLI_span.hh" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -47,13 +48,37 @@ #include "BKE_pointcache.h" #include "BKE_simulation.h" +#include "NOD_node_tree_multi_function.hh" #include "NOD_simulation.h" +#include "BLI_map.hh" #include "BLT_translation.h" +#include "FN_attributes_ref.hh" +#include "FN_multi_function_network_evaluation.hh" +#include "FN_multi_function_network_optimization.hh" + #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "SIM_simulation_update.hh" + +using StateInitFunction = void (*)(SimulationState *state); +using StateResetFunction = void (*)(SimulationState *state); +using StateRemoveFunction = void (*)(SimulationState *state); +using StateCopyFunction = void (*)(const SimulationState *src, SimulationState *dst); + +struct SimulationStateType { + const char *name; + int size; + StateInitFunction init; + StateResetFunction reset; + StateRemoveFunction remove; + StateCopyFunction copy; +}; + +static const SimulationStateType *try_get_state_type(blender::StringRefNull type_name); + static void simulation_init_data(ID *id) { Simulation *simulation = (Simulation *)id; @@ -63,20 +88,12 @@ static void simulation_init_data(ID *id) bNodeTree *ntree = ntreeAddTree(nullptr, "Simulation Nodetree", ntreeType_Simulation->idname); simulation->nodetree = ntree; - - /* Add a default particle simulation state for now. */ - ParticleSimulationState *state = (ParticleSimulationState *)MEM_callocN( - sizeof(ParticleSimulationState), __func__); - CustomData_reset(&state->attributes); - - state->point_cache = BKE_ptcache_add(&state->ptcaches); - BLI_addtail(&simulation->states, state); } static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag) { Simulation *simulation_dst = (Simulation *)id_dst; - Simulation *simulation_src = (Simulation *)id_src; + const Simulation *simulation_src = (const Simulation *)id_src; /* We always need allocation of our private ID data. */ const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE; @@ -89,19 +106,14 @@ static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons } BLI_listbase_clear(&simulation_dst->states); - LISTBASE_FOREACH (const SimulationState *, state_src, &simulation_src->states) { - switch ((eSimulationStateType)state_src->type) { - case SIM_STATE_TYPE_PARTICLES: { - ParticleSimulationState *particle_state_dst = (ParticleSimulationState *)MEM_callocN( - sizeof(ParticleSimulationState), __func__); - CustomData_reset(&particle_state_dst->attributes); - - BLI_addtail(&simulation_dst->states, particle_state_dst); - break; - } - } + SimulationState *state_dst = BKE_simulation_state_add( + simulation_dst, state_src->type, state_src->name); + BKE_simulation_state_copy_data(state_src, state_dst); } + + BLI_listbase_clear(&simulation_dst->dependencies); + BLI_duplicatelist(&simulation_dst->dependencies, &simulation_src->dependencies); } static void simulation_free_data(ID *id) @@ -116,17 +128,9 @@ static void simulation_free_data(ID *id) simulation->nodetree = nullptr; } - LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) { - switch ((eSimulationStateType)state->type) { - case SIM_STATE_TYPE_PARTICLES: { - ParticleSimulationState *particle_state = (ParticleSimulationState *)state; - CustomData_free(&particle_state->attributes, particle_state->tot_particles); - BKE_ptcache_free_list(&particle_state->ptcaches); - break; - } - } - MEM_freeN(state); - } + BKE_simulation_state_remove_all(simulation); + + BLI_freelistN(&simulation->dependencies); } static void simulation_foreach_id(ID *id, LibraryForeachIDData *data) @@ -136,6 +140,9 @@ static void simulation_foreach_id(ID *id, LibraryForeachIDData *data) /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree); } + LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { + BKE_LIB_FOREACHID_PROCESS_ID(data, dependency->id, IDWALK_CB_USER); + } } IDTypeInfo IDType_ID_SIM = { @@ -164,103 +171,203 @@ void *BKE_simulation_add(Main *bmain, const char *name) return simulation; } -namespace blender::bke { +SimulationState *BKE_simulation_state_add(Simulation *simulation, + const char *type, + const char *name) +{ + BLI_assert(simulation != nullptr); + BLI_assert(name != nullptr); + + const SimulationStateType *state_type = try_get_state_type(type); + BLI_assert(state_type != nullptr); + + SimulationState *state = (SimulationState *)MEM_callocN(state_type->size, AT); + state->type = BLI_strdup(type); + state->name = BLI_strdup(name); + + state_type->init(state); + BLI_addtail(&simulation->states, state); + return state; +} -static MutableSpan<float3> get_particle_positions(ParticleSimulationState *state) +void BKE_simulation_state_remove(Simulation *simulation, SimulationState *state) { - return MutableSpan<float3>( - (float3 *)CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Position"), - state->tot_particles); + BLI_assert(simulation != nullptr); + BLI_assert(state != nullptr); + BLI_assert(BLI_findindex(&simulation->states, state) >= 0); + + BLI_remlink(&simulation->states, state); + const SimulationStateType *state_type = try_get_state_type(state->type); + BLI_assert(state_type != nullptr); + state_type->remove(state); + MEM_freeN(state->name); + MEM_freeN(state->type); + MEM_freeN(state); } -static void ensure_attributes_exist(ParticleSimulationState *state) +void BKE_simulation_state_remove_all(Simulation *simulation) { - if (CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Position") == nullptr) { - CustomData_add_layer_named( - &state->attributes, CD_LOCATION, CD_CALLOC, nullptr, state->tot_particles, "Position"); + BLI_assert(simulation != nullptr); + + while (!BLI_listbase_is_empty(&simulation->states)) { + BKE_simulation_state_remove(simulation, (SimulationState *)simulation->states.first); } } -static void copy_particle_state_to_cow(ParticleSimulationState *state_orig, - ParticleSimulationState *state_cow) +void BKE_simulation_state_reset(Simulation *UNUSED(simulation), SimulationState *state) { - ensure_attributes_exist(state_cow); - CustomData_free(&state_cow->attributes, state_cow->tot_particles); - CustomData_copy(&state_orig->attributes, - &state_cow->attributes, - CD_MASK_ALL, - CD_DUPLICATE, - state_orig->tot_particles); - state_cow->current_frame = state_orig->current_frame; - state_cow->tot_particles = state_orig->tot_particles; + BLI_assert(state != nullptr); + + const SimulationStateType *state_type = try_get_state_type(state->type); + BLI_assert(state_type != nullptr); + state_type->reset(state); } -static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation) +void BKE_simulation_state_reset_all(Simulation *simulation) { - int current_frame = scene->r.cfra; + BLI_assert(simulation != nullptr); - ParticleSimulationState *state_cow = (ParticleSimulationState *)simulation->states.first; - ParticleSimulationState *state_orig = (ParticleSimulationState *)state_cow->head.orig_state; - - if (current_frame == state_cow->current_frame) { - return; + LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { + BKE_simulation_state_reset(simulation, state); } +} - /* Number of particles should be stored in the cache, but for now assume it is constant. */ - state_cow->tot_particles = state_orig->tot_particles; - CustomData_realloc(&state_cow->attributes, state_orig->tot_particles); - ensure_attributes_exist(state_cow); +void BKE_simulation_state_copy_data(const SimulationState *src_state, SimulationState *dst_state) +{ + BLI_assert(src_state != nullptr); + BLI_assert(dst_state != nullptr); + BLI_assert(STREQ(src_state->type, dst_state->type)); - PTCacheID pid_cow; - BKE_ptcache_id_from_sim_particles(&pid_cow, state_cow); - BKE_ptcache_id_time(&pid_cow, scene, current_frame, nullptr, nullptr, nullptr); + const SimulationStateType *state_type = try_get_state_type(src_state->type); + BLI_assert(state_type != nullptr); + state_type->copy(src_state, dst_state); +} - /* If successfull, this will read the state directly into the cow state. */ - int cache_result = BKE_ptcache_read(&pid_cow, current_frame, true); - if (cache_result == PTCACHE_READ_EXACT) { - state_cow->current_frame = current_frame; - return; +SimulationState *BKE_simulation_state_try_find_by_name(Simulation *simulation, const char *name) +{ + if (simulation == nullptr) { + return nullptr; + } + if (name == nullptr) { + return nullptr; } - /* Below we modify the original state/cache. Only the active depsgraph is allowed to do that. */ - if (!DEG_is_active(depsgraph)) { - return; + LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { + if (STREQ(state->name, name)) { + return state; + } } + return nullptr; +} - PTCacheID pid_orig; - BKE_ptcache_id_from_sim_particles(&pid_orig, state_orig); - BKE_ptcache_id_time(&pid_orig, scene, current_frame, nullptr, nullptr, nullptr); +SimulationState *BKE_simulation_state_try_find_by_name_and_type(Simulation *simulation, + const char *name, + const char *type) +{ + if (type == nullptr) { + return nullptr; + } - if (current_frame == 1) { - state_orig->tot_particles = 100; - state_orig->current_frame = 1; - CustomData_realloc(&state_orig->attributes, state_orig->tot_particles); - ensure_attributes_exist(state_orig); + SimulationState *state = BKE_simulation_state_try_find_by_name(simulation, name); + if (state == nullptr) { + return nullptr; + } + if (STREQ(state->type, type)) { + return state; + } + return nullptr; +} - MutableSpan<float3> positions = get_particle_positions(state_orig); - for (uint i : positions.index_range()) { - positions[i] = {i / 10.0f, 0, 0}; - } +void BKE_simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation) +{ + blender::sim::update_simulation_in_depsgraph(depsgraph, scene, simulation); +} - BKE_ptcache_write(&pid_orig, current_frame); - copy_particle_state_to_cow(state_orig, state_cow); +void BKE_simulation_update_dependencies(Simulation *simulation, Main *bmain) +{ + bool dependencies_changed = blender::sim::update_simulation_dependencies(simulation); + if (dependencies_changed) { + DEG_relations_tag_update(bmain); } - else if (current_frame == state_orig->current_frame + 1) { - state_orig->current_frame = current_frame; - ensure_attributes_exist(state_orig); - MutableSpan<float3> positions = get_particle_positions(state_orig); - for (float3 &position : positions) { - position.z += 0.1f; - } +} - BKE_ptcache_write(&pid_orig, current_frame); - copy_particle_state_to_cow(state_orig, state_cow); +using StateTypeMap = blender::Map<std::string, std::unique_ptr<SimulationStateType>>; + +template<typename T> +static void add_state_type(StateTypeMap &map, + const char *name, + void (*init)(T *state), + void (*reset)(T *state), + void (*remove)(T *state), + void (*copy)(const T *src, T *dst)) +{ + SimulationStateType state_type{ + name, + (int)sizeof(T), + (StateInitFunction)init, + (StateResetFunction)reset, + (StateRemoveFunction)remove, + (StateCopyFunction)copy, + }; + map.add_new(name, std::make_unique<SimulationStateType>(state_type)); +} + +static StateTypeMap init_state_types() +{ + StateTypeMap map; + add_state_type<ParticleSimulationState>( + map, + SIM_TYPE_NAME_PARTICLE_SIMULATION, + [](ParticleSimulationState *state) { CustomData_reset(&state->attributes); }, + [](ParticleSimulationState *state) { + CustomData_free(&state->attributes, state->tot_particles); + state->tot_particles = 0; + state->next_particle_id = 0; + }, + [](ParticleSimulationState *state) { + CustomData_free(&state->attributes, state->tot_particles); + }, + [](const ParticleSimulationState *src, ParticleSimulationState *dst) { + CustomData_free(&dst->attributes, dst->tot_particles); + dst->tot_particles = src->tot_particles; + dst->next_particle_id = src->next_particle_id; + CustomData_copy( + &src->attributes, &dst->attributes, CD_MASK_ALL, CD_DUPLICATE, src->tot_particles); + }); + + add_state_type<ParticleMeshEmitterSimulationState>( + map, + SIM_TYPE_NAME_PARTICLE_MESH_EMITTER, + [](ParticleMeshEmitterSimulationState *UNUSED(state)) {}, + [](ParticleMeshEmitterSimulationState *state) { state->last_birth_time = 0.0f; }, + [](ParticleMeshEmitterSimulationState *UNUSED(state)) {}, + [](const ParticleMeshEmitterSimulationState *src, ParticleMeshEmitterSimulationState *dst) { + dst->last_birth_time = src->last_birth_time; + }); + return map; +} + +static StateTypeMap &get_state_types() +{ + static StateTypeMap state_type_map = init_state_types(); + return state_type_map; +} + +static const SimulationStateType *try_get_state_type(blender::StringRefNull type_name) +{ + std::unique_ptr<SimulationStateType> *type = get_state_types().lookup_ptr_as(type_name); + if (type == nullptr) { + return nullptr; } + return type->get(); } -} // namespace blender::bke +template<> const char *BKE_simulation_get_state_type_name<ParticleSimulationState>() +{ + return SIM_TYPE_NAME_PARTICLE_SIMULATION; +} -void BKE_simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation) +template<> const char *BKE_simulation_get_state_type_name<ParticleMeshEmitterSimulationState>() { - blender::bke::simulation_data_update(depsgraph, scene, simulation); + return SIM_TYPE_NAME_PARTICLE_MESH_EMITTER; } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 9c7abbdf876..b7b325644ca 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -165,24 +165,28 @@ static void free_softbody_intern(SoftBody *sb); /*physical unit of force is [kg * m / sec^2]*/ -static float sb_grav_force_scale(Object *UNUSED(ob)) -/* since unit of g is [m/sec^2] and F = mass * g we rescale unit mass of node to 1 gramm - * put it to a function here, so we can add user options later without touching simulation code +/** + * Since unit of g is [m/sec^2] and F = mass * g we re-scale unit mass of node to 1 gram + * put it to a function here, so we can add user options later without touching simulation code. */ +static float sb_grav_force_scale(Object *UNUSED(ob)) { return (0.001f); } -static float sb_fric_force_scale(Object *UNUSED(ob)) -/* rescaling unit of drag [1 / sec] to somehow reasonable - * put it to a function here, so we can add user options later without touching simulation code +/** + * Re-scaling unit of drag [1 / sec] to somehow reasonable + * put it to a function here, so we can add user options later without touching simulation code. */ +static float sb_fric_force_scale(Object *UNUSED(ob)) { return (0.01f); } +/** + * Defining the frames to *real* time relation. + */ static float sb_time_scale(Object *ob) -/* defining the frames to *real* time relation */ { SoftBody *sb = ob->soft; /* is supposed to be there */ if (sb) { @@ -481,7 +485,6 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M) mima->maxy = max_ff(mima->maxy, v[1] + hull); mima->maxz = max_ff(mima->maxz, v[2] + hull); } - return; } static void ccd_mesh_free(ccd_Mesh *ccdm) diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 18fd8a10cc1..1fcfc9b060f 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -123,7 +123,7 @@ static void sound_foreach_cache(ID *id, .cache_v = sound->waveform, }; - function_callback(id, &key, &sound->waveform, user_data); + function_callback(id, &key, &sound->waveform, 0, user_data); } IDTypeInfo IDType_ID_SO = { diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index 8455b60c894..46341652544 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -875,7 +875,6 @@ BLI_INLINE void studiolight_spherical_harmonics_eval(StudioLight *sl, color[i] = studiolight_spherical_harmonics_geomerics_eval( normal, sh[0][i], sh[1][i], sh[2][i], sh[3][i]); } - return; #else /* L0 */ mul_v3_v3fl(color, sl->spherical_harmonics_coefs[0], 0.282095f); diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index a1e218390c3..c992990e0a0 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -1618,6 +1618,18 @@ static int prev_adjacent_edge_point_index(const SubdivCCG *subdiv_ccg, const int return point_index - 1; } +/* When the point index corresponds to a grid corner, returns the point index which corresponds to + * the corner of the adjacent grid, as the adjacent edge has two separate points for each grid + * corner at the middle of the edge. */ +static int adjacent_grid_corner_point_index_on_edge(const SubdivCCG *subdiv_ccg, + const int point_index) +{ + if (point_index == subdiv_ccg->grid_size) { + return point_index - 1; + } + return point_index + 1; +} + /* Common implementation of neighbor calculation when input coordinate is at the edge between two * coarse faces, but is not at the coarse vertex. */ static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg, @@ -1626,6 +1638,7 @@ static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg, SubdivCCGNeighbors *r_neighbors) { + const bool is_corner = is_corner_grid_coord(subdiv_ccg, coord); const int adjacent_edge_index = adjacent_edge_index_from_coord(subdiv_ccg, coord); BLI_assert(adjacent_edge_index >= 0); BLI_assert(adjacent_edge_index < subdiv_ccg->num_adjacent_edges); @@ -1633,15 +1646,27 @@ static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg, /* 2 neighbor points along the edge, plus one inner point per every adjacent grid. */ const int num_adjacent_faces = adjacent_edge->num_adjacent_faces; - subdiv_ccg_neighbors_init( - r_neighbors, num_adjacent_faces + 2, (include_duplicates) ? num_adjacent_faces - 1 : 0); + int num_duplicates = 0; + if (include_duplicates) { + num_duplicates += num_adjacent_faces - 1; + if (is_corner) { + /* When the coord is a grid corner, add an extra duplicate per adjacent grid in all adjacent + * faces to the edge. */ + num_duplicates += num_adjacent_faces; + } + } + subdiv_ccg_neighbors_init(r_neighbors, num_adjacent_faces + 2, num_duplicates); const int point_index = adjacent_edge_point_index_from_coord( subdiv_ccg, coord, adjacent_edge_index); + const int point_index_duplicate = adjacent_grid_corner_point_index_on_edge(subdiv_ccg, + point_index); + const int next_point_index = next_adjacent_edge_point_index(subdiv_ccg, point_index); const int prev_point_index = prev_adjacent_edge_point_index(subdiv_ccg, point_index); - for (int i = 0, duplicate_i = num_adjacent_faces; i < num_adjacent_faces; ++i) { + int duplicate_i = num_adjacent_faces; + for (int i = 0; i < num_adjacent_faces; ++i) { SubdivCCGCoord *boundary_coords = adjacent_edge->boundary_coords[i]; /* One step into the grid from the edge for each adjacent face. */ SubdivCCGCoord grid_coord = boundary_coords[point_index]; @@ -1657,7 +1682,15 @@ static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg, r_neighbors->coords[duplicate_i + 2] = grid_coord; duplicate_i++; } + + /* When it is a corner, add the duplicate of the adjacent grid in the same face. */ + if (include_duplicates && is_corner) { + SubdivCCGCoord duplicate_corner_grid_coord = boundary_coords[point_index_duplicate]; + r_neighbors->coords[duplicate_i + 2] = duplicate_corner_grid_coord; + duplicate_i++; + } } + BLI_assert(duplicate_i - num_adjacent_faces == num_duplicates); } /* The corner is at the middle of edge between faces. */ @@ -1834,4 +1867,70 @@ const int *BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG *subdiv_ccg) return subdiv_ccg->cache_.start_face_grid_index; } +static void adjacet_vertices_index_from_adjacent_edge(const SubdivCCG *subdiv_ccg, + const SubdivCCGCoord *coord, + const MLoop *mloop, + const MPoly *mpoly, + int *r_v1, + int *r_v2) +{ + const int grid_size_1 = subdiv_ccg->grid_size - 1; + const int poly_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord->grid_index); + const MPoly *p = &mpoly[poly_index]; + *r_v1 = mloop[coord->grid_index].v; + if (coord->x == grid_size_1) { + const MLoop *next = ME_POLY_LOOP_NEXT(mloop, p, coord->grid_index); + *r_v2 = next->v; + } + if (coord->y == grid_size_1) { + const MLoop *prev = ME_POLY_LOOP_PREV(mloop, p, coord->grid_index); + *r_v2 = prev->v; + } +} + +SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG *subdiv_ccg, + const SubdivCCGCoord *coord, + const MLoop *mloop, + const MPoly *mpoly, + int *r_v1, + int *r_v2) +{ + + const int grid_size_1 = subdiv_ccg->grid_size - 1; + if (is_corner_grid_coord(subdiv_ccg, coord)) { + if (coord->x == 0 && coord->y == 0) { + /* Grid corner in the center of a poly. */ + return SUBDIV_CCG_ADJACENT_NONE; + } + if (coord->x == grid_size_1 && coord->y == grid_size_1) { + /* Grid corner adjacent to a coarse mesh vertex. */ + *r_v1 = *r_v2 = mloop[coord->grid_index].v; + return SUBDIV_CCG_ADJACENT_VERTEX; + } + /* Grid corner adjacent to the middle of a coarse mesh edge. */ + adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, mloop, mpoly, r_v1, r_v2); + return SUBDIV_CCG_ADJACENT_EDGE; + } + + if (is_boundary_grid_coord(subdiv_ccg, coord)) { + if (!is_inner_edge_grid_coordinate(subdiv_ccg, coord)) { + /* Grid boundary adjacent to a coarse mesh edge. */ + adjacet_vertices_index_from_adjacent_edge(subdiv_ccg, coord, mloop, mpoly, r_v1, r_v2); + return SUBDIV_CCG_ADJACENT_EDGE; + } + } + return SUBDIV_CCG_ADJACENT_NONE; +} + +void BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG *subdiv_ccg, int grid_index) +{ + if (subdiv_ccg->grid_hidden[grid_index] != NULL) { + return; + } + + CCGKey key; + BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); + subdiv_ccg->grid_hidden[grid_index] = BLI_BITMAP_NEW(key.grid_area, __func__); +} + /** \} */ diff --git a/source/blender/blenkernel/intern/subdiv_converter.h b/source/blender/blenkernel/intern/subdiv_converter.h index fb0e84ade13..ea0efe994b5 100644 --- a/source/blender/blenkernel/intern/subdiv_converter.h +++ b/source/blender/blenkernel/intern/subdiv_converter.h @@ -17,8 +17,7 @@ * All rights reserved. */ -#ifndef __SUBDIV_CONVERTER_H__ -#define __SUBDIV_CONVERTER_H__ +#pragma once /** \file * \ingroup bke @@ -51,5 +50,3 @@ int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSe /* TODO(sergey): Find a way to make it OpenSubdiv_FVarLinearInterpolation, * without breaking compilation without OpenSubdiv. */ int BKE_subdiv_converter_fvar_linear_from_settings(const SubdivSettings *settings); - -#endif /* __SUBDIV_CONVERTER_H__ */ diff --git a/source/blender/blenkernel/intern/subdiv_inline.h b/source/blender/blenkernel/intern/subdiv_inline.h index a51a33feb3d..ba45d0a4997 100644 --- a/source/blender/blenkernel/intern/subdiv_inline.h +++ b/source/blender/blenkernel/intern/subdiv_inline.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __SUBDIV_INLINE_H__ -#define __SUBDIV_INLINE_H__ +#pragma once #include "BLI_assert.h" #include "BLI_compiler_compat.h" @@ -114,5 +113,3 @@ BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_char(char edge_crease) const float edge_crease_f = edge_crease / 255.0f; return BKE_subdiv_edge_crease_to_sharpness_f(edge_crease_f); } - -#endif /* __SUBDIV_INLINE_H__ */ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 97d95cb7e46..f17467e4a26 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -509,7 +509,7 @@ void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingOb } } -/* Check whether there're any tracks in the clipboard. */ +/* Check whether there are any tracks in the clipboard. */ bool BKE_tracking_clipboard_has_tracks(void) { return (BLI_listbase_is_empty(&tracking_clipboard.tracks) == false); diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index e09e92588c6..b9c6bb83157 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -215,7 +215,7 @@ static void use_values_from_fcurves(StabContext *ctx, bool toggle) /* Prepare per call private working area. * Used for access to possibly animated values: retrieve available F-curves. */ -static StabContext *initialize_stabilization_working_context(MovieClip *clip) +static StabContext *init_stabilization_working_context(MovieClip *clip) { StabContext *ctx = MEM_callocN(sizeof(StabContext), "2D stabilization animation runtime data"); ctx->clip = clip; @@ -841,14 +841,14 @@ static int establish_track_initialization_order(StabContext *ctx, TrackInitOrder * * NOTE: when done, this track is marked as initialized */ -static void initialize_track_for_stabilization(StabContext *ctx, - MovieTrackingTrack *track, - int reference_frame, - float aspect, - const float average_translation[2], - const float pivot[2], - const float average_angle, - const float average_scale_step) +static void init_track_for_stabilization(StabContext *ctx, + MovieTrackingTrack *track, + int reference_frame, + float aspect, + const float average_translation[2], + const float pivot[2], + const float average_angle, + const float average_scale_step) { float pos[2], angle, len; TrackStabilizationBase *local_data = access_stabilization_baseline_data(ctx, track); @@ -876,7 +876,7 @@ static void initialize_track_for_stabilization(StabContext *ctx, local_data->is_init_for_stabilization = true; } -static void initialize_all_tracks(StabContext *ctx, float aspect) +static void init_all_tracks(StabContext *ctx, float aspect) { size_t track_len = 0; MovieClip *clip = ctx->clip; @@ -936,14 +936,14 @@ static void initialize_all_tracks(StabContext *ctx, float aspect) &average_angle, &average_scale_step); } - initialize_track_for_stabilization(ctx, - track, - reference_frame, - aspect, - average_translation, - pivot, - average_angle, - average_scale_step); + init_track_for_stabilization(ctx, + track, + reference_frame, + aspect, + average_translation, + pivot, + average_angle, + average_scale_step); } cleanup: @@ -1257,9 +1257,9 @@ static float calculate_autoscale_factor(StabContext *ctx, int size, float aspect */ static StabContext *init_stabilizer(MovieClip *clip, int size, float aspect) { - StabContext *ctx = initialize_stabilization_working_context(clip); + StabContext *ctx = init_stabilization_working_context(clip); BLI_assert(ctx != NULL); - initialize_all_tracks(ctx, aspect); + init_all_tracks(ctx, aspect); if (ctx->stab->flag & TRACKING_AUTOSCALE) { ctx->stab->scale = 1.0; ctx->stab->scale = calculate_autoscale_factor(ctx, size, aspect); diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index e155dedeef0..0809e8dda6d 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -507,9 +507,7 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, /* Might not be final place for this to be called - probably only want to call it from some * undo handlers, not all of them? */ - if (BKE_lib_override_library_is_enabled()) { - BKE_lib_override_library_main_operations_create(G_MAIN, false); - } + BKE_lib_override_library_main_operations_create(G_MAIN, false); /* Remove all undos after (also when 'ustack->step_active == NULL'). */ while (ustack->steps.last != ustack->step_active) { diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index f37feab4b85..efe10b02940 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -1005,7 +1005,6 @@ bool bUnit_ReplaceString( /* Fix cases like "-1m50cm" which would evaluate to -0.5m without this. */ changed |= unit_distribute_negatives(str, len_max); - printf("%s\n", str); /* Try to find a default unit from current or previous string. */ default_unit = unit_detect_from_str(usys, str, str_prev); diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 18859869b4e..633ad250a67 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -218,7 +218,9 @@ static struct VolumeFileCache { cache.erase(entry); } else if (entry.num_tree_users == 0) { - entry.grid->clear(); + /* Note we replace the grid rather than clearing, so that if there is + * any other shared pointer to the grid it will keep the tree. */ + entry.grid = entry.grid->copyGridWithNewTree(); entry.is_loaded = false; } } @@ -239,15 +241,14 @@ struct VolumeGrid { VolumeGrid(const VolumeFileCache::Entry &template_entry) : entry(NULL), is_loaded(false) { entry = GLOBAL_CACHE.add_metadata_user(template_entry); - vdb = entry->grid; } - VolumeGrid(const openvdb::GridBase::Ptr &vdb) : vdb(vdb), entry(NULL), is_loaded(true) + VolumeGrid(const openvdb::GridBase::Ptr &grid) : entry(NULL), local_grid(grid), is_loaded(true) { } VolumeGrid(const VolumeGrid &other) - : vdb(other.vdb), entry(other.entry), is_loaded(other.is_loaded) + : entry(other.entry), local_grid(other.local_grid), is_loaded(other.is_loaded) { if (entry) { GLOBAL_CACHE.copy_user(*entry, is_loaded); @@ -330,7 +331,7 @@ struct VolumeGrid { void clear_reference(const char *UNUSED(volume_name)) { /* Clear any reference to a grid in the file cache. */ - vdb = vdb->copyGridWithNewTree(); + local_grid = grid()->copyGridWithNewTree(); if (entry) { GLOBAL_CACHE.remove_user(*entry, is_loaded); entry = NULL; @@ -344,7 +345,7 @@ struct VolumeGrid { * file cache. Load file grid into memory first if needed. */ load(volume_name, filepath); /* TODO: avoid deep copy if we are the only user. */ - vdb = vdb->deepCopyGrid(); + local_grid = grid()->deepCopyGrid(); if (entry) { GLOBAL_CACHE.remove_user(*entry, is_loaded); entry = NULL; @@ -356,7 +357,7 @@ struct VolumeGrid { { /* Don't use vdb.getName() since it copies the string, we want a pointer to the * original so it doesn't get freed out of scope. */ - openvdb::StringMetadata::ConstPtr name_meta = vdb->getMetadata<openvdb::StringMetadata>( + openvdb::StringMetadata::ConstPtr name_meta = grid()->getMetadata<openvdb::StringMetadata>( openvdb::GridBase::META_GRID_NAME); return (name_meta) ? name_meta->value().c_str() : ""; } @@ -371,10 +372,22 @@ struct VolumeGrid { } } - /* OpenVDB grid. */ - openvdb::GridBase::Ptr vdb; - /* File cache entry. */ + const bool grid_is_loaded() const + { + return is_loaded; + } + + const openvdb::GridBase::Ptr &grid() const + { + return (entry) ? entry->grid : local_grid; + } + + protected: + /* File cache entry when grid comes directly from a file and may be shared + * with other volume datablocks. */ VolumeFileCache::Entry *entry; + /* OpenVDB grid if it's not shared through the file cache. */ + openvdb::GridBase::Ptr local_grid; /* Indicates if the tree has been loaded for this grid. Note that vdb.tree() * may actually be loaded by another user while this is false. But only after * calling load() and is_loaded changes to true is it safe to access. */ @@ -494,7 +507,7 @@ static void volume_foreach_cache(ID *id, /* cache_v */ volume->runtime.grids, }; - function_callback(id, &key, (void **)&volume->runtime.grids, user_data); + function_callback(id, &key, (void **)&volume->runtime.grids, 0, user_data); } IDTypeInfo IDType_ID_VO = { @@ -1047,7 +1060,7 @@ void BKE_volume_grid_unload(const Volume *volume, VolumeGrid *grid) bool BKE_volume_grid_is_loaded(const VolumeGrid *grid) { #ifdef WITH_OPENVDB - return grid->is_loaded; + return grid->grid_is_loaded(); #else UNUSED_VARS(grid); return true; @@ -1069,7 +1082,7 @@ const char *BKE_volume_grid_name(const VolumeGrid *volume_grid) VolumeGridType BKE_volume_grid_type(const VolumeGrid *volume_grid) { #ifdef WITH_OPENVDB - const openvdb::GridBase::Ptr &grid = volume_grid->vdb; + const openvdb::GridBase::Ptr &grid = volume_grid->grid(); if (grid->isType<openvdb::FloatGrid>()) { return VOLUME_GRID_FLOAT; @@ -1138,7 +1151,7 @@ int BKE_volume_grid_channels(const VolumeGrid *grid) void BKE_volume_grid_transform_matrix(const VolumeGrid *volume_grid, float mat[4][4]) { #ifdef WITH_OPENVDB - const openvdb::GridBase::Ptr &grid = volume_grid->vdb; + const openvdb::GridBase::Ptr &grid = volume_grid->grid(); const openvdb::math::Transform &transform = grid->transform(); /* Perspective not supported for now, getAffineMap() will leave out the @@ -1162,7 +1175,7 @@ bool BKE_volume_grid_bounds(const VolumeGrid *volume_grid, float min[3], float m { #ifdef WITH_OPENVDB /* TODO: we can get this from grid metadata in some cases? */ - const openvdb::GridBase::Ptr &grid = volume_grid->vdb; + const openvdb::GridBase::Ptr &grid = volume_grid->grid(); BLI_assert(BKE_volume_grid_is_loaded(volume_grid)); openvdb::CoordBBox coordbbox; @@ -1287,14 +1300,14 @@ void BKE_volume_grid_remove(Volume *volume, VolumeGrid *grid) #ifdef WITH_OPENVDB openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_metadata(const VolumeGrid *grid) { - return grid->vdb; + return grid->grid(); } openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const Volume *volume, VolumeGrid *grid) { BKE_volume_grid_load(volume, grid); - return grid->vdb; + return grid->grid(); } openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const Volume *volume, @@ -1310,6 +1323,6 @@ openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const Volume *volume, grid->duplicate_reference(volume_name, grids.filepath); } - return grid->vdb; + return grid->grid(); } #endif diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index c72747a8c51..7057e9ab5bd 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __NLA_PRIVATE_H__ -#define __NLA_PRIVATE_H__ +#pragma once #include "BLI_bitmap.h" #include "BLI_ghash.h" @@ -32,6 +31,8 @@ extern "C" { #endif +struct AnimationEvalContext; + /* --------------- NLA Evaluation DataTypes ----------------------- */ /* used for list of strips to accumulate at current time */ @@ -168,13 +169,17 @@ float nlastrip_get_frame(NlaStrip *strip, float cframe, short mode); /* these functions are only defined here to avoid problems with the order * in which they get defined. */ -NlaEvalStrip *nlastrips_ctime_get_strip( - ListBase *list, ListBase *strips, short index, float ctime, const bool flush_to_original); +NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, + ListBase *strips, + short index, + const struct AnimationEvalContext *anim_eval_context, + const bool flush_to_original); void nlastrip_evaluate(PointerRNA *ptr, NlaEvalData *channels, ListBase *modifiers, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot, + const struct AnimationEvalContext *anim_eval_context, const bool flush_to_original); void nladata_flush_channels(PointerRNA *ptr, NlaEvalData *channels, @@ -184,5 +189,3 @@ void nladata_flush_channels(PointerRNA *ptr, #ifdef __cplusplus } #endif - -#endif /* __NLA_PRIVATE_H__ */ diff --git a/source/blender/blenkernel/particle_private.h b/source/blender/blenkernel/particle_private.h index 6f80089be29..33277d1caac 100644 --- a/source/blender/blenkernel/particle_private.h +++ b/source/blender/blenkernel/particle_private.h @@ -21,8 +21,7 @@ * \ingroup bke */ -#ifndef __PARTICLE_PRIVATE_H__ -#define __PARTICLE_PRIVATE_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -72,5 +71,3 @@ void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, #ifdef __cplusplus } #endif - -#endif /* __PARTICLE_PRIVATE_H__ */ diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h index 955a0b8753e..0965cef0d9b 100644 --- a/source/blender/blenkernel/tracking_private.h +++ b/source/blender/blenkernel/tracking_private.h @@ -24,8 +24,7 @@ * by multiple tracking files but which should not be public. */ -#ifndef __TRACKING_PRIVATE_H__ -#define __TRACKING_PRIVATE_H__ +#pragma once #include "BLI_threads.h" @@ -152,5 +151,3 @@ void tracking_image_accessor_destroy(TrackingImageAccessor *accessor); #ifdef __cplusplus } #endif - -#endif /* __TRACKING_PRIVATE_H__ */ |