Refactor ID copying (and to some extent, ID freeing).
authorBastien Montagne <montagne29@wanadoo.fr>
Mon, 7 Aug 2017 14:39:55 +0000 (16:39 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Mon, 7 Aug 2017 14:39:55 +0000 (16:39 +0200)
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).

This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.

It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).

Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!

As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.

Design task : T51804
Phab Diff: D2714

102 files changed:
source/blender/blenkernel/BKE_action.h
source/blender/blenkernel/BKE_animsys.h
source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/BKE_brush.h
source/blender/blenkernel/BKE_cachefile.h
source/blender/blenkernel/BKE_camera.h
source/blender/blenkernel/BKE_constraint.h
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_font.h
source/blender/blenkernel/BKE_freestyle.h
source/blender/blenkernel/BKE_gpencil.h
source/blender/blenkernel/BKE_group.h
source/blender/blenkernel/BKE_idprop.h
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/BKE_key.h
source/blender/blenkernel/BKE_lamp.h
source/blender/blenkernel/BKE_lattice.h
source/blender/blenkernel/BKE_library.h
source/blender/blenkernel/BKE_linestyle.h
source/blender/blenkernel/BKE_mask.h
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/BKE_mball.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/BKE_movieclip.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/BKE_paint.h
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/BKE_pointcache.h
source/blender/blenkernel/BKE_rigidbody.h
source/blender/blenkernel/BKE_sca.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/BKE_speaker.h
source/blender/blenkernel/BKE_text.h
source/blender/blenkernel/BKE_texture.h
source/blender/blenkernel/BKE_tracking.h
source/blender/blenkernel/BKE_world.h
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/cachefile.c
source/blender/blenkernel/intern/camera.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/font.c
source/blender/blenkernel/intern/freestyle.c
source/blender/blenkernel/intern/gpencil.c
source/blender/blenkernel/intern/group.c
source/blender/blenkernel/intern/idprop.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/lamp.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/library_remap.c
source/blender/blenkernel/intern/linestyle.c
source/blender/blenkernel/intern/mask.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mball.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/paint.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/rigidbody.c
source/blender/blenkernel/intern/sca.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/sound.c
source/blender/blenkernel/intern/speaker.c
source/blender/blenkernel/intern/text.c
source/blender/blenkernel/intern/texture.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenkernel/intern/world.c
source/blender/blenlib/BLI_vfontdata.h
source/blender/blenlib/intern/freetypefont.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/armature/armature_relations.c
source/blender/editors/io/io_cache.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_relations.c
source/blender/editors/physics/particle_object.c
source/blender/editors/render/render_shading.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/makesdna/DNA_ID.h
source/blender/modifiers/intern/MOD_armature.c
source/blender/modifiers/intern/MOD_bevel.c
source/blender/modifiers/intern/MOD_displace.c
source/blender/modifiers/intern/MOD_wave.c
source/blender/modifiers/intern/MOD_weightvgedit.c
source/blender/modifiers/intern/MOD_weightvgmix.c
source/blender/modifiers/intern/MOD_weightvgproximity.c
source/blender/windowmanager/intern/wm.c

index 5db0c3c91300208b85ca0bacd5d490f8ab2f326b..28be2b04c71dc68ff92d7a15c1e099201da80e08 100644 (file)
@@ -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);
index 420ae4bb12dd1e4937975229b3498a67c5ea4060..534a57765f618783a5a0637b23e323196a4d7a81 100644 (file)
@@ -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);
index 6bfc8c918d64c43000b46ba808fd05fe96a86ef8..1cc42f788d55b0c5cc3e7dc7d604f65362e396c5 100644 (file)
@@ -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. */
index 42e4e73f2d5e777699c3bc514c2ade9c5dd1c691..dedb75a080a569bcdf7c515043597b2552ab9e6f 100644 (file)
@@ -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);
index f1e643c4a1945b154d35c210bb8eff208d2bc700..e9712681090ab37e5b82d0fda899f3e866944d38 100644 (file)
@@ -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);
index b2f22aacb280dd3f713c28b294593ede9618d2dd..04dee70faa68baeeeb26071942776ddda70ddf23 100644 (file)
@@ -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);
index 047d1787f76896dc7c4e9174d86a422bcc02e325..4e0eb5c65acf90e07803efc0df4fbf6da5e1cdce 100644 (file)
@@ -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);
index 635e999dd9585a524a14be65383c5761a55c19d1..b6eea42724d4c273ddef0c585c86ce403eff1032 100644 (file)
@@ -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);
index e7ae0f606e7c402ed0d873b0c2b16991d03bd421..60ad061bf779c0f7a835f5df8331c7bfc4483507 100644 (file)
@@ -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);
index 50407f3bdfcc5feee03a14084a742e8e1bf96345..1045fde00394cad3154432737cb13e1b495552d6 100644 (file)
@@ -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);
index bdd28baf137111f46e4773a47e518cbd7a31df6c..b6de922c245f31a97bb84bd27af8467de1903769 100644 (file)
@@ -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);
index 684251c9561669d43bdc26c77760aaee80a11536..404d1704c785d9a9c94c68eda21467503a725931 100644 (file)
@@ -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);
index ab8728faedb64fadd31afe675187f0c4b2b0a710..5d8cd02756d02fb6538bed13995b5e6f47890204 100644 (file)
@@ -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;
 
