diff options
102 files changed, 2132 insertions, 1302 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 5db0c3c9130..28be2b04c71 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -57,8 +57,9 @@ extern "C" { /* Allocate a new bAction with the given name */ struct bAction *add_empty_action(struct Main *bmain, const char name[]); -/* Allocate a copy of the given Action and all its data */ -struct bAction *BKE_action_copy(struct Main *bmain, const struct bAction *src); +void BKE_action_copy_data(struct Main *bmain, struct bAction *act_dst, const struct bAction *act_src, const int flag); +/* Allocate a copy of the given Action and all its data */ +struct bAction *BKE_action_copy(struct Main *bmain, const struct bAction *act_src); /* Deallocate all of the Action's data, but not the Action itself */ void BKE_action_free(struct bAction *act); @@ -150,6 +151,7 @@ void BKE_pose_free_data_ex(struct bPose *pose, bool do_id_user); void BKE_pose_free_data(struct bPose *pose); void BKE_pose_free(struct bPose *pose); void BKE_pose_free_ex(struct bPose *pose, bool do_id_user); +void BKE_pose_copy_data_ex(struct bPose **dst, const struct bPose *src, const int flag, 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); struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name); diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 420ae4bb12d..534a57765f6 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -67,10 +67,10 @@ bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct b void BKE_animdata_free(struct ID *id, const bool do_id_user); /* Copy AnimData */ -struct AnimData *BKE_animdata_copy(struct AnimData *adt, const bool do_action); +struct AnimData *BKE_animdata_copy(struct Main *bmain, struct AnimData *adt, const bool do_action); /* Copy AnimData */ -bool BKE_animdata_copy_id(struct ID *id_to, struct ID *id_from, const bool do_action); +bool BKE_animdata_copy_id(struct Main *bmain, struct ID *id_to, struct ID *id_from, const bool do_action); /* Copy AnimData Actions */ void BKE_animdata_copy_id_action(struct ID *id, const bool set_newid); @@ -102,7 +102,7 @@ struct KS_Path *BKE_keyingset_add_path(struct KeyingSet *ks, struct ID *id, cons struct KS_Path *BKE_keyingset_find_path(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode); /* Copy all KeyingSets in the given list */ -void BKE_keyingsets_copy(struct ListBase *newlist, struct ListBase *list); +void BKE_keyingsets_copy(struct ListBase *newlist, const struct ListBase *list); /* Free the given Keying Set path */ void BKE_keyingset_free_path(struct KeyingSet *ks, struct KS_Path *ksp); diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 6bfc8c918d6..1cc42f788d5 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -77,6 +77,7 @@ int BKE_armature_bonelist_count(struct ListBase *lb); void BKE_armature_bonelist_free(struct ListBase *lb); void BKE_armature_free(struct bArmature *arm); void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool lib_local); +void BKE_armature_copy_data(struct Main *bmain, struct bArmature *arm_dst, const struct bArmature *arm_src, const int flag); struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature *arm); /* Bounding box. */ diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 42e4e73f2d5..dedb75a080a 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -44,6 +44,7 @@ void BKE_brush_system_exit(void); void BKE_brush_init(struct Brush *brush); struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode); struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode); +void BKE_brush_copy_data(struct Main *bmain, struct Brush *brush_dst, const struct Brush *brush_src, const int flag); struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush); void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local); void BKE_brush_unlink(struct Main *bmain, struct Brush *brush); diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h index f1e643c4a19..e9712681090 100644 --- a/source/blender/blenkernel/BKE_cachefile.h +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -47,6 +47,8 @@ void BKE_cachefile_init(struct CacheFile *cache_file); void BKE_cachefile_free(struct CacheFile *cache_file); +void BKE_cachefile_copy_data( + struct Main *bmain, struct CacheFile *cache_file_dst, const struct CacheFile *cache_file_src, const int flag); struct CacheFile *BKE_cachefile_copy(struct Main *bmain, const struct CacheFile *cache_file); void BKE_cachefile_make_local(struct Main *bmain, struct CacheFile *cache_file, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index b2f22aacb28..04dee70faa6 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -52,6 +52,7 @@ struct GPUFXSettings; void BKE_camera_init(struct Camera *cam); void *BKE_camera_add(struct Main *bmain, const char *name); +void BKE_camera_copy_data(struct Main *bmain, struct Camera *cam_dst, const struct Camera *cam_src, const int flag); struct Camera *BKE_camera_copy(struct Main *bmain, const struct Camera *cam); void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool lib_local); void BKE_camera_free(struct Camera *ca); diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 047d1787f76..4e0eb5c65ac 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -120,6 +120,7 @@ void BKE_constraint_unique_name(struct bConstraint *con, struct ListBase *list); void BKE_constraints_free(struct ListBase *list); void BKE_constraints_free_ex(struct ListBase *list, bool do_id_user); void BKE_constraints_copy(struct ListBase *dst, const struct ListBase *src, bool do_extern); +void BKE_constraints_copy_ex(struct ListBase *dst, const struct ListBase *src, const int flag, bool do_extern); void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, void *userdata); void BKE_constraint_free_data(struct bConstraint *con); void BKE_constraint_free_data_ex(struct bConstraint *con, bool do_id_user); diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 635e999dd95..b6eea42724d 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -78,6 +78,7 @@ void BKE_curve_free(struct Curve *cu); void BKE_curve_editfont_free(struct Curve *cu); void BKE_curve_init(struct Curve *cu); struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type); +void BKE_curve_copy_data(struct Main *bmain, struct Curve *cu_dst, const struct Curve *cu_src, const int flag); struct Curve *BKE_curve_copy(struct Main *bmain, const struct Curve *cu); void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool lib_local); short BKE_curve_type_get(struct Curve *cu); diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index e7ae0f606e7..60ad061bf77 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -78,6 +78,7 @@ void BKE_vfont_builtin_register(void *mem, int size); void BKE_vfont_free_data(struct VFont *vfont); void BKE_vfont_free(struct VFont *sc); void BKE_vfont_init(struct VFont *vfont); +void BKE_vfont_copy_data(struct Main *bmain, struct VFont *vfont_dst, const struct VFont *vfont_src, const int flag); struct VFont *BKE_vfont_builtin_get(void); struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath); struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists); diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h index 50407f3bdfc..1045fde0039 100644 --- a/source/blender/blenkernel/BKE_freestyle.h +++ b/source/blender/blenkernel/BKE_freestyle.h @@ -50,7 +50,7 @@ typedef struct FreestyleModuleSettings FreestyleModuleSettings; /* FreestyleConfig */ void BKE_freestyle_config_init(FreestyleConfig *config); void BKE_freestyle_config_free(FreestyleConfig *config); -void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config); +void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag); /* FreestyleConfig.modules */ FreestyleModuleConfig *BKE_freestyle_module_add(FreestyleConfig *config); diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index bdd28baf137..b6de922c245 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -60,6 +60,7 @@ struct bGPdata *BKE_gpencil_data_addnew(const char name[]); struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src); struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src); +void BKE_gpencil_copy_data(struct Main *bmain, struct bGPdata *gpd_dst, const struct bGPdata *gpd_src, const int flag); struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, const struct bGPdata *gpd, bool internal_copy); void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 684251c9561..404d1704c78 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -42,6 +42,7 @@ struct Scene; void BKE_group_free(struct Group *group); struct Group *BKE_group_add(struct Main *bmain, const char *name); +void BKE_group_copy_data(struct Main *bmain, struct Group *group_dst, const struct Group *group_src, const int flag); struct Group *BKE_group_copy(struct Main *bmain, const struct Group *group); void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local); bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index ab8728faedb..5d8cd02756d 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -58,7 +58,7 @@ typedef union IDPropertyTemplate { /* ----------- Property Array Type ---------- */ IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -IDProperty *IDP_CopyIDPArray(const IDProperty *array) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* shallow copies item */ void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL(); @@ -103,6 +103,7 @@ IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *na /*-------- Main Functions --------*/ struct IDProperty *IDP_GetProperties(struct ID *id, const bool create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); struct IDProperty *IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +struct IDProperty *IDP_CopyProperty_ex(const struct IDProperty *prop, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is_strict) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index e155b0719cc..3f8be511212 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -250,6 +250,7 @@ void BKE_image_packfiles_from_mem(struct ReportList *reports, struct Image *ima, void BKE_image_print_memlist(void); /* empty image block, of similar type and filename */ +void BKE_image_copy_data(struct Main *bmain, struct Image *ima_dst, const struct Image *ima_src, const int flag); struct Image *BKE_image_copy(struct Main *bmain, const struct Image *ima); /* merge source into dest, and free source */ diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 94e8a24fbc5..5eef44ef896 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -51,6 +51,7 @@ extern "C" { void BKE_key_free(struct Key *sc); void BKE_key_free_nolib(struct Key *key); struct Key *BKE_key_add(struct ID *id); +void BKE_key_copy_data(struct Main *bmain, struct Key *key_dst, const struct Key *key_src, const int flag); struct Key *BKE_key_copy(struct Main *bmain, const struct Key *key); struct Key *BKE_key_copy_nolib(struct Key *key); void BKE_key_sort(struct Key *key); diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 713ca80fb1a..b68da654520 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -44,6 +44,7 @@ struct Scene; void BKE_lamp_init(struct Lamp *la); struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT; +void BKE_lamp_copy_data(struct Main *bmain, struct Lamp *la_dst, const struct Lamp *la_src, const int flag); struct Lamp *BKE_lamp_copy(struct Main *bmain, const struct Lamp *la) ATTR_WARN_UNUSED_RESULT; struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT; void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index ec1cf79832d..f7d006785d2 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -47,6 +47,7 @@ struct MDeformVert; void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb); void BKE_lattice_init(struct Lattice *lt); struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name); +void BKE_lattice_copy_data(struct Main *bmain, struct Lattice *lt_dst, const struct Lattice *lt_src, const int flag); struct Lattice *BKE_lattice_copy(struct Main *bmain, const struct Lattice *lt); void BKE_lattice_free(struct Lattice *lt); void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 258dcc84449..b5104b35b3c 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -52,11 +52,38 @@ struct PropertyRNA; size_t BKE_libblock_get_alloc_info(short type, const char **name); void *BKE_libblock_alloc_notest(short type); -void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BKE_libblock_init_empty(struct ID *id); + +/** + * New ID creation/copying options. + */ +enum { + /* *** Generic options (should be handled by all ID types copying, ID creation, etc.). *** */ + /* Create datablock outside of any main database - similar to 'localize' functions of materials etc. */ + LIB_ID_CREATE_NO_MAIN = 1 << 0, + /* Do not affect user refcount of datablocks used by new one (which also gets zero usercount then). + * Implies LIB_ID_CREATE_NO_MAIN. */ + LIB_ID_CREATE_NO_USER_REFCOUNT = 1 << 1, + /* Assume given 'newid' already points to allocated memory for whole datablock (ID + data) - USE WITH CAUTION! + * Implies LIB_ID_CREATE_NO_MAIN. */ + LIB_ID_CREATE_NO_ALLOCATE = 1 << 2, + + LIB_ID_CREATE_NO_DEG_TAG = 1 << 8, /* Do not tag new ID for update in depsgraph. */ + + /* Specific options to some ID types or usages, may be ignored by unrelated ID copying functions. */ + LIB_ID_COPY_NO_PROXY_CLEAR = 1 << 16, /* Object only, needed by make_local code. */ + LIB_ID_COPY_NO_PREVIEW = 1 << 17, /* Do not copy preview data, when supported. */ + LIB_ID_COPY_CACHES = 1 << 18, /* Copy runtime data caches. */ + /* XXX TODO Do we want to keep that? would rather try to get rid of it... */ + LIB_ID_COPY_ACTIONS = 1 << 19, /* EXCEPTION! Deep-copy actions used by animdata of copied ID. */ +}; + +void BKE_libblock_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag); void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +/* "Deprecated" old API. */ void *BKE_libblock_copy_nolib(const struct ID *id, const bool do_action) ATTR_NONNULL(); -void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action); + void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL(); void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL(); @@ -64,13 +91,45 @@ struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* library_remap.c (keep here since they're general functions) */ -void BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL(); -void BKE_libblock_free_datablock(struct ID *id) ATTR_NONNULL(); +/** + * New freeing logic options. + */ +enum { + /* *** Generic options (should be handled by all ID types freeing). *** */ + /* Do not try to remove freed ID from given Main (passed Main may be NULL). */ + LIB_ID_FREE_NO_MAIN = 1 << 0, + /* Do not affect user refcount of datablocks used by freed one. + * Implies LIB_ID_FREE_NO_MAIN. */ + LIB_ID_FREE_NO_USER_REFCOUNT = 1 << 1, + /* Assume freed ID datablock memory is managed elsewhere, do not free it + * (still calls relevant ID type's freeing function though) - USE WITH CAUTION! + * Implies LIB_ID_FREE_NO_MAIN. */ + LIB_ID_FREE_NOT_ALLOCATED = 1 << 2, + + LIB_ID_FREE_NO_DEG_TAG = 1 << 8, /* Do not tag freed ID for update in depsgraph. */ + LIB_ID_FREE_NO_UI_USER = 1 << 9, /* Do not attempt to remove freed ID from UI data/notifiers/... */ +}; + +void BKE_id_free_ex(struct Main *bmain, void *idv, int flag, const bool use_flag_from_idtag); +void BKE_id_free(struct Main *bmain, void *idv); +/* Those three naming are bad actually, should be BKE_id_free... (since it goes beyond mere datablock). */ +/* "Deprecated" old API */ void BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) ATTR_NONNULL(); +void BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL(); void BKE_libblock_free_us(struct Main *bmain, void *idv) ATTR_NONNULL(); -void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL(); + +void BKE_libblock_management_main_add(struct Main *bmain, void *idv); +void BKE_libblock_management_main_remove(struct Main *bmain, void *idv); + +void BKE_libblock_management_usercounts_set(struct Main *bmain, void *idv); +void BKE_libblock_management_usercounts_clear(struct Main *bmain, void *idv); + +/* TODO should be named "BKE_id_delete()". */ void BKE_libblock_delete(struct Main *bmain, void *idv) ATTR_NONNULL(); +void BKE_libblock_free_datablock(struct ID *id, const int flag) ATTR_NONNULL(); +void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL(); + void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id); void id_lib_extern(struct ID *id); void BKE_library_filepath_set(struct Library *lib, const char *filepath); @@ -87,6 +146,7 @@ void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_ bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local); bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop); bool id_copy(struct Main *bmain, const struct ID *id, struct ID **newid, bool test); +bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag, const bool test); void id_sort_by_name(struct ListBase *lb, struct ID *id); void BKE_id_expand_local(struct Main *bmain, struct ID *id); void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id); diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h index c7b323d0f6e..3ba4fbe0338 100644 --- a/source/blender/blenkernel/BKE_linestyle.h +++ b/source/blender/blenkernel/BKE_linestyle.h @@ -52,6 +52,9 @@ struct bContext; void BKE_linestyle_init(struct FreestyleLineStyle *linestyle); FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name); void BKE_linestyle_free(FreestyleLineStyle *linestyle); +void BKE_linestyle_copy_data( + struct Main *bmain, struct FreestyleLineStyle *linestyle_dst, const struct FreestyleLineStyle *linestyle_src, + const int flag); FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle); void BKE_linestyle_make_local(struct Main *bmain, struct FreestyleLineStyle *linestyle, const bool lib_local); @@ -63,10 +66,14 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type); LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type); -LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m); -LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m); -LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m); -LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m); +LineStyleModifier *BKE_linestyle_color_modifier_copy( + FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag); +LineStyleModifier *BKE_linestyle_alpha_modifier_copy( + FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag); +LineStyleModifier *BKE_linestyle_thickness_modifier_copy( + FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag); +LineStyleModifier *BKE_linestyle_geometry_modifier_copy( + FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag); int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier); int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 0735d2d97a1..6e154241af7 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -122,6 +122,7 @@ void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const eMask /* general */ struct Mask *BKE_mask_new(struct Main *bmain, const char *name); +void BKE_mask_copy_data(struct Main *bmain, struct Mask *mask_dst, const struct Mask *mask_src, const int flag); struct Mask *BKE_mask_copy_nolib(struct Mask *mask); struct Mask *BKE_mask_copy(struct Main *bmain, const struct Mask *mask); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 7da962dd6d6..c6ebda2c399 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -54,6 +54,7 @@ void BKE_material_init(struct Material *ma); void BKE_material_remap_object(struct Object *ob, const unsigned int *remap); void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst); struct Material *BKE_material_add(struct Main *bmain, const char *name); +void BKE_material_copy_data(struct Main *bmain, struct Material *ma_dst, const struct Material *ma_src, const int flag); struct Material *BKE_material_copy(struct Main *bmain, const struct Material *ma); struct Material *localize_material(struct Material *ma); struct Material *give_node_material(struct Material *ma); /* returns node material or self */ diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index c00a0743ebb..a02a068b920 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -41,6 +41,7 @@ struct MetaElem; void BKE_mball_free(struct MetaBall *mb); void BKE_mball_init(struct MetaBall *mb); struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name); +void BKE_mball_copy_data(struct Main *bmain, struct MetaBall *mb_dst, const struct MetaBall *mb_src, const int flag); struct MetaBall *BKE_mball_copy(struct Main *bmain, const struct MetaBall *mb); void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index b55b8b2dd3c..9480679f817 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -87,6 +87,7 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v); void BKE_mesh_free(struct Mesh *me); void BKE_mesh_init(struct Mesh *me); struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name); +void BKE_mesh_copy_data(struct Main *bmain, struct Mesh *me_dst, const struct Mesh *me_src, const int flag); struct Mesh *BKE_mesh_copy(struct Main *bmain, const struct Mesh *me); void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd); void BKE_mesh_ensure_skin_customdata(struct Mesh *me); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index b241b5ca5b7..30c47a4b192 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -344,6 +344,7 @@ bool modifier_unique_name(struct ListBase *modifiers, struct ModifierDa void modifier_copyData_generic(const struct ModifierData *md, struct ModifierData *target); void modifier_copyData(struct ModifierData *md, struct ModifierData *target); +void modifier_copyData_ex(struct ModifierData *md, struct ModifierData *target, const int flag); bool modifier_dependsOnTime(struct ModifierData *md); bool modifier_supportsMapping(struct ModifierData *md); bool modifier_supportsCage(struct Scene *scene, struct ModifierData *md); diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 69fdad5ef7b..3ddf75f204e 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -41,6 +41,7 @@ struct MovieDistortion; void BKE_movieclip_free(struct MovieClip *clip); +void BKE_movieclip_copy_data(struct Main *bmain, struct MovieClip *clip_dst, const struct MovieClip *clip_src, const int flag); struct MovieClip *BKE_movieclip_copy(struct Main *bmain, const struct MovieClip *clip); void BKE_movieclip_make_local(struct Main *bmain, struct MovieClip *clip, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index d5279c5b0ce..81de70ca8a4 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -335,6 +335,7 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char /* copy/free funcs, need to manage ID users */ void ntreeFreeTree(struct bNodeTree *ntree); +void BKE_node_tree_copy_data(struct Main *bmain, struct bNodeTree *ntree_dst, const struct bNodeTree *ntree_src, const int flag); struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user); struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntree); /* node->id user count */ @@ -452,6 +453,7 @@ void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node); void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node); void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node); +struct bNode *BKE_node_copy_ex(struct bNodeTree *ntree, struct bNode *node_src, const int flag); struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node); struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 0a5035f9a9b..d1a4033957b 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -53,10 +53,10 @@ void BKE_object_workob_clear(struct Object *workob); void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob); void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src); -struct SoftBody *copy_softbody(const struct SoftBody *sb, bool copy_caches); -struct BulletSoftBody *copy_bulletsoftbody(const struct BulletSoftBody *sb); -struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys); -void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src); +struct SoftBody *copy_softbody(const struct SoftBody *sb, const int flag); +struct BulletSoftBody *copy_bulletsoftbody(const struct BulletSoftBody *sb, const int flag); +struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys, const int flag); +void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src, const int flag); void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src); void BKE_object_free_particlesystems(struct Object *ob); void BKE_object_free_softbody(struct Object *ob); @@ -105,7 +105,7 @@ bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene); struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene); struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene); -struct Object *BKE_object_copy_ex(struct Main *bmain, const struct Object *ob, bool copy_caches); +void BKE_object_copy_data(struct Main *bmain, struct Object *ob_dst, const struct Object *ob_src, const int flag); struct Object *BKE_object_copy(struct Main *bmain, const struct Object *ob); void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local); void BKE_object_make_local_ex(struct Main *bmain, struct Object *ob, const bool lib_local, const bool clear_proxy); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 821dc211591..f7e6ab59d20 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -99,6 +99,8 @@ void BKE_paint_set_overlay_override(enum OverlayFlags flag); /* palettes */ void BKE_palette_free(struct Palette *palette); struct Palette *BKE_palette_add(struct Main *bmain, const char *name); +void BKE_palette_copy_data( + struct Main *bmain, struct Palette *palette_dst, const struct Palette *palette_src, const int flag); struct Palette *BKE_palette_copy(struct Main *bmain, const struct Palette *palette); void BKE_palette_make_local(struct Main *bmain, struct Palette *palette, const bool lib_local); struct PaletteColor *BKE_palette_color_add(struct Palette *palette); @@ -109,12 +111,14 @@ void BKE_palette_clear(struct Palette *palette); /* paint curves */ struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name); void BKE_paint_curve_free(struct PaintCurve *pc); +void BKE_paint_curve_copy_data( + struct Main *bmain, struct PaintCurve *pc_dst, const struct PaintCurve *pc_src, const int flag); struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, const struct PaintCurve *pc); void BKE_paint_curve_make_local(struct Main *bmain, struct PaintCurve *pc, const bool lib_local); void BKE_paint_init(struct Scene *sce, PaintMode mode, const char col[3]); void BKE_paint_free(struct Paint *p); -void BKE_paint_copy(struct Paint *src, struct Paint *tar); +void BKE_paint_copy(struct Paint *src, struct Paint *tar, const int flag); void BKE_paint_cavity_curve_preset(struct Paint *p, int preset); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 470e2e468f0..ddb4f9c37bd 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -324,6 +324,9 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name); void object_remove_particle_system(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(const char *name, struct Main *main); +void BKE_particlesettings_copy_data( + struct Main *bmain, struct ParticleSettings *part_dst, const struct ParticleSettings *part_src, + const int flag); struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, const struct ParticleSettings *part); void BKE_particlesettings_make_local(struct Main *bmain, struct ParticleSettings *part, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 02f6c435ee2..f0819c8d79d 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -314,7 +314,7 @@ struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches); void BKE_ptcache_free_mem(struct ListBase *mem_cache); void BKE_ptcache_free(struct PointCache *cache); void BKE_ptcache_free_list(struct ListBase *ptcaches); -struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, bool copy_data); +struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, const int flag); /********************** Baking *********************/ diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index c72f067a111..3c7274ca3c5 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -49,8 +49,8 @@ void BKE_rigidbody_free_constraint(struct Object *ob); /* ...... */ -struct RigidBodyOb *BKE_rigidbody_copy_object(const struct Object *ob); -struct RigidBodyCon *BKE_rigidbody_copy_constraint(const struct Object *ob); +struct RigidBodyOb *BKE_rigidbody_copy_object(const struct Object *ob, const int flag); +struct RigidBodyCon *BKE_rigidbody_copy_constraint(const struct Object *ob, const int flag); /* Callback format for performing operations on ID-pointers for rigidbody world. */ typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cb_flag); @@ -66,7 +66,7 @@ struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Obje struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type); /* copy */ -struct RigidBodyWorld *BKE_rigidbody_world_copy(struct RigidBodyWorld *rbw); +struct RigidBodyWorld *BKE_rigidbody_world_copy(struct RigidBodyWorld *rbw, const int flag); void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw); /* 'validate' (i.e. make new or replace old) Physics-Engine objects */ diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h index 10cddd7b454..35bcd91a9b1 100644 --- a/source/blender/blenkernel/BKE_sca.h +++ b/source/blender/blenkernel/BKE_sca.h @@ -52,16 +52,16 @@ void free_actuators(struct ListBase *lb); void free_sensor(struct bSensor *sens); void free_sensors(struct ListBase *lb); -struct bSensor *copy_sensor(struct bSensor *sens); -void copy_sensors(struct ListBase *lbn, const struct ListBase *lbo); +struct bSensor *copy_sensor(struct bSensor *sens, const int flag); +void copy_sensors(struct ListBase *lbn, const struct ListBase *lbo, const int flag); void init_sensor(struct bSensor *sens); struct bSensor *new_sensor(int type); -struct bController *copy_controller(struct bController *cont); -void copy_controllers(struct ListBase *lbn, const struct ListBase *lbo); +struct bController *copy_controller(struct bController *cont, const int flag); +void copy_controllers(struct ListBase *lbn, const struct ListBase *lbo, const int flag); void init_controller(struct bController *cont); struct bController *new_controller(int type); -struct bActuator *copy_actuator(struct bActuator *act); -void copy_actuators(struct ListBase *lbn, const struct ListBase *lbo); +struct bActuator *copy_actuator(struct bActuator *act, const int flag); +void copy_actuators(struct ListBase *lbn, const struct ListBase *lbo, const int flag); void init_actuator(struct bActuator *act); struct bActuator *new_actuator(int type); void clear_sca_new_poins_ob(struct Object *ob); @@ -70,7 +70,7 @@ void set_sca_new_poins_ob(struct Object *ob); void set_sca_new_poins(void); void BKE_sca_logic_links_remap(struct Main *bmain, struct Object *ob_old, struct Object *ob_new); -void BKE_sca_logic_copy(struct Object *ob_new, const struct Object *ob); +void BKE_sca_logic_copy(struct Object *ob_new, const struct Object *ob, const int flag); void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up); void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index d2152950bff..f1680b6ccbf 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -98,6 +98,7 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene); void BKE_scene_set_background(struct Main *bmain, struct Scene *sce); struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name); +void BKE_scene_copy_data(struct Main *bmain, struct Scene *sce_dst, const struct Scene *sce_src, const int flag); struct Scene *BKE_scene_copy(struct Main *bmain, struct Scene *sce, int type); void BKE_scene_groups_relink(struct Scene *sce); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 811e9136fc9..87d63b7d6f6 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -352,8 +352,8 @@ void BKE_sequencer_refresh_sound_length(struct Scene *scene); void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); void BKE_sequence_base_dupli_recursive( - struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, - int dupe_flag); + const struct Scene *scene, struct Scene *scene_to, struct ListBase *nseqbase, const struct ListBase *seqbase, + int dupe_flag, const int flag); bool BKE_sequence_is_valid_check(struct Sequence *seq); void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce); diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index a5c626e74d7..6f8274fabc8 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -80,6 +80,8 @@ void BKE_sound_load(struct Main *main, struct bSound *sound); void BKE_sound_free(struct bSound *sound); +void BKE_sound_copy_data(struct Main *bmain, struct bSound *sound_dst, const struct bSound *sound_src, const int flag); + void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool lib_local); #if defined(__AUD_C_API_H__) || defined(WITH_SYSTEM_AUDASPACE) diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h index 907558f9203..57f4c37f129 100644 --- a/source/blender/blenkernel/BKE_speaker.h +++ b/source/blender/blenkernel/BKE_speaker.h @@ -33,6 +33,7 @@ struct Speaker; void BKE_speaker_init(struct Speaker *spk); void *BKE_speaker_add(struct Main *bmain, const char *name); +void BKE_speaker_copy_data(struct Main *bmain, struct Speaker *spk_dst, const struct Speaker *spk_src, const int flag); struct Speaker *BKE_speaker_copy(struct Main *bmain, const struct Speaker *spk); void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool lib_local); void BKE_speaker_free(struct Speaker *spk); diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index c8fb483cdf2..14d3318e059 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -52,6 +52,7 @@ bool BKE_text_reload(struct Text *text); struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const char *relpath, const bool is_internal); struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath); +void BKE_text_copy_data(struct Main *bmain, struct Text *ta_dst, const struct Text *ta_src, const int flag); struct Text *BKE_text_copy (struct Main *bmain, const struct Text *ta); void BKE_text_make_local (struct Main *bmain, struct Text *text, const bool lib_local); void BKE_text_clear (struct Text *text); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 190fdeafaec..8a9171673ea 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -70,6 +70,7 @@ void colorband_update_sort(struct ColorBand *coba); void BKE_texture_free(struct Tex *tex); void BKE_texture_default(struct Tex *tex); +void BKE_texture_copy_data(struct Main *bmain, struct Tex *tex_dst, const struct Tex *tex_src, const int flag); struct Tex *BKE_texture_copy(struct Main *bmain, const struct Tex *tex); struct Tex *BKE_texture_add(struct Main *bmain, const char *name); struct Tex *BKE_texture_localize(struct Tex *tex); @@ -114,13 +115,13 @@ void BKE_texture_colormapping_default(struct ColorMapping *color void BKE_texture_envmap_free_data(struct EnvMap *env); void BKE_texture_envmap_free(struct EnvMap *env); struct EnvMap *BKE_texture_envmap_add(void); -struct EnvMap *BKE_texture_envmap_copy(const struct EnvMap *env); +struct EnvMap *BKE_texture_envmap_copy(const struct EnvMap *env, const int flag); void BKE_texture_pointdensity_init_data(struct PointDensity *pd); void BKE_texture_pointdensity_free_data(struct PointDensity *pd); void BKE_texture_pointdensity_free(struct PointDensity *pd); struct PointDensity *BKE_texture_pointdensity_add(void); -struct PointDensity *BKE_texture_pointdensity_copy(const struct PointDensity *pd); +struct PointDensity *BKE_texture_pointdensity_copy(const struct PointDensity *pd, const int flag); void BKE_texture_voxeldata_free_data(struct VoxelData *vd); void BKE_texture_voxeldata_free(struct VoxelData *vd); @@ -129,7 +130,7 @@ struct VoxelData *BKE_texture_voxeldata_copy(struct VoxelData *vd); void BKE_texture_ocean_free(struct OceanTex *ot); struct OceanTex *BKE_texture_ocean_add(void); -struct OceanTex *BKE_texture_ocean_copy(const struct OceanTex *ot); +struct OceanTex *BKE_texture_ocean_copy(const struct OceanTex *ot, const int flag); bool BKE_texture_dependsOnTime(const struct Tex *texture); bool BKE_texture_is_image_user(const struct Tex *tex); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index b48be382073..d05ed1800fb 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -52,7 +52,7 @@ struct rcti; /* **** Common functions **** */ void BKE_tracking_free(struct MovieTracking *tracking); -void BKE_tracking_copy(struct MovieTracking *tracking_dst, const struct MovieTracking *tracking_src); +void BKE_tracking_copy(struct MovieTracking *tracking_dst, const struct MovieTracking *tracking_src, const int flag); void BKE_tracking_settings_init(struct MovieTracking *tracking); diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h index 18ae61f7653..2a811496bb9 100644 --- a/source/blender/blenkernel/BKE_world.h +++ b/source/blender/blenkernel/BKE_world.h @@ -39,6 +39,7 @@ struct World; void BKE_world_free(struct World *sc); void BKE_world_init(struct World *wrld); struct World *add_world(struct Main *bmian, const char *name); +void BKE_world_copy_data(struct Main *bmain, struct World *wrld_dst, const struct World *wrld_src, const int flag); struct World *BKE_world_copy(struct Main *bmain, const struct World *wrld); struct World *localize_world(struct World *wrld); void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool lib_local); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 885ea36d404..bb4e09364d4 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -88,7 +88,7 @@ bAction *add_empty_action(Main *bmain, const char name[]) { bAction *act; - act = BKE_libblock_alloc(bmain, ID_AC, name); + act = BKE_libblock_alloc(bmain, ID_AC, name, 0); return act; } @@ -120,46 +120,56 @@ void BKE_action_free(bAction *act) /* .................................. */ -bAction *BKE_action_copy(Main *bmain, const bAction *src) +/** + * Only copy internal data of Action ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_action_copy_data(Main *UNUSED(bmain), bAction *act_dst, const bAction *act_src, const int UNUSED(flag)) { - bAction *dst = NULL; - bActionGroup *dgrp, *sgrp; - FCurve *dfcu, *sfcu; - - if (src == NULL) - return NULL; - dst = BKE_libblock_copy(bmain, &src->id); - + bActionGroup *grp_dst, *grp_src; + FCurve *fcu_dst, *fcu_src; + /* duplicate the lists of groups and markers */ - BLI_duplicatelist(&dst->groups, &src->groups); - BLI_duplicatelist(&dst->markers, &src->markers); - + BLI_duplicatelist(&act_dst->groups, &act_src->groups); + BLI_duplicatelist(&act_dst->markers, &act_src->markers); + /* copy F-Curves, fixing up the links as we go */ - BLI_listbase_clear(&dst->curves); - - for (sfcu = src->curves.first; sfcu; sfcu = sfcu->next) { + BLI_listbase_clear(&act_dst->curves); + + for (fcu_src = act_src->curves.first; fcu_src; fcu_src = fcu_src->next) { /* duplicate F-Curve */ - dfcu = copy_fcurve(sfcu); - BLI_addtail(&dst->curves, dfcu); - + fcu_dst = copy_fcurve(fcu_src); /* XXX TODO pass subdata flag? But surprisingly does not seem to be doing any ID refcounting... */ + BLI_addtail(&act_dst->curves, fcu_dst); + /* fix group links (kindof bad list-in-list search, but this is the most reliable way) */ - for (dgrp = dst->groups.first, sgrp = src->groups.first; dgrp && sgrp; dgrp = dgrp->next, sgrp = sgrp->next) { - if (sfcu->grp == sgrp) { - dfcu->grp = dgrp; - - if (dgrp->channels.first == sfcu) - dgrp->channels.first = dfcu; - if (dgrp->channels.last == sfcu) - dgrp->channels.last = dfcu; - + for (grp_dst = act_dst->groups.first, grp_src = act_src->groups.first; + grp_dst && grp_src; + grp_dst = grp_dst->next, grp_src = grp_src->next) + { + if (fcu_src->grp == grp_src) { + fcu_dst->grp = grp_dst; + + if (grp_dst->channels.first == fcu_src) { + grp_dst->channels.first = fcu_dst; + } + if (grp_dst->channels.last == fcu_src) { + grp_dst->channels.last = fcu_dst; + } break; } } } - - BKE_id_copy_ensure_local(bmain, &src->id, &dst->id); +} - return dst; +bAction *BKE_action_copy(Main *bmain, const bAction *act_src) +{ + bAction *act_copy; + BKE_id_copy_ex(bmain, &act_src->id, (ID **)&act_copy, 0, false); + return act_copy; } /* *************** Action Groups *************** */ @@ -523,7 +533,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose) * * \param dst Should be freed already, makes entire duplicate. */ -void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constraints) +void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const bool copy_constraints) { bPose *outPose; bPoseChannel *pchan; @@ -553,9 +563,8 @@ void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constrain outPose->avs = src->avs; for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { - - if (pchan->custom) { - id_us_plus(&pchan->custom->id); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)pchan->custom); } /* warning, O(n2) here, if done without the hash, but these are rarely used features. */ @@ -570,13 +579,13 @@ void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constrain } if (copy_constraints) { - BKE_constraints_copy(&listb, &pchan->constraints, true); // BKE_constraints_copy NULLs listb + BKE_constraints_copy_ex(&listb, &pchan->constraints, flag, true); // BKE_constraints_copy NULLs listb pchan->constraints = listb; pchan->mpath = NULL; /* motion paths should not get copied yet... */ } if (pchan->prop) { - pchan->prop = IDP_CopyProperty(pchan->prop); + pchan->prop = IDP_CopyProperty_ex(pchan->prop, flag); } } @@ -588,6 +597,11 @@ void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constrain *dst = outPose; } +void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constraints) +{ + BKE_pose_copy_data_ex(dst, src, 0, copy_constraints); +} + void BKE_pose_itasc_init(bItasc *itasc) { if (itasc) { diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 539901a59d5..6afa251bce7 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -259,7 +259,7 @@ void BKE_animdata_free(ID *id, const bool do_id_user) /* Copying -------------------------------------------- */ /* Make a copy of the given AnimData - to be used when copying datablocks */ -AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action) +AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action) { AnimData *dadt; @@ -270,8 +270,9 @@ AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action) /* make a copy of action - at worst, user has to delete copies... */ if (do_action) { - dadt->action = BKE_action_copy(G.main, adt->action); - dadt->tmpact = BKE_action_copy(G.main, adt->tmpact); + BLI_assert(bmain != NULL); + BKE_id_copy_ex(bmain, (ID *)dadt->action, (ID **)&dadt->action, 0, false); + BKE_id_copy_ex(bmain, (ID *)dadt->tmpact, (ID **)&dadt->tmpact, 0, false); } else { id_us_plus((ID *)dadt->action); @@ -291,7 +292,7 @@ AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action) return dadt; } -bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action) +bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const bool do_action) { AnimData *adt; @@ -303,7 +304,7 @@ bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action) adt = BKE_animdata_from_id(id_from); if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id_to; - iat->adt = BKE_animdata_copy(adt, do_action); + iat->adt = BKE_animdata_copy(bmain, adt, do_action); } return true; @@ -1347,7 +1348,7 @@ void BKE_keyingset_free_path(KeyingSet *ks, KS_Path *ksp) } /* Copy all KeyingSets in the given list */ -void BKE_keyingsets_copy(ListBase *newlist, ListBase *list) +void BKE_keyingsets_copy(ListBase *newlist, const ListBase *list) { KeyingSet *ksn; KS_Path *kspn; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 35b6fe113bd..669344e18d7 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -83,7 +83,7 @@ bArmature *BKE_armature_add(Main *bmain, const char *name) { bArmature *arm; - arm = BKE_libblock_alloc(bmain, ID_AR, name); + arm = BKE_libblock_alloc(bmain, ID_AR, name, 0); arm->deformflag = ARM_DEF_VGROUP | ARM_DEF_ENVELOPE; arm->flag = ARM_COL_CUSTOM; /* custom bone-group colors */ arm->layer = 1; @@ -150,54 +150,70 @@ void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local) BKE_id_make_local_generic(bmain, &arm->id, true, lib_local); } -static void copy_bonechildren(Bone *newBone, const Bone *oldBone, const Bone *actBone, Bone **newActBone) +static void copy_bonechildren( + Bone *bone_dst, const Bone *bone_src, const Bone *bone_src_act, Bone **r_bone_dst_act, const int flag) { - Bone *curBone, *newChildBone; + Bone *bone_src_child, *bone_dst_child; - if (oldBone == actBone) - *newActBone = newBone; + if (bone_src == bone_src_act) { + *r_bone_dst_act = bone_dst; + } - if (oldBone->prop) - newBone->prop = IDP_CopyProperty(oldBone->prop); + if (bone_src->prop) { + bone_dst->prop = IDP_CopyProperty_ex(bone_src->prop, flag); + } /* Copy this bone's list */ - BLI_duplicatelist(&newBone->childbase, &oldBone->childbase); + BLI_duplicatelist(&bone_dst->childbase, &bone_src->childbase); /* For each child in the list, update it's children */ - newChildBone = newBone->childbase.first; - for (curBone = oldBone->childbase.first; curBone; curBone = curBone->next) { - newChildBone->parent = newBone; - copy_bonechildren(newChildBone, curBone, actBone, newActBone); - newChildBone = newChildBone->next; + for (bone_src_child = bone_src->childbase.first, bone_dst_child = bone_dst->childbase.first; + bone_src_child; + bone_src_child = bone_src_child->next, bone_dst_child = bone_dst_child->next) + { + bone_dst_child->parent = bone_dst; + copy_bonechildren(bone_dst_child, bone_src_child, bone_src_act, r_bone_dst_act, flag); } } -bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm) +/** + * Only copy internal data of Armature ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_armature_copy_data(Main *UNUSED(bmain), bArmature *arm_dst, const bArmature *arm_src, const int flag) { - bArmature *newArm; - Bone *oldBone, *newBone; - Bone *newActBone = NULL; + Bone *bone_src, *bone_dst; + Bone *bone_dst_act = NULL; + + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; - newArm = BKE_libblock_copy(bmain, &arm->id); - BLI_duplicatelist(&newArm->bonebase, &arm->bonebase); + BLI_duplicatelist(&arm_dst->bonebase, &arm_src->bonebase); /* Duplicate the childrens' lists */ - newBone = newArm->bonebase.first; - for (oldBone = arm->bonebase.first; oldBone; oldBone = oldBone->next) { - newBone->parent = NULL; - copy_bonechildren(newBone, oldBone, arm->act_bone, &newActBone); - newBone = newBone->next; + bone_dst = arm_dst->bonebase.first; + for (bone_src = arm_src->bonebase.first; bone_src; bone_src = bone_src->next) { + bone_dst->parent = NULL; + copy_bonechildren(bone_dst, bone_src, arm_src->act_bone, &bone_dst_act, flag_subdata); + bone_dst = bone_dst->next; } - newArm->act_bone = newActBone; - - newArm->edbo = NULL; - newArm->act_edbone = NULL; - newArm->sketch = NULL; + arm_dst->act_bone = bone_dst_act; - BKE_id_copy_ensure_local(bmain, &arm->id, &newArm->id); + arm_dst->edbo = NULL; + arm_dst->act_edbone = NULL; + arm_dst->sketch = NULL; +} - return newArm; +bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm) +{ + bArmature *arm_copy; + BKE_id_copy_ex(bmain, &arm->id, (ID **)&arm_copy, 0, false); + return arm_copy; } static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name) diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index aae323a5056..03b0710c8fc 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -152,7 +152,7 @@ Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode) { Brush *brush; - brush = BKE_libblock_alloc(bmain, ID_BR, name); + brush = BKE_libblock_alloc(bmain, ID_BR, name, 0); BKE_brush_init(brush); @@ -172,34 +172,38 @@ struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode) return NULL; } -Brush *BKE_brush_copy(Main *bmain, const Brush *brush) +/** + * Only copy internal data of Brush ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_brush_copy_data(Main *UNUSED(bmain), Brush *brush_dst, const Brush *brush_src, const int flag) { - Brush *brushn; - - brushn = BKE_libblock_copy(bmain, &brush->id); - - if (brush->mtex.tex) - id_us_plus((ID *)brush->mtex.tex); - - if (brush->mask_mtex.tex) - id_us_plus((ID *)brush->mask_mtex.tex); - - if (brush->paint_curve) - id_us_plus((ID *)brush->paint_curve); - - if (brush->icon_imbuf) - brushn->icon_imbuf = IMB_dupImBuf(brush->icon_imbuf); + if (brush_src->icon_imbuf) { + brush_dst->icon_imbuf = IMB_dupImBuf(brush_src->icon_imbuf); + } - brushn->preview = NULL; + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { + BKE_previewimg_id_copy(&brush_dst->id, &brush_src->id); + } + else { + brush_dst->preview = NULL; + } - brushn->curve = curvemapping_copy(brush->curve); + brush_dst->curve = curvemapping_copy(brush_src->curve); /* enable fake user by default */ - id_fake_user_set(&brushn->id); - - BKE_id_copy_ensure_local(bmain, &brush->id, &brushn->id); + id_fake_user_set(&brush_dst->id); +} - return brushn; +Brush *BKE_brush_copy(Main *bmain, const Brush *brush) +{ + Brush *brush_copy; + BKE_id_copy_ex(bmain, &brush->id, (ID **)&brush_copy, 0, false); + return brush_copy; } /** Free (or release) any data used by this brush (does not free the brush itself). */ diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index cf619a32783..1916531b066 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -66,7 +66,7 @@ void BKE_cachefiles_exit(void) void *BKE_cachefile_add(Main *bmain, const char *name) { - CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, name); + CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, name, 0); BKE_cachefile_init(cache_file); @@ -100,16 +100,26 @@ void BKE_cachefile_free(CacheFile *cache_file) BLI_freelistN(&cache_file->object_paths); } -CacheFile *BKE_cachefile_copy(Main *bmain, const CacheFile *cache_file) +/** + * Only copy internal data of CacheFile ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_cachefile_copy_data( + Main *UNUSED(bmain), CacheFile *cache_file_dst, const CacheFile *UNUSED(cache_file_src), const int UNUSED(flag)) { - CacheFile *new_cache_file = BKE_libblock_copy(bmain, &cache_file->id); - new_cache_file->handle = NULL; - - BLI_listbase_clear(&new_cache_file->object_paths); - - BKE_id_copy_ensure_local(bmain, &cache_file->id, &new_cache_file->id); + cache_file_dst->handle = NULL; + BLI_listbase_clear(&cache_file_dst->object_paths); +} - return new_cache_file; +CacheFile *BKE_cachefile_copy(Main *bmain, const CacheFile *cache_file) +{ + CacheFile *cache_file_copy; + BKE_id_copy_ex(bmain, &cache_file->id, (ID **)&cache_file_copy, 0, false); + return cache_file_copy; } void BKE_cachefile_make_local(Main *bmain, CacheFile *cache_file, const bool lib_local) diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 915c08674a4..719125b3317 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -86,22 +86,31 @@ void *BKE_camera_add(Main *bmain, const char *name) { Camera *cam; - cam = BKE_libblock_alloc(bmain, ID_CA, name); + cam = BKE_libblock_alloc(bmain, ID_CA, name, 0); BKE_camera_init(cam); return cam; } -Camera *BKE_camera_copy(Main *bmain, const Camera *cam) +/** + * Only copy internal data of Camera ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *UNUSED(cam_dst), const Camera *UNUSED(cam_src), const int UNUSED(flag)) { - Camera *camn; - - camn = BKE_libblock_copy(bmain, &cam->id); - - BKE_id_copy_ensure_local(bmain, &cam->id, &camn->id); + /* Nothing to do! */ +} - return camn; +Camera *BKE_camera_copy(Main *bmain, const Camera *cam) +{ + Camera *cam_copy; + BKE_id_copy_ex(bmain, &cam->id, (ID **)&cam_copy, 0, false); + return cam_copy; } void BKE_camera_make_local(Main *bmain, Camera *cam, const bool lib_local) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 07a6b304dff..c05feb7faf4 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4737,29 +4737,30 @@ static void con_fix_copied_refs_cb(bConstraint *UNUSED(con), ID **idpoin, bool i } /* duplicate all of the constraints in a constraint stack */ -void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern) +void BKE_constraints_copy_ex(ListBase *dst, const ListBase *src, const int flag, bool do_extern) { bConstraint *con, *srccon; - + BLI_listbase_clear(dst); BLI_duplicatelist(dst, src); - + for (con = dst->first, srccon = src->first; con && srccon; srccon = srccon->next, con = con->next) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - + /* make a new copy of the constraint's data */ con->data = MEM_dupallocN(con->data); - + /* only do specific constraints if required */ if (cti) { /* perform custom copying operations if needed */ if (cti->copy_data) cti->copy_data(con, srccon); - - /* fix usercounts for all referenced data in referenced data */ - if (cti->id_looper) + + /* Fix usercounts for all referenced data that need it. */ + if (cti->id_looper && (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { cti->id_looper(con, con_fix_copied_refs_cb, NULL); - + } + /* for proxies we don't want to make extern */ if (do_extern) { /* go over used ID-links for this constraint to ensure that they are valid for proxies */ @@ -4770,6 +4771,11 @@ void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern) } } +void BKE_constraints_copy(ListBase *dst, const ListBase *src, bool do_extern) +{ + BKE_constraints_copy_ex(dst, src, 0, do_extern); +} + /* ......... */ bConstraint *BKE_constraints_find_name(ListBase *list, const char *name) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 7c22a34c7d1..e08fdcf10e9 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -179,7 +179,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type) { Curve *cu; - cu = BKE_libblock_alloc(bmain, ID_CU, name); + cu = BKE_libblock_alloc(bmain, ID_CU, name, 0); cu->type = type; BKE_curve_init(cu); @@ -187,42 +187,39 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type) return cu; } -Curve *BKE_curve_copy(Main *bmain, const Curve *cu) +/** + * Only copy internal data of Curve ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_curve_copy_data(Main *bmain, Curve *cu_dst, const Curve *cu_src, const int flag) { - Curve *cun; - int a; - - cun = BKE_libblock_copy(bmain, &cu->id); + BLI_listbase_clear(&cu_dst->nurb); + BKE_nurbList_duplicate(&(cu_dst->nurb), &(cu_src->nurb)); - BLI_listbase_clear(&cun->nurb); - BKE_nurbList_duplicate(&(cun->nurb), &(cu->nurb)); + cu_dst->mat = MEM_dupallocN(cu_src->mat); - cun->mat = MEM_dupallocN(cu->mat); - for (a = 0; a < cun->totcol; a++) { - id_us_plus((ID *)cun->mat[a]); - } - - cun->str = MEM_dupallocN(cu->str); - cun->strinfo = MEM_dupallocN(cu->strinfo); - cun->tb = MEM_dupallocN(cu->tb); - cun->bb = MEM_dupallocN(cu->bb); + cu_dst->str = MEM_dupallocN(cu_src->str); + cu_dst->strinfo = MEM_dupallocN(cu_src->strinfo); + cu_dst->tb = MEM_dupallocN(cu_src->tb); + cu_dst->bb = MEM_dupallocN(cu_src->bb); - if (cu->key) { - cun->key = BKE_key_copy(bmain, cu->key); - cun->key->from = (ID *)cun; + if (cu_src->key) { + BKE_id_copy_ex(bmain, &cu_src->key->id, (ID **)&cu_dst->key, flag, false); } - cun->editnurb = NULL; - cun->editfont = NULL; - - id_us_plus((ID *)cun->vfont); - id_us_plus((ID *)cun->vfontb); - id_us_plus((ID *)cun->vfonti); - id_us_plus((ID *)cun->vfontbi); - - BKE_id_copy_ensure_local(bmain, &cu->id, &cun->id); + cu_dst->editnurb = NULL; + cu_dst->editfont = NULL; +} - return cun; +Curve *BKE_curve_copy(Main *bmain, const Curve *cu) +{ + Curve *cu_copy; + BKE_id_copy_ex(bmain, &cu->id, (ID **)&cu_copy, 0, false); + return cu_copy; } void BKE_curve_make_local(Main *bmain, Curve *cu, const bool lib_local) diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 401fed74c52..d6b28cfaf70 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -106,6 +106,23 @@ void BKE_vfont_free(struct VFont *vf) } } +void BKE_vfont_copy_data(Main *UNUSED(bmain), VFont *vfont_dst, const VFont *UNUSED(vfont_src), const int flag) +{ + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + + /* Just to be sure, should not have any value actually after reading time. */ + vfont_dst->temp_pf = NULL; + + if (vfont_dst->packedfile) { + vfont_dst->packedfile = dupPackedFile(vfont_dst->packedfile); + } + + if (vfont_dst->data) { + vfont_dst->data = BLI_vfontdata_copy(vfont_dst->data, flag_subdata); + } +} + static void *builtin_font_data = NULL; static int builtin_font_size = 0; @@ -249,7 +266,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath) vfd = BLI_vfontdata_from_freetypefont(pf); if (vfd) { - vfont = BKE_libblock_alloc(bmain, ID_VF, filename); + vfont = BKE_libblock_alloc(bmain, ID_VF, filename, 0); vfont->data = vfd; /* if there's a font name, use it for the ID name */ diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c index 0a0b023df82..e45a938a4fc 100644 --- a/source/blender/blenkernel/intern/freestyle.c +++ b/source/blender/blenkernel/intern/freestyle.c @@ -44,7 +44,7 @@ // function declarations static FreestyleLineSet *alloc_lineset(void); -static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset); +static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag); static FreestyleModuleConfig *alloc_module(void); static void copy_module(FreestyleModuleConfig *new_module, FreestyleModuleConfig *module); @@ -79,7 +79,7 @@ void BKE_freestyle_config_free(FreestyleConfig *config) BLI_freelistN(&config->modules); } -void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config) +void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag) { FreestyleLineSet *lineset, *new_lineset; FreestyleModuleConfig *module, *new_module; @@ -93,7 +93,7 @@ void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *con BLI_listbase_clear(&new_config->linesets); for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) { new_lineset = alloc_lineset(); - copy_lineset(new_lineset, lineset); + copy_lineset(new_lineset, lineset, flag); BLI_addtail(&new_config->linesets, (void *)new_lineset); } @@ -105,11 +105,9 @@ void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *con } } -static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset) +static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset, const int flag) { new_lineset->linestyle = lineset->linestyle; - if (new_lineset->linestyle) - id_us_plus(&new_lineset->linestyle->id); new_lineset->flags = lineset->flags; new_lineset->selection = lineset->selection; new_lineset->qi = lineset->qi; @@ -118,10 +116,12 @@ static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *linese new_lineset->edge_types = lineset->edge_types; new_lineset->exclude_edge_types = lineset->exclude_edge_types; new_lineset->group = lineset->group; - if (new_lineset->group) { - id_us_plus(&new_lineset->group->id); - } strcpy(new_lineset->name, lineset->name); + + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)new_lineset->linestyle); + id_us_plus((ID *)new_lineset->group); + } } static FreestyleModuleConfig *alloc_module(void) diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 758438bb051..ee0d0b41898 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -627,7 +627,7 @@ bGPdata *BKE_gpencil_data_addnew(const char name[]) bGPdata *gpd; /* allocate memory for a new block */ - gpd = BKE_libblock_alloc(G.main, ID_GD, name); + gpd = BKE_libblock_alloc(G.main, ID_GD, name, 0); /* initial settings */ gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND); @@ -753,47 +753,62 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src) return gpl_dst; } -/* make a copy of a given gpencil datablock */ -bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy) +/** + * Only copy internal data of GreasePencil ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_gpencil_copy_data(Main *UNUSED(bmain), bGPdata *gpd_dst, const bGPdata *gpd_src, const int UNUSED(flag)) { - const bGPDlayer *gpl_src; - bGPDlayer *gpl_dst; - bGPdata *gpd_dst; + /* copy layers */ + BLI_listbase_clear(&gpd_dst->layers); + for (const bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) { + /* make a copy of source layer and its data */ + bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); /* TODO here too could add unused flags... */ + BLI_addtail(&gpd_dst->layers, gpl_dst); + } - /* error checking */ - if (gpd_src == NULL) { - return NULL; + /* copy palettes */ + BLI_listbase_clear(&gpd_dst->palettes); + for (const bGPDpalette *palette_src = gpd_src->palettes.first; palette_src; palette_src = palette_src->next) { + bGPDpalette *palette_dst = BKE_gpencil_palette_duplicate(palette_src); /* TODO here too could add unused flags... */ + BLI_addtail(&gpd_dst->palettes, palette_dst); } - - /* make a copy of the base-data */ +} + +/* make a copy of a given gpencil datablock */ +bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy) +{ + /* Yuck and super-uber-hyper yuck!!! + * Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it, + * so for now keep old code for that one. */ if (internal_copy) { + const bGPDlayer *gpl_src; + bGPDlayer *gpl_dst; + bGPdata *gpd_dst; + /* make a straight copy for undo buffers used during stroke drawing */ gpd_dst = MEM_dupallocN(gpd_src); + + /* copy layers */ + BLI_listbase_clear(&gpd_dst->layers); + for (gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) { + /* make a copy of source layer and its data */ + gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); + BLI_addtail(&gpd_dst->layers, gpl_dst); + } + + /* return new */ + return gpd_dst; } else { - /* make a copy when others use this */ - gpd_dst = BKE_libblock_copy(bmain, &gpd_src->id); - } - - /* copy layers */ - BLI_listbase_clear(&gpd_dst->layers); - for (gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) { - /* make a copy of source layer and its data */ - gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); - BLI_addtail(&gpd_dst->layers, gpl_dst); - } - if (!internal_copy) { - /* copy palettes */ - bGPDpalette *palette_src, *palette_dst; - BLI_listbase_clear(&gpd_dst->palettes); - for (palette_src = gpd_src->palettes.first; palette_src; palette_src = palette_src->next) { - palette_dst = BKE_gpencil_palette_duplicate(palette_src); - BLI_addtail(&gpd_dst->palettes, palette_dst); - } + bGPdata *gpd_copy; + BKE_id_copy_ex(bmain, &gpd_src->id, (ID **)&gpd_copy, 0, false); + return gpd_copy; } - - /* return new */ - return gpd_dst; } void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local) diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 932f41ac4ba..fd6e9681e64 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -79,7 +79,7 @@ Group *BKE_group_add(Main *bmain, const char *name) { Group *group; - group = BKE_libblock_alloc(bmain, ID_GR, name); + group = BKE_libblock_alloc(bmain, ID_GR, name, 0); id_us_min(&group->id); id_us_ensure_real(&group->id); group->layer = (1 << 20) - 1; @@ -89,19 +89,32 @@ Group *BKE_group_add(Main *bmain, const char *name) return group; } -Group *BKE_group_copy(Main *bmain, const Group *group) +/** + * Only copy internal data of Group ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *group_src, const int flag) { - Group *groupn; - - groupn = BKE_libblock_copy(bmain, &group->id); - BLI_duplicatelist(&groupn->gobject, &group->gobject); + BLI_duplicatelist(&group_dst->gobject, &group_src->gobject); /* Do not copy group's preview (same behavior as for objects). */ - groupn->preview = NULL; - - BKE_id_copy_ensure_local(bmain, &group->id, &groupn->id); + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ + BKE_previewimg_id_copy(&group_dst->id, &group_src->id); + } + else { + group_dst->preview = NULL; + } +} - return groupn; +Group *BKE_group_copy(Main *bmain, const Group *group) +{ + Group *group_copy; + BKE_id_copy_ex(bmain, &group->id, (ID **)&group_copy, 0, false); + return group_copy; } void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index e98181be444..45b41fa01ed 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -90,7 +90,7 @@ IDProperty *IDP_NewIDPArray(const char *name) return prop; } -IDProperty *IDP_CopyIDPArray(const IDProperty *array) +IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag) { /* don't use MEM_dupallocN because this may be part of an array */ IDProperty *narray, *tmp; @@ -109,7 +109,7 @@ IDProperty *IDP_CopyIDPArray(const IDProperty *array) * then free it. this makes for more maintainable * code than simply reimplementing the copy functions * in this loop.*/ - tmp = IDP_CopyProperty(GETPROP(narray, i)); + tmp = IDP_CopyProperty_ex(GETPROP(narray, i), flag); memcpy(GETPROP(narray, i), tmp, sizeof(IDProperty)); MEM_freeN(tmp); } @@ -285,9 +285,9 @@ void IDP_FreeArray(IDProperty *prop) } -static IDProperty *idp_generic_copy(const IDProperty *prop) +static IDProperty *idp_generic_copy(const IDProperty *prop, const int UNUSED(flag)) { - IDProperty *newp = MEM_callocN(sizeof(IDProperty), "IDProperty array dup"); + IDProperty *newp = MEM_callocN(sizeof(IDProperty), __func__); BLI_strncpy(newp->name, prop->name, MAX_IDPROP_NAME); newp->type = prop->type; @@ -298,9 +298,9 @@ static IDProperty *idp_generic_copy(const IDProperty *prop) return newp; } -static IDProperty *IDP_CopyArray(const IDProperty *prop) +static IDProperty *IDP_CopyArray(const IDProperty *prop, const int flag) { - IDProperty *newp = idp_generic_copy(prop); + IDProperty *newp = idp_generic_copy(prop, flag); if (prop->data.pointer) { newp->data.pointer = MEM_dupallocN(prop->data.pointer); @@ -310,7 +310,7 @@ static IDProperty *IDP_CopyArray(const IDProperty *prop) int a; for (a = 0; a < prop->len; a++) - array[a] = IDP_CopyProperty(array[a]); + array[a] = IDP_CopyProperty_ex(array[a], flag); } } newp->len = prop->len; @@ -363,12 +363,12 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) return prop; } -static IDProperty *IDP_CopyString(const IDProperty *prop) +static IDProperty *IDP_CopyString(const IDProperty *prop, const int flag) { IDProperty *newp; BLI_assert(prop->type == IDP_STRING); - newp = idp_generic_copy(prop); + newp = idp_generic_copy(prop, flag); if (prop->data.pointer) newp->data.pointer = MEM_dupallocN(prop->data.pointer); @@ -442,15 +442,17 @@ void IDP_FreeString(IDProperty *prop) /** \name IDProperty ID API * \{ */ -static IDProperty *IDP_CopyID(const IDProperty *prop) +static IDProperty *IDP_CopyID(const IDProperty *prop, const int flag) { IDProperty *newp; BLI_assert(prop->type == IDP_ID); - newp = idp_generic_copy(prop); + newp = idp_generic_copy(prop, flag); newp->data.pointer = prop->data.pointer; - id_us_plus(IDP_Id(newp)); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus(IDP_Id(newp)); + } return newp; } @@ -467,16 +469,16 @@ static IDProperty *IDP_CopyID(const IDProperty *prop) /** * Checks if a property with the same name as prop exists, and if so replaces it. */ -static IDProperty *IDP_CopyGroup(const IDProperty *prop) +static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag) { IDProperty *newp, *link; BLI_assert(prop->type == IDP_GROUP); - newp = idp_generic_copy(prop); + newp = idp_generic_copy(prop, flag); newp->len = prop->len; for (link = prop->data.group.first; link; link = link->next) { - BLI_addtail(&newp->data.group, IDP_CopyProperty(link)); + BLI_addtail(&newp->data.group, IDP_CopyProperty_ex(link, flag)); } return newp; @@ -730,18 +732,23 @@ static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user) /** \name IDProperty Main API * \{ */ -IDProperty *IDP_CopyProperty(const IDProperty *prop) +IDProperty *IDP_CopyProperty_ex(const IDProperty *prop, const int flag) { switch (prop->type) { - case IDP_GROUP: return IDP_CopyGroup(prop); - case IDP_STRING: return IDP_CopyString(prop); - case IDP_ID: return IDP_CopyID(prop); - case IDP_ARRAY: return IDP_CopyArray(prop); - case IDP_IDPARRAY: return IDP_CopyIDPArray(prop); - default: return idp_generic_copy(prop); + case IDP_GROUP: return IDP_CopyGroup(prop, flag); + case IDP_STRING: return IDP_CopyString(prop, flag); + case IDP_ID: return IDP_CopyID(prop, flag); + case IDP_ARRAY: return IDP_CopyArray(prop, flag); + case IDP_IDPARRAY: return IDP_CopyIDPArray(prop, flag); + default: return idp_generic_copy(prop, flag); } } +IDProperty *IDP_CopyProperty(const IDProperty *prop) +{ + return IDP_CopyProperty_ex(prop, 0); +} + /* Updates ID pointers after an object has been copied */ /* TODO Nuke this once its only user has been correctly converted to use generic ID management from BKE_library! */ void IDP_RelinkProperty(struct IDProperty *prop) diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index abe08def197..bbe6814f6b7 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -382,7 +382,7 @@ static Image *image_alloc(Main *bmain, const char *name, short source, short typ { Image *ima; - ima = BKE_libblock_alloc(bmain, ID_IM, name); + ima = BKE_libblock_alloc(bmain, ID_IM, name, 0); if (ima) { image_init(ima, source, type); } @@ -433,39 +433,53 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src) } } -/* empty image block, of similar type and filename */ -Image *BKE_image_copy(Main *bmain, const Image *ima) +/** + * Only copy internal data of Image ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_image_copy_data(Main *UNUSED(bmain), Image *ima_dst, const Image *ima_src, const int flag) { - Image *nima = image_alloc(bmain, ima->id.name + 2, ima->source, ima->type); - - BLI_strncpy(nima->name, ima->name, sizeof(ima->name)); - - nima->flag = ima->flag; - nima->tpageflag = ima->tpageflag; - - nima->gen_x = ima->gen_x; - nima->gen_y = ima->gen_y; - nima->gen_type = ima->gen_type; - copy_v4_v4(nima->gen_color, ima->gen_color); - - nima->animspeed = ima->animspeed; + BKE_color_managed_colorspace_settings_copy(&ima_dst->colorspace_settings, &ima_src->colorspace_settings); - nima->aspx = ima->aspx; - nima->aspy = ima->aspy; + copy_image_packedfiles(&ima_dst->packedfiles, &ima_src->packedfiles); - BKE_color_managed_colorspace_settings_copy(&nima->colorspace_settings, &ima->colorspace_settings); + ima_dst->stereo3d_format = MEM_dupallocN(ima_src->stereo3d_format); + BLI_duplicatelist(&ima_dst->views, &ima_src->views); - copy_image_packedfiles(&nima->packedfiles, &ima->packedfiles); + /* Cleanup stuff that cannot be copied. */ + ima_dst->cache = NULL; + ima_dst->rr = NULL; + for (int i = 0; i < IMA_MAX_RENDER_SLOT; i++) { + ima_dst->renders[i] = NULL; + } - /* nima->stere3d_format is already allocated by image_alloc... */ - *nima->stereo3d_format = *ima->stereo3d_format; - BLI_duplicatelist(&nima->views, &ima->views); + BLI_listbase_clear(&ima_dst->anims); - BKE_previewimg_id_copy(&nima->id, &ima->id); + ima_dst->totbind = 0; + for (int i = 0; i < TEXTARGET_COUNT; i++) { + ima_dst->bindcode[i] = 0; + ima_dst->gputexture[i] = NULL; + } + ima_dst->repbind = NULL; - BKE_id_copy_ensure_local(bmain, &ima->id, &nima->id); + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { + BKE_previewimg_id_copy(&ima_dst->id, &ima_src->id); + } + else { + ima_dst->preview = NULL; + } +} - return nima; +/* empty image block, of similar type and filename */ +Image *BKE_image_copy(Main *bmain, const Image *ima) +{ + Image *ima_copy; + BKE_id_copy_ex(bmain, &ima->id, (ID **)&ima_copy, 0, false); + return ima_copy; } void BKE_image_make_local(Main *bmain, Image *ima, const bool lib_local) diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 98b251294ae..364817438c5 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -107,7 +107,7 @@ Key *BKE_key_add(ID *id) /* common function */ Key *key; char *el; - key = BKE_libblock_alloc(G.main, ID_KE, "Key"); + key = BKE_libblock_alloc(G.main, ID_KE, "Key", 0); key->type = KEY_NORMAL; key->from = id; @@ -151,31 +151,40 @@ Key *BKE_key_add(ID *id) /* common function */ return key; } -Key *BKE_key_copy(Main *bmain, const Key *key) +/** + * Only copy internal data of ShapeKey ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_key_copy_data(Main *UNUSED(bmain), Key *key_dst, const Key *key_src, const int UNUSED(flag)) { - Key *keyn; - KeyBlock *kbn, *kb; - - keyn = BKE_libblock_copy(bmain, &key->id); - - BLI_duplicatelist(&keyn->block, &key->block); - - kb = key->block.first; - kbn = keyn->block.first; - while (kbn) { - - if (kbn->data) kbn->data = MEM_dupallocN(kbn->data); - if (kb == key->refkey) keyn->refkey = kbn; - - kbn = kbn->next; - kb = kb->next; - } + BLI_duplicatelist(&key_dst->block, &key_src->block); - BKE_id_copy_ensure_local(bmain, &key->id, &keyn->id); + KeyBlock *kb_dst, *kb_src; + for (kb_src = key_src->block.first, kb_dst = key_dst->block.first; + kb_dst; + kb_src = kb_src->next, kb_dst = kb_dst->next) + { + if (kb_dst->data) { + kb_dst->data = MEM_dupallocN(kb_dst->data); + } + if (kb_src == key_src->refkey) { + key_dst->refkey = kb_dst; + } + } +} - return keyn; +Key *BKE_key_copy(Main *bmain, const Key *key) +{ + Key *key_copy; + BKE_id_copy_ex(bmain, &key->id, (ID **)&key_copy, 0, false); + return key_copy; } +/* XXX TODO get rid of this! */ Key *BKE_key_copy_nolib(Key *key) { Key *keyn; diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 2242ba379fb..e8ef346927e 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -109,42 +109,60 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name) { Lamp *la; - la = BKE_libblock_alloc(bmain, ID_LA, name); + la = BKE_libblock_alloc(bmain, ID_LA, name, 0); BKE_lamp_init(la); return la; } -Lamp *BKE_lamp_copy(Main *bmain, const Lamp *la) +/** + * Only copy internal data of Lamp ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_lamp_copy_data(Main *bmain, Lamp *la_dst, const Lamp *la_src, const int flag) { - Lamp *lan; - int a; - - lan = BKE_libblock_copy(bmain, &la->id); - - for (a = 0; a < MAX_MTEX; a++) { - if (lan->mtex[a]) { - lan->mtex[a] = MEM_mallocN(sizeof(MTex), "copylamptex"); - memcpy(lan->mtex[a], la->mtex[a], sizeof(MTex)); - id_us_plus((ID *)lan->mtex[a]->tex); + for (int a = 0; a < MAX_MTEX; a++) { + if (la_dst->mtex[a]) { + la_dst->mtex[a] = MEM_mallocN(sizeof(*la_dst->mtex[a]), __func__); + *la_dst->mtex[a] = *la_src->mtex[a]; } } - - lan->curfalloff = curvemapping_copy(la->curfalloff); - if (la->nodetree) - lan->nodetree = ntreeCopyTree(bmain, la->nodetree); + la_dst->curfalloff = curvemapping_copy(la_src->curfalloff); - BKE_previewimg_id_copy(&lan->id, &la->id); + if (la_src->nodetree) { + BKE_id_copy_ex(bmain, (ID *)la_src->nodetree, (ID **)&la_dst->nodetree, flag, false); + } - BKE_id_copy_ensure_local(bmain, &la->id, &lan->id); + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { + BKE_previewimg_id_copy(&la_dst->id, &la_src->id); + } + else { + la_dst->preview = NULL; + } +} - return lan; +Lamp *BKE_lamp_copy(Main *bmain, const Lamp *la) +{ + Lamp *la_copy; + BKE_id_copy_ex(bmain, &la->id, (ID **)&la_copy, 0, false); + return la_copy; } Lamp *localize_lamp(Lamp *la) { + /* TODO replace with something like + * Lamp *la_copy; + * BKE_id_copy_ex(bmain, &la->id, (ID **)&la_copy, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT, false); + * return la_copy; + * + * ... Once f*** nodes are fully converted to that too :( */ + Lamp *lan; int a; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index c9d7dddf25a..ea4c3f380ff 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -270,39 +270,46 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name) { Lattice *lt; - lt = BKE_libblock_alloc(bmain, ID_LT, name); + lt = BKE_libblock_alloc(bmain, ID_LT, name, 0); BKE_lattice_init(lt); return lt; } -Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt) +/** + * Only copy internal data of Lattice ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_lattice_copy_data(Main *bmain, Lattice *lt_dst, const Lattice *lt_src, const int flag) { - Lattice *ltn; - - ltn = BKE_libblock_copy(bmain, <->id); - ltn->def = MEM_dupallocN(lt->def); + lt_dst->def = MEM_dupallocN(lt_src->def); - if (lt->key) { - ltn->key = BKE_key_copy(bmain, ltn->key); - ltn->key->from = (ID *)ltn; - } - - if (lt->dvert) { - int tot = lt->pntsu * lt->pntsv * lt->pntsw; - ltn->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert"); - BKE_defvert_array_copy(ltn->dvert, lt->dvert, tot); + if (lt_src->key) { + BKE_id_copy_ex(bmain, <_src->key->id, (ID **)<_dst->key, flag, false); } - ltn->editlatt = NULL; + if (lt_src->dvert) { + int tot = lt_src->pntsu * lt_src->pntsv * lt_src->pntsw; + lt_dst->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert"); + BKE_defvert_array_copy(lt_dst->dvert, lt_src->dvert, tot); + } - BKE_id_copy_ensure_local(bmain, <->id, <n->id); + lt_dst->editlatt = NULL; +} - return ltn; +Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt) +{ + Lattice *lt_copy; + BKE_id_copy_ex(bmain, <->id, (ID **)<_copy, 0, false); + return lt_copy; } -/** Free (or release) any data used by this lattice (does not free the lattice itself). */ + /** Free (or release) any data used by this lattice (does not free the lattice itself). */ void BKE_lattice_free(Lattice *lt) { BKE_animdata_free(<->id, false); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 2ea7342ff34..18e4f332dc2 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -383,7 +383,6 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) switch ((ID_Type)GS(id->name)) { case ID_SCE: - /* Partially implemented (has no copy...). */ if (!test) BKE_scene_make_local(bmain, (Scene *)id, lib_local); return true; case ID_OB: @@ -423,14 +422,12 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) if (!test) BKE_world_make_local(bmain, (World *)id, lib_local); return true; case ID_VF: - /* Partially implemented (has no copy...). */ if (!test) BKE_vfont_make_local(bmain, (VFont *)id, lib_local); return true; case ID_TXT: if (!test) BKE_text_make_local(bmain, (Text *)id, lib_local); return true; case ID_SO: - /* Partially implemented (has no copy...). */ if (!test) BKE_sound_make_local(bmain, (bSound *)id, lib_local); return true; case ID_GR: @@ -484,114 +481,187 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) return false; } +struct IDCopyLibManagementData { + const ID *id_src; + int flag; +}; + +/* Increases usercount as required, and remap self ID pointers. */ +static int id_copy_libmanagement_cb(void *user_data, ID *id_self, ID **id_pointer, int cb_flag) +{ + struct IDCopyLibManagementData *data = user_data; + ID *id = *id_pointer; + + /* Remap self-references to new copied ID. */ + if (id == data->id_src) { + id = *id_pointer = id_self; + } + + /* Increase used IDs refcount if needed and required. */ + if ((data->flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && (cb_flag & IDWALK_CB_USER)) { + id_us_plus(id); + } + + return IDWALK_RET_NOP; +} + /** - * Invokes the appropriate copy method for the block and returns the result in - * newid, unless test. Returns true if the block can be copied. + * Generic entry point for copying a datablock (new API). + * + * \note Copy is only affecting given data-block (no ID used by copied one will be affected, besides usercount). + * There is only one exception, if LIB_ID_COPY_ACTIONS is defined, actions used by animdata will be duplicated. + * + * \note Usercount of new copy is always set to 1. + * + * \param bmain Main database, may be NULL only if LIB_ID_COPY_NO_MAIN is specified. + * \param id Source datablock. + * \param r_newid Pointer to new (copied) ID pointer. + * \param flag Set of copy options, see DNA_ID.h enum for details (leave to zero for default, full copy). + * \param test If set, do not do any copy, just test whether copy is supported. + * \return False when copying that ID type is not supported, true otherwise. */ -bool id_copy(Main *bmain, const ID *id, ID **newid, bool test) +/* XXX TODO remove test thing, *all* IDs should be copyable that way! */ +bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, const bool test) { - if (!test) { - *newid = NULL; +#define LIB_ID_TYPES_NOCOPY ID_LI, ID_SCR, ID_WM, /* Not supported */ \ + ID_IP /* Deprecated */ + + BLI_assert(test || (r_newid != NULL)); + if (r_newid != NULL) { + *r_newid = NULL; + } + if (id == NULL) { + return false; + } + + if (ELEM(GS(id->name), LIB_ID_TYPES_NOCOPY)) { + return false; + } + else if (test) { + return true; } - /* conventions: - * - make shallow copy, only this ID block - * - id.us of the new ID is set to 1 */ + BKE_libblock_copy_ex(bmain, id, r_newid, flag); + switch ((ID_Type)GS(id->name)) { + case ID_SCE: + BKE_scene_copy_data(bmain, (Scene *)*r_newid, (Scene *)id, flag); + break; case ID_OB: - if (!test) *newid = (ID *)BKE_object_copy(bmain, (Object *)id); - return true; + BKE_object_copy_data(bmain, (Object *)*r_newid, (Object *)id, flag); + break; case ID_ME: - if (!test) *newid = (ID *)BKE_mesh_copy(bmain, (Mesh *)id); - return true; + BKE_mesh_copy_data(bmain, (Mesh *)*r_newid, (Mesh *)id, flag); + break; case ID_CU: - if (!test) *newid = (ID *)BKE_curve_copy(bmain, (Curve *)id); - return true; + BKE_curve_copy_data(bmain, (Curve *)*r_newid, (Curve *)id, flag); + break; case ID_MB: - if (!test) *newid = (ID *)BKE_mball_copy(bmain, (MetaBall *)id); - return true; + BKE_mball_copy_data(bmain, (MetaBall *)*r_newid, (MetaBall *)id, flag); + break; case ID_MA: - if (!test) *newid = (ID *)BKE_material_copy(bmain, (Material *)id); - return true; + BKE_material_copy_data(bmain, (Material *)*r_newid, (Material *)id, flag); + break; case ID_TE: - if (!test) *newid = (ID *)BKE_texture_copy(bmain, (Tex *)id); - return true; + BKE_texture_copy_data(bmain, (Tex *)*r_newid, (Tex *)id, flag); + break; case ID_IM: - if (!test) *newid = (ID *)BKE_image_copy(bmain, (Image *)id); - return true; + BKE_image_copy_data(bmain, (Image *)*r_newid, (Image *)id, flag); + break; case ID_LT: - if (!test) *newid = (ID *)BKE_lattice_copy(bmain, (Lattice *)id); - return true; + BKE_lattice_copy_data(bmain, (Lattice *)*r_newid, (Lattice *)id, flag); + break; case ID_LA: - if (!test) *newid = (ID *)BKE_lamp_copy(bmain, (Lamp *)id); - return true; + BKE_lamp_copy_data(bmain, (Lamp *)*r_newid, (Lamp *)id, flag); + break; case ID_SPK: - if (!test) *newid = (ID *)BKE_speaker_copy(bmain, (Speaker *)id); - return true; + BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag); + break; case ID_CA: - if (!test) *newid = (ID *)BKE_camera_copy(bmain, (Camera *)id); - return true; + BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag); + break; case ID_KE: - if (!test) *newid = (ID *)BKE_key_copy(bmain, (Key *)id); - return true; + BKE_key_copy_data(bmain, (Key *)*r_newid, (Key *)id, flag); + break; case ID_WO: - if (!test) *newid = (ID *)BKE_world_copy(bmain, (World *)id); - return true; + BKE_world_copy_data(bmain, (World *)*r_newid, (World *)id, flag); + break; case ID_TXT: - if (!test) *newid = (ID *)BKE_text_copy(bmain, (Text *)id); - return true; + BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag); + break; case ID_GR: - if (!test) *newid = (ID *)BKE_group_copy(bmain, (Group *)id); - return true; + BKE_group_copy_data(bmain, (Group *)*r_newid, (Group *)id, flag); + break; case ID_AR: - if (!test) *newid = (ID *)BKE_armature_copy(bmain, (bArmature *)id); - return true; + BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag); + break; case ID_AC: - if (!test) *newid = (ID *)BKE_action_copy(bmain, (bAction *)id); - return true; + BKE_action_copy_data(bmain, (bAction *)*r_newid, (bAction *)id, flag); + break; case ID_NT: - if (!test) *newid = (ID *)ntreeCopyTree(bmain, (bNodeTree *)id); - return true; + BKE_node_tree_copy_data(bmain, (bNodeTree *)*r_newid, (bNodeTree *)id, flag); + break; case ID_BR: - if (!test) *newid = (ID *)BKE_brush_copy(bmain, (Brush *)id); - return true; + BKE_brush_copy_data(bmain, (Brush *)*r_newid, (Brush *)id, flag); + break; case ID_PA: - if (!test) *newid = (ID *)BKE_particlesettings_copy(bmain, (ParticleSettings *)id); - return true; + BKE_particlesettings_copy_data(bmain, (ParticleSettings *)*r_newid, (ParticleSettings *)id, flag); + break; case ID_GD: - if (!test) *newid = (ID *)BKE_gpencil_data_duplicate(bmain, (bGPdata *)id, false); - return true; + BKE_gpencil_copy_data(bmain, (bGPdata *)*r_newid, (bGPdata *)id, flag); + break; case ID_MC: - if (!test) *newid = (ID *)BKE_movieclip_copy(bmain, (MovieClip *)id); - return true; + BKE_movieclip_copy_data(bmain, (MovieClip *)*r_newid, (MovieClip *)id, flag); + break; case ID_MSK: - if (!test) *newid = (ID *)BKE_mask_copy(bmain, (Mask *)id); - return true; + BKE_mask_copy_data(bmain, (Mask *)*r_newid, (Mask *)id, flag); + break; case ID_LS: - if (!test) *newid = (ID *)BKE_linestyle_copy(bmain, (FreestyleLineStyle *)id); - return true; + BKE_linestyle_copy_data(bmain, (FreestyleLineStyle *)*r_newid, (FreestyleLineStyle *)id, flag); + break; case ID_PAL: - if (!test) *newid = (ID *)BKE_palette_copy(bmain, (Palette *)id); - return true; + BKE_palette_copy_data(bmain, (Palette *)*r_newid, (Palette *)id, flag); + break; case ID_PC: - if (!test) *newid = (ID *)BKE_paint_curve_copy(bmain, (PaintCurve *)id); - return true; + BKE_paint_curve_copy_data(bmain, (PaintCurve *)*r_newid, (PaintCurve *)id, flag); + break; case ID_CF: - if (!test) *newid = (ID *)BKE_cachefile_copy(bmain, (CacheFile *)id); - return true; - case ID_SCE: + BKE_cachefile_copy_data(bmain, (CacheFile *)*r_newid, (CacheFile *)id, flag); + break; + case ID_SO: + BKE_sound_copy_data(bmain, (bSound *)*r_newid, (bSound *)id, flag); + break; + case ID_VF: + BKE_vfont_copy_data(bmain, (VFont *)*r_newid, (VFont *)id, flag); + break; case ID_LI: case ID_SCR: case ID_WM: - return false; /* can't be copied from here */ - case ID_VF: - case ID_SO: - return false; /* not implemented */ case ID_IP: - return false; /* deprecated */ + BLI_assert(0); /* Should have been rejected at start of function! */ + break; } - - return false; + + /* Update ID refcount, remap pointers to self in new ID. */ + struct IDCopyLibManagementData data = {.id_src=id, .flag=flag}; + BKE_library_foreach_ID_link(bmain, *r_newid, id_copy_libmanagement_cb, &data, IDWALK_NOP); + + /* Do not make new copy local in case we are copying outside of main... + * XXX TODO: is this behavior OK, or should we need own flag to control that? */ + if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) { + BKE_id_copy_ensure_local(bmain, id, *r_newid); + } + + return true; +} + +/** + * Invokes the appropriate copy method for the block and returns the result in + * newid, unless test. Returns true if the block can be copied. + */ +bool id_copy(Main *bmain, const ID *id, ID **newid, bool test) +{ + return BKE_id_copy_ex(bmain, id, newid, 0, test); } /** Does *not* set ID->newid pointer. */ @@ -623,6 +693,101 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) return false; } +static int libblock_management_us_plus(void *UNUSED(user_data), ID *UNUSED(id_self), ID **id_pointer, int cb_flag) +{ + if (cb_flag & IDWALK_CB_USER) { + id_us_plus(*id_pointer); + } + if (cb_flag & IDWALK_CB_USER_ONE) { + id_us_ensure_real(*id_pointer); + } + + return IDWALK_RET_NOP; +} + +static int libblock_management_us_min(void *UNUSED(user_data), ID *UNUSED(id_self), ID **id_pointer, int cb_flag) +{ + if (cb_flag & IDWALK_CB_USER) { + id_us_min(*id_pointer); + } + /* We can do nothing in IDWALK_CB_USER_ONE case! */ + + return IDWALK_RET_NOP; +} + +/** Add a 'NO_MAIN' datablock to given main (also sets usercounts of its IDs if needed). */ +void BKE_libblock_management_main_add(Main *bmain, void *idv) +{ + ID *id = idv; + + BLI_assert(bmain != NULL); + if ((id->tag & LIB_TAG_NO_MAIN) == 0) { + return; + } + + if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) { + /* We cannot add non-allocated ID to Main! */ + return; + } + + /* We cannot allow non-userrefcounting IDs in Main database! */ + if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) { + BKE_library_foreach_ID_link(bmain, id, libblock_management_us_plus, NULL, IDWALK_NOP); + } + + ListBase *lb = which_libbase(bmain, GS(id->name)); + BKE_main_lock(bmain); + BLI_addtail(lb, id); + new_id(lb, id, NULL); + /* alphabetic insertion: is in new_id */ + id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT); + BKE_main_unlock(bmain); +} + +/** Remove a datablock from given main (set it to 'NO_MAIN' status). */ +void BKE_libblock_management_main_remove(Main *bmain, void *idv) +{ + ID *id = idv; + + BLI_assert(bmain != NULL); + if ((id->tag & LIB_TAG_NO_MAIN) != 0) { + return; + } + + /* For now, allow userrefcounting IDs to get out of Main - can be handy in some cases... */ + + ListBase *lb = which_libbase(bmain, GS(id->name)); + BKE_main_lock(bmain); + BLI_remlink(lb, id); + id->tag |= LIB_TAG_NO_MAIN; + BKE_main_unlock(bmain); +} + +void BKE_libblock_management_usercounts_set(Main *bmain, void *idv) +{ + ID *id = idv; + + if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) == 0) { + return; + } + + BKE_library_foreach_ID_link(bmain, id, libblock_management_us_plus, NULL, IDWALK_NOP); + id->tag &= ~LIB_TAG_NO_USER_REFCOUNT; +} + +void BKE_libblock_management_usercounts_clear(Main *bmain, void *idv) +{ + ID *id = idv; + + /* We do not allow IDs in Main database to not be userrefcounting. */ + if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0 || (id->tag & LIB_TAG_NO_MAIN) != 0) { + return; + } + + BKE_library_foreach_ID_link(bmain, id, libblock_management_us_min, NULL, IDWALK_NOP); + id->tag |= LIB_TAG_NO_USER_REFCOUNT; +} + ListBase *which_libbase(Main *mainlib, short type) { switch ((ID_Type)type) { @@ -932,23 +1097,43 @@ void *BKE_libblock_alloc_notest(short type) * The user count is set to 1, all other content (apart from name and links) being * initialized to zero. */ -void *BKE_libblock_alloc(Main *bmain, short type, const char *name) +void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int flag) { ID *id = NULL; - ListBase *lb = which_libbase(bmain, type); + + BLI_assert((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0); id = BKE_libblock_alloc_notest(type); + + if ((flag & LIB_ID_CREATE_NO_MAIN) != 0) { + id->tag |= LIB_TAG_NO_MAIN; + } + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0) { + id->tag |= LIB_TAG_NO_USER_REFCOUNT; + } + if (id) { - BKE_main_lock(bmain); - BLI_addtail(lb, id); - id->us = 1; id->icon_id = 0; *( (short *)id->name) = type; - new_id(lb, id, name); - /* alphabetic insertion: is in new_id */ - BKE_main_unlock(bmain); + if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) { + id->us = 1; + } + if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) { + ListBase *lb = which_libbase(bmain, type); + + BKE_main_lock(bmain); + BLI_addtail(lb, id); + new_id(lb, id, name); + /* alphabetic insertion: is in new_id */ + BKE_main_unlock(bmain); + + /* TODO to be removed from here! */ + if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) { + DAG_id_type_tag(bmain, type); + } + } } - DAG_id_type_tag(bmain, type); + return id; } @@ -1071,70 +1256,80 @@ void BKE_libblock_init_empty(ID *id) /* by spec, animdata is first item after ID */ /* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */ -static void id_copy_animdata(ID *id, const bool do_action) +static void id_copy_animdata(Main *bmain, ID *id, const bool do_action) { AnimData *adt = BKE_animdata_from_id(id); if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id; - iat->adt = BKE_animdata_copy(iat->adt, do_action); /* could be set to false, need to investigate */ + iat->adt = BKE_animdata_copy(bmain, iat->adt, do_action); /* could be set to false, need to investigate */ } } -/* material nodes use this since they are not treated as libdata */ -void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action) +void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) { - if (id_from->properties) - id->properties = IDP_CopyProperty(id_from->properties); + ID *new_id = *r_newid; + + /* Grrrrrrrrr... Not adding 'root' nodetrees to bmain.... grrrrrrrrrrrrrrrrrrrr! */ + /* This is taken from original ntree copy code, might be weak actually? */ + const bool use_nodetree_alloc_exception = ((GS(id->name) == ID_NT) && (bmain != NULL) && + (BLI_findindex(&bmain->nodetree, id) < 0)); + + BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL); + BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0); + BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0); + + if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) { + /* r_newid already contains pointer to allocated memory. */ + /* TODO do we want to memset(0) whole mem before filling it? */ + BLI_strncpy(new_id->name, id->name, sizeof(new_id->name)); + new_id->us = 0; + new_id->tag |= LIB_TAG_NOT_ALLOCATED | LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT; + /* TODO Do we want/need to copy more from ID struct itself? */ + } + else { + new_id = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag | (use_nodetree_alloc_exception ? LIB_ID_CREATE_NO_MAIN : 0)); + } + BLI_assert(new_id != NULL); + + const size_t id_len = BKE_libblock_get_alloc_info(GS(new_id->name), NULL); + const size_t id_offset = sizeof(ID); + if ((int)id_len - (int)id_offset > 0) { /* signed to allow neg result */ /* XXX ????? */ + const char *cp = (const char *)id; + char *cpn = (char *)new_id; + + memcpy(cpn + id_offset, cp + id_offset, id_len - id_offset); + } + + if (id->properties) { + new_id->properties = IDP_CopyProperty_ex(id->properties, flag); + } /* the duplicate should get a copy of the animdata */ - id_copy_animdata(id, do_action); + id_copy_animdata(bmain, new_id, (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0); + + if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0) { + DAG_id_type_tag(bmain, GS(new_id->name)); + } + + *r_newid = new_id; } /* used everywhere in blenkernel */ void *BKE_libblock_copy(Main *bmain, const ID *id) { ID *idn; - size_t idn_len; - - idn = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2); - assert(idn != NULL); + BKE_libblock_copy_ex(bmain, id, &idn, 0); - idn_len = MEM_allocN_len(idn); - if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */ - const char *cp = (const char *)id; - char *cpn = (char *)idn; - - memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID)); - } - - BKE_libblock_copy_data(idn, id, false); - return idn; } void *BKE_libblock_copy_nolib(const ID *id, const bool do_action) { ID *idn; - size_t idn_len; - - idn = BKE_libblock_alloc_notest(GS(id->name)); - assert(idn != NULL); - - BLI_strncpy(idn->name, id->name, sizeof(idn->name)); - - idn_len = MEM_allocN_len(idn); - if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */ - const char *cp = (const char *)id; - char *cpn = (char *)idn; - - memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID)); - } - - idn->us = 1; - BKE_libblock_copy_data(idn, id, do_action); + BKE_libblock_copy_ex(NULL, id, &idn, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | (do_action ? LIB_ID_COPY_ACTIONS : 0)); return idn; } diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index 5e5ba44f039..ed9063e7640 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -730,9 +730,11 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user) IDP_FreeProperty_ex(id->properties, do_id_user); MEM_freeN(id->properties); } + + /* XXX TODO remove animdata handling from each type's freeing func, and do it here, like for copy! */ } -void BKE_libblock_free_datablock(ID *id) +void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag)) { const short type = GS(id->name); switch (type) { @@ -842,6 +844,90 @@ void BKE_libblock_free_datablock(ID *id) } } + +void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag) +{ + ID *id = idv; + + if (use_flag_from_idtag) { + if ((id->tag & LIB_TAG_NO_MAIN) != 0) { + flag |= LIB_ID_FREE_NO_MAIN; + } + else { + flag &= ~LIB_ID_FREE_NO_MAIN; + } + + if ((id->tag & LIB_TAG_NO_USER_REFCOUNT) != 0) { + flag |= LIB_ID_FREE_NO_USER_REFCOUNT; + } + else { + flag &= ~LIB_ID_FREE_NO_USER_REFCOUNT; + } + + if ((id->tag & LIB_TAG_NOT_ALLOCATED) != 0) { + flag |= LIB_ID_FREE_NOT_ALLOCATED; + } + else { + flag &= ~LIB_ID_FREE_NOT_ALLOCATED; + } + } + + BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || bmain != NULL); + BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NOT_ALLOCATED) == 0); + BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0); + + const short type = GS(id->name); + + if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) { + DAG_id_type_tag(bmain, type); + } + +#ifdef WITH_PYTHON + BPY_id_release(id); +#endif + + if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) { + BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); + } + + BKE_libblock_free_datablock(id, flag); + + /* avoid notifying on removed data */ + if (bmain) { + BKE_main_lock(bmain); + } + + if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) { + if (free_notifier_reference_cb) { + free_notifier_reference_cb(id); + } + + if (remap_editor_id_reference_cb) { + remap_editor_id_reference_cb(id, NULL); + } + } + + if ((flag & LIB_ID_FREE_NO_MAIN) == 0) { + ListBase *lb = which_libbase(bmain, type); + BLI_remlink(lb, id); + } + + BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0); + + if (bmain) { + BKE_main_unlock(bmain); + } + + if ((flag & LIB_ID_FREE_NOT_ALLOCATED) == 0) { + MEM_freeN(id); + } +} + +void BKE_id_free(Main *bmain, void *idv) +{ + BKE_id_free_ex(bmain, idv, 0, true); +} + /** * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c * @@ -866,7 +952,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); } - BKE_libblock_free_datablock(id); + BKE_libblock_free_datablock(id, 0); /* avoid notifying on removed data */ BKE_main_lock(bmain); diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 771e81ddc4f..1b1a12e702a 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -119,7 +119,7 @@ FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name) { FreestyleLineStyle *linestyle; - linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(bmain, ID_LS, name); + linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(bmain, ID_LS, name, 0); BKE_linestyle_init(linestyle); @@ -155,73 +155,54 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle) BKE_linestyle_geometry_modifier_remove(linestyle, m); } -FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle) +/** + * Only copy internal data of Linestyle ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_linestyle_copy_data( + struct Main *bmain, FreestyleLineStyle *linestyle_dst, const FreestyleLineStyle *linestyle_src, const int flag) { - FreestyleLineStyle *new_linestyle; - LineStyleModifier *m; - int a; + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; - new_linestyle = BKE_linestyle_new(bmain, linestyle->id.name + 2); - BKE_linestyle_free(new_linestyle); - - for (a = 0; a < MAX_MTEX; a++) { - if (linestyle->mtex[a]) { - new_linestyle->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_linestyle_copy"); - memcpy(new_linestyle->mtex[a], linestyle->mtex[a], sizeof(MTex)); - id_us_plus((ID *)new_linestyle->mtex[a]->tex); + for (int a = 0; a < MAX_MTEX; a++) { + if (linestyle_src->mtex[a]) { + linestyle_dst->mtex[a] = MEM_mallocN(sizeof(*linestyle_dst->mtex[a]), __func__); + *linestyle_dst->mtex[a] = *linestyle_src->mtex[a]; } } - if (linestyle->nodetree) { - new_linestyle->nodetree = ntreeCopyTree(bmain, linestyle->nodetree); + if (linestyle_src->nodetree) { + BKE_id_copy_ex(bmain, (ID *)linestyle_src->nodetree, (ID **)&linestyle_dst->nodetree, flag, false); } - new_linestyle->r = linestyle->r; - new_linestyle->g = linestyle->g; - new_linestyle->b = linestyle->b; - new_linestyle->alpha = linestyle->alpha; - new_linestyle->thickness = linestyle->thickness; - new_linestyle->thickness_position = linestyle->thickness_position; - new_linestyle->thickness_ratio = linestyle->thickness_ratio; - new_linestyle->flag = linestyle->flag; - new_linestyle->caps = linestyle->caps; - new_linestyle->chaining = linestyle->chaining; - new_linestyle->rounds = linestyle->rounds; - new_linestyle->split_length = linestyle->split_length; - new_linestyle->min_angle = linestyle->min_angle; - new_linestyle->max_angle = linestyle->max_angle; - new_linestyle->min_length = linestyle->min_length; - new_linestyle->max_length = linestyle->max_length; - new_linestyle->chain_count = linestyle->chain_count; - new_linestyle->split_dash1 = linestyle->split_dash1; - new_linestyle->split_gap1 = linestyle->split_gap1; - new_linestyle->split_dash2 = linestyle->split_dash2; - new_linestyle->split_gap2 = linestyle->split_gap2; - new_linestyle->split_dash3 = linestyle->split_dash3; - new_linestyle->split_gap3 = linestyle->split_gap3; - new_linestyle->dash1 = linestyle->dash1; - new_linestyle->gap1 = linestyle->gap1; - new_linestyle->dash2 = linestyle->dash2; - new_linestyle->gap2 = linestyle->gap2; - new_linestyle->dash3 = linestyle->dash3; - new_linestyle->gap3 = linestyle->gap3; - new_linestyle->panel = linestyle->panel; - new_linestyle->sort_key = linestyle->sort_key; - new_linestyle->integration_type = linestyle->integration_type; - new_linestyle->texstep = linestyle->texstep; - new_linestyle->pr_texture = linestyle->pr_texture; - new_linestyle->use_nodes = linestyle->use_nodes; - for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) - BKE_linestyle_color_modifier_copy(new_linestyle, m); - for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next) - BKE_linestyle_alpha_modifier_copy(new_linestyle, m); - for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next) - BKE_linestyle_thickness_modifier_copy(new_linestyle, m); - for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next) - BKE_linestyle_geometry_modifier_copy(new_linestyle, m); - - BKE_id_copy_ensure_local(bmain, &linestyle->id, &new_linestyle->id); - - return new_linestyle; + LineStyleModifier *m; + BLI_listbase_clear(&linestyle_dst->color_modifiers); + for (m = (LineStyleModifier *)linestyle_src->color_modifiers.first; m; m = m->next) { + BKE_linestyle_color_modifier_copy(linestyle_dst, m, flag_subdata); + } + BLI_listbase_clear(&linestyle_dst->alpha_modifiers); + for (m = (LineStyleModifier *)linestyle_src->alpha_modifiers.first; m; m = m->next) { + BKE_linestyle_alpha_modifier_copy(linestyle_dst, m, flag_subdata); + } + BLI_listbase_clear(&linestyle_dst->thickness_modifiers); + for (m = (LineStyleModifier *)linestyle_src->thickness_modifiers.first; m; m = m->next) { + BKE_linestyle_thickness_modifier_copy(linestyle_dst, m, flag_subdata); + } + BLI_listbase_clear(&linestyle_dst->geometry_modifiers); + for (m = (LineStyleModifier *)linestyle_src->geometry_modifiers.first; m; m = m->next) { + BKE_linestyle_geometry_modifier_copy(linestyle_dst, m, flag_subdata); + } +} + +FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle) +{ + FreestyleLineStyle *linestyle_copy; + BKE_id_copy_ex(bmain, &linestyle->id, (ID **)&linestyle_copy, 0, false); + return linestyle_copy; } void BKE_linestyle_make_local(struct Main *bmain, FreestyleLineStyle *linestyle, const bool lib_local) @@ -355,7 +336,8 @@ LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyl return m; } -LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_color_modifier_copy( + FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag) { LineStyleModifier *new_m; @@ -388,9 +370,10 @@ LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linesty { LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)m; LineStyleColorModifier_DistanceFromObject *q = (LineStyleColorModifier_DistanceFromObject *)new_m; - if (p->target) - id_us_plus(&p->target->id); q->target = p->target; + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)q->target); + } q->color_ramp = MEM_dupallocN(p->color_ramp); q->range_min = p->range_min; q->range_max = p->range_max; @@ -594,7 +577,8 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl return m; } -LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_alpha_modifier_copy( + FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int UNUSED(flag)) { LineStyleModifier *new_m; @@ -863,7 +847,8 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *line return m; } -LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_thickness_modifier_copy( + FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int flag) { LineStyleModifier *new_m; @@ -901,9 +886,10 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *lin { LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)m; LineStyleThicknessModifier_DistanceFromObject *q = (LineStyleThicknessModifier_DistanceFromObject *)new_m; - if (p->target) - id_us_plus(&p->target->id); q->target = p->target; + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)q->target); + } q->curve = curvemapping_copy(p->curve); q->flags = p->flags; q->range_min = p->range_min; @@ -1195,7 +1181,8 @@ LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *lines return m; } -LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_geometry_modifier_copy( + FreestyleLineStyle *linestyle, const LineStyleModifier *m, const int UNUSED(flag)) { LineStyleModifier *new_m; diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index ae27e9bcd34..435bc949af0 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -794,7 +794,7 @@ static Mask *mask_alloc(Main *bmain, const char *name) { Mask *mask; - mask = BKE_libblock_alloc(bmain, ID_MSK, name); + mask = BKE_libblock_alloc(bmain, ID_MSK, name, 0); id_fake_user_set(&mask->id); @@ -821,6 +821,7 @@ Mask *BKE_mask_new(Main *bmain, const char *name) } /* TODO(sergey): Use generic BKE_libblock_copy_nolib() instead. */ +/* TODO(bastien): Use new super cool & generic BKE_id_copy_ex() instead! */ Mask *BKE_mask_copy_nolib(Mask *mask) { Mask *mask_new; @@ -840,22 +841,29 @@ Mask *BKE_mask_copy_nolib(Mask *mask) return mask_new; } -Mask *BKE_mask_copy(Main *bmain, const Mask *mask) +/** + * Only copy internal data of Mask ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_mask_copy_data(Main *UNUSED(bmain), Mask *mask_dst, const Mask *mask_src, const int UNUSED(flag)) { - Mask *mask_new; + BLI_listbase_clear(&mask_dst->masklayers); - mask_new = BKE_libblock_copy(bmain, &mask->id); - - BLI_listbase_clear(&mask_new->masklayers); - - BKE_mask_layer_copy_list(&mask_new->masklayers, &mask->masklayers); + BKE_mask_layer_copy_list(&mask_dst->masklayers, &mask_src->masklayers); /* TODO add unused flag to those as well. */ /* enable fake user by default */ - id_fake_user_set(&mask_new->id); - - BKE_id_copy_ensure_local(bmain, &mask->id, &mask_new->id); + id_fake_user_set(&mask_dst->id); +} - return mask_new; +Mask *BKE_mask_copy(Main *bmain, const Mask *mask) +{ + Mask *mask_copy; + BKE_id_copy_ex(bmain, &mask->id, (ID **)&mask_copy, 0, false); + return mask_copy; } void BKE_mask_make_local(Main *bmain, Mask *mask, const bool lib_local) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index f21efb71180..710af30aa3a 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -212,50 +212,68 @@ Material *BKE_material_add(Main *bmain, const char *name) { Material *ma; - ma = BKE_libblock_alloc(bmain, ID_MA, name); + ma = BKE_libblock_alloc(bmain, ID_MA, name, 0); BKE_material_init(ma); return ma; } -/* XXX keep synced with next function */ -Material *BKE_material_copy(Main *bmain, const Material *ma) +/** + * Only copy internal data of Material ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_src, const int flag) { - Material *man; - int a; - - man = BKE_libblock_copy(bmain, &ma->id); - - id_lib_extern((ID *)man->group); - - for (a = 0; a < MAX_MTEX; a++) { - if (ma->mtex[a]) { - man->mtex[a] = MEM_mallocN(sizeof(MTex), "copymaterial"); - memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex)); - id_us_plus((ID *)man->mtex[a]->tex); + for (int a = 0; a < MAX_MTEX; a++) { + if (ma_src->mtex[a]) { + ma_dst->mtex[a] = MEM_mallocN(sizeof(*ma_dst->mtex[a]), __func__); + *ma_dst->mtex[a] = *ma_src->mtex[a]; } } - - if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col); - if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec); - - if (ma->nodetree) { - man->nodetree = ntreeCopyTree(bmain, ma->nodetree); + + if (ma_src->ramp_col) { + ma_dst->ramp_col = MEM_dupallocN(ma_src->ramp_col); + } + if (ma_src->ramp_spec) { + ma_dst->ramp_spec = MEM_dupallocN(ma_src->ramp_spec); } - BKE_previewimg_id_copy(&man->id, &ma->id); + if (ma_src->nodetree) { + BKE_id_copy_ex(bmain, (ID *)ma_src->nodetree, (ID **)&ma_dst->nodetree, flag, false); + } - BLI_listbase_clear(&man->gpumaterial); + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { + BKE_previewimg_id_copy(&ma_dst->id, &ma_src->id); + } + else { + ma_dst->preview = NULL; + } - BKE_id_copy_ensure_local(bmain, &ma->id, &man->id); + BLI_listbase_clear(&ma_dst->gpumaterial); +} - return man; +Material *BKE_material_copy(Main *bmain, const Material *ma) +{ + Material *ma_copy; + BKE_id_copy_ex(bmain, &ma->id, (ID **)&ma_copy, 0, false); + return ma_copy; } /* XXX (see above) material copy without adding to main dbase */ Material *localize_material(Material *ma) { + /* TODO replace with something like + * Material *ma_copy; + * BKE_id_copy_ex(bmain, &ma->id, (ID **)&ma_copy, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT, false); + * return ma_copy; + * + * ... Once f*** nodes are fully converted to that too :( */ + Material *man; int a; diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index b80579014d6..930e28ab7fb 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -96,33 +96,36 @@ MetaBall *BKE_mball_add(Main *bmain, const char *name) { MetaBall *mb; - mb = BKE_libblock_alloc(bmain, ID_MB, name); + mb = BKE_libblock_alloc(bmain, ID_MB, name, 0); BKE_mball_init(mb); return mb; } -MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb) +/** + * Only copy internal data of MetaBall ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_mball_copy_data(Main *UNUSED(bmain), MetaBall *mb_dst, const MetaBall *mb_src, const int UNUSED(flag)) { - MetaBall *mbn; - int a; - - mbn = BKE_libblock_copy(bmain, &mb->id); + BLI_duplicatelist(&mb_dst->elems, &mb_src->elems); - BLI_duplicatelist(&mbn->elems, &mb->elems); - - mbn->mat = MEM_dupallocN(mb->mat); - for (a = 0; a < mbn->totcol; a++) { - id_us_plus((ID *)mbn->mat[a]); - } + mb_dst->mat = MEM_dupallocN(mb_src->mat); - mbn->editelems = NULL; - mbn->lastelem = NULL; - - BKE_id_copy_ensure_local(bmain, &mb->id, &mbn->id); + mb_dst->editelems = NULL; + mb_dst->lastelem = NULL; +} - return mbn; +MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb) +{ + MetaBall *mb_copy; + BKE_id_copy_ex(bmain, &mb->id, (ID **)&mb_copy, 0, false); + return mb_copy; } void BKE_mball_make_local(Main *bmain, MetaBall *mb, const bool lib_local) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 6233caa43fa..b89541173e1 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -494,53 +494,56 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name) { Mesh *me; - me = BKE_libblock_alloc(bmain, ID_ME, name); + me = BKE_libblock_alloc(bmain, ID_ME, name, 0); BKE_mesh_init(me); return me; } -Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me) +/** + * Only copy internal data of Mesh ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int flag) { - Mesh *men; - int a; - const int do_tessface = ((me->totface != 0) && (me->totpoly == 0)); /* only do tessface if we have no polys */ - - men = BKE_libblock_copy(bmain, &me->id); - - men->mat = MEM_dupallocN(me->mat); - for (a = 0; a < men->totcol; a++) { - id_us_plus((ID *)men->mat[a]); - } - id_us_plus((ID *)men->texcomesh); + const bool do_tessface = ((me_src->totface != 0) && (me_src->totpoly == 0)); /* only do tessface if we have no polys */ - CustomData_copy(&me->vdata, &men->vdata, CD_MASK_MESH, CD_DUPLICATE, men->totvert); - CustomData_copy(&me->edata, &men->edata, CD_MASK_MESH, CD_DUPLICATE, men->totedge); - CustomData_copy(&me->ldata, &men->ldata, CD_MASK_MESH, CD_DUPLICATE, men->totloop); - CustomData_copy(&me->pdata, &men->pdata, CD_MASK_MESH, CD_DUPLICATE, men->totpoly); + me_dst->mat = MEM_dupallocN(me_src->mat); + + CustomData_copy(&me_src->vdata, &me_dst->vdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totvert); + CustomData_copy(&me_src->edata, &me_dst->edata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totedge); + CustomData_copy(&me_src->ldata, &me_dst->ldata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totloop); + CustomData_copy(&me_src->pdata, &me_dst->pdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totpoly); if (do_tessface) { - CustomData_copy(&me->fdata, &men->fdata, CD_MASK_MESH, CD_DUPLICATE, men->totface); + CustomData_copy(&me_src->fdata, &me_dst->fdata, CD_MASK_MESH, CD_DUPLICATE, me_dst->totface); } else { - mesh_tessface_clear_intern(men, false); + mesh_tessface_clear_intern(me_dst, false); } - BKE_mesh_update_customdata_pointers(men, do_tessface); + BKE_mesh_update_customdata_pointers(me_dst, do_tessface); - men->edit_btmesh = NULL; + me_dst->edit_btmesh = NULL; - men->mselect = MEM_dupallocN(men->mselect); - men->bb = MEM_dupallocN(men->bb); + me_dst->mselect = MEM_dupallocN(me_dst->mselect); + me_dst->bb = MEM_dupallocN(me_dst->bb); - if (me->key) { - men->key = BKE_key_copy(bmain, me->key); - men->key->from = (ID *)men; + /* TODO Do we want to add flag to prevent this? */ + if (me_src->key) { + BKE_id_copy_ex(bmain, &me_src->key->id, (ID **)&me_dst->key, flag, false); } +} - BKE_id_copy_ensure_local(bmain, &me->id, &men->id); - - return men; +Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me) +{ + Mesh *me_copy; + BKE_id_copy_ex(bmain, &me->id, (ID **)&me_copy, 0, false); + return me_copy; } BMesh *BKE_mesh_to_bmesh( @@ -2447,7 +2450,9 @@ Mesh *BKE_mesh_new_from_object( int uv_from_orco; /* copies object and modifiers (but not the data) */ - Object *tmpobj = BKE_object_copy_ex(bmain, ob, true); + Object *tmpobj; + /* TODO: make it temp copy outside bmain! */ + BKE_id_copy_ex(bmain, &ob->id, (ID **)&tmpobj, LIB_ID_COPY_CACHES, false); tmpcu = (Curve *)tmpobj->data; id_us_min(&tmpcu->id); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 2276d56b9c6..118bafa94d2 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -59,6 +59,8 @@ #include "BKE_appdir.h" #include "BKE_key.h" +#include "BKE_library.h" +#include "BKE_library_query.h" #include "BKE_multires.h" #include "BKE_DerivedMesh.h" @@ -269,14 +271,37 @@ void modifier_copyData_generic(const ModifierData *md_src, ModifierData *md_dst) memcpy(md_dst_data, md_src_data, (size_t)mti->structSize - data_size); } -void modifier_copyData(ModifierData *md, ModifierData *target) +static void modifier_copy_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag) +{ + ID *id = *idpoin; + if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) { + id_us_plus(id); + } +} + +void modifier_copyData_ex(ModifierData *md, ModifierData *target, const int flag) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); target->mode = md->mode; - if (mti->copyData) + if (mti->copyData) { mti->copyData(md, target); + } + + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + if (mti->foreachIDLink) { + mti->foreachIDLink(target, NULL, modifier_copy_data_id_us_cb, NULL); + } + else if (mti->foreachObjectLink) { + mti->foreachObjectLink(target, NULL, (ObjectWalkFunc)modifier_copy_data_id_us_cb, NULL); + } + } +} + +void modifier_copyData(ModifierData *md, ModifierData *target) +{ + modifier_copyData_ex(md, target, 0); } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index dfa8742a295..16d597e25fa 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -588,7 +588,7 @@ static MovieClip *movieclip_alloc(Main *bmain, const char *name) { MovieClip *clip; - clip = BKE_libblock_alloc(bmain, ID_MC, name); + clip = BKE_libblock_alloc(bmain, ID_MC, name, 0); clip->aspx = clip->aspy = 1.0f; @@ -1488,25 +1488,33 @@ void BKE_movieclip_free(MovieClip *clip) BKE_animdata_free((ID *) clip, false); } -MovieClip *BKE_movieclip_copy(Main *bmain, const MovieClip *clip) +/** + * Only copy internal data of MovieClip ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_movieclip_copy_data(Main *UNUSED(bmain), MovieClip *clip_dst, const MovieClip *clip_src, const int flag) { - MovieClip *clip_new; - - clip_new = BKE_libblock_copy(bmain, &clip->id); + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; - clip_new->anim = NULL; - clip_new->cache = NULL; + clip_dst->anim = NULL; + clip_dst->cache = NULL; - BKE_tracking_copy(&clip_new->tracking, &clip->tracking); - clip_new->tracking_context = NULL; + BKE_tracking_copy(&clip_dst->tracking, &clip_src->tracking, flag_subdata); + clip_dst->tracking_context = NULL; - id_us_plus((ID *)clip_new->gpd); - - BKE_color_managed_colorspace_settings_copy(&clip_new->colorspace_settings, &clip->colorspace_settings); - - BKE_id_copy_ensure_local(bmain, &clip->id, &clip_new->id); + BKE_color_managed_colorspace_settings_copy(&clip_dst->colorspace_settings, &clip_src->colorspace_settings); +} - return clip_new; +MovieClip *BKE_movieclip_copy(Main *bmain, const MovieClip *clip) +{ + MovieClip *clip_copy; + BKE_id_copy_ex(bmain, &clip->id, (ID **)&clip_copy, 0, false); + return clip_copy; } void BKE_movieclip_make_local(Main *bmain, MovieClip *clip, const bool lib_local) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 5acfe4a0aa4..b11b328a01c 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -902,80 +902,100 @@ bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type) return nodeAddNode(C, ntree, idname); } -static void node_socket_copy(bNodeSocket *dst, bNodeSocket *src) +static void node_socket_copy(bNodeSocket *sock_dst, bNodeSocket *sock_src, const int flag) { - src->new_sock = dst; - - if (src->prop) - dst->prop = IDP_CopyProperty(src->prop); - - if (src->default_value) - dst->default_value = MEM_dupallocN(src->default_value); - - dst->stack_index = 0; + sock_src->new_sock = sock_dst; + + if (sock_src->prop) { + sock_dst->prop = IDP_CopyProperty_ex(sock_src->prop, flag); + } + + if (sock_src->default_value) { + sock_dst->default_value = MEM_dupallocN(sock_src->default_value); + } + + sock_dst->stack_index = 0; /* XXX some compositor node (e.g. image, render layers) still store * some persistent buffer data here, need to clear this to avoid dangling pointers. */ - dst->cache = NULL; + sock_dst->cache = NULL; } /* keep socket listorder identical, for copying links */ /* ntree is the target tree */ -bNode *nodeCopyNode(bNodeTree *ntree, bNode *node) +bNode *BKE_node_copy_ex(bNodeTree *ntree, bNode *node_src, const int flag) { - bNode *nnode = MEM_callocN(sizeof(bNode), "dupli node"); - bNodeSocket *sock, *oldsock; - bNodeLink *link, *oldlink; + bNode *node_dst = MEM_callocN(sizeof(bNode), "dupli node"); + bNodeSocket *sock_dst, *sock_src; + bNodeLink *link_dst, *link_src; - *nnode = *node; + *node_dst = *node_src; /* can be called for nodes outside a node tree (e.g. clipboard) */ if (ntree) { - nodeUniqueName(ntree, nnode); + nodeUniqueName(ntree, node_dst); - BLI_addtail(&ntree->nodes, nnode); + BLI_addtail(&ntree->nodes, node_dst); } - BLI_duplicatelist(&nnode->inputs, &node->inputs); - oldsock = node->inputs.first; - for (sock = nnode->inputs.first; sock; sock = sock->next, oldsock = oldsock->next) - node_socket_copy(sock, oldsock); - - BLI_duplicatelist(&nnode->outputs, &node->outputs); - oldsock = node->outputs.first; - for (sock = nnode->outputs.first; sock; sock = sock->next, oldsock = oldsock->next) - node_socket_copy(sock, oldsock); - - if (node->prop) - nnode->prop = IDP_CopyProperty(node->prop); - - BLI_duplicatelist(&nnode->internal_links, &node->internal_links); - oldlink = node->internal_links.first; - for (link = nnode->internal_links.first; link; link = link->next, oldlink = oldlink->next) { - link->fromnode = nnode; - link->tonode = nnode; - link->fromsock = link->fromsock->new_sock; - link->tosock = link->tosock->new_sock; + BLI_duplicatelist(&node_dst->inputs, &node_src->inputs); + for (sock_dst = node_dst->inputs.first, sock_src = node_src->inputs.first; + sock_dst != NULL; + sock_dst = sock_dst->next, sock_src = sock_src->next) + { + node_socket_copy(sock_dst, sock_src, flag); } - - /* don't increase node->id users, freenode doesn't decrement either */ - - if (node->typeinfo->copyfunc) - node->typeinfo->copyfunc(ntree, nnode, node); - - node->new_node = nnode; - nnode->new_node = NULL; - - if (nnode->typeinfo->copyfunc_api) { + + BLI_duplicatelist(&node_dst->outputs, &node_src->outputs); + for (sock_dst = node_dst->outputs.first, sock_src = node_src->outputs.first; + sock_dst != NULL; + sock_dst = sock_dst->next, sock_src = sock_src->next) + { + node_socket_copy(sock_dst, sock_src, flag); + } + + if (node_src->prop) { + node_dst->prop = IDP_CopyProperty_ex(node_src->prop, flag); + } + + BLI_duplicatelist(&node_dst->internal_links, &node_src->internal_links); + for (link_dst = node_dst->internal_links.first, link_src = node_src->internal_links.first; + link_dst != NULL; + link_dst = link_dst->next, link_src = link_src->next) + { + link_dst->fromnode = node_dst; + link_dst->tonode = node_dst; + link_dst->fromsock = link_dst->fromsock->new_sock; + link_dst->tosock = link_dst->tosock->new_sock; + } + + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus(node_dst->id); + } + + if (node_src->typeinfo->copyfunc) { + node_src->typeinfo->copyfunc(ntree, node_dst, node_src); + } + + node_src->new_node = node_dst; + node_dst->new_node = NULL; + + if (node_dst->typeinfo->copyfunc_api) { PointerRNA ptr; - RNA_pointer_create((ID *)ntree, &RNA_Node, nnode, &ptr); - - nnode->typeinfo->copyfunc_api(&ptr, node); + RNA_pointer_create((ID *)ntree, &RNA_Node, node_dst, &ptr); + + node_dst->typeinfo->copyfunc_api(&ptr, node_src); } - - if (ntree) + + if (ntree) { ntree->update |= NTREE_UPDATE_NODES; - - return nnode; + } + + return node_dst; +} + +bNode *nodeCopyNode(bNodeTree *ntree, bNode *node) +{ + return BKE_node_copy_ex(ntree, node, LIB_ID_CREATE_NO_USER_REFCOUNT); } /* also used via rna api, so we check for proper input output direction */ @@ -1172,7 +1192,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) * node groups and other tree types are created as library data. */ if (bmain) { - ntree = BKE_libblock_alloc(bmain, ID_NT, name); + ntree = BKE_libblock_alloc(bmain, ID_NT, name, 0); } else { ntree = MEM_callocN(sizeof(bNodeTree), "new node tree"); @@ -1191,119 +1211,101 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) return ntree; } -/* Warning: this function gets called during some rather unexpected times - * - this gets called when executing compositing updates (for threaded previews) - * - when the nodetree datablock needs to be copied (i.e. when users get copied) - * - for scene duplication use ntreeSwapID() after so we don't have stale pointers. +/** + * Only copy internal data of NodeTree ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. * - * do_make_extern: keep enabled for general use, only reason _not_ to enable is when - * copying for internal use (threads for eg), where you wont want it to modify the - * scene data. + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */ -static bNodeTree *ntreeCopyTree_internal( - const bNodeTree *ntree, Main *bmain, - bool skip_database, bool do_id_user, bool do_make_extern, bool copy_previews) +void BKE_node_tree_copy_data(Main *UNUSED(bmain), bNodeTree *ntree_dst, const bNodeTree *ntree_src, const int flag) { - bNodeTree *newtree; - bNode *node /*, *nnode */ /* UNUSED */, *last; - bNodeSocket *sock, *oldsock; - bNodeLink *link; - - if (ntree == NULL) return NULL; - - /* is ntree part of library? */ - if (bmain && !skip_database && BLI_findindex(&bmain->nodetree, ntree) >= 0) { - newtree = BKE_libblock_copy(bmain, &ntree->id); - } - else { - newtree = BKE_libblock_copy_nolib(&ntree->id, true); - } + bNode *node_src; + bNodeSocket *sock_dst, *sock_src; + bNodeLink *link_dst; - id_us_plus((ID *)newtree->gpd); + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; - /* in case a running nodetree is copied */ - newtree->execdata = NULL; + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)ntree_dst->gpd); + } - newtree->duplilock = NULL; - - BLI_listbase_clear(&newtree->nodes); - BLI_listbase_clear(&newtree->links); - - last = ntree->nodes.last; - for (node = ntree->nodes.first; node; node = node->next) { + /* in case a running nodetree is copied */ + ntree_dst->execdata = NULL; - /* ntreeUserDecrefID inline */ - if (do_id_user) { - id_us_plus(node->id); - } + ntree_dst->duplilock = NULL; - if (do_make_extern) { - id_lib_extern(node->id); - } + BLI_listbase_clear(&ntree_dst->nodes); + BLI_listbase_clear(&ntree_dst->links); - node->new_node = NULL; - /* nnode = */ nodeCopyNode(newtree, node); /* sets node->new */ - - /* make sure we don't copy new nodes again! */ - if (node == last) - break; + for (node_src = ntree_src->nodes.first; node_src; node_src = node_src->next) { + BKE_node_copy_ex(ntree_dst, node_src, flag_subdata); } - + /* copy links */ - BLI_duplicatelist(&newtree->links, &ntree->links); - for (link = newtree->links.first; link; link = link->next) { - link->fromnode = (link->fromnode ? link->fromnode->new_node : NULL); - link->fromsock = (link->fromsock ? link->fromsock->new_sock : NULL); - link->tonode = (link->tonode ? link->tonode->new_node : NULL); - link->tosock = (link->tosock ? link->tosock->new_sock : NULL); + BLI_duplicatelist(&ntree_dst->links, &ntree_src->links); + for (link_dst = ntree_dst->links.first; link_dst; link_dst = link_dst->next) { + link_dst->fromnode = (link_dst->fromnode ? link_dst->fromnode->new_node : NULL); + link_dst->fromsock = (link_dst->fromsock ? link_dst->fromsock->new_sock : NULL); + link_dst->tonode = (link_dst->tonode ? link_dst->tonode->new_node : NULL); + link_dst->tosock = (link_dst->tosock ? link_dst->tosock->new_sock : NULL); /* update the link socket's pointer */ - if (link->tosock) - link->tosock->link = link; + if (link_dst->tosock) { + link_dst->tosock->link = link_dst; + } } - + /* copy interface sockets */ - BLI_duplicatelist(&newtree->inputs, &ntree->inputs); - oldsock = ntree->inputs.first; - for (sock = newtree->inputs.first; sock; sock = sock->next, oldsock = oldsock->next) - node_socket_copy(sock, oldsock); - - BLI_duplicatelist(&newtree->outputs, &ntree->outputs); - oldsock = ntree->outputs.first; - for (sock = newtree->outputs.first; sock; sock = sock->next, oldsock = oldsock->next) - node_socket_copy(sock, oldsock); - + BLI_duplicatelist(&ntree_dst->inputs, &ntree_src->inputs); + for (sock_dst = ntree_dst->inputs.first, sock_src = ntree_src->inputs.first; + sock_dst != NULL; + sock_dst = sock_dst->next, sock_src = sock_src->next) + { + node_socket_copy(sock_dst, sock_src, flag_subdata); + } + + BLI_duplicatelist(&ntree_dst->outputs, &ntree_src->outputs); + for (sock_dst = ntree_dst->outputs.first, sock_src = ntree_src->outputs.first; + sock_dst != NULL; + sock_dst = sock_dst->next, sock_src = sock_src->next) + { + node_socket_copy(sock_dst, sock_src, flag_subdata); + } + /* copy preview hash */ - if (ntree->previews && copy_previews) { + if (ntree_src->previews && (flag & LIB_ID_COPY_NO_PREVIEW) == 0) { bNodeInstanceHashIterator iter; - - newtree->previews = BKE_node_instance_hash_new("node previews"); - - NODE_INSTANCE_HASH_ITER(iter, ntree->previews) { + + ntree_dst->previews = BKE_node_instance_hash_new("node previews"); + + NODE_INSTANCE_HASH_ITER(iter, ntree_src->previews) { bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); - BKE_node_instance_hash_insert(newtree->previews, key, BKE_node_preview_copy(preview)); + BKE_node_instance_hash_insert(ntree_dst->previews, key, BKE_node_preview_copy(preview)); } } - else - newtree->previews = NULL; - + else { + ntree_dst->previews = NULL; + } + /* update node->parent pointers */ - for (node = newtree->nodes.first; node; node = node->next) { - if (node->parent) - node->parent = node->parent->new_node; + for (node_src = ntree_dst->nodes.first; node_src; node_src = node_src->next) { + if (node_src->parent) { + node_src->parent = node_src->parent->new_node; + } } - - /* node tree will generate its own interface type */ - newtree->interface_type = NULL; - - BKE_id_copy_ensure_local(bmain, &ntree->id, &newtree->id); - return newtree; + /* node tree will generate its own interface type */ + ntree_dst->interface_type = NULL; } bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user) { - return ntreeCopyTree_internal(ntree, bmain, false, do_id_user, true, true); + bNodeTree *ntree_copy; + BKE_id_copy_ex(bmain, (ID *)ntree, (ID **)&ntree_copy, do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT, false); + return ntree_copy; } bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree) { @@ -1994,10 +1996,11 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) adt->tmpact = NULL; } - /* Make full copy. + /* Make full copy outside of Main database. * Note: previews are not copied here. */ - ltree = ntreeCopyTree_internal(ntree, G.main, true, false, false, false); + BKE_id_copy_ex(G.main, (ID *)ntree, (ID **)<ree, + LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_COPY_NO_PREVIEW, false); ltree->flag |= NTREE_IS_LOCALIZED; for (node = ltree->nodes.first; node; node = node->next) { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index f3086396c3a..cb851d2f955 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -312,7 +312,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr modifier_unique_name(&ob_dst->modifiers, nmd); } - BKE_object_copy_particlesystems(ob_dst, ob_src); + BKE_object_copy_particlesystems(ob_dst, ob_src, 0); /* TODO: smoke?, cloth? */ } @@ -670,7 +670,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) if (!name) name = get_obdata_defname(type); - ob = BKE_libblock_alloc(bmain, ID_OB, name); + ob = BKE_libblock_alloc(bmain, ID_OB, name, 0); /* default object vars */ ob->type = type; @@ -837,7 +837,7 @@ struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene) #endif /* WITH_GAMEENGINE */ -SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches) +SoftBody *copy_softbody(const SoftBody *sb, const int flag) { SoftBody *sbn; @@ -845,7 +845,7 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches) sbn = MEM_dupallocN(sb); - if (copy_caches == false) { + if ((flag & LIB_ID_COPY_CACHES) == 0) { sbn->totspring = sbn->totpoint = 0; sbn->bpoint = NULL; sbn->bspring = NULL; @@ -874,7 +874,7 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches) sbn->scratch = NULL; - sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, copy_caches); + sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, flag); if (sb->effector_weights) sbn->effector_weights = MEM_dupallocN(sb->effector_weights); @@ -882,7 +882,7 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches) return sbn; } -BulletSoftBody *copy_bulletsoftbody(const BulletSoftBody *bsb) +BulletSoftBody *copy_bulletsoftbody(const BulletSoftBody *bsb, const int UNUSED(flag)) { BulletSoftBody *bsbn; @@ -893,7 +893,7 @@ BulletSoftBody *copy_bulletsoftbody(const BulletSoftBody *bsb) return bsbn; } -ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys) +ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int flag) { ParticleSystem *psysn; ParticleData *pa; @@ -930,7 +930,7 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys) if (psys->clmd) { psysn->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); - modifier_copyData((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd); + modifier_copyData_ex((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd, flag); psys->hair_in_dm = psys->hair_out_dm = NULL; } @@ -948,7 +948,8 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys) BLI_listbase_clear(&psysn->childcachebufs); psysn->renderdata = NULL; - psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, false); + /* XXX Never copy caches here? */ + psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag & ~LIB_ID_COPY_CACHES); /* XXX - from reading existing code this seems correct but intended usage of * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */ @@ -956,12 +957,14 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys) psysn->clmd->point_cache = psysn->pointcache; } - id_us_plus((ID *)psysn->part); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)psysn->part); + } return psysn; } -void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src) +void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src, const int flag) { ParticleSystem *psys, *npsys; ModifierData *md; @@ -973,7 +976,7 @@ void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src) BLI_listbase_clear(&ob_dst->particlesystem); for (psys = ob_src->particlesystem.first; psys; psys = psys->next) { - npsys = BKE_object_copy_particlesystem(psys); + npsys = BKE_object_copy_particlesystem(psys, flag); BLI_addtail(&ob_dst->particlesystem, npsys); @@ -1010,23 +1013,25 @@ void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src) { if (ob_src->soft) { ob_dst->softflag = ob_src->softflag; - ob_dst->soft = copy_softbody(ob_src->soft, false); + ob_dst->soft = copy_softbody(ob_src->soft, 0); } } -static void copy_object_pose(Object *obn, const Object *ob) +static void copy_object_pose(Object *obn, const Object *ob, const int flag) { bPoseChannel *chan; /* note: need to clear obn->pose pointer first, so that BKE_pose_copy_data works (otherwise there's a crash) */ obn->pose = NULL; - BKE_pose_copy_data(&obn->pose, ob->pose, 1); /* 1 = copy constraints */ + BKE_pose_copy_data_ex(&obn->pose, ob->pose, flag, true); /* true = copy constraints */ for (chan = obn->pose->chanbase.first; chan; chan = chan->next) { bConstraint *con; chan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE); + /* XXX Remapping object pointing onto itself should be handled by generic BKE_library_remap stuff, but... + * the flush_constraint_targets callback am not sure about, so will delay that for now. */ for (con = chan->constraints.first; con; con = con->next) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; @@ -1047,13 +1052,10 @@ static void copy_object_pose(Object *obn, const Object *ob) } } -static void copy_object_lod(Object *obn, const Object *ob) +static void copy_object_lod(Object *obn, const Object *ob, const int UNUSED(flag)) { BLI_duplicatelist(&obn->lodlevels, &ob->lodlevels); - if (obn->lodlevels.first) - ((LodLevel *)obn->lodlevels.first)->source = obn; - obn->currentlod = (LodLevel *)obn->lodlevels.first; } @@ -1098,98 +1100,99 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src) copy_v3_v3(ob_tar->size, ob_src->size); } -Object *BKE_object_copy_ex(Main *bmain, const Object *ob, bool copy_caches) +/** + * Only copy internal data of Object ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_src, const int flag) { - Object *obn; ModifierData *md; - int a; - obn = BKE_libblock_copy(bmain, &ob->id); - - if (ob->totcol) { - obn->mat = MEM_dupallocN(ob->mat); - obn->matbits = MEM_dupallocN(ob->matbits); - obn->totcol = ob->totcol; + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + + if (ob_src->totcol) { + ob_dst->mat = MEM_dupallocN(ob_src->mat); + ob_dst->matbits = MEM_dupallocN(ob_src->matbits); + ob_dst->totcol = ob_src->totcol; } - if (ob->iuser) obn->iuser = MEM_dupallocN(ob->iuser); + if (ob_src->iuser) ob_dst->iuser = MEM_dupallocN(ob_src->iuser); - if (ob->bb) obn->bb = MEM_dupallocN(ob->bb); - obn->flag &= ~OB_FROMGROUP; + if (ob_src->bb) ob_dst->bb = MEM_dupallocN(ob_src->bb); + ob_dst->flag &= ~OB_FROMGROUP; - BLI_listbase_clear(&obn->modifiers); + BLI_listbase_clear(&ob_dst->modifiers); - for (md = ob->modifiers.first; md; md = md->next) { + for (md = ob_src->modifiers.first; md; md = md->next) { ModifierData *nmd = modifier_new(md->type); BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); - modifier_copyData(md, nmd); - BLI_addtail(&obn->modifiers, nmd); + modifier_copyData_ex(md, nmd, flag_subdata); + BLI_addtail(&ob_dst->modifiers, nmd); } - BLI_listbase_clear(&obn->prop); - BKE_bproperty_copy_list(&obn->prop, &ob->prop); + BLI_listbase_clear(&ob_dst->prop); + BKE_bproperty_copy_list(&ob_dst->prop, &ob_src->prop); - BKE_sca_logic_copy(obn, ob); + BKE_sca_logic_copy(ob_dst, ob_src, flag_subdata); - if (ob->pose) { - copy_object_pose(obn, ob); + if (ob_src->pose) { + copy_object_pose(ob_dst, ob_src, flag_subdata); /* backwards compat... non-armatures can get poses in older files? */ - if (ob->type == OB_ARMATURE) - BKE_pose_rebuild(obn, obn->data); + if (ob_src->type == OB_ARMATURE) + BKE_pose_rebuild(ob_dst, ob_dst->data); } - defgroup_copy_list(&obn->defbase, &ob->defbase); - BKE_constraints_copy(&obn->constraints, &ob->constraints, true); - - obn->mode = OB_MODE_OBJECT; - obn->sculpt = NULL; + defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase); + BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true); - /* increase user numbers */ - id_us_plus((ID *)obn->data); - id_us_plus((ID *)obn->poselib); - id_us_plus((ID *)obn->gpd); - id_us_plus((ID *)obn->dup_group); + ob_dst->mode = OB_MODE_OBJECT; + ob_dst->sculpt = NULL; - for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); - - if (ob->pd) { - obn->pd = MEM_dupallocN(ob->pd); - if (obn->pd->tex) - id_us_plus(&(obn->pd->tex->id)); - if (obn->pd->rng) - obn->pd->rng = MEM_dupallocN(ob->pd->rng); + if (ob_src->pd) { + ob_dst->pd = MEM_dupallocN(ob_src->pd); + if (ob_dst->pd->rng) { + ob_dst->pd->rng = MEM_dupallocN(ob_src->pd->rng); + } } - obn->soft = copy_softbody(ob->soft, copy_caches); - obn->bsoft = copy_bulletsoftbody(ob->bsoft); - obn->rigidbody_object = BKE_rigidbody_copy_object(ob); - obn->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob); + ob_dst->soft = copy_softbody(ob_src->soft, flag_subdata); + ob_dst->bsoft = copy_bulletsoftbody(ob_src->bsoft, flag_subdata); + ob_dst->rigidbody_object = BKE_rigidbody_copy_object(ob_src, flag_subdata); + ob_dst->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob_src, flag_subdata); - BKE_object_copy_particlesystems(obn, ob); + BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata); - obn->derivedDeform = NULL; - obn->derivedFinal = NULL; + ob_dst->derivedDeform = NULL; + ob_dst->derivedFinal = NULL; - BLI_listbase_clear(&obn->gpulamp); - BLI_listbase_clear(&obn->pc_ids); + BLI_listbase_clear(&ob_dst->gpulamp); + BLI_listbase_clear(&ob_dst->pc_ids); - obn->mpath = NULL; + ob_dst->mpath = NULL; - copy_object_lod(obn, ob); + copy_object_lod(ob_dst, ob_src, flag_subdata); - /* Copy runtime surve data. */ - obn->curve_cache = NULL; - - BKE_id_copy_ensure_local(bmain, &ob->id, &obn->id); + /* Do not copy runtime curve data. */ + ob_dst->curve_cache = NULL; /* Do not copy object's preview (mostly due to the fact renderers create temp copy of objects). */ - obn->preview = NULL; - - return obn; + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ + BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id); + } + else { + ob_dst->preview = NULL; + } } /* copy objects, will re-initialize cached simulation data */ Object *BKE_object_copy(Main *bmain, const Object *ob) { - return BKE_object_copy_ex(bmain, ob, false); + Object *ob_copy; + BKE_id_copy_ex(bmain, &ob->id, (ID **)&ob_copy, 0, false); + return ob_copy; } void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, const bool clear_proxy) @@ -1387,7 +1390,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob) /* type conversions */ if (target->type == OB_ARMATURE) { - copy_object_pose(ob, target); /* data copy, object pointers in constraints */ + copy_object_pose(ob, target, 0); /* data copy, object pointers in constraints */ BKE_pose_rest(ob->pose); /* clear all transforms in channels */ BKE_pose_rebuild(ob, ob->data); /* set all internal links */ diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index c7cfe55f659..9fc2136df86 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -309,24 +309,31 @@ PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name) { PaintCurve *pc; - pc = BKE_libblock_alloc(bmain, ID_PC, name); + pc = BKE_libblock_alloc(bmain, ID_PC, name, 0); return pc; } -PaintCurve *BKE_paint_curve_copy(Main *bmain, const PaintCurve *pc) +/** + * Only copy internal data of PaintCurve ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_paint_curve_copy_data(Main *UNUSED(bmain), PaintCurve *pc_dst, const PaintCurve *pc_src, const int UNUSED(flag)) { - PaintCurve *pc_new; - - pc_new = BKE_libblock_copy(bmain, &pc->id); - - if (pc->tot_points != 0) { - pc_new->points = MEM_dupallocN(pc->points); + if (pc_src->tot_points != 0) { + pc_dst->points = MEM_dupallocN(pc_src->points); } +} - BKE_id_copy_ensure_local(bmain, &pc->id, &pc_new->id); - - return pc_new; +PaintCurve *BKE_paint_curve_copy(Main *bmain, const PaintCurve *pc) +{ + PaintCurve *pc_copy; + BKE_id_copy_ex(bmain, &pc->id, (ID **)&pc_copy, 0, false); + return pc_copy; } void BKE_paint_curve_make_local(Main *bmain, PaintCurve *pc, const bool lib_local) @@ -388,7 +395,7 @@ Palette *BKE_palette_add(Main *bmain, const char *name) { Palette *palette; - palette = BKE_libblock_alloc(bmain, ID_PAL, name); + palette = BKE_libblock_alloc(bmain, ID_PAL, name, 0); /* enable fake user by default */ id_fake_user_set(&palette->id); @@ -396,17 +403,24 @@ Palette *BKE_palette_add(Main *bmain, const char *name) return palette; } -Palette *BKE_palette_copy(Main *bmain, const Palette *palette) +/** + * Only copy internal data of Palette ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_palette_copy_data(Main *UNUSED(bmain), Palette *palette_dst, const Palette *palette_src, const int UNUSED(flag)) { - Palette *palette_new; - - palette_new = BKE_libblock_copy(bmain, &palette->id); - - BLI_duplicatelist(&palette_new->colors, &palette->colors); - - BKE_id_copy_ensure_local(bmain, &palette->id, &palette_new->id); + BLI_duplicatelist(&palette_dst->colors, &palette_src->colors); +} - return palette_new; +Palette *BKE_palette_copy(Main *bmain, const Palette *palette) +{ + Palette *palette_copy; + BKE_id_copy_ex(bmain, &palette->id, (ID **)&palette_copy, 0, false); + return palette_copy; } void BKE_palette_make_local(Main *bmain, Palette *palette, const bool lib_local) @@ -537,12 +551,15 @@ void BKE_paint_free(Paint *paint) * still do a id_us_plus(), rather then if we were copying between 2 existing * scenes where a matching value should decrease the existing user count as * with paint_brush_set() */ -void BKE_paint_copy(Paint *src, Paint *tar) +void BKE_paint_copy(Paint *src, Paint *tar, const int flag) { tar->brush = src->brush; - id_us_plus((ID *)tar->brush); - id_us_plus((ID *)tar->palette); tar->cavity_curve = curvemapping_copy(src->cavity_curve); + + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)tar->brush); + id_us_plus((ID *)tar->palette); + } } void BKE_paint_stroke_get_average(Scene *scene, Object *ob, float stroke[3]) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 416d63cfefb..8c94cdfe784 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3300,7 +3300,7 @@ ParticleSettings *psys_new_settings(const char *name, Main *main) if (main == NULL) main = G.main; - part = BKE_libblock_alloc(main, ID_PA, name); + part = BKE_libblock_alloc(main, ID_PA, name, 0); default_particle_settings(part); @@ -3331,38 +3331,45 @@ void BKE_particlesettings_rough_curve_init(ParticleSettings *part) part->roughcurve = cumap; } -ParticleSettings *BKE_particlesettings_copy(Main *bmain, const ParticleSettings *part) +/** + * Only copy internal data of ParticleSettings ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_particlesettings_copy_data( + Main *UNUSED(bmain), ParticleSettings *part_dst, const ParticleSettings *part_src, const int UNUSED(flag)) { - ParticleSettings *partn; - int a; + part_dst->pd = MEM_dupallocN(part_src->pd); + part_dst->pd2 = MEM_dupallocN(part_src->pd2); + part_dst->effector_weights = MEM_dupallocN(part_src->effector_weights); + part_dst->fluid = MEM_dupallocN(part_src->fluid); - partn = BKE_libblock_copy(bmain, &part->id); + if (part_src->clumpcurve) { + part_dst->clumpcurve = curvemapping_copy(part_src->clumpcurve); + } + if (part_src->roughcurve) { + part_dst->roughcurve = curvemapping_copy(part_src->roughcurve); + } - partn->pd = MEM_dupallocN(part->pd); - partn->pd2 = MEM_dupallocN(part->pd2); - partn->effector_weights = MEM_dupallocN(part->effector_weights); - partn->fluid = MEM_dupallocN(part->fluid); + part_dst->boids = boid_copy_settings(part_src->boids); - if (part->clumpcurve) - partn->clumpcurve = curvemapping_copy(part->clumpcurve); - if (part->roughcurve) - partn->roughcurve = curvemapping_copy(part->roughcurve); - - partn->boids = boid_copy_settings(part->boids); - - for (a = 0; a < MAX_MTEX; a++) { - if (part->mtex[a]) { - partn->mtex[a] = MEM_mallocN(sizeof(MTex), "psys_copy_tex"); - memcpy(partn->mtex[a], part->mtex[a], sizeof(MTex)); - id_us_plus((ID *)partn->mtex[a]->tex); + for (int a = 0; a < MAX_MTEX; a++) { + if (part_src->mtex[a]) { + part_dst->mtex[a] = MEM_dupallocN(part_src->mtex[a]); } } - BLI_duplicatelist(&partn->dupliweights, &part->dupliweights); - - BKE_id_copy_ensure_local(bmain, &part->id, &partn->id); + BLI_duplicatelist(&part_dst->dupliweights, &part_src->dupliweights); +} - return partn; +ParticleSettings *BKE_particlesettings_copy(Main *bmain, const ParticleSettings *part) +{ + ParticleSettings *part_copy; + BKE_id_copy_ex(bmain, &part->id, (ID **)&part_copy, 0, false); + return part_copy; } void BKE_particlesettings_make_local(Main *bmain, ParticleSettings *part, const bool lib_local) diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index a7e00a8103a..2a61efcd1f9 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3449,7 +3449,7 @@ void BKE_ptcache_free_list(ListBase *ptcaches) } } -static PointCache *ptcache_copy(PointCache *cache, bool copy_data) +static PointCache *ptcache_copy(PointCache *cache, const bool copy_data) { PointCache *ncache; @@ -3492,14 +3492,15 @@ static PointCache *ptcache_copy(PointCache *cache, bool copy_data) } /* returns first point cache */ -PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcaches_old, bool copy_data) +PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcaches_old, const int flag) { PointCache *cache = ptcaches_old->first; BLI_listbase_clear(ptcaches_new); - for (; cache; cache=cache->next) - BLI_addtail(ptcaches_new, ptcache_copy(cache, copy_data)); + for (; cache; cache=cache->next) { + BLI_addtail(ptcaches_new, ptcache_copy(cache, (flag & LIB_ID_COPY_CACHES) != 0)); + } return ptcaches_new->first; } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index e8c0cf53d0b..5a925af456c 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -184,7 +184,7 @@ void BKE_rigidbody_free_constraint(Object *ob) * be added to relevant groups later... */ -RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob) +RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int UNUSED(flag)) { RigidBodyOb *rboN = NULL; @@ -204,7 +204,7 @@ RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob) return rboN; } -RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob) +RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int UNUSED(flag)) { RigidBodyCon *rbcN = NULL; @@ -945,24 +945,26 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) return rbw; } -RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) +RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw, const int flag) { - RigidBodyWorld *rbwn = MEM_dupallocN(rbw); + RigidBodyWorld *rbw_copy = MEM_dupallocN(rbw); - if (rbw->effector_weights) - rbwn->effector_weights = MEM_dupallocN(rbw->effector_weights); - if (rbwn->group) - id_us_plus(&rbwn->group->id); - if (rbwn->constraints) - id_us_plus(&rbwn->constraints->id); + if (rbw->effector_weights) { + rbw_copy->effector_weights = MEM_dupallocN(rbw->effector_weights); + } + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)rbw_copy->group); + id_us_plus((ID *)rbw_copy->constraints); + } - rbwn->pointcache = BKE_ptcache_copy_list(&rbwn->ptcaches, &rbw->ptcaches, false); + /* XXX Never copy caches here? */ + rbw_copy->pointcache = BKE_ptcache_copy_list(&rbw_copy->ptcaches, &rbw->ptcaches, flag & ~LIB_ID_COPY_CACHES); - rbwn->objects = NULL; - rbwn->physics_world = NULL; - rbwn->numbodies = 0; + rbw_copy->objects = NULL; + rbw_copy->physics_world = NULL; + rbw_copy->numbodies = 0; - return rbwn; + return rbw_copy; } void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw) diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 19d646daf9f..fb81ed4d47f 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -72,7 +72,7 @@ void free_sensors(ListBase *lb) } } -bSensor *copy_sensor(bSensor *sens) +bSensor *copy_sensor(bSensor *sens, const int UNUSED(flag)) { bSensor *sensn; @@ -87,14 +87,14 @@ bSensor *copy_sensor(bSensor *sens) return sensn; } -void copy_sensors(ListBase *lbn, const ListBase *lbo) +void copy_sensors(ListBase *lbn, const ListBase *lbo, const int flag) { bSensor *sens, *sensn; lbn->first= lbn->last= NULL; sens= lbo->first; while (sens) { - sensn= copy_sensor(sens); + sensn= copy_sensor(sens, flag); BLI_addtail(lbn, sensn); sens= sens->next; } @@ -234,7 +234,7 @@ void free_controllers(ListBase *lb) } } -bController *copy_controller(bController *cont) +bController *copy_controller(bController *cont, const int UNUSED(flag)) { bController *contn; @@ -251,14 +251,14 @@ bController *copy_controller(bController *cont) return contn; } -void copy_controllers(ListBase *lbn, const ListBase *lbo) +void copy_controllers(ListBase *lbn, const ListBase *lbo, const int flag) { bController *cont, *contn; lbn->first= lbn->last= NULL; cont= lbo->first; while (cont) { - contn= copy_controller(cont); + contn= copy_controller(cont, flag); BLI_addtail(lbn, contn); cont= cont->next; } @@ -359,7 +359,7 @@ void free_actuators(ListBase *lb) } } -bActuator *copy_actuator(bActuator *act) +bActuator *copy_actuator(bActuator *act, const int flag) { bActuator *actn; @@ -374,29 +374,31 @@ bActuator *copy_actuator(bActuator *act) case ACT_SHAPEACTION: { bActionActuator *aa = (bActionActuator *)act->data; - if (aa->act) + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { id_us_plus((ID *)aa->act); + } break; } case ACT_SOUND: { bSoundActuator *sa = (bSoundActuator *)act->data; - if (sa->sound) + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { id_us_plus((ID *)sa->sound); + } break; } } return actn; } -void copy_actuators(ListBase *lbn, const ListBase *lbo) +void copy_actuators(ListBase *lbn, const ListBase *lbo, const int flag) { bActuator *act, *actn; lbn->first= lbn->last= NULL; act= lbo->first; while (act) { - actn= copy_actuator(act); + actn= copy_actuator(act, flag); BLI_addtail(lbn, actn); act= act->next; } @@ -783,11 +785,11 @@ void BKE_sca_logic_links_remap(Main *bmain, Object *ob_old, Object *ob_new) * Handle the copying of logic data into a new object, including internal logic links update. * External links (links between logic bricks of different objects) must be handled separately. */ -void BKE_sca_logic_copy(Object *ob_new, const Object *ob) +void BKE_sca_logic_copy(Object *ob_new, const Object *ob, const int flag) { - copy_sensors(&ob_new->sensors, &ob->sensors); - copy_controllers(&ob_new->controllers, &ob->controllers); - copy_actuators(&ob_new->actuators, &ob->actuators); + copy_sensors(&ob_new->sensors, &ob->sensors, flag); + copy_controllers(&ob_new->controllers, &ob->controllers, flag); + copy_actuators(&ob_new->actuators, &ob->actuators, flag); for (bSensor *sens = ob_new->sensors.first; sens; sens = sens->next) { if (sens->flag & SENS_NEW) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index a15f270a3ee..9002003d380 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -154,223 +154,316 @@ static void remove_sequencer_fcurves(Scene *sce) } } -Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) -{ - Scene *scen; - SceneRenderLayer *srl, *new_srl; - FreestyleLineSet *lineset; - ToolSettings *ts; - Base *base, *obase; - - if (type == SCE_COPY_EMPTY) { - ListBase rl, rv; - scen = BKE_scene_add(bmain, sce->id.name + 2); - - rl = scen->r.layers; - rv = scen->r.views; - curvemapping_free_data(&scen->r.mblur_shutter_curve); - scen->r = sce->r; - scen->r.layers = rl; - scen->r.actlay = 0; - scen->r.views = rv; - scen->unit = sce->unit; - scen->physics_settings = sce->physics_settings; - scen->gm = sce->gm; - scen->audio = sce->audio; - - if (sce->id.properties) - scen->id.properties = IDP_CopyProperty(sce->id.properties); - - MEM_freeN(scen->toolsettings); - BKE_sound_destroy_scene(scen); - } - else { - scen = BKE_libblock_copy(bmain, &sce->id); - BLI_duplicatelist(&(scen->base), &(sce->base)); - - if (type != SCE_COPY_FULL) { - id_us_plus((ID *)scen->world); - } - id_us_plus((ID *)scen->set); - /* id_us_plus((ID *)scen->gm.dome.warptext); */ /* XXX Not refcounted? see readfile.c */ - - scen->ed = NULL; - scen->theDag = NULL; - scen->depsgraph = NULL; - scen->obedit = NULL; - scen->stats = NULL; - scen->fps_info = NULL; - - if (sce->rigidbody_world) - scen->rigidbody_world = BKE_rigidbody_world_copy(sce->rigidbody_world); - - BLI_duplicatelist(&(scen->markers), &(sce->markers)); - BLI_duplicatelist(&(scen->transform_spaces), &(sce->transform_spaces)); - BLI_duplicatelist(&(scen->r.layers), &(sce->r.layers)); - BLI_duplicatelist(&(scen->r.views), &(sce->r.views)); - BKE_keyingsets_copy(&(scen->keyingsets), &(sce->keyingsets)); - - if (sce->nodetree) { - /* ID's are managed on both copy and switch */ - scen->nodetree = ntreeCopyTree(bmain, sce->nodetree); - BKE_libblock_relink_ex(bmain, scen->nodetree, &sce->id, &scen->id, false); +/** + * Only copy internal data of Scene ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, const int flag) +{ + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + + sce_dst->ed = NULL; + sce_dst->theDag = NULL; + sce_dst->depsgraph = NULL; + sce_dst->obedit = NULL; + sce_dst->stats = NULL; + sce_dst->fps_info = NULL; + + BLI_duplicatelist(&(sce_dst->base), &(sce_src->base)); + for (Base *base_dst = sce_dst->base.first, *base_src = sce_src->base.first; + base_dst; + base_dst = base_dst->next, base_src = base_src->next) + { + if (base_src == sce_src->basact) { + sce_dst->basact = base_dst; } + } - obase = sce->base.first; - base = scen->base.first; - while (base) { - id_us_plus(&base->object->id); - if (obase == sce->basact) scen->basact = base; - - obase = obase->next; - base = base->next; - } + BLI_duplicatelist(&(sce_dst->markers), &(sce_src->markers)); + BLI_duplicatelist(&(sce_dst->transform_spaces), &(sce_src->transform_spaces)); + BLI_duplicatelist(&(sce_dst->r.layers), &(sce_src->r.layers)); + BLI_duplicatelist(&(sce_dst->r.views), &(sce_src->r.views)); + BKE_keyingsets_copy(&(sce_dst->keyingsets), &(sce_src->keyingsets)); - /* copy action and remove animation used by sequencer */ - BKE_animdata_copy_id_action(&scen->id, false); + if (sce_src->nodetree) { + BKE_id_copy_ex(bmain, (ID *)sce_src->nodetree, (ID **)&sce_dst->nodetree, flag, false); + BKE_libblock_relink_ex(bmain, sce_dst->nodetree, (void *)(&sce_src->id), &sce_dst->id, false); + } - if (type != SCE_COPY_FULL) - remove_sequencer_fcurves(scen); + if (sce_src->rigidbody_world) { + sce_dst->rigidbody_world = BKE_rigidbody_world_copy(sce_src->rigidbody_world, flag_subdata); + } - /* copy Freestyle settings */ - new_srl = scen->r.layers.first; - for (srl = sce->r.layers.first; srl; srl = srl->next) { - if (new_srl->prop != NULL) { - new_srl->prop = IDP_CopyProperty(new_srl->prop); - } - BKE_freestyle_config_copy(&new_srl->freestyleConfig, &srl->freestyleConfig); - if (type == SCE_COPY_FULL) { - for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { - if (lineset->linestyle) { - /* Has been incremented by BKE_freestyle_config_copy(). */ - id_us_min(&lineset->linestyle->id); - lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle); - } - } - } - new_srl = new_srl->next; + /* copy Freestyle settings */ + for (SceneRenderLayer *srl_dst = sce_dst->r.layers.first, *srl_src = sce_src->r.layers.first; + srl_src; + srl_dst = srl_dst->next, srl_src = srl_src->next) + { + if (srl_dst->prop != NULL) { + srl_dst->prop = IDP_CopyProperty_ex(srl_dst->prop, flag_subdata); } + BKE_freestyle_config_copy(&srl_dst->freestyleConfig, &srl_src->freestyleConfig, flag_subdata); } /* copy color management settings */ - BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings); - BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings); - BKE_color_managed_colorspace_settings_copy(&scen->sequencer_colorspace_settings, &sce->sequencer_colorspace_settings); + BKE_color_managed_display_settings_copy(&sce_dst->display_settings, &sce_src->display_settings); + BKE_color_managed_view_settings_copy(&sce_dst->view_settings, &sce_src->view_settings); + BKE_color_managed_colorspace_settings_copy(&sce_dst->sequencer_colorspace_settings, &sce_src->sequencer_colorspace_settings); - BKE_color_managed_display_settings_copy(&scen->r.im_format.display_settings, &sce->r.im_format.display_settings); - BKE_color_managed_view_settings_copy(&scen->r.im_format.view_settings, &sce->r.im_format.view_settings); + BKE_color_managed_display_settings_copy(&sce_dst->r.im_format.display_settings, &sce_src->r.im_format.display_settings); + BKE_color_managed_view_settings_copy(&sce_dst->r.im_format.view_settings, &sce_src->r.im_format.view_settings); - BKE_color_managed_display_settings_copy(&scen->r.bake.im_format.display_settings, &sce->r.bake.im_format.display_settings); - BKE_color_managed_view_settings_copy(&scen->r.bake.im_format.view_settings, &sce->r.bake.im_format.view_settings); + BKE_color_managed_display_settings_copy(&sce_dst->r.bake.im_format.display_settings, &sce_src->r.bake.im_format.display_settings); + BKE_color_managed_view_settings_copy(&sce_dst->r.bake.im_format.view_settings, &sce_src->r.bake.im_format.view_settings); - curvemapping_copy_data(&scen->r.mblur_shutter_curve, &sce->r.mblur_shutter_curve); + curvemapping_copy_data(&sce_dst->r.mblur_shutter_curve, &sce_src->r.mblur_shutter_curve); /* tool settings */ - scen->toolsettings = MEM_dupallocN(sce->toolsettings); - - ts = scen->toolsettings; - if (ts) { + if (sce_dst->toolsettings != NULL) { + ToolSettings *ts = sce_dst->toolsettings = MEM_dupallocN(sce_dst->toolsettings); if (ts->vpaint) { ts->vpaint = MEM_dupallocN(ts->vpaint); ts->vpaint->paintcursor = NULL; ts->vpaint->vpaint_prev = NULL; ts->vpaint->wpaint_prev = NULL; - BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint); + BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag_subdata); } if (ts->wpaint) { ts->wpaint = MEM_dupallocN(ts->wpaint); ts->wpaint->paintcursor = NULL; ts->wpaint->vpaint_prev = NULL; ts->wpaint->wpaint_prev = NULL; - BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint); + BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag_subdata); } if (ts->sculpt) { ts->sculpt = MEM_dupallocN(ts->sculpt); - BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint); + BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag_subdata); } if (ts->uvsculpt) { ts->uvsculpt = MEM_dupallocN(ts->uvsculpt); - BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint); + BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag_subdata); } - BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint); + BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag_subdata); ts->imapaint.paintcursor = NULL; - id_us_plus((ID *)ts->imapaint.stencil); - id_us_plus((ID *)ts->imapaint.clone); - id_us_plus((ID *)ts->imapaint.canvas); ts->particle.paintcursor = NULL; ts->particle.scene = NULL; ts->particle.object = NULL; - + /* duplicate Grease Pencil Drawing Brushes */ BLI_listbase_clear(&ts->gp_brushes); - for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) { + for (bGPDbrush *brush = sce_src->toolsettings->gp_brushes.first; brush; brush = brush->next) { bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush); BLI_addtail(&ts->gp_brushes, newbrush); } - + /* duplicate Grease Pencil interpolation curve */ ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo); } - + /* make a private copy of the avicodecdata */ - if (sce->r.avicodecdata) { - scen->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata); - scen->r.avicodecdata->lpFormat = MEM_dupallocN(scen->r.avicodecdata->lpFormat); - scen->r.avicodecdata->lpParms = MEM_dupallocN(scen->r.avicodecdata->lpParms); + if (sce_src->r.avicodecdata) { + sce_dst->r.avicodecdata = MEM_dupallocN(sce_src->r.avicodecdata); + sce_dst->r.avicodecdata->lpFormat = MEM_dupallocN(sce_dst->r.avicodecdata->lpFormat); + sce_dst->r.avicodecdata->lpParms = MEM_dupallocN(sce_dst->r.avicodecdata->lpParms); } - + /* make a private copy of the qtcodecdata */ - if (sce->r.qtcodecdata) { - scen->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata); - scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms); + if (sce_src->r.qtcodecdata) { + sce_dst->r.qtcodecdata = MEM_dupallocN(sce_src->r.qtcodecdata); + sce_dst->r.qtcodecdata->cdParms = MEM_dupallocN(sce_dst->r.qtcodecdata->cdParms); } - - if (sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */ - scen->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties); + + if (sce_src->r.ffcodecdata.properties) { /* intentionally check sce_dst not sce_src. */ /* XXX ??? comment outdated... */ + sce_dst->r.ffcodecdata.properties = IDP_CopyProperty_ex(sce_src->r.ffcodecdata.properties, flag_subdata); } - /* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations - * are done outside of blenkernel with ED_objects_single_users! */ + /* before scene copy */ + BKE_sound_create_scene(sce_dst); - /* camera */ - if (type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) { - ID_NEW_REMAP(scen->camera); + /* Copy sequencer, this is local data! */ + if (sce_src->ed) { + sce_dst->ed = MEM_callocN(sizeof(*sce_dst->ed), __func__); + sce_dst->ed->seqbasep = &sce_dst->ed->seqbase; + BKE_sequence_base_dupli_recursive( + sce_src, sce_dst, &sce_dst->ed->seqbase, &sce_src->ed->seqbase, SEQ_DUPE_ALL, flag_subdata); } - - /* before scene copy */ - BKE_sound_create_scene(scen); - /* world */ - if (type == SCE_COPY_FULL) { - if (scen->world) { - scen->world = BKE_world_copy(bmain, scen->world); - BKE_animdata_copy_id_action((ID *)scen->world, false); + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { + BKE_previewimg_id_copy(&sce_dst->id, &sce_src->id); + } + else { + sce_dst->preview = NULL; + } +} + +Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) +{ + Scene *sce_copy; + + /* TODO this should/could most likely be replaced by call to more generic code at some point... + * But for now, let's keep it well isolated here. */ + if (type == SCE_COPY_EMPTY) { + ToolSettings *ts; + ListBase rl, rv; + + sce_copy = BKE_scene_add(bmain, sce->id.name + 2); + + rl = sce_copy->r.layers; + rv = sce_copy->r.views; + curvemapping_free_data(&sce_copy->r.mblur_shutter_curve); + sce_copy->r = sce->r; + sce_copy->r.layers = rl; + sce_copy->r.actlay = 0; + sce_copy->r.views = rv; + sce_copy->unit = sce->unit; + sce_copy->physics_settings = sce->physics_settings; + sce_copy->gm = sce->gm; + sce_copy->audio = sce->audio; + + if (sce->id.properties) + sce_copy->id.properties = IDP_CopyProperty(sce->id.properties); + + MEM_freeN(sce_copy->toolsettings); + BKE_sound_destroy_scene(sce_copy); + + /* copy color management settings */ + BKE_color_managed_display_settings_copy(&sce_copy->display_settings, &sce->display_settings); + BKE_color_managed_view_settings_copy(&sce_copy->view_settings, &sce->view_settings); + BKE_color_managed_colorspace_settings_copy(&sce_copy->sequencer_colorspace_settings, &sce->sequencer_colorspace_settings); + + BKE_color_managed_display_settings_copy(&sce_copy->r.im_format.display_settings, &sce->r.im_format.display_settings); + BKE_color_managed_view_settings_copy(&sce_copy->r.im_format.view_settings, &sce->r.im_format.view_settings); + + BKE_color_managed_display_settings_copy(&sce_copy->r.bake.im_format.display_settings, &sce->r.bake.im_format.display_settings); + BKE_color_managed_view_settings_copy(&sce_copy->r.bake.im_format.view_settings, &sce->r.bake.im_format.view_settings); + + curvemapping_copy_data(&sce_copy->r.mblur_shutter_curve, &sce->r.mblur_shutter_curve); + + /* tool settings */ + sce_copy->toolsettings = MEM_dupallocN(sce->toolsettings); + + ts = sce_copy->toolsettings; + if (ts) { + if (ts->vpaint) { + ts->vpaint = MEM_dupallocN(ts->vpaint); + ts->vpaint->paintcursor = NULL; + ts->vpaint->vpaint_prev = NULL; + ts->vpaint->wpaint_prev = NULL; + BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, 0); + } + if (ts->wpaint) { + ts->wpaint = MEM_dupallocN(ts->wpaint); + ts->wpaint->paintcursor = NULL; + ts->wpaint->vpaint_prev = NULL; + ts->wpaint->wpaint_prev = NULL; + BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, 0); + } + if (ts->sculpt) { + ts->sculpt = MEM_dupallocN(ts->sculpt); + BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, 0); + } + if (ts->uvsculpt) { + ts->uvsculpt = MEM_dupallocN(ts->uvsculpt); + BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, 0); + } + + BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, 0); + ts->imapaint.paintcursor = NULL; + id_us_plus((ID *)ts->imapaint.stencil); + id_us_plus((ID *)ts->imapaint.clone); + id_us_plus((ID *)ts->imapaint.canvas); + ts->particle.paintcursor = NULL; + ts->particle.scene = NULL; + ts->particle.object = NULL; + + /* duplicate Grease Pencil Drawing Brushes */ + BLI_listbase_clear(&ts->gp_brushes); + for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) { + bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush); + BLI_addtail(&ts->gp_brushes, newbrush); + } + + /* duplicate Grease Pencil interpolation curve */ + ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo); + } + + /* make a private copy of the avicodecdata */ + if (sce->r.avicodecdata) { + sce_copy->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata); + sce_copy->r.avicodecdata->lpFormat = MEM_dupallocN(sce_copy->r.avicodecdata->lpFormat); + sce_copy->r.avicodecdata->lpParms = MEM_dupallocN(sce_copy->r.avicodecdata->lpParms); } - if (sce->ed) { - scen->ed = MEM_callocN(sizeof(Editing), "addseq"); - scen->ed->seqbasep = &scen->ed->seqbase; - BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL); + /* make a private copy of the qtcodecdata */ + if (sce->r.qtcodecdata) { + sce_copy->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata); + sce_copy->r.qtcodecdata->cdParms = MEM_dupallocN(sce_copy->r.qtcodecdata->cdParms); } + + if (sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */ + sce_copy->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties); + } + + /* before scene copy */ + BKE_sound_create_scene(sce_copy); + + /* grease pencil */ + sce_copy->gpd = NULL; + + sce_copy->preview = NULL; + + return sce_copy; } - - /* grease pencil */ - if (scen->gpd) { + else { + BKE_id_copy_ex(bmain, (ID *)sce, (ID **)&sce_copy, LIB_ID_COPY_ACTIONS, false); + + /* Extra actions, most notably SCE_FULL_COPY also duplicates several 'children' datablocks... */ + if (type == SCE_COPY_FULL) { - scen->gpd = BKE_gpencil_data_duplicate(bmain, scen->gpd, false); - } - else if (type == SCE_COPY_EMPTY) { - scen->gpd = NULL; + /* Copy Freestyle LineStyle datablocks. */ + for (SceneRenderLayer *srl_dst = sce_copy->r.layers.first; srl_dst; srl_dst = srl_dst->next) { + for (FreestyleLineSet *lineset = srl_dst->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + if (lineset->linestyle) { + /* XXX Not copying anim/actions here? */ + BKE_id_copy_ex(bmain, (ID *)lineset->linestyle, (ID **)&lineset->linestyle, 0, false); + } + } + } + + /* Full copy of world (included animations) */ + if (sce_copy->world) { + BKE_id_copy_ex(bmain, (ID *)sce_copy->world, (ID **)&sce_copy->world, LIB_ID_COPY_ACTIONS, false); + } + + /* Full copy of GreasePencil. */ + /* XXX Not copying anim/actions here? */ + if (sce_copy->gpd) { + BKE_id_copy_ex(bmain, (ID *)sce_copy->gpd, (ID **)&sce_copy->gpd, 0, false); + } } else { - id_us_plus((ID *)scen->gpd); + /* Remove sequencer if not full copy */ + /* XXX Why in Hell? :/ */ + remove_sequencer_fcurves(sce_copy); + BKE_sequencer_editing_free(sce_copy); } - } - BKE_previewimg_id_copy(&scen->id, &sce->id); + /* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations + * are done outside of blenkernel with ED_objects_single_users! */ - return scen; + /* camera */ + if (ELEM(type, SCE_COPY_LINK_DATA, SCE_COPY_FULL)) { + ID_NEW_REMAP(sce_copy->camera); + } + + return sce_copy; + } } void BKE_scene_groups_relink(Scene *sce) @@ -843,7 +936,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) { Scene *sce; - sce = BKE_libblock_alloc(bmain, ID_SCE, name); + sce = BKE_libblock_alloc(bmain, ID_SCE, name, 0); id_us_min(&sce->id); id_us_ensure_real(&sce->id); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 669f76cf90b..a7991139b3f 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -5371,7 +5371,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad return seq; } -static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag) +static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dupe_flag, const int flag) { Scene *sce_audio = scene_to ? scene_to : scene; Sequence *seqn = MEM_dupallocN(seq); @@ -5397,7 +5397,7 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup } if (seq->prop) { - seqn->prop = IDP_CopyProperty(seq->prop); + seqn->prop = IDP_CopyProperty_ex(seq->prop, flag); } if (seqn->modifiers.first) { @@ -5435,7 +5435,9 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup if (seq->scene_sound) seqn->scene_sound = BKE_sound_add_scene_sound_defaults(sce_audio, seqn); - id_us_plus((ID *)seqn->sound); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)seqn->sound); + } } else if (seq->type == SEQ_TYPE_IMAGE) { seqn->strip->stripdata = @@ -5491,7 +5493,7 @@ Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence * Sequence *seqn; seq->tmp = NULL; - seqn = seq_dupli(scene, scene_to, seq, dupe_flag); + seqn = seq_dupli(scene, scene_to, seq, dupe_flag, 0); if (seq->type == SEQ_TYPE_META) { Sequence *s; for (s = seq->seqbase.first; s; s = s->next) { @@ -5508,19 +5510,19 @@ Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence * } void BKE_sequence_base_dupli_recursive( - Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, - int dupe_flag) + const Scene *scene, Scene *scene_to, ListBase *nseqbase, const ListBase *seqbase, + int dupe_flag, const int flag) { Sequence *seq; Sequence *seqn = NULL; - Sequence *last_seq = BKE_sequencer_active_get(scene); + Sequence *last_seq = BKE_sequencer_active_get((Scene *)scene); /* always include meta's strips */ int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL; for (seq = seqbase->first; seq; seq = seq->next) { seq->tmp = NULL; if ((seq->flag & SELECT) || (dupe_flag & SEQ_DUPE_ALL)) { - seqn = seq_dupli(scene, scene_to, seq, dupe_flag); + seqn = seq_dupli((Scene *)scene, scene_to, seq, dupe_flag, flag); if (seqn) { /*should never fail */ if (dupe_flag & SEQ_DUPE_CONTEXT) { seq->flag &= ~SEQ_ALLSEL; @@ -5531,12 +5533,12 @@ void BKE_sequence_base_dupli_recursive( if (seq->type == SEQ_TYPE_META) { BKE_sequence_base_dupli_recursive( scene, scene_to, &seqn->seqbase, &seq->seqbase, - dupe_flag_recursive); + dupe_flag_recursive, flag); } if (dupe_flag & SEQ_DUPE_CONTEXT) { if (seq == last_seq) { - BKE_sequencer_active_set(scene, seqn); + BKE_sequencer_active_set(scene_to, seqn); } } } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 8469351c54a..45d1f969d64 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -83,7 +83,7 @@ bSound *BKE_sound_new_file(struct Main *bmain, const char *filepath) BLI_path_abs(str, path); - sound = BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath)); + sound = BKE_libblock_alloc(bmain, ID_SO, BLI_path_basename(filepath), 0); BLI_strncpy(sound->name, filepath, FILE_MAX); /* sound->type = SOUND_TYPE_FILE; */ /* XXX unused currently */ @@ -155,6 +155,34 @@ void BKE_sound_free(bSound *sound) } } +/** + * Only copy internal data of Sound ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_sound_copy_data(Main *bmain, bSound *sound_dst, const bSound *UNUSED(sound_src), const int UNUSED(flag)) +{ + sound_dst->handle = NULL; + sound_dst->cache = NULL; + sound_dst->waveform = NULL; + sound_dst->playback_handle = NULL; + sound_dst->spinlock = NULL; /* Think this is OK? Otherwise, easy to create new spinlock here... */ + + /* Just to be sure, should not have any value actually after reading time. */ + sound_dst->ipo = NULL; + sound_dst->newpackedfile = NULL; + + if (sound_dst->packedfile) { + sound_dst->packedfile = dupPackedFile(sound_dst->packedfile); + } + + /* Initialize whole runtime (audaspace) stuff. */ + BKE_sound_load(bmain, sound_dst); +} + void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local) { BKE_id_make_local_generic(bmain, &sound->id, true, lib_local); diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c index d00e4b1a0d2..9d604a9382a 100644 --- a/source/blender/blenkernel/intern/speaker.c +++ b/source/blender/blenkernel/intern/speaker.c @@ -61,25 +61,31 @@ void *BKE_speaker_add(Main *bmain, const char *name) { Speaker *spk; - spk = BKE_libblock_alloc(bmain, ID_SPK, name); + spk = BKE_libblock_alloc(bmain, ID_SPK, name, 0); BKE_speaker_init(spk); return spk; } -Speaker *BKE_speaker_copy(Main *bmain, const Speaker *spk) +/** + * Only copy internal data of Speaker ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_speaker_copy_data(Main *UNUSED(bmain), Speaker *UNUSED(spk_dst), const Speaker *UNUSED(spk_src), const int UNUSED(flag)) { - Speaker *spkn; - - spkn = BKE_libblock_copy(bmain, &spk->id); - - if (spkn->sound) - id_us_plus(&spkn->sound->id); - - BKE_id_copy_ensure_local(bmain, &spk->id, &spkn->id); + /* Nothing to do! */ +} - return spkn; +Speaker *BKE_speaker_copy(Main *bmain, const Speaker *spk) +{ + Speaker *spk_copy; + BKE_id_copy_ex(bmain, &spk->id, (ID **)&spk_copy, 0, false); + return spk_copy; } void BKE_speaker_make_local(Main *bmain, Speaker *spk, const bool lib_local) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 466bef7ff36..7c4aa81ee46 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -224,7 +224,7 @@ Text *BKE_text_add(Main *bmain, const char *name) { Text *ta; - ta = BKE_libblock_alloc(bmain, ID_TXT, name); + ta = BKE_libblock_alloc(bmain, ID_TXT, name, 0); BKE_text_init(ta); @@ -410,7 +410,7 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const return false; } - ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(filepath_abs)); + ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(filepath_abs), 0); ta->id.us = 0; BLI_listbase_clear(&ta->lines); @@ -449,53 +449,49 @@ Text *BKE_text_load(Main *bmain, const char *file, const char *relpath) return BKE_text_load_ex(bmain, file, relpath, false); } -Text *BKE_text_copy(Main *bmain, const Text *ta) +/** + * Only copy internal data of Text ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_text_copy_data(Main *UNUSED(bmain), Text *ta_dst, const Text *ta_src, const int UNUSED(flag)) { - Text *tan; - TextLine *line, *tmp; - - tan = BKE_libblock_copy(bmain, &ta->id); - /* file name can be NULL */ - if (ta->name) { - tan->name = BLI_strdup(ta->name); - } - else { - tan->name = NULL; + if (ta_src->name) { + ta_dst->name = BLI_strdup(ta_src->name); } - tan->flags = ta->flags | TXT_ISDIRTY; - - BLI_listbase_clear(&tan->lines); - tan->curl = tan->sell = NULL; - tan->compiled = NULL; - - tan->nlines = ta->nlines; + ta_dst->flags |= TXT_ISDIRTY; + + BLI_listbase_clear(&ta_dst->lines); + ta_dst->curl = ta_dst->sell = NULL; + ta_dst->compiled = NULL; - line = ta->lines.first; /* Walk down, reconstructing */ - while (line) { - tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); - tmp->line = MEM_mallocN(line->len + 1, "textline_string"); - tmp->format = NULL; - - strcpy(tmp->line, line->line); + for (TextLine *line_src = ta_src->lines.first; line_src; line_src = line_src->next) { + TextLine *line_dst = MEM_mallocN(sizeof(*line_dst), __func__); - tmp->len = line->len; - - BLI_addtail(&tan->lines, tmp); - - line = line->next; - } + line_dst->line = BLI_strdup(line_src->line); + line_dst->format = NULL; + line_dst->len = line_src->len; - tan->curl = tan->sell = tan->lines.first; - tan->curc = tan->selc = 0; + BLI_addtail(&ta_dst->lines, line_dst); + } - init_undo_text(tan); + ta_dst->curl = ta_dst->sell = ta_dst->lines.first; + ta_dst->curc = ta_dst->selc = 0; - BKE_id_copy_ensure_local(bmain, &ta->id, &tan->id); + init_undo_text(ta_dst); +} - return tan; +Text *BKE_text_copy(Main *bmain, const Text *ta) +{ + Text *ta_copy; + BKE_id_copy_ex(bmain, &ta->id, (ID **)&ta_copy, 0, false); + return ta_copy; } void BKE_text_make_local(Main *bmain, Text *text, const bool lib_local) diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 1e0659d3d67..89a3842a230 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -707,7 +707,7 @@ Tex *BKE_texture_add(Main *bmain, const char *name) { Tex *tex; - tex = BKE_libblock_alloc(bmain, ID_TE, name); + tex = BKE_libblock_alloc(bmain, ID_TE, name, 0); BKE_texture_default(tex); @@ -846,41 +846,71 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot) /* ------------------------------------------------------------------------- */ -Tex *BKE_texture_copy(Main *bmain, const Tex *tex) +/** + * Only copy internal data of Texture ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const int flag) { - Tex *texn; - - texn = BKE_libblock_copy(bmain, &tex->id); - if (BKE_texture_is_image_user(tex)) { - id_us_plus((ID *)texn->ima); + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + + if (!BKE_texture_is_image_user(tex_src)) { + tex_dst->ima = NULL; } - else { - texn->ima = NULL; + + if (tex_dst->coba) { + tex_dst->coba = MEM_dupallocN(tex_dst->coba); + } + if (tex_dst->env) { + tex_dst->env = BKE_texture_envmap_copy(tex_dst->env, flag_subdata); + } + if (tex_dst->pd) { + tex_dst->pd = BKE_texture_pointdensity_copy(tex_dst->pd, flag_subdata); + } + if (tex_dst->vd) { + tex_dst->vd = MEM_dupallocN(tex_dst->vd); + } + if (tex_dst->ot) { + tex_dst->ot = BKE_texture_ocean_copy(tex_dst->ot, flag_subdata); } - - if (texn->coba) texn->coba = MEM_dupallocN(texn->coba); - if (texn->env) texn->env = BKE_texture_envmap_copy(texn->env); - if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd); - if (texn->vd) texn->vd = MEM_dupallocN(texn->vd); - if (texn->ot) texn->ot = BKE_texture_ocean_copy(texn->ot); - if (tex->nodetree) { - if (tex->nodetree->execdata) { - ntreeTexEndExecTree(tex->nodetree->execdata); + if (tex_src->nodetree) { + if (tex_src->nodetree->execdata) { + ntreeTexEndExecTree(tex_src->nodetree->execdata); } - texn->nodetree = ntreeCopyTree(bmain, tex->nodetree); + BKE_id_copy_ex(bmain, (ID *)tex_src->nodetree, (ID **)&tex_dst->nodetree, flag, false); } - BKE_previewimg_id_copy(&texn->id, &tex->id); - - BKE_id_copy_ensure_local(bmain, &tex->id, &texn->id); + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { + BKE_previewimg_id_copy(&tex_dst->id, &tex_src->id); + } + else { + tex_dst->preview = NULL; + } +} - return texn; +Tex *BKE_texture_copy(Main *bmain, const Tex *tex) +{ + Tex *tex_copy; + BKE_id_copy_ex(bmain, &tex->id, (ID **)&tex_copy, 0, false); + return tex_copy; } /* texture copy without adding to main dbase */ Tex *BKE_texture_localize(Tex *tex) { + /* TODO replace with something like + * Tex *tex_copy; + * BKE_id_copy_ex(bmain, &tex->id, (ID **)&tex_copy, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT, false); + * return tex_copy; + * + * ... Once f*** nodes are fully converted to that too :( */ + Tex *texn; texn = BKE_libblock_copy_nolib(&tex->id, false); @@ -889,17 +919,17 @@ Tex *BKE_texture_localize(Tex *tex) if (texn->coba) texn->coba = MEM_dupallocN(texn->coba); if (texn->env) { - texn->env = BKE_texture_envmap_copy(texn->env); + texn->env = BKE_texture_envmap_copy(texn->env, LIB_ID_CREATE_NO_USER_REFCOUNT); id_us_min(&texn->env->ima->id); } - if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd); + if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd, LIB_ID_CREATE_NO_USER_REFCOUNT); if (texn->vd) { texn->vd = MEM_dupallocN(texn->vd); if (texn->vd->dataset) texn->vd->dataset = MEM_dupallocN(texn->vd->dataset); } if (texn->ot) { - texn->ot = BKE_texture_ocean_copy(tex->ot); + texn->ot = BKE_texture_ocean_copy(tex->ot, LIB_ID_CREATE_NO_USER_REFCOUNT); } texn->preview = NULL; @@ -1263,16 +1293,20 @@ EnvMap *BKE_texture_envmap_add(void) /* ------------------------------------------------------------------------- */ -EnvMap *BKE_texture_envmap_copy(const EnvMap *env) +EnvMap *BKE_texture_envmap_copy(const EnvMap *env, const int flag) { EnvMap *envn; int a; envn = MEM_dupallocN(env); envn->ok = 0; - for (a = 0; a < 6; a++) envn->cube[a] = NULL; - if (envn->ima) id_us_plus((ID *)envn->ima); - + for (a = 0; a < 6; a++) { + envn->cube[a] = NULL; + } + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus((ID *)envn->ima); + } + return envn; } @@ -1336,14 +1370,16 @@ PointDensity *BKE_texture_pointdensity_add(void) return pd; } -PointDensity *BKE_texture_pointdensity_copy(const PointDensity *pd) +PointDensity *BKE_texture_pointdensity_copy(const PointDensity *pd, const int UNUSED(flag)) { PointDensity *pdn; pdn = MEM_dupallocN(pd); pdn->point_tree = NULL; pdn->point_data = NULL; - if (pdn->coba) pdn->coba = MEM_dupallocN(pdn->coba); + if (pdn->coba) { + pdn->coba = MEM_dupallocN(pdn->coba); + } pdn->falloff_curve = curvemapping_copy(pdn->falloff_curve); /* can be NULL */ return pdn; } @@ -1430,7 +1466,7 @@ OceanTex *BKE_texture_ocean_add(void) return ot; } -OceanTex *BKE_texture_ocean_copy(const OceanTex *ot) +OceanTex *BKE_texture_ocean_copy(const OceanTex *ot, const int UNUSED(flag)) { OceanTex *otn = MEM_dupallocN(ot); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 9120d384a16..b4ef381534f 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -190,7 +190,7 @@ void BKE_tracking_free(MovieTracking *tracking) } /* Copy the whole list of tracks. */ -static void tracking_tracks_copy(ListBase *tracks_dst, const ListBase *tracks_src, GHash *tracks_mapping) +static void tracking_tracks_copy(ListBase *tracks_dst, const ListBase *tracks_src, GHash *tracks_mapping, const int flag) { MovieTrackingTrack *track_dst, *track_src; @@ -202,7 +202,9 @@ static void tracking_tracks_copy(ListBase *tracks_dst, const ListBase *tracks_sr if (track_src->markers) { track_dst->markers = MEM_dupallocN(track_src->markers); } - id_us_plus(&track_dst->gpd->id); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus(&track_dst->gpd->id); + } BLI_addtail(tracks_dst, track_dst); BLI_ghash_insert(tracks_mapping, track_src, track_dst); } @@ -210,7 +212,8 @@ static void tracking_tracks_copy(ListBase *tracks_dst, const ListBase *tracks_sr /* copy the whole list of plane tracks (need whole MovieTracking structures due to embedded pointers to tracks). * WARNING: implies tracking_[dst/src] and their tracks have already been copied. */ -static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, const ListBase *plane_tracks_src, GHash *tracks_mapping) +static void tracking_plane_tracks_copy( + ListBase *plane_tracks_dst, const ListBase *plane_tracks_src, GHash *tracks_mapping, const int flag) { MovieTrackingPlaneTrack *plane_track_dst, *plane_track_src; @@ -225,14 +228,17 @@ static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, const ListBas for (int i = 0; i < plane_track_dst->point_tracksnr; i++) { plane_track_dst->point_tracks[i] = BLI_ghash_lookup(tracks_mapping, plane_track_src->point_tracks[i]); } - id_us_plus(&plane_track_dst->image->id); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + id_us_plus(&plane_track_dst->image->id); + } BLI_addtail(plane_tracks_dst, plane_track_dst); } } /* Copy reconstruction structure. */ static void tracking_reconstruction_copy( - MovieTrackingReconstruction *reconstruction_dst, const MovieTrackingReconstruction *reconstruction_src) + MovieTrackingReconstruction *reconstruction_dst, const MovieTrackingReconstruction *reconstruction_src, + const int UNUSED(flag)) { *reconstruction_dst = *reconstruction_src; if (reconstruction_src->cameras) { @@ -242,23 +248,25 @@ static void tracking_reconstruction_copy( /* Copy stabilization structure. */ static void tracking_stabilization_copy( - MovieTrackingStabilization *stabilization_dst, const MovieTrackingStabilization *stabilization_src) + MovieTrackingStabilization *stabilization_dst, const MovieTrackingStabilization *stabilization_src, + const int UNUSED(flag)) { *stabilization_dst = *stabilization_src; } /* Copy tracking object. */ static void tracking_object_copy( - MovieTrackingObject *object_dst, const MovieTrackingObject *object_src, GHash *tracks_mapping) + MovieTrackingObject *object_dst, const MovieTrackingObject *object_src, GHash *tracks_mapping, const int flag) { *object_dst = *object_src; - tracking_tracks_copy(&object_dst->tracks, &object_src->tracks, tracks_mapping); - tracking_plane_tracks_copy(&object_dst->plane_tracks, &object_src->plane_tracks, tracks_mapping); - tracking_reconstruction_copy(&object_dst->reconstruction, &object_src->reconstruction); + tracking_tracks_copy(&object_dst->tracks, &object_src->tracks, tracks_mapping, flag); + tracking_plane_tracks_copy(&object_dst->plane_tracks, &object_src->plane_tracks, tracks_mapping, flag); + tracking_reconstruction_copy(&object_dst->reconstruction, &object_src->reconstruction, flag); } /* Copy list of tracking objects. */ -static void tracking_objects_copy(ListBase *objects_dst, const ListBase *objects_src, GHash *tracks_mapping) +static void tracking_objects_copy( + ListBase *objects_dst, const ListBase *objects_src, GHash *tracks_mapping, const int flag) { MovieTrackingObject *object_dst, *object_src; @@ -266,22 +274,22 @@ static void tracking_objects_copy(ListBase *objects_dst, const ListBase *objects for (object_src = objects_src->first; object_src != NULL; object_src = object_src->next) { object_dst = MEM_mallocN(sizeof(*object_dst), __func__); - tracking_object_copy(object_dst, object_src, tracks_mapping); + tracking_object_copy(object_dst, object_src, tracks_mapping, flag); BLI_addtail(objects_dst, object_dst); } } /* Copy tracking structure content. */ -void BKE_tracking_copy(MovieTracking *tracking_dst, const MovieTracking *tracking_src) +void BKE_tracking_copy(MovieTracking *tracking_dst, const MovieTracking *tracking_src, const int flag) { GHash *tracks_mapping = BLI_ghash_ptr_new(__func__); *tracking_dst = *tracking_src; - tracking_tracks_copy(&tracking_dst->tracks, &tracking_src->tracks, tracks_mapping); - tracking_plane_tracks_copy(&tracking_dst->plane_tracks, &tracking_src->plane_tracks, tracks_mapping); - tracking_reconstruction_copy(&tracking_dst->reconstruction, &tracking_src->reconstruction); - tracking_stabilization_copy(&tracking_dst->stabilization, &tracking_src->stabilization); + tracking_tracks_copy(&tracking_dst->tracks, &tracking_src->tracks, tracks_mapping, flag); + tracking_plane_tracks_copy(&tracking_dst->plane_tracks, &tracking_src->plane_tracks, tracks_mapping, flag); + tracking_reconstruction_copy(&tracking_dst->reconstruction, &tracking_src->reconstruction, flag); + tracking_stabilization_copy(&tracking_dst->stabilization, &tracking_src->stabilization, flag); if (tracking_src->act_track) { tracking_dst->act_track = BLI_ghash_lookup(tracks_mapping, tracking_src->act_track); } @@ -299,7 +307,7 @@ void BKE_tracking_copy(MovieTracking *tracking_dst, const MovieTracking *trackin } /* Warning! Will override tracks_mapping. */ - tracking_objects_copy(&tracking_dst->objects, &tracking_src->objects, tracks_mapping); + tracking_objects_copy(&tracking_dst->objects, &tracking_src->objects, tracks_mapping, flag); /* Those remaining are runtime data, they will be reconstructed as needed, do not bother copying them. */ tracking_dst->dopesheet.ok = false; diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 363c36e644d..e79b06a44fe 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -112,43 +112,59 @@ World *add_world(Main *bmain, const char *name) { World *wrld; - wrld = BKE_libblock_alloc(bmain, ID_WO, name); + wrld = BKE_libblock_alloc(bmain, ID_WO, name, 0); BKE_world_init(wrld); return wrld; } -World *BKE_world_copy(Main *bmain, const World *wrld) +/** + * Only copy internal data of World ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_world_copy_data(Main *bmain, World *wrld_dst, const World *wrld_src, const int flag) { - World *wrldn; - int a; - - wrldn = BKE_libblock_copy(bmain, &wrld->id); - - for (a = 0; a < MAX_MTEX; a++) { - if (wrld->mtex[a]) { - wrldn->mtex[a] = MEM_mallocN(sizeof(MTex), "BKE_world_copy"); - memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex)); - id_us_plus((ID *)wrldn->mtex[a]->tex); + for (int a = 0; a < MAX_MTEX; a++) { + if (wrld_src->mtex[a]) { + wrld_dst->mtex[a] = MEM_dupallocN(wrld_src->mtex[a]); } } - if (wrld->nodetree) { - wrldn->nodetree = ntreeCopyTree(bmain, wrld->nodetree); + if (wrld_src->nodetree) { + BKE_id_copy_ex(bmain, (ID *)wrld_src->nodetree, (ID **)&wrld_dst->nodetree, flag, false); } - - BKE_previewimg_id_copy(&wrldn->id, &wrld->id); - BLI_listbase_clear(&wrldn->gpumaterial); + BLI_listbase_clear(&wrld_dst->gpumaterial); - BKE_id_copy_ensure_local(bmain, &wrld->id, &wrldn->id); + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { + BKE_previewimg_id_copy(&wrld_dst->id, &wrld_src->id); + } + else { + wrld_dst->preview = NULL; + } +} - return wrldn; +World *BKE_world_copy(Main *bmain, const World *wrld) +{ + World *wrld_copy; + BKE_id_copy_ex(bmain, &wrld->id, (ID **)&wrld_copy, 0, false); + return wrld_copy; } World *localize_world(World *wrld) { + /* TODO replace with something like + * World *wrld_copy; + * BKE_id_copy_ex(bmain, &wrld->id, (ID **)&wrld_copy, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT, false); + * return wrld_copy; + * + * ... Once f*** nodes are fully converted to that too :( */ + World *wrldn; int a; diff --git a/source/blender/blenlib/BLI_vfontdata.h b/source/blender/blenlib/BLI_vfontdata.h index 8a7079b6c5f..0cd50319a33 100644 --- a/source/blender/blenlib/BLI_vfontdata.h +++ b/source/blender/blenlib/BLI_vfontdata.h @@ -52,8 +52,10 @@ typedef struct VChar { } VChar; VFontData *BLI_vfontdata_from_freetypefont(struct PackedFile *pf); +VFontData *BLI_vfontdata_copy(const VFontData *vfont_src, const int flag); VChar *BLI_vfontchar_from_freetypefont(struct VFont *vfont, unsigned long character); +VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int flag); #endif diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 8719c92a2a6..b97e41402d7 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -481,6 +481,21 @@ VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf) return vfd; } +static void *vfontdata_copy_characters_value_cb(const void *src) { + return BLI_vfontchar_copy(src, 0); +} + +VFontData *BLI_vfontdata_copy(const VFontData *vfont_src, const int UNUSED(flag)) +{ + VFontData *vfont_dst = MEM_dupallocN(vfont_src); + + if (vfont_src->characters != NULL) { + vfont_dst->characters = BLI_ghash_copy(vfont_src->characters, NULL, vfontdata_copy_characters_value_cb); + } + + return vfont_dst; +} + VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character) { VChar *che = NULL; @@ -503,6 +518,20 @@ VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character) return che; } +/* Yeah, this is very bad... But why is this in BLI in the first place, since it uses Nurb data? + * Anyway, do not feel like duplicating whole Nurb copy code here, so unless someone has a better idea... */ +#include "../../blenkernel/BKE_curve.h" + +VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int UNUSED(flag)) +{ + VChar *vchar_dst = MEM_dupallocN(vchar_src); + + BLI_listbase_clear(&vchar_dst->nurbsbase); + BKE_nurbList_duplicate(&vchar_dst->nurbsbase, &vchar_src->nurbsbase); + + return vchar_dst; +} + #if 0 /* Freetype2 Outline struct */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f224f0b5633..31964373716 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -638,7 +638,7 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab /* Add library datablock itself to 'main' Main, since libraries are **never** linked data. * Fixes bug where you could end with all ID_LI datablocks having the same name... */ - lib = BKE_libblock_alloc(mainlist->first, ID_LI, "Lib"); + lib = BKE_libblock_alloc(mainlist->first, ID_LI, "Lib", 0); lib->id.us = ID_FAKE_USERS(lib); /* Important, consistency with main ID reading code from read_libblock(). */ BLI_strncpy(lib->name, filepath, sizeof(lib->name)); BLI_strncpy(lib->filepath, name1, sizeof(lib->filepath)); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index ee9665dc834..6c5bfb01829 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -3841,6 +3841,9 @@ static bool write_file_handle( } for (; id; id = id->next) { + /* We should never attempt to write non-regular IDs (i.e. all kind of temp/runtime ones). */ + BLI_assert((id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0); + switch ((ID_Type)GS(id->name)) { case ID_WM: write_windowmanager(wd, (wmWindowManager *)id); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 1c342657eec..417d7c8ba3b 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -380,7 +380,7 @@ int join_armature_exec(bContext *C, wmOperator *op) if (base->object->adt) { if (ob->adt == NULL) { /* no animdata, so just use a copy of the whole thing */ - ob->adt = BKE_animdata_copy(base->object->adt, false); + ob->adt = BKE_animdata_copy(bmain, base->object->adt, false); } else { /* merge in data - we'll fix the drivers manually */ @@ -391,7 +391,7 @@ int join_armature_exec(bContext *C, wmOperator *op) if (curarm->adt) { if (arm->adt == NULL) { /* no animdata, so just use a copy of the whole thing */ - arm->adt = BKE_animdata_copy(curarm->adt, false); + arm->adt = BKE_animdata_copy(bmain, curarm->adt, false); } else { /* merge in data - we'll fix the drivers manually */ diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index a5e90ebbe7a..975bbddd893 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -93,7 +93,7 @@ static int cachefile_open_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); - CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename)); + CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename), 0); BLI_strncpy(cache_file->filepath, filename, FILE_MAX); BKE_cachefile_reload(bmain, cache_file); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index edd7b5dd1be..34554db1318 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -773,9 +773,9 @@ static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob) /* now copy it, this also works without logicbricks! */ clear_sca_new_poins_ob(ob); - copy_sensors(&base->object->sensors, &ob->sensors); - copy_controllers(&base->object->controllers, &ob->controllers); - copy_actuators(&base->object->actuators, &ob->actuators); + copy_sensors(&base->object->sensors, &ob->sensors, 0); + copy_controllers(&base->object->controllers, &ob->controllers, 0); + copy_actuators(&base->object->actuators, &ob->actuators, 0); set_sca_new_poins_ob(base->object); /* some menu settings */ @@ -934,7 +934,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) base->object->collision_boundtype = ob->collision_boundtype; } base->object->margin = ob->margin; - base->object->bsoft = copy_bulletsoftbody(ob->bsoft); + base->object->bsoft = copy_bulletsoftbody(ob->bsoft, 0); } else if (event == 17) { /* tex space */ @@ -1042,7 +1042,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) base->object->softflag = ob->softflag; if (base->object->soft) sbFree(base->object->soft); - base->object->soft = copy_softbody(ob->soft, false); + base->object->soft = copy_softbody(ob->soft, 0); if (!modifiers_findByType(base->object, eModifierType_Softbody)) { BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody)); @@ -2106,9 +2106,9 @@ static int logicbricks_copy_exec(bContext *C, wmOperator *UNUSED(op)) /* now copy it, this also works without logicbricks! */ clear_sca_new_poins_ob(ob); - copy_sensors(&ob_iter->sensors, &ob->sensors); - copy_controllers(&ob_iter->controllers, &ob->controllers); - copy_actuators(&ob_iter->actuators, &ob->actuators); + copy_sensors(&ob_iter->sensors, &ob->sensors, 0); + copy_controllers(&ob_iter->controllers, &ob->controllers, 0); + copy_actuators(&ob_iter->actuators, &ob->actuators, 0); set_sca_new_poins_ob(ob_iter); /* some menu settings */ @@ -2169,7 +2169,7 @@ static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op)) copy_v3_v3(ob_iter->anisotropicFriction, ob->anisotropicFriction); ob_iter->collision_boundtype = ob->collision_boundtype; ob_iter->margin = ob->margin; - ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft); + ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft, 0); if (ob->restrictflag & OB_RESTRICT_RENDER) ob_iter->restrictflag |= OB_RESTRICT_RENDER; else diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 3284af2df69..5b6fe96861d 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1581,13 +1581,13 @@ static int make_links_data_exec(bContext *C, wmOperator *op) DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA); break; case MAKE_LINKS_ANIMDATA: - BKE_animdata_copy_id((ID *)ob_dst, (ID *)ob_src, false); + BKE_animdata_copy_id(bmain, (ID *)ob_dst, (ID *)ob_src, false); if (ob_dst->data && ob_src->data) { if (ID_IS_LINKED_DATABLOCK(obdata_id)) { is_lib = true; break; } - BKE_animdata_copy_id((ID *)ob_dst->data, (ID *)ob_src->data, false); + BKE_animdata_copy_id(bmain, (ID *)ob_dst->data, (ID *)ob_src->data, false); } DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); break; diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 4a4474868a2..29b652e1326 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -1035,7 +1035,7 @@ static bool copy_particle_systems_to_object(Main *bmain, psys_from; psys_from = PSYS_FROM_NEXT(psys_from), ++i) { - psys = BKE_object_copy_particlesystem(psys_from); + psys = BKE_object_copy_particlesystem(psys_from, 0); tmp_psys[i] = psys; if (psys_start == NULL) diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 9bdb34f5384..28bce6b3798 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -1298,16 +1298,16 @@ static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op) switch (freestyle_get_modifier_type(&ptr)) { case LS_MODIFIER_TYPE_COLOR: - BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier); + BKE_linestyle_color_modifier_copy(lineset->linestyle, modifier, 0); break; case LS_MODIFIER_TYPE_ALPHA: - BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier); + BKE_linestyle_alpha_modifier_copy(lineset->linestyle, modifier, 0); break; case LS_MODIFIER_TYPE_THICKNESS: - BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier); + BKE_linestyle_thickness_modifier_copy(lineset->linestyle, modifier, 0); break; case LS_MODIFIER_TYPE_GEOMETRY: - BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier); + BKE_linestyle_geometry_modifier_copy(lineset->linestyle, modifier, 0); break; default: BKE_report(op->reports, RPT_ERROR, "The object the data pointer refers to is not a valid modifier"); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index f469686b0b2..18372939590 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -467,7 +467,7 @@ bScreen *ED_screen_add(wmWindow *win, Scene *scene, const char *name) bScreen *sc; ScrVert *sv1, *sv2, *sv3, *sv4; - sc = BKE_libblock_alloc(G.main, ID_SCR, name); + sc = BKE_libblock_alloc(G.main, ID_SCR, name, 0); sc->scene = scene; sc->do_refresh = true; sc->redraws_flag = TIME_ALL_3D_WIN | TIME_ALL_ANIM_WIN; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index e63569ac386..1ace61481a6 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2162,7 +2162,7 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) if (ed == NULL) return OPERATOR_CANCELLED; - BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT); + BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_CONTEXT, 0); if (nseqbase.first) { Sequence *seq = nseqbase.first; @@ -3200,7 +3200,7 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME); + BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, ed->seqbasep, SEQ_DUPE_UNIQUE_NAME, 0); /* To make sure the copied strips have unique names between each other add * them temporarily to the end of the original seqbase. (bug 25932) @@ -3267,7 +3267,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *UNUSED(op)) ED_sequencer_deselect_all(scene); ofs = scene->r.cfra - seqbase_clipboard_frame; - BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME); + BKE_sequence_base_dupli_recursive(scene, NULL, &nseqbase, &seqbase_clipboard, SEQ_DUPE_UNIQUE_NAME, 0); /* transform pasted strips before adding */ if (ofs) { diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index da0f505c4f3..a940e4bf65d 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -127,8 +127,7 @@ typedef struct ID { /** * LIB_TAG_... tags (runtime only, cleared at read time). */ - short tag; - short pad_s1; + int tag; int us; int icon_id; IDProperty *properties; @@ -350,6 +349,13 @@ enum { LIB_TAG_ID_RECALC_DATA = 1 << 13, LIB_TAG_ANIM_NO_RECALC = 1 << 14, LIB_TAG_ID_RECALC_ALL = (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA), + + /* RESET_NEVER tag datablock for freeing etc. behavior (usually set when copying real one into temp/runtime one). */ + LIB_TAG_NO_MAIN = 1 << 16, /* Datablock is not listed in Main database. */ + LIB_TAG_NO_USER_REFCOUNT = 1 << 17, /* Datablock does not refcount usages of other IDs. */ + /* Datablock was not allocated by standard system (BKE_libblock_alloc), do not free its memory + * (usual type-specific freeing is called though). */ + LIB_TAG_NOT_ALLOCATED = 1 << 18, }; /* To filter ID types (filter_id) */ diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 2400dbcb898..f2f76f13883 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -64,13 +64,13 @@ static void initData(ModifierData *md) static void copyData(ModifierData *md, ModifierData *target) { +#if 0 ArmatureModifierData *amd = (ArmatureModifierData *) md; +#endif ArmatureModifierData *tamd = (ArmatureModifierData *) target; - tamd->object = amd->object; - tamd->deformflag = amd->deformflag; - tamd->multi = amd->multi; - BLI_strncpy(tamd->defgrp_name, amd->defgrp_name, sizeof(tamd->defgrp_name)); + modifier_copyData_generic(md, target); + tamd->prevCos = NULL; } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md)) diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 5874029ae08..93dc0203f83 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -65,19 +65,11 @@ static void initData(ModifierData *md) static void copyData(ModifierData *md, ModifierData *target) { +#if 0 BevelModifierData *bmd = (BevelModifierData *) md; BevelModifierData *tbmd = (BevelModifierData *) target; - - tbmd->value = bmd->value; - tbmd->res = bmd->res; - tbmd->flags = bmd->flags; - tbmd->val_flags = bmd->val_flags; - tbmd->lim_flags = bmd->lim_flags; - tbmd->e_flags = bmd->e_flags; - tbmd->mat = bmd->mat; - tbmd->profile = bmd->profile; - tbmd->bevel_angle = bmd->bevel_angle; - BLI_strncpy(tbmd->defgrp_name, bmd->defgrp_name, sizeof(tbmd->defgrp_name)); +#endif + modifier_copyData_generic(md, target); } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 3325f05025f..fb8c0dd05a5 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -75,14 +75,10 @@ static void copyData(ModifierData *md, ModifierData *target) { #if 0 DisplaceModifierData *dmd = (DisplaceModifierData *) md; -#endif DisplaceModifierData *tdmd = (DisplaceModifierData *) target; +#endif modifier_copyData_generic(md, target); - - if (tdmd->texture) { - id_us_plus(&tdmd->texture->id); - } } static void freeData(ModifierData *md) diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index f0c4940816e..b4990c5250e 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -90,14 +90,10 @@ static void copyData(ModifierData *md, ModifierData *target) { #if 0 WaveModifierData *wmd = (WaveModifierData *) md; -#endif WaveModifierData *twmd = (WaveModifierData *) target; +#endif modifier_copyData_generic(md, target); - - if (twmd->texture) { - id_us_plus(&twmd->texture->id); - } } static bool dependsOnTime(ModifierData *UNUSED(md)) diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 85d6e5186a1..13a97c1c13d 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -93,10 +93,6 @@ static void copyData(ModifierData *md, ModifierData *target) modifier_copyData_generic(md, target); twmd->cmap_curve = curvemapping_copy(wmd->cmap_curve); - - if (twmd->mask_texture) { - id_us_plus(&twmd->mask_texture->id); - } } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 543dc7eb900..392f42040b0 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -138,14 +138,10 @@ static void copyData(ModifierData *md, ModifierData *target) { #if 0 WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md; -#endif WeightVGMixModifierData *twmd = (WeightVGMixModifierData *) target; +#endif modifier_copyData_generic(md, target); - - if (twmd->mask_texture) { - id_us_plus(&twmd->mask_texture->id); - } } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 5457792a744..2ca380ba5c2 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -288,14 +288,10 @@ static void copyData(ModifierData *md, ModifierData *target) { #if 0 WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md; -#endif WeightVGProximityModifierData *twmd = (WeightVGProximityModifierData *) target; +#endif modifier_copyData_generic(md, target); - - if (twmd->mask_texture) { - id_us_plus(&twmd->mask_texture->id); - } } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 67e961b9cd0..1738dabde2d 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -430,7 +430,7 @@ void wm_clear_default_size(bContext *C) /* on startup, it adds all data, for matching */ void wm_add_default(bContext *C) { - wmWindowManager *wm = BKE_libblock_alloc(CTX_data_main(C), ID_WM, "WinMan"); + wmWindowManager *wm = BKE_libblock_alloc(CTX_data_main(C), ID_WM, "WinMan", 0); wmWindow *win; bScreen *screen = CTX_wm_screen(C); /* XXX from file read hrmf */ |