index e155b0719cc5393b58a440481d89a71d28e17054..3f8be511212e1c073fa4ff63b5c09c43a0a6c58b 100644 (file)
@@ -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 */
index 94e8a24fbc551304a9c3aa9bcbaac2b890b4921a..5eef44ef896b9ab0a6c1143faf739869be76ef0e 100644 (file)
@@ -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);
index 713ca80fb1a4b598a951788d1d411e1ff96b50ab..b68da654520f1567e3e8fd42a0518ef1d9122907 100644 (file)
@@ -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);
index ec1cf79832dede942feaaa376b75d71922e6b2fa..f7d006785d27ad6a928b7951c1d79f593019aa97 100644 (file)
@@ -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);
index 258dcc84449ded2c6ccf16e17592229a57d377f2..b5104b35b3cadac52d243030b660534df189b794 100644 (file)
@@ -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);
index c7b323d0f6e8a5a5607044fc67b3bf926f6ccf0b..3ba4fbe03385dc01e3704c710d58a2feafc3b0e7 100644 (file)
@@ -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);
index 0735d2d97a101f8427f5770a441e66afa89922ca..6e154241af712761f56804572b34f48d4f95491e 100644 (file)
@@ -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);
 
index 7da962dd6d6c5730f6ced250dbe56f9a77adc5db..c6ebda2c399872c7c8999bd9242cbe58c2dd9ab5 100644 (file)
@@ -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 */
index c00a0743ebbb8797898cfd463fda356a8d691fab..a02a068b920848e10f71cdaea50d2c175df83505 100644 (file)
@@ -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);
index b55b8b2dd3c87964aa24c69d9a7ee96536ff753a..9480679f817b9259e4f9adea2dda0f14a3106ca0 100644 (file)
@@ -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);
index b241b5ca5b72bd00467c076fb7f1ee73cf6fe754..30c47a4b192db8d953289f6c3e9651cf920c9ef7 100644 (file)
@@ -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);
index 69fdad5ef7bde8db910f5f8cd48a82eecb041db9..3ddf75f204e97c18884616eb087e67009eb731ac 100644 (file)
@@ -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);
 
index d5279c5b0ce860f5cc0108396effe63478c64635..81de70ca8a462866ca7cc9f2e64e6c40aa2e1807 100644 (file)
@@ -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);
index 0a5035f9a9baccad800557a08b02c97941bfe26d..d1a4033957b8a70f7d441d124a7cc61307995c5d 100644 (file)
@@ -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);
index 821dc21159100d281b848d3fc4111ae56d42aaad..f7e6ab59d2058712e14d0ed2b936b9699206ce79 100644 (file)
@@ -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);
 
index 470e2e468f0219025d52bf27d395c469fe1b8a4e..ddb4f9c37bd67a5074debc18bcafa1ebf788284a 100644 (file)
@@ -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);
 
index 02f6c435ee267dcb6ced20fd8083f7fc10d72ffa..f0819c8d79d67457fcb1d515be36ec5958634f38 100644 (file)
@@ -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 *********************/
 
index c72f067a11149b96c603d49ea8a8f87171cacac9..3c7274ca3c5b65276b02a171e4d0b76851ddb486 100644 (file)
@@ -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 */
index 10cddd7b4546716fc1d7cd689a94f9e9e899066a..35bcd91a9b17e14e2e4badbafbacaafbebcdbf33 100644 (file)
@@ -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);
index d2152950bff48a82bc883f1cf7dd194a22ce8cc1..f1680b6ccbf755be294b249c24a6daeaec8d94c4 100644 (file)
@@ -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);
 
index 811e9136fc9d01a42065c96de438f9033fde413c..87d63b7d6f63c021cf3429887ca8d6c71e45a6c9 100644 (file)
@@ -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);
index a5c626e74d7bae52d3834c807ac52b4038be0fbe..6f8274fabc86e67ef5a71bb1177d19cea8189da2 100644 (file)
@@ -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)
index 907558f92036d54560dc4b5a2a575370b11a130a..57f4c37f1294f35a619c30197529db0d7f12a09e 100644 (file)
@@ -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);
index c8fb483cdf272d7fc2124554631cd5b2cab3641c..14d3318e0599ac7b71377a71c9a65959d6e9bc94 100644 (file)
@@ -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);
index 190fdeafaec058cb1dc5a3a2f318941303d2fbca..8a9171673ea3de837c0b43c86d4f148eab1a1a5e 100644 (file)
@@ -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);
index b48be38207356f73c40a4c849fea39b65a73e056..d05ed1800fb5e0ea595de6b6a9025ebc64c60585 100644 (file)
@@ -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);
 
index 18ae61f76536d7cd305d1a25f125380499539d36..2a811496bb9dcd272662b82844ae45af07289025 100644 (file)
@@ -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);
index 885ea36d404ad9295946aa0078b8a3f2996fbe1c..bb4e09364d477e81405dc8a9943f51070c91234c 100644 (file)
@@ -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) {
index 539901a59d5e81b5d6617e0c98606692fd27479d..6afa251bce787e0c60bb47ed58079183cc21b37d 100644 (file)
@@ -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;
index 35b6fe113bd85ceef0bfe7fab93e70844a72c8ef..669344e18d7c8406bc90a34cd6c54f69ef924086 100644 (file)
@@ -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)
index aae323a50569d7fc988e94bcf64453c60c125327..03b0710c8fc1f0bb6cfdcfda337ccd25c074c62d 100644 (file)
@@ -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). */
index cf619a32783b6c66139a9adef1586de57959c132..1916531b066a23bd2905a373fcfaea5a82303bb5 100644 (file)
@@ -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)
index 915c08674a477c55fef6460779522728cdb3a876..719125b331704f91e7e9113652912811dc48fdce 100644 (file)
@@ -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)
index 07a6b304dffc75bbebad784dbca325890cee6b25..c05feb7faf4f83507651e676d80e16b33519fbdf 100644 (file)
@@ -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)
index 7c22a34c7d14afb976c6f4b5f9ef2b7175225577..e08fdcf10e97f60c2f5310153cb1c30b4aed4035 100644 (file)
@@ -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)
index 401fed74c52ae8e80e2a6ee053d758a183f1c575..d6b28cfaf70d9c7451c4a841c73c1f0ba93e0e10 100644 (file)
@@ -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 */
index 0a0b023df82dcc4fdb4c074aec3bd7f11e83671c..e45a938a4fc8183e129f4736cc7749270d525e57 100644 (file)
@@ -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)
index 758438bb051d073ba5e00ca7b1c834ab5afa9058..ee0d0b418982cbb6524241904a28ebb48634e60b 100644 (file)
@@ -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)
index 932f41ac4ba89b8623d8efc008dade9802ce419e..fd6e9681e64995f48b9a23b512bcc70415f3354b 100644 (file)
@@ -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)
index e98181be4440ec79fabe943b54fe7b35442a8e0e..45b41fa01ed88596a4e53756c4f7eecdfd97b630 100644 (file)
@@ -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)
index abe08def197416220f7ed5b78a43bd05ee931ef7..bbe6814f6b74419b78d9ddd7b9d14dbe46fcd38f 100644 (file)
@@ -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)
index 98b251294aef9963e92fe5b3b1f5a6217a2aae21..364817438c5ffd819b9e664d63acf99b88870aff 100644 (file)
@@ -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;
index 2242ba379fb86f2c13ce5795b0c3b1c579b7d1d7..e8ef346927ea8828917d19c67d2500bd6bcb6f7b 100644 (file)
@@ -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;
        
index c9d7dddf25a371187031dbbbeb55a74a6d69489b..ea4c3f380ffc62a7927211860d0f0c50b56b749d 100644 (file)
@@ -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, &lt->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, &lt_src->key->id, (ID **)&lt_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, &lt->id, &ltn->id);
+       lt_dst->editlatt = NULL;
+}
 
-       return ltn;
+Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt)
+{
+       Lattice *lt_copy;
+       BKE_id_copy_ex(bmain, &lt->id, (ID **)&lt_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(&lt->id, false);
index 2ea7342ff34fb55c935b32d1d5ecdec64bb0d01e..18e4f332dc22442267fe0cf5e48354b8ef5a90fd 100644 (file)
@@ -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;
 }
index 5e5ba44f0399c5d3f4d32b63ed344a4578a7fb6a..ed9063e76405a22504bff5e938c1ab585192f7ce 100644 (file)
@@ -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);
index 771e81ddc4fc8f061443a28728685b4ae8dbb865..1b1a12e702a72a5549241f7ca8df88564ef97e60 100644 (file)
@@ -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;
 
index ae27e9bcd34c84fd491194f06923da0d3535db1e..435bc949af0d6c5b7cb57cf6b4d114e7c28a0daf 100644 (file)
@@ -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)
index f21efb71180a1b0f213ce82d786dcfd0199d9205..710af30aa3ae456b9860df5f33a965b420b29468 100644 (file)
@@ -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;
        
index b80579014d61c691a35902dc7df00cd1bb1d4e92..930e28ab7fb9133ef98ea1ca65aa21e5b418eb18 100644 (file)
@@ -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)
index 6233caa43fa5eff770bf1df9698a700cd64ea378..b89541173e102bf08c817260c0a6dc3bfc9213d0 100644 (file)
@@ -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);
 
index 2276d56b9c6f63c92a892b97a521e4c28c9170bf..118bafa94d27a5efe4e9444883b810fb2bc5bbc8 100644 (file)
@@ -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);
 }
 
 
index dfa8742a295676b48535bfebf12d9d2851f897e4..16d597e25fad615a8aed4762ab87aa7372df0d24 100644 (file)
@@ -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)
index 5acfe4a0aa44490d5e3801039ef8347384c3caf9..b11b328a01c18356cb89191baa7dd4614d5a3088 100644 (file)
@@ -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 **)&ltree,
+                              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) {
index f3086396c3a34604b3914742fb9e6d3d2f534074..cb851d2f95596b2123906163a9fb1fdfad454ed1 100644 (file)
@@ -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 */
                
index c7cfe55f65941001e45a4033f5db5d11b78a212e..9fc2136df86d53836675f6884d4db7fc5288ddfa 100644 (file)
@@ -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])
index 416d63cfefb7aeaf448c711a9fc1a73df57e5caf..8c94cdfe784d6cc18b76ea6bbe2ce2cca17db702 100644 (file)
@@ -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)
index a7e00a8103a391ae53d2b97b70b107efa283ff3a..2a61efcd1f934d9747ab11b6e2cb7cb522fd2479 100644 (file)
@@ -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;
 }
index e8c0cf53d0b7b40daf79c06b03f68f92a9dd445a..5a925af456ce03ce63e948383ba6f398472dfb25 100644 (file)
@@ -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)
index 19d646daf9f56f2bb0d12041803ea31d0aef8730..fb81ed4d47fe1fe9ada25f4eb8072561632f54b4 100644 (file)
@@ -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) {
index a15f270a3eef934a06f2889841a7df52c7990d15..9002003d380fbcedb60d0c411dd64d94e37b72ff 100644 (file)
@@ -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);
 
index 669f76cf90b56a50af5d3af8e718715fbcac4ee2..a7991139b3fd376d08143211f52a2333b6ed98f5 100644 (file)
@@ -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);
                                        }
                                }
                        }
index 8469351c54aa8ed886b034a23bae6b9ee6af6455..45d1f969d6458466b37b23cc2a203fcb816de3a4 100644 (file)
@@ -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);
index d00e4b1a0d29cfab0bb2929ffa32bbb2c741965a..9d604a9382a9bba1e970073a0e7863f9dc847159 100644 (file)
@@ -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)
index 466bef7ff36bdb6c161f7d1cecf8d6c41f300fca..7c4aa81ee46d774b4cb8b30c8d9d9bb916ea01f3 100644 (file)
@@ -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)
index 1e0659d3d67760071dc144357cf8eda73b4b2557..89a3842a23098fc024183dd8e4d330490ac219ba 100644 (file)
@@ -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);
        
index 9120d384a16ef13971d45374800679034d1f0140..b4ef381534f18e67837c7c2d4c65e0df48839120 100644 (file)
@@ -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;
index 363c36e644d318750d4c6eab4657975ab0734314..e79b06a44fe2760a8c53922d1c81b19a5a3f9cb4 100644 (file)
@@ -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;
        
index 8a7079b6c5f3cb8265ac8a7061082c57fda0711c..0cd50319a3356f55104954952d033d1f813079b5 100644 (file)
@@ -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
 
index 8719c92a2a6d7c897d5d0452d957e18260e73759..b97e41402d74f892594366dacc6c510a27d998e9 100644 (file)
@@ -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 */
index f224f0b56330465d015904c77d040d9286b25681..319643737167bf9d891ca6b4a95865d2e8b139f1 100644 (file)
@@ -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));
index ee9665dc834e3de8ac2fd645aa88fb417e52fe2d..6c5bfb01829e392b840919b23b1609cba7658b80 100644 (file)
@@ -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);
index 1c342657eecdc5f293abfee1b3c11450fdbfcd29..417d7c8ba3bc1ca67ec659b0c8853707424a1744 100644 (file)
@@ -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 */
index a5e90ebbe7a1ee302b40ebdaa263b218de1ce7ad..975bbddd8931b180440c2036215073940fd40e0c 100644 (file)
@@ -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);
 
index edd7b5dd1be3a12d2eacd5b3029ef6951aeaf813..34554db131887236cbe9f7457922abb4ed1840e5 100644 (file)
@@ -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
index 3284af2df694bda904899aa5e8310ca322f26248..5b6fe96861d3b1e37880ba504a0150ea3d20e373 100644 (file)
@@ -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;
index 4a4474868a2181a02a9bc2bbaa3550c3ec57767f..29b652e13264070bb51cd24a1b72ddc4ed96b12d 100644 (file)
@@ -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)
index 9bdb34f5384564f8c92944b1bed0976e2bbbd1fb..28bce6b3798dfc3374842c1d396b7c9e1f6f141e 100644 (file)
@@ -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");
index f469686b0b220a4550eb863724c85562314dc2bc..18372939590e642298e882bfa09a5b9d53871f55 100644 (file)
@@ -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;
index e63569ac3867fe33955bc9afd0cbdf9e3e45a3e2..1ace61481a693a04233f5f4047d3a994ad36068d 100644 (file)
@@ -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) {
index da0f505c4f38393f49bb049a105a7d37a3c06db4..a940e4bf65d925a37032115e9eb23f9d697300ff 100644 (file)
@@ -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) */
index 2400dbcb89815d58a3bb2cf8a7bd1dd423030468..f2f76f138833ea7c72ca690dc01d3d5fb3dae427 100644 (file)
@@ -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))
index 5874029ae0862279b9eec1964bf0ab7b8842b7b2..93dc0203f83932bc6e5682c217ba17732fd14581 100644 (file)
@@ -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)
index 3325f05025f030cd52a25fe6e70411651850b6a6..fb8c0dd05a539b8f4db8a905b409bb05969d2fb1 100644 (file)
@@ -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)
index f0c4940816e4d7055c1bcf9b07407714904f164c..b4990c5250e2ddc5be3c3dafb157c19e9864f03d 100644 (file)
@@ -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))
index 85d6e5186a120d870d271f117d73f58f096517c7..13a97c1c13d6e77a4b14cdb806398196693962c1 100644 (file)
@@ -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)
index 543dc7eb90088a391b046af0b932410b7801b25a..392f42040b0cbc90809bcc4098ccff2b2146a0df 100644 (file)
@@ -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)
index 5457792a744fd5dcd43026f429acedcb9b1d8ffb..2ca380ba5c217aaebb1139ced014e34917905e65 100644 (file)
@@ -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)
index 67e961b9cd0157da635b1a22894669210dc8c4a5..1738dabde2da784ab592ae2db4290197216dc59d 100644 (file)
@@ -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 */