Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_animsys.h2
-rw-r--r--source/blender/blenkernel/BKE_curve.h1
-rw-r--r--source/blender/blenkernel/BKE_group.h1
-rw-r--r--source/blender/blenkernel/BKE_library.h18
-rw-r--r--source/blender/blenkernel/BKE_library_query.h1
-rw-r--r--source/blender/blenkernel/BKE_library_remap.h76
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h2
-rw-r--r--source/blender/blenkernel/BKE_mask.h3
-rw-r--r--source/blender/blenkernel/BKE_mball.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh.h3
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/BKE_sca.h1
-rw-r--r--source/blender/blenkernel/BKE_scene.h3
-rw-r--r--source/blender/blenkernel/BKE_screen.h7
-rw-r--r--source/blender/blenkernel/BKE_sound.h2
-rw-r--r--source/blender/blenkernel/BKE_world.h1
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/action.c15
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c18
-rw-r--r--source/blender/blenkernel/intern/armature.c31
-rw-r--r--source/blender/blenkernel/intern/brush.c16
-rw-r--r--source/blender/blenkernel/intern/camera.c3
-rw-r--r--source/blender/blenkernel/intern/curve.c53
-rw-r--r--source/blender/blenkernel/intern/effect.c3
-rw-r--r--source/blender/blenkernel/intern/font.c3
-rw-r--r--source/blender/blenkernel/intern/gpencil.c9
-rw-r--r--source/blender/blenkernel/intern/group.c66
-rw-r--r--source/blender/blenkernel/intern/image.c13
-rw-r--r--source/blender/blenkernel/intern/key.c6
-rw-r--r--source/blender/blenkernel/intern/lamp.c2
-rw-r--r--source/blender/blenkernel/intern/lattice.c23
-rw-r--r--source/blender/blenkernel/intern/library.c270
-rw-r--r--source/blender/blenkernel/intern/library_query.c76
-rw-r--r--source/blender/blenkernel/intern/library_remap.c768
-rw-r--r--source/blender/blenkernel/intern/linestyle.c42
-rw-r--r--source/blender/blenkernel/intern/mask.c59
-rw-r--r--source/blender/blenkernel/intern/material.c42
-rw-r--r--source/blender/blenkernel/intern/mball.c23
-rw-r--r--source/blender/blenkernel/intern/mesh.c42
-rw-r--r--source/blender/blenkernel/intern/movieclip.c4
-rw-r--r--source/blender/blenkernel/intern/node.c38
-rw-r--r--source/blender/blenkernel/intern/object.c473
-rw-r--r--source/blender/blenkernel/intern/paint.c11
-rw-r--r--source/blender/blenkernel/intern/particle.c25
-rw-r--r--source/blender/blenkernel/intern/sca.c71
-rw-r--r--source/blender/blenkernel/intern/scene.c86
-rw-r--r--source/blender/blenkernel/intern/screen.c17
-rw-r--r--source/blender/blenkernel/intern/sequencer.c4
-rw-r--r--source/blender/blenkernel/intern/sound.c15
-rw-r--r--source/blender/blenkernel/intern/speaker.c5
-rw-r--r--source/blender/blenkernel/intern/text.c9
-rw-r--r--source/blender/blenkernel/intern/texture.c37
-rw-r--r--source/blender/blenkernel/intern/world.c30
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.cpp2
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c2
-rw-r--r--source/blender/editors/include/ED_buttons.h2
-rw-r--r--source/blender/editors/include/ED_node.h2
-rw-r--r--source/blender/editors/include/ED_outliner.h6
-rw-r--r--source/blender/editors/include/ED_util.h2
-rw-r--r--source/blender/editors/include/ED_view3d.h2
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c2
-rw-r--r--source/blender/editors/object/object_add.c4
-rw-r--r--source/blender/editors/object/object_group.c4
-rw-r--r--source/blender/editors/render/render_preview.c8
-rw-r--r--source/blender/editors/screen/screen_edit.c5
-rw-r--r--source/blender/editors/sound/sound_ops.c2
-rw-r--r--source/blender/editors/space_action/space_action.c17
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c30
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c58
-rw-r--r--source/blender/editors/space_clip/space_clip.c21
-rw-r--r--source/blender/editors/space_graph/space_graph.c17
-rw-r--r--source/blender/editors/space_image/space_image.c30
-rw-r--r--source/blender/editors/space_logic/space_logic.c21
-rw-r--r--source/blender/editors/space_nla/space_nla.c17
-rw-r--r--source/blender/editors/space_node/node_edit.c28
-rw-r--r--source/blender/editors/space_node/space_node.c37
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c33
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h1
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c11
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c36
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c19
-rw-r--r--source/blender/editors/space_text/space_text.c18
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c63
-rw-r--r--source/blender/editors/util/ed_util.c19
-rw-r--r--source/blender/makesrna/intern/rna_ID.c2
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c9
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c4
-rw-r--r--source/blender/render/intern/source/render_texture.c3
-rw-r--r--source/blender/windowmanager/WM_api.h2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c4
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c5
94 files changed, 1582 insertions, 1508 deletions
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 6524afff051..772e08589c1 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -62,7 +62,7 @@ struct AnimData *BKE_animdata_add_id(struct ID *id);
bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct bAction *act);
/* Free AnimData */
-void BKE_animdata_free(struct ID *id);
+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);
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 061270b8b41..23b3128f328 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -66,7 +66,6 @@ typedef struct CurveCache {
#define CU_DO_2DFILL(cu) ((((cu)->flag & CU_3D) == 0) && (((cu)->flag & (CU_FRONT | CU_BACK)) != 0))
/* ** Curve ** */
-void BKE_curve_unlink(struct Curve *cu);
void BKE_curve_free(struct Curve *cu);
void BKE_curve_editfont_free(struct Curve *cu);
void BKE_curve_init(struct Curve *cu);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 9056e48cf50..ae6e52b613b 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -41,7 +41,6 @@ struct Object;
struct Scene;
void BKE_group_free(struct Group *group);
-void BKE_group_unlink(struct Main *bmain, struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
struct Group *BKE_group_copy(struct Group *group);
bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 2215fbfbd7d..56f040ab260 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -60,13 +60,15 @@ void BKE_libblock_relink(struct ID *id);
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();
+struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+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_ex(struct Main *bmain, void *idv, bool do_id_user) ATTR_NONNULL();
void BKE_libblock_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
void BKE_libblock_free_data(struct Main *bmain, struct ID *id) ATTR_NONNULL();
-
-struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BKE_libblock_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
void id_lib_extern(struct ID *id);
@@ -82,7 +84,6 @@ void id_fake_user_clear(struct ID *id);
bool id_make_local(struct ID *id, bool test);
bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
bool id_copy(struct ID *id, struct ID **newid, bool test);
-bool id_unlink(struct ID *id, int test);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
bool new_id(struct ListBase *lb, struct ID *id, const char *name);
@@ -119,16 +120,11 @@ void BKE_main_lib_objects_recalc_all(struct Main *bmain);
/* (MAX_ID_NAME - 2) + 3 */
void BKE_id_ui_prefix(char name[66 + 1], const struct ID *id);
+void BKE_library_free(struct Library *lib);
+
void BKE_library_make_local(
struct Main *bmain, const struct Library *lib, const bool untagged_only, const bool set_fake);
-typedef void (*BKE_library_free_window_manager_cb)(struct bContext *, struct wmWindowManager *);
-typedef void (*BKE_library_free_notifier_reference_cb)(const void *);
-typedef void (*BKE_library_free_editor_id_reference_cb)(const struct ID *);
-
-void BKE_library_callback_free_window_manager_set(BKE_library_free_window_manager_cb func);
-void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func);
-void BKE_library_callback_free_editor_id_reference_set(BKE_library_free_editor_id_reference_cb func);
/* use when "" is given to new_id() */
#define ID_FALLBACK_NAME N_("Untitled")
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index 2e73be576f9..c89dce99caa 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -32,6 +32,7 @@
*/
struct ID;
+struct Main;
/* Tips for the callback for cases it's gonna to modify the pointer. */
enum {
diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h
new file mode 100644
index 00000000000..e85a3e60751
--- /dev/null
+++ b/source/blender/blenkernel/BKE_library_remap.h
@@ -0,0 +1,76 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_LIBRARY_REMAP_H__
+#define __BKE_LIBRARY_REMAP_H__
+
+/** \file BKE_library_remap.h
+ * \ingroup bke
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_compiler_attrs.h"
+
+/* BKE_libblock_free, delete are declared in BKE_library.h for convenience. */
+
+/* Also IDRemap->flag. */
+enum {
+ /* Do not remap indirect usages of IDs (that is, when user is some linked data). */
+ ID_REMAP_SKIP_INDIRECT_USAGE = 1 << 0,
+ /* This flag should always be set, *except for 'unlink' scenarios* (only relevant when new_id == NULL).
+ * Basically, when unset, NEVER_NULL ID usages will keep pointing to old_id, but (if needed) old_id user count
+ * will still be decremented. This is mandatory for 'delete ID' case, but in all other situation this would lead
+ * to invalid user counts! */
+ ID_REMAP_SKIP_NEVER_NULL_USAGE = 1 << 1,
+ /* This tells the callback func to flag with LIB_DOIT all IDs using target one with a 'never NULL' pointer
+ * (like e.g. Object->data). */
+ ID_REMAP_FLAG_NEVER_NULL_USAGE = 1 << 2,
+ /* This tells the callback func to force setting IDs using target one with a 'never NULL' pointer to NULL.
+ * WARNING! Use with extreme care, this will leave database in broken state! */
+ ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3,
+};
+
+/* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */
+void BKE_libblock_remap_locked(
+ struct Main *bmain, void *old_idv, void *new_idv,
+ const short remap_flags) ATTR_NONNULL(1, 2);
+void BKE_libblock_remap(
+ struct Main *bmain, void *old_idv, void *new_idv,
+ const short remap_flags) ATTR_NONNULL(1, 2);
+
+void BKE_libblock_unlink(struct Main *bmain, void *idv, const bool do_flag_never_null) ATTR_NONNULL();
+
+void BKE_libblock_relink_ex(void *idv, void *old_idv, void *new_idv, const bool us_min_never_null) ATTR_NONNULL(1);
+
+
+typedef void (*BKE_library_free_window_manager_cb)(struct bContext *, struct wmWindowManager *);
+typedef void (*BKE_library_free_notifier_reference_cb)(const void *);
+typedef void (*BKE_library_remap_editor_id_reference_cb)(struct ID *, struct ID *);
+
+void BKE_library_callback_free_window_manager_set(BKE_library_free_window_manager_cb func);
+void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func);
+void BKE_library_callback_remap_editor_id_reference_set(BKE_library_remap_editor_id_reference_cb func);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_LIBRARY_REMAP_H__ */ \ No newline at end of file
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
index e3eead4102c..e343cd29622 100644
--- a/source/blender/blenkernel/BKE_linestyle.h
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -79,8 +79,6 @@ void BKE_linestyle_geometry_modifier_move(FreestyleLineStyle *linestyle, LineSty
void BKE_linestyle_modifier_list_color_ramps(FreestyleLineStyle *linestyle, ListBase *listbase);
char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, struct ColorBand *color_ramp);
-void BKE_linestyle_target_object_unlink(FreestyleLineStyle *linestyle, struct Object *ob);
-
bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_shading_nodes);
void BKE_linestyle_default_shader(const struct bContext *C, FreestyleLineStyle *linestyle);
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 25893d54dca..f3d12b5a8cc 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -125,8 +125,7 @@ struct Mask *BKE_mask_new(struct Main *bmain, const char *name);
struct Mask *BKE_mask_copy_nolib(struct Mask *mask);
struct Mask *BKE_mask_copy(struct Mask *mask);
-void BKE_mask_free_nolib(struct Mask *mask);
-void BKE_mask_free(struct Main *bmain, struct Mask *mask);
+void BKE_mask_free(struct Mask *mask);
void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2]);
void BKE_mask_coord_from_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2]);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 0574b88bef3..b8258455c65 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -38,7 +38,6 @@ struct Object;
struct Scene;
struct MetaElem;
-void BKE_mball_unlink(struct MetaBall *mb);
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);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index d8d869015a3..9330f41d19a 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -81,8 +81,7 @@ int poly_get_adj_loops_from_vert(
int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
-void BKE_mesh_unlink(struct Mesh *me);
-void BKE_mesh_free(struct Mesh *me, int unlink);
+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);
struct Mesh *BKE_mesh_copy_ex(struct Main *bmain, struct Mesh *me);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 4b92c1f7a3a..bf198c9b86b 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -334,7 +334,6 @@ void ntreeInitDefault(struct bNodeTree *ntree);
struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
/* copy/free funcs, need to manage ID users */
-void ntreeFreeTree_ex(struct bNodeTree *ntree, const bool do_id_user);
void ntreeFreeTree(struct bNodeTree *ntree);
struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user);
struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index c591ec2a0aa..f46fb73f4c9 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -65,7 +65,6 @@ void BKE_object_free_curve_cache(struct Object *ob);
void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
void BKE_object_free(struct Object *ob);
-void BKE_object_free_ex(struct Object *ob, bool do_id_user);
void BKE_object_free_derived_caches(struct Object *ob);
void BKE_object_free_caches(struct Object *object);
@@ -79,7 +78,6 @@ void BKE_object_free_modifiers(struct Object *ob);
void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob);
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
-void BKE_object_unlink(struct Main *bmain, struct Object *ob);
bool BKE_object_exists_check(struct Object *obtest);
bool BKE_object_is_in_editmode(struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index fa448aa97b8..1743a4431fd 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -67,7 +67,6 @@ void clear_sca_new_poins_ob(struct Object *ob);
void clear_sca_new_poins(void);
void set_sca_new_poins_ob(struct Object *ob);
void set_sca_new_poins(void);
-void sca_remove_ob_poin(struct Object *obt, struct Object *ob);
void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up);
void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 12bfc07e958..ccb7dc8e015 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -100,10 +100,11 @@ struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
struct Scene *BKE_scene_copy(struct Scene *sce, int type);
void BKE_scene_groups_relink(struct Scene *sce);
-void BKE_scene_unlink(struct Main *bmain, struct Scene *sce, struct Scene *newsce);
struct Object *BKE_scene_camera_find(struct Scene *sc);
+#ifdef DURIAN_CAMERA_SWITCH
struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH
+#endif
int BKE_scene_camera_switch_update(struct Scene *scene);
char *BKE_scene_find_marker_name(struct Scene *scene, int frame);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index d05df3470b5..14e978b23f2 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -99,6 +99,9 @@ typedef struct SpaceType {
/* return context data */
int (*context)(const struct bContext *, const char *, struct bContextDataResult *);
+ /* Used when we want to replace an ID by another (or NULL). */
+ void (*id_remap)(struct ScrArea *, struct SpaceLink *, struct ID *, struct ID *);
+
/* region type definitions */
ListBase regiontypes;
@@ -274,8 +277,8 @@ void BKE_spacedata_freelist(ListBase *lb);
void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
void BKE_spacedata_draw_locks(int set);
-void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *));
-void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
+void BKE_spacedata_callback_id_remap_set(void (*func)(struct ScrArea *, struct SpaceLink *, struct ID *, struct ID *));
+void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID *id);
/* area/regions */
struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index 67db2537c8f..18d9fe061a8 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -72,8 +72,6 @@ struct bSound *BKE_sound_new_buffer(struct Main *bmain, struct bSound *source);
struct bSound *BKE_sound_new_limiter(struct Main *bmain, struct bSound *source, float start, float end);
#endif
-void BKE_sound_delete(struct Main *bmain, struct bSound *sound);
-
void BKE_sound_cache(struct bSound *sound);
void BKE_sound_delete_cache(struct bSound *sound);
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
index 8d7ab230919..0be61fe0229 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -37,7 +37,6 @@ struct Main;
struct World;
void BKE_world_free(struct World *sc);
-void BKE_world_free_ex(struct World *sc, bool do_id_user);
void BKE_world_init(struct World *wrld);
struct World *add_world(struct Main *bmian, const char *name);
struct World *BKE_world_copy(struct World *wrld);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 86264224851..6af9f8a71ee 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -123,6 +123,7 @@ set(SRC
intern/library.c
intern/library_idmap.c
intern/library_query.c
+ intern/library_remap.c
intern/linestyle.c
intern/mask.c
intern/mask_evaluate.c
@@ -247,6 +248,7 @@ set(SRC
BKE_library.h
BKE_library_idmap.h
BKE_library_query.h
+ BKE_library_remap.h
BKE_linestyle.h
BKE_main.h
BKE_mask.h
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index df9b9683687..46ee8a4d888 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -159,22 +159,19 @@ void BKE_action_make_local(bAction *act)
/* .................................. */
+/** Free (or release) any data used by this action (does not free the action itself). */
void BKE_action_free(bAction *act)
-{
- /* sanity check */
- if (act == NULL)
- return;
-
+{
+ /* No animdata here. */
+
/* Free F-Curves */
free_fcurves(&act->curves);
/* Free groups */
- if (act->groups.first)
- BLI_freelistN(&act->groups);
+ BLI_freelistN(&act->groups);
/* Free pose-references (aka local markers) */
- if (act->markers.first)
- BLI_freelistN(&act->markers);
+ BLI_freelistN(&act->markers);
}
/* .................................. */
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 99aae6239e8..91b33f3efd3 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -216,7 +216,7 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
/* Freeing -------------------------------------------- */
/* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */
-void BKE_animdata_free(ID *id)
+void BKE_animdata_free(ID *id, const bool do_id_user)
{
/* Only some ID-blocks have this info for now, so we cast the
* types that do to be of type IdAdtTemplate
@@ -227,12 +227,14 @@ void BKE_animdata_free(ID *id)
/* check if there's any AnimData to start with */
if (adt) {
- /* unlink action (don't free, as it's in its own list) */
- if (adt->action)
- id_us_min(&adt->action->id);
- /* same goes for the temporarily displaced action */
- if (adt->tmpact)
- id_us_min(&adt->tmpact->id);
+ if (do_id_user) {
+ /* unlink action (don't free, as it's in its own list) */
+ if (adt->action)
+ id_us_min(&adt->action->id);
+ /* same goes for the temporarily displaced action */
+ if (adt->tmpact)
+ id_us_min(&adt->tmpact->id);
+ }
/* free nla data */
free_nladata(&adt->nla_tracks);
@@ -292,7 +294,7 @@ bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action)
if ((id_to && id_from) && (GS(id_to->name) != GS(id_from->name)))
return false;
- BKE_animdata_free(id_to);
+ BKE_animdata_free(id_to, true);
adt = BKE_animdata_from_id(id_from);
if (adt) {
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 04b4733fd44..038993777cf 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -120,30 +120,25 @@ void BKE_armature_bonelist_free(ListBase *lb)
BLI_freelistN(lb);
}
+/** Free (or release) any data used by this armature (does not free the armature itself). */
void BKE_armature_free(bArmature *arm)
{
- if (arm) {
- BKE_armature_bonelist_free(&arm->bonebase);
+ BKE_animdata_free(&arm->id, false);
- /* free editmode data */
- if (arm->edbo) {
- BLI_freelistN(arm->edbo);
+ BKE_armature_bonelist_free(&arm->bonebase);
- MEM_freeN(arm->edbo);
- arm->edbo = NULL;
- }
+ /* free editmode data */
+ if (arm->edbo) {
+ BLI_freelistN(arm->edbo);
- /* free sketch */
- if (arm->sketch) {
- freeSketch(arm->sketch);
- arm->sketch = NULL;
- }
+ MEM_freeN(arm->edbo);
+ arm->edbo = NULL;
+ }
- /* free animation data */
- if (arm->adt) {
- BKE_animdata_free(&arm->id);
- arm->adt = NULL;
- }
+ /* free sketch */
+ if (arm->sketch) {
+ freeSketch(arm->sketch);
+ arm->sketch = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index da7863096e3..a3e006a162f 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -202,22 +202,18 @@ Brush *BKE_brush_copy(Brush *brush)
return brushn;
}
-/* not brush itself */
+/** Free (or release) any data used by this brush (does not free the brush itself). */
void BKE_brush_free(Brush *brush)
{
- id_us_min((ID *)brush->mtex.tex);
- id_us_min((ID *)brush->mask_mtex.tex);
- id_us_min((ID *)brush->paint_curve);
-
- if (brush->icon_imbuf)
+ if (brush->icon_imbuf) {
IMB_freeImBuf(brush->icon_imbuf);
-
- BKE_previewimg_free(&(brush->preview));
+ }
curvemapping_free(brush->curve);
- if (brush->gradient)
- MEM_freeN(brush->gradient);
+ MEM_SAFE_FREE(brush->gradient);
+
+ BKE_previewimg_free(&(brush->preview));
}
/**
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 96bac2c2f41..eabee742327 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -153,9 +153,10 @@ void BKE_camera_make_local(Camera *cam)
}
}
+/** Free (or release) any data used by this camera (does not free the camera itself). */
void BKE_camera_free(Camera *ca)
{
- BKE_animdata_free((ID *)ca);
+ BKE_animdata_free((ID *)ca, false);
}
/******************************** Camera Usage *******************************/
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 8afb451f768..dec6ff22360 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -69,36 +69,6 @@ static int cu_isectLL(const float v1[3], const float v2[3], const float v3[3], c
short cox, short coy,
float *lambda, float *mu, float vec[3]);
-void BKE_curve_unlink(Curve *cu)
-{
- int a;
-
- for (a = 0; a < cu->totcol; a++) {
- if (cu->mat[a])
- id_us_min(&cu->mat[a]->id);
- cu->mat[a] = NULL;
- }
- if (cu->vfont)
- id_us_min(&cu->vfont->id);
- cu->vfont = NULL;
-
- if (cu->vfontb)
- id_us_min(&cu->vfontb->id);
- cu->vfontb = NULL;
-
- if (cu->vfonti)
- id_us_min(&cu->vfonti->id);
- cu->vfonti = NULL;
-
- if (cu->vfontbi)
- id_us_min(&cu->vfontbi->id);
- cu->vfontbi = NULL;
-
- if (cu->key)
- id_us_min(&cu->key->id);
- cu->key = NULL;
-}
-
/* frees editcurve entirely */
void BKE_curve_editfont_free(Curve *cu)
{
@@ -136,26 +106,21 @@ void BKE_curve_editNurb_free(Curve *cu)
}
}
-/* don't free curve itself */
+/** Free (or release) any data used by this curve (does not free the curve itself). */
void BKE_curve_free(Curve *cu)
{
+ BKE_animdata_free((ID *)cu, false);
+
BKE_nurbList_free(&cu->nurb);
BKE_curve_editfont_free(cu);
BKE_curve_editNurb_free(cu);
- BKE_curve_unlink(cu);
- BKE_animdata_free((ID *)cu);
-
- if (cu->mat)
- MEM_freeN(cu->mat);
- if (cu->str)
- MEM_freeN(cu->str);
- if (cu->strinfo)
- MEM_freeN(cu->strinfo);
- if (cu->bb)
- MEM_freeN(cu->bb);
- if (cu->tb)
- MEM_freeN(cu->tb);
+
+ MEM_SAFE_FREE(cu->mat);
+ MEM_SAFE_FREE(cu->str);
+ MEM_SAFE_FREE(cu->strinfo);
+ MEM_SAFE_FREE(cu->bb);
+ MEM_SAFE_FREE(cu->tb);
}
void BKE_curve_init(Curve *cu)
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index f06dd6f9de4..a8268c03d95 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -139,9 +139,6 @@ void free_partdeflect(PartDeflect *pd)
if (!pd)
return;
- if (pd->tex)
- id_us_min(&pd->tex->id);
-
if (pd->rng)
BLI_rng_free(pd->rng);
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 812d1c66923..5e1f8814ed6 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -95,10 +95,9 @@ void BKE_vfont_free_data(struct VFont *vfont)
}
}
+/** Free (or release) any data used by this font (does not free the font itself). */
void BKE_vfont_free(struct VFont *vf)
{
- if (vf == NULL) return;
-
BKE_vfont_free_data(vf);
if (vf->packedfile) {
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index f3eb5430bce..af1bcd0c545 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -113,16 +113,13 @@ void free_gpencil_layers(ListBase *list)
}
/* Free all of GPencil datablock's related data, but not the block itself */
+/** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
void BKE_gpencil_free(bGPdata *gpd)
{
+ BKE_animdata_free(&gpd->id, false);
+
/* free layers */
free_gpencil_layers(&gpd->layers);
-
- /* free animation data */
- if (gpd->adt) {
- BKE_animdata_free(&gpd->id);
- gpd->adt = NULL;
- }
}
/* -------- Container Creation ---------- */
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index a44eb1df9fe..4fdee7e3633 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -60,79 +60,19 @@ static void free_group_object(GroupObject *go)
MEM_freeN(go);
}
-
+/** Free (or release) any data used by this group (does not free the group itself). */
void BKE_group_free(Group *group)
{
/* don't free group itself */
GroupObject *go;
- BKE_previewimg_free(&group->preview);
+ /* No animdata here. */
while ((go = BLI_pophead(&group->gobject))) {
free_group_object(go);
}
-}
-void BKE_group_unlink(Main *bmain, Group *group)
-{
- Material *ma;
- Object *ob;
- Scene *sce;
- SceneRenderLayer *srl;
- ParticleSystem *psys;
-
- for (ma = bmain->mat.first; ma; ma = ma->id.next) {
- if (ma->group == group)
- ma->group = NULL;
- }
- for (ma = bmain->mat.first; ma; ma = ma->id.next) {
- if (ma->group == group)
- ma->group = NULL;
- }
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- Base *base = sce->base.first;
-
- /* ensure objects are not in this group */
- for (; base; base = base->next) {
- if (BKE_group_object_unlink(group, base->object, sce, base) &&
- BKE_group_object_find(NULL, base->object) == NULL)
- {
- base->object->flag &= ~OB_FROMGROUP;
- base->flag &= ~OB_FROMGROUP;
- }
- }
-
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- FreestyleLineSet *lineset;
-
- if (srl->light_override == group)
- srl->light_override = NULL;
- for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
- if (lineset->group == group)
- lineset->group = NULL;
- }
- }
- }
-
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
-
- if (ob->dup_group == group) {
- ob->dup_group = NULL;
- }
-
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys->part->dup_group == group)
- psys->part->dup_group = NULL;
-#if 0 /* not used anymore, only keps for readfile.c, no need to account for this */
- if (psys->part->eff_group == group)
- psys->part->eff_group = NULL;
-#endif
- }
- }
-
- /* group stays in library, but no members */
- BKE_group_free(group);
- group->id.us = 0;
+ BKE_previewimg_free(&group->preview);
}
Group *BKE_group_add(Main *bmain, const char *name)
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 0b2c844cb2c..14a445649ad 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -324,20 +324,16 @@ void BKE_image_free_buffers(Image *ima)
ima->ok = IMA_OK;
}
-/* called by library too, do not free ima itself */
+/** Free (or release) any data used by this image (does not free the image itself). */
void BKE_image_free(Image *ima)
{
int a;
+ /* Also frees animdata. */
BKE_image_free_buffers(ima);
image_free_packedfiles(ima);
- BKE_icon_id_delete(&ima->id);
- ima->id.icon_id = 0;
-
- BKE_previewimg_free(&ima->preview);
-
for (a = 0; a < IMA_MAX_RENDER_SLOT; a++) {
if (ima->renders[a]) {
RE_FreeRenderResult(ima->renders[a]);
@@ -346,7 +342,10 @@ void BKE_image_free(Image *ima)
}
BKE_image_free_views(ima);
- MEM_freeN(ima->stereo3d_format);
+ MEM_SAFE_FREE(ima->stereo3d_format);
+
+ BKE_icon_id_delete(&ima->id);
+ BKE_previewimg_free(&ima->preview);
}
/* only image block itself */
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 362f41335d2..2517e2cc197 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -74,11 +74,13 @@
#define IPO_BEZTRIPLE 100
#define IPO_BPOINT 101
+
+/** Free (or release) any data used by this shapekey (does not free the key itself). */
void BKE_key_free(Key *key)
{
KeyBlock *kb;
-
- BKE_animdata_free((ID *)key);
+
+ BKE_animdata_free((ID *)key, false);
while ((kb = BLI_pophead(&key->block))) {
if (kb->data)
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 49a573489ef..692b703f721 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -234,7 +234,7 @@ void BKE_lamp_free(Lamp *la)
MEM_freeN(mtex);
}
- BKE_animdata_free((ID *)la);
+ BKE_animdata_free((ID *)la, false);
curvemapping_free(la->curfalloff);
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index b350e932281..58c0a567116 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -300,24 +300,27 @@ Lattice *BKE_lattice_copy(Lattice *lt)
return ltn;
}
+/** Free (or release) any data used by this lattice (does not free the lattice itself). */
void BKE_lattice_free(Lattice *lt)
{
- if (lt->def) MEM_freeN(lt->def);
- if (lt->dvert) BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ BKE_animdata_free(&lt->id, false);
+
+ MEM_SAFE_FREE(lt->def);
+ if (lt->dvert) {
+ BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ lt->dvert = NULL;
+ }
if (lt->editlatt) {
Lattice *editlt = lt->editlatt->latt;
- if (editlt->def) MEM_freeN(editlt->def);
- if (editlt->dvert) BKE_defvert_array_free(editlt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ if (editlt->def)
+ MEM_freeN(editlt->def);
+ if (editlt->dvert)
+ BKE_defvert_array_free(editlt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
MEM_freeN(editlt);
MEM_freeN(lt->editlatt);
- }
-
- /* free animation data */
- if (lt->adt) {
- BKE_animdata_free(&lt->id);
- lt->adt = NULL;
+ lt->editlatt = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 961b45df4e6..fe16df18813 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -84,7 +84,6 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
-#include "BKE_fcurve.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_group.h"
@@ -92,7 +91,6 @@
#include "BKE_idcode.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
-#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
@@ -103,16 +101,12 @@
#include "BKE_material.h"
#include "BKE_main.h"
#include "BKE_mball.h"
-#include "BKE_movieclip.h"
#include "BKE_mask.h"
#include "BKE_node.h"
#include "BKE_object.h"
-#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_packedFile.h"
#include "BKE_speaker.h"
-#include "BKE_sound.h"
-#include "BKE_screen.h"
#include "BKE_scene.h"
#include "BKE_text.h"
#include "BKE_texture.h"
@@ -125,10 +119,6 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
-#ifdef WITH_PYTHON
-#include "BPY_extern.h"
-#endif
-
/* GS reads the memory pointed at in a specific ordering.
* only use this definition, makes little and big endian systems
* work fine, in conjunction with MAKE_ID */
@@ -182,7 +172,6 @@ void id_us_ensure_real(ID *id)
}
}
-/* Unused currently... */
void id_us_clear_real(ID *id)
{
if (id && (id->tag & LIB_TAG_EXTRAUSER)) {
@@ -232,9 +221,7 @@ void id_us_min(ID *id)
if (id->us <= limit) {
printf("ID user decrement error: %s (from '%s'): %d <= %d\n",
id->name, id->lib ? id->lib->filepath : "[Main]", id->us, limit);
- /* We cannot assert here, because of how we 'delete' datablocks currently (setting their usercount to zero),
- * this is weak but it's how it works for now. */
- /* BLI_assert(0); */
+ BLI_assert(0);
id->us = limit;
}
else {
@@ -462,37 +449,6 @@ bool id_copy(ID *id, ID **newid, bool test)
return false;
}
-bool id_unlink(ID *id, int test)
-{
- Main *mainlib = G.main;
- short type = GS(id->name);
-
- switch (type) {
- case ID_TXT:
- if (test) return true;
- BKE_text_unlink(mainlib, (Text *)id);
- break;
- case ID_GR:
- if (test) return true;
- BKE_group_unlink(mainlib, (Group *)id);
- break;
- case ID_OB:
- if (test) return true;
- BKE_object_unlink(mainlib, (Object *)id);
- break;
- }
-
- if (id->us == 0) {
- if (test) return true;
-
- BKE_libblock_free(mainlib, id);
-
- return true;
- }
-
- return false;
-}
-
bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
{
ID *newid = NULL;
@@ -1111,234 +1067,12 @@ void BKE_libblock_relink(ID *id)
BKE_library_foreach_ID_link(id, id_relink_looper, NULL, 0);
}
-static void BKE_library_free(Library *lib)
+void BKE_library_free(Library *lib)
{
if (lib->packedfile)
freePackedFile(lib->packedfile);
}
-static BKE_library_free_window_manager_cb free_windowmanager_cb = NULL;
-
-void BKE_library_callback_free_window_manager_set(BKE_library_free_window_manager_cb func)
-{
- free_windowmanager_cb = func;
-}
-
-static BKE_library_free_notifier_reference_cb free_notifier_reference_cb = NULL;
-
-void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func)
-{
- free_notifier_reference_cb = func;
-}
-
-static BKE_library_free_editor_id_reference_cb free_editor_id_reference_cb = NULL;
-
-void BKE_library_callback_free_editor_id_reference_set(BKE_library_free_editor_id_reference_cb func)
-{
- free_editor_id_reference_cb = func;
-}
-
-static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
-{
- ChannelDriver *driver;
- FCurve *fcu;
-
- /* find the driver this belongs to and update it */
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- driver = fcu->driver;
-
- if (driver) {
- DriverVar *dvar;
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- DRIVER_TARGETS_USED_LOOPER(dvar)
- {
- if (dtar->id == userdata)
- dtar->id = NULL;
- }
- DRIVER_TARGETS_LOOPER_END
- }
- }
- }
-}
-
-void BKE_libblock_free_data(Main *bmain, ID *id)
-{
- if (id->properties) {
- IDP_FreeProperty(id->properties);
- MEM_freeN(id->properties);
- }
-
- /* this ID may be a driver target! */
- BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id);
-}
-
-/* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */
-void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
-{
- ID *id = idv;
- short type = GS(id->name);
- ListBase *lb = which_libbase(bmain, type);
-
- DAG_id_type_tag(bmain, type);
-
-#ifdef WITH_PYTHON
- BPY_id_release(id);
-#endif
-
- switch (type) { /* GetShort from util.h */
- case ID_SCE:
- BKE_scene_free((Scene *)id);
- break;
- case ID_LI:
- BKE_library_free((Library *)id);
- break;
- case ID_OB:
- BKE_object_free_ex((Object *)id, do_id_user);
- break;
- case ID_ME:
- BKE_mesh_free((Mesh *)id, 1);
- break;
- case ID_CU:
- BKE_curve_free((Curve *)id);
- break;
- case ID_MB:
- BKE_mball_free((MetaBall *)id);
- break;
- case ID_MA:
- BKE_material_free((Material *)id);
- break;
- case ID_TE:
- BKE_texture_free((Tex *)id);
- break;
- case ID_IM:
- BKE_image_free((Image *)id);
- break;
- case ID_LT:
- BKE_lattice_free((Lattice *)id);
- break;
- case ID_LA:
- BKE_lamp_free((Lamp *)id);
- break;
- case ID_CA:
- BKE_camera_free((Camera *) id);
- break;
- case ID_IP:
- BKE_ipo_free((Ipo *)id);
- break;
- case ID_KE:
- BKE_key_free((Key *)id);
- break;
- case ID_WO:
- BKE_world_free((World *)id);
- break;
- case ID_SCR:
- BKE_screen_free((bScreen *)id);
- break;
- case ID_VF:
- BKE_vfont_free((VFont *)id);
- break;
- case ID_TXT:
- BKE_text_free((Text *)id);
- break;
- case ID_SPK:
- BKE_speaker_free((Speaker *)id);
- break;
- case ID_SO:
- BKE_sound_free((bSound *)id);
- break;
- case ID_GR:
- BKE_group_free((Group *)id);
- break;
- case ID_AR:
- BKE_armature_free((bArmature *)id);
- break;
- case ID_AC:
- BKE_action_free((bAction *)id);
- break;
- case ID_NT:
- ntreeFreeTree_ex((bNodeTree *)id, do_id_user);
- break;
- case ID_BR:
- BKE_brush_free((Brush *)id);
- break;
- case ID_PA:
- BKE_particlesettings_free((ParticleSettings *)id);
- break;
- case ID_WM:
- if (free_windowmanager_cb)
- free_windowmanager_cb(NULL, (wmWindowManager *)id);
- break;
- case ID_GD:
- BKE_gpencil_free((bGPdata *)id);
- break;
- case ID_MC:
- BKE_movieclip_free((MovieClip *)id);
- break;
- case ID_MSK:
- BKE_mask_free(bmain, (Mask *)id);
- break;
- case ID_LS:
- BKE_linestyle_free((FreestyleLineStyle *)id);
- break;
- case ID_PAL:
- BKE_palette_free((Palette *)id);
- break;
- case ID_PC:
- BKE_paint_curve_free((PaintCurve *)id);
- break;
- }
-
- /* avoid notifying on removed data */
- BKE_main_lock(bmain);
-
- if (free_notifier_reference_cb) {
- free_notifier_reference_cb(id);
- }
-
- if (free_editor_id_reference_cb) {
- free_editor_id_reference_cb(id);
- }
-
- BLI_remlink(lb, id);
-
- BKE_libblock_free_data(bmain, id);
- BKE_main_unlock(bmain);
-
- MEM_freeN(id);
-}
-
-void BKE_libblock_free(Main *bmain, void *idv)
-{
- BKE_libblock_free_ex(bmain, idv, true);
-}
-
-void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */
-{
- ID *id = idv;
-
- id_us_min(id);
-
- /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding groups when deleting an object.
- * Since only 'user_one' usage of objects is groups, and only 'real user' usage of objects is scenes,
- * removing that 'user_one' tag when there is no more real (scene) users of an object ensures it gets
- * fully unlinked.
- * Otherwise, there is no real way to get rid of an object anymore - better handling of this is TODO.
- */
- if ((GS(id->name) == ID_OB) && (id->us == 1)) {
- id_us_clear_real(id);
- }
-
- if (id->us == 0) {
- switch (GS(id->name)) {
- case ID_OB:
- BKE_object_unlink(bmain, (Object *)id);
- break;
- }
-
- BKE_libblock_free(bmain, id);
- }
-}
-
Main *BKE_main_new(void)
{
Main *bmain = MEM_callocN(sizeof(Main), "new main");
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 4fe408e755a..be3dde2753a 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -29,6 +29,7 @@
#include <stdlib.h>
+#include "MEM_guardedalloc.h"
#include "DNA_actuator_types.h"
#include "DNA_anim_types.h"
@@ -61,6 +62,7 @@
#include "DNA_world_types.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_ghash.h"
#include "BLI_linklist_stack.h"
@@ -69,6 +71,7 @@
#include "BKE_fcurve.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
+#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_rigidbody.h"
@@ -198,9 +201,24 @@ static void library_foreach_actuatorsObjectLooper(
FOREACH_FINALIZE_VOID;
}
+static void library_foreach_nla_strip(LibraryForeachIDData *data, NlaStrip *strip)
+{
+ NlaStrip *substrip;
+
+ FOREACH_CALLBACK_INVOKE(data, strip->act, IDWALK_USER);
+
+ for (substrip = strip->strips.first; substrip; substrip = substrip->next) {
+ library_foreach_nla_strip(data, substrip);
+ }
+
+ FOREACH_FINALIZE_VOID;
+}
+
static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *adt)
{
FCurve *fcu;
+ NlaTrack *nla_track;
+ NlaStrip *nla_strip;
for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
ChannelDriver *driver = fcu->driver;
@@ -216,6 +234,15 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *
}
}
+ FOREACH_CALLBACK_INVOKE(data, adt->action, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, adt->tmpact, IDWALK_USER);
+
+ for (nla_track = adt->nla_tracks.first; nla_track; nla_track = nla_track->next) {
+ for (nla_strip = nla_track->strips.first; nla_strip; nla_strip = nla_strip->next) {
+ library_foreach_nla_strip(data, nla_strip);
+ }
+ }
+
FOREACH_FINALIZE_VOID;
}
@@ -276,6 +303,12 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
switch (GS(id->name)) {
+ case ID_LI:
+ {
+ Library *lib = (Library *) id;
+ CALLBACK_INVOKE(lib->parent, IDWALK_NOP);
+ break;
+ }
case ID_SCE:
{
Scene *scene = (Scene *) id;
@@ -287,7 +320,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
CALLBACK_INVOKE(scene->world, IDWALK_USER);
CALLBACK_INVOKE(scene->set, IDWALK_NOP);
CALLBACK_INVOKE(scene->clip, IDWALK_USER);
- CALLBACK_INVOKE(scene->nodetree, IDWALK_NOP);
+ if (scene->nodetree) {
+ /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
+ BKE_library_foreach_ID_link((ID *)scene->nodetree, callback, user_data, flag);
+ }
/* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later,
* since basact is just a pointer to one of those items. */
CALLBACK_INVOKE(scene->obedit, IDWALK_NOP);
@@ -438,6 +474,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data);
}
+ if (object->soft && object->soft->effector_weights) {
+ CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_NOP);
+ }
+
BKE_sca_sensors_id_loop(&object->sensors, library_foreach_sensorsObjectLooper, &data);
BKE_sca_controllers_id_loop(&object->controllers, library_foreach_controllersObjectLooper, &data);
BKE_sca_actuators_id_loop(&object->actuators, library_foreach_actuatorsObjectLooper, &data);
@@ -489,7 +529,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
library_foreach_mtex(&data, material->mtex[i]);
}
}
- CALLBACK_INVOKE(material->nodetree, IDWALK_NOP);
+ if (material->nodetree) {
+ /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
+ BKE_library_foreach_ID_link((ID *)material->nodetree, callback, user_data, flag);
+ }
CALLBACK_INVOKE(material->group, IDWALK_USER);
break;
}
@@ -497,7 +540,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_TE:
{
Tex *texture = (Tex *) id;
- CALLBACK_INVOKE(texture->nodetree, IDWALK_NOP);
+ if (texture->nodetree) {
+ /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
+ BKE_library_foreach_ID_link((ID *)texture->nodetree, callback, user_data, flag);
+ }
CALLBACK_INVOKE(texture->ima, IDWALK_USER);
if (texture->env) {
CALLBACK_INVOKE(texture->env->object, IDWALK_NOP);
@@ -527,7 +573,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
library_foreach_mtex(&data, lamp->mtex[i]);
}
}
- CALLBACK_INVOKE(lamp->nodetree, IDWALK_NOP);
+ if (lamp->nodetree) {
+ /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
+ BKE_library_foreach_ID_link((ID *)lamp->nodetree, callback, user_data, flag);
+ }
break;
}
@@ -560,7 +609,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
library_foreach_mtex(&data, world->mtex[i]);
}
}
- CALLBACK_INVOKE(world->nodetree, IDWALK_NOP);
+ if (world->nodetree) {
+ /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
+ BKE_library_foreach_ID_link((ID *)world->nodetree, callback, user_data, flag);
+ }
break;
}
@@ -700,7 +752,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
library_foreach_mtex(&data, linestyle->mtex[i]);
}
}
- CALLBACK_INVOKE(linestyle->nodetree, IDWALK_NOP);
+ if (linestyle->nodetree) {
+ /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
+ BKE_library_foreach_ID_link((ID *)linestyle->nodetree, callback, user_data, flag);
+ }
for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) {
if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
@@ -769,11 +824,18 @@ typedef struct IDUsersIter {
int count; /* Set by callback. */
} IDUsersIter;
-static int foreach_libblock_id_users_callback(void *user_data, ID *UNUSED(self_id), ID **id_p, int UNUSED(cb_flag))
+static int foreach_libblock_id_users_callback(void *user_data, ID *UNUSED(self_id), ID **id_p, int cb_flag)
{
IDUsersIter *iter = user_data;
if (*id_p && (*id_p == iter->id)) {
+#if 0
+ printf("%s uses %s (refcounted: %d, userone: %d, used_one: %d, used_one_active: %d)\n",
+ iter->curr_id->name, iter->id->name, (cb_flag & IDWALK_USER) ? 1 : 0, (cb_flag & IDWALK_USER_ONE) ? 1 : 0,
+ (iter->id->tag & LIB_TAG_EXTRAUSER) ? 1 : 0, (iter->id->tag & LIB_TAG_EXTRAUSER_SET) ? 1 : 0);
+#else
+ UNUSED_VARS(cb_flag);
+#endif
iter->count++;
}
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
new file mode 100644
index 00000000000..4bde0752ef3
--- /dev/null
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -0,0 +1,768 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/library_remap.c
+ * \ingroup bke
+ *
+ * Contains management of ID's and libraries remap, unlink and free logic.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+
+#include "MEM_guardedalloc.h"
+
+/* all types are needed here, in order to do memory operations */
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_group_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_linestyle_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_mask_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_speaker_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_text_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_world_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_action.h"
+#include "BKE_animsys.h"
+#include "BKE_armature.h"
+#include "BKE_brush.h"
+#include "BKE_camera.h"
+#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
+#include "BKE_font.h"
+#include "BKE_group.h"
+#include "BKE_gpencil.h"
+#include "BKE_idprop.h"
+#include "BKE_image.h"
+#include "BKE_ipo.h"
+#include "BKE_key.h"
+#include "BKE_lamp.h"
+#include "BKE_lattice.h"
+#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
+#include "BKE_linestyle.h"
+#include "BKE_mesh.h"
+#include "BKE_material.h"
+#include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_movieclip.h"
+#include "BKE_mask.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_particle.h"
+#include "BKE_speaker.h"
+#include "BKE_sound.h"
+#include "BKE_screen.h"
+#include "BKE_scene.h"
+#include "BKE_text.h"
+#include "BKE_texture.h"
+#include "BKE_world.h"
+
+#ifdef WITH_PYTHON
+#include "BPY_extern.h"
+#endif
+
+static BKE_library_free_window_manager_cb free_windowmanager_cb = NULL;
+
+void BKE_library_callback_free_window_manager_set(BKE_library_free_window_manager_cb func)
+{
+ free_windowmanager_cb = func;
+}
+
+static BKE_library_free_notifier_reference_cb free_notifier_reference_cb = NULL;
+
+void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func)
+{
+ free_notifier_reference_cb = func;
+}
+
+static BKE_library_remap_editor_id_reference_cb remap_editor_id_reference_cb = NULL;
+
+void BKE_library_callback_remap_editor_id_reference_set(BKE_library_remap_editor_id_reference_cb func)
+{
+ remap_editor_id_reference_cb = func;
+}
+
+typedef struct IDRemap {
+ ID *old_id;
+ ID *new_id;
+ ID *id; /* The ID in which we are replacing old_id by new_id usages. */
+ short flag;
+
+ /* 'Output' data. */
+ short status;
+ int skipped_direct; /* Number of direct usecases that could not be remapped (e.g.: obdata when in edit mode). */
+ int skipped_indirect; /* Number of indirect usecases that could not be remapped. */
+ int skipped_refcounted; /* Number of skipped usecases that refcount the datablock. */
+} IDRemap;
+
+/* IDRemap->flag enums defined in BKE_library.h */
+
+/* IDRemap->status */
+enum {
+ /* *** Set by callback. *** */
+ ID_REMAP_IS_LINKED_DIRECT = 1 << 0, /* new_id is directly linked in current .blend. */
+ ID_REMAP_IS_USER_ONE_SKIPPED = 1 << 1, /* There was some skipped 'user_one' usages of old_id. */
+};
+
+static int foreach_libblock_remap_callback(void *user_data, ID *UNUSED(id_self), ID **id_p, int cb_flag)
+{
+ IDRemap *id_remap_data = user_data;
+ ID *old_id = id_remap_data->old_id;
+ ID *new_id = id_remap_data->new_id;
+ ID *id = id_remap_data->id;
+
+ if (!old_id) { /* Used to cleanup all IDs used by a specific one. */
+ BLI_assert(!new_id);
+ old_id = *id_p;
+ }
+
+ if (*id_p && (*id_p == old_id)) {
+ /* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
+ * on the other hand since they get reset to lib data on file open/reload it is indirect too...
+ * Edit Mode is also a 'skip direct' case. */
+ const bool is_obj = (GS(id->name) == ID_OB);
+ const bool is_proxy = (is_obj && (((Object *)id)->proxy || ((Object *)id)->proxy_group));
+ const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
+ /* Note that indirect data from same file as processed ID is **not** considered indirect! */
+ const bool is_indirect = ((id->lib != NULL) && (id->lib != old_id->lib));
+ const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
+ const bool is_never_null = ((cb_flag & IDWALK_NEVER_NULL) && (new_id == NULL) &&
+ (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
+ const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
+
+ if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_NEVER_NULL)) {
+ id->tag |= LIB_TAG_DOIT;
+ }
+
+ /* Special hack in case it's Object->data and we are in edit mode (skipped_direct too). */
+ if ((is_never_null && skip_never_null) ||
+ (is_obj_editmode && (((Object *)id)->data == *id_p)) ||
+ (skip_indirect && (is_proxy || is_indirect)))
+ {
+ if (is_never_null || is_proxy || is_obj_editmode) {
+ id_remap_data->skipped_direct++;
+ }
+ else {
+ id_remap_data->skipped_indirect++;
+ }
+ if (cb_flag & IDWALK_USER) {
+ id_remap_data->skipped_refcounted++;
+ }
+ else if (cb_flag & IDWALK_USER_ONE) {
+ /* No need to count number of times this happens, just a flag is enough. */
+ id_remap_data->status |= ID_REMAP_IS_USER_ONE_SKIPPED;
+ }
+ }
+ else {
+ if (!is_never_null) {
+ *id_p = new_id;
+ }
+ if (cb_flag & IDWALK_USER) {
+ id_us_min(old_id);
+ /* We do not want to handle LIB_TAG_INDIRECT/LIB_TAG_EXTERN here. */
+ if (new_id)
+ new_id->us++;
+ }
+ else if (cb_flag & IDWALK_USER_ONE) {
+ id_us_ensure_real(new_id);
+ /* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET) are assumed to be set as needed,
+ * that extra user is processed in final handling... */
+ }
+ if (!is_indirect) {
+ id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
+ }
+ }
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+/**
+ * Execute the 'data' part of the remapping (that is, all ID pointers from other ID datablocks).
+ *
+ * Behavior differs depending on whether given \a id is NULL or not:
+ * - \a id NULL: \a old_id must be non-NULL, \a new_id may be NULL (unlinking \a old_id) or not
+ * (remapping \a old_id to \a new_id). The whole \a bmain database is checked, and all pointers to \a old_id
+ * are remapped to \a new_id.
+ * - \a id is non-NULL:
+ * + If \a old_id is NULL, \a new_id must also be NULL, and all ID pointers from \a id are cleared (i.e. \a id
+ * does not references any other datablock anymore).
+ * + If \a old_id is non-NULL, behavior is as with a NULL \a id, but only for given \a id.
+ *
+ * \param bmain: the Main data storage to operate on (can be NULL if \a id is non-NULL).
+ * \param id: the datablock to operate on (can be NULL if \a bmain is non-NULL).
+ * \param old_id: the datablock to dereference (may be NULL if \a id is non-NULL).
+ * \param new_id: the new datablock to replace \a old_id references with (may be NULL).
+ * \param r_id_remap_data: if non-NULL, the IDRemap struct to use (uselful to retrieve info about remapping process).
+ */
+static void libblock_remap_data(
+ Main *bmain, ID *id, ID *old_id, ID *new_id, const short remap_flags, IDRemap *r_id_remap_data)
+{
+ IDRemap id_remap_data;
+ ListBase *lb_array[MAX_LIBARRAY];
+ int i;
+
+ if (r_id_remap_data == NULL) {
+ r_id_remap_data = &id_remap_data;
+ }
+ r_id_remap_data->old_id = old_id;
+ r_id_remap_data->new_id = new_id;
+ r_id_remap_data->id = NULL;
+ r_id_remap_data->flag = remap_flags;
+ r_id_remap_data->status = 0;
+ r_id_remap_data->skipped_direct = 0;
+ r_id_remap_data->skipped_indirect = 0;
+ r_id_remap_data->skipped_refcounted = 0;
+
+ if (id) {
+#ifdef DEBUG_PRINT
+ printf("\tchecking id %s (%p, %p)\n", id->name, id, id->lib);
+#endif
+ r_id_remap_data->id = id;
+ BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+ }
+ else {
+ i = set_listbasepointers(bmain, lb_array);
+
+ /* Note that this is a very 'bruteforce' approach, maybe we could use some depsgraph to only process
+ * objects actually using given old_id... sounds rather unlikely currently, though, so this will do for now. */
+
+ while (i--) {
+ ID *id_curr = lb_array[i]->first;
+
+ for (; id_curr; id_curr = id_curr->next) {
+ /* Note that we cannot skip indirect usages of old_id here (if requested), we still need to check it for
+ * the user count handling...
+ * XXX No more true (except for debug usage of those skipping counters). */
+ r_id_remap_data->id = id_curr;
+ BKE_library_foreach_ID_link(
+ id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
+ }
+ }
+ }
+
+ /* XXX We may not want to always 'transfer' fakeuser from old to new id... Think for now it's desired behavior
+ * though, we can always add an option (flag) to control this later if needed. */
+ if (old_id && (old_id->flag & LIB_FAKEUSER)) {
+ id_fake_user_clear(old_id);
+ id_fake_user_set(new_id);
+ }
+
+ id_us_clear_real(old_id);
+
+ if (new_id && (new_id->tag & LIB_TAG_INDIRECT) && (r_id_remap_data->status & ID_REMAP_IS_LINKED_DIRECT)) {
+ new_id->tag &= ~LIB_TAG_INDIRECT;
+ new_id->tag |= LIB_TAG_EXTERN;
+ }
+
+#ifdef DEBUG_PRINT
+ printf("%s: %d occurences skipped (%d direct and %d indirect ones)\n", __func__,
+ r_id_remap_data->skipped_direct + r_id_remap_data->skipped_indirect,
+ r_id_remap_data->skipped_direct, r_id_remap_data->skipped_indirect);
+#endif
+}
+
+/**
+ * Replace all references in given Main to \a old_id by \a new_id
+ * (if \a new_id is NULL, it unlinks \a old_id).
+ */
+void BKE_libblock_remap_locked(
+ Main *bmain, void *old_idv, void *new_idv,
+ const short remap_flags)
+{
+ IDRemap id_remap_data;
+ ID *old_id = old_idv;
+ ID *new_id = new_idv;
+ int skipped_direct, skipped_refcounted;
+
+ BLI_assert(old_id != NULL);
+ BLI_assert((new_id == NULL) || GS(old_id->name) == GS(new_id->name));
+ BLI_assert(old_id != new_id);
+
+ /* Some pre-process updates.
+ * This is a bit ugly, but cannot see a way to avoid it. Maybe we should do a per-ID callback for this instead?
+ */
+ if (GS(old_id->name) == ID_OB) {
+ Object *old_ob = (Object *)old_id;
+ Object *new_ob = (Object *)new_id;
+
+ if (new_ob == NULL) {
+ Scene *sce;
+ Base *base;
+
+ for (sce = bmain->scene.first; sce; sce = sce->id.next) {
+ base = BKE_scene_base_find(sce, old_ob);
+
+ if (base) {
+ id_us_min((ID *)base->object);
+ BKE_scene_base_unlink(sce, base);
+ MEM_freeN(base);
+ }
+ }
+ }
+ }
+
+ libblock_remap_data(bmain, NULL, old_id, new_id, remap_flags, &id_remap_data);
+
+ if (free_notifier_reference_cb) {
+ free_notifier_reference_cb(old_id);
+ }
+
+ /* We assume editors do not hold references to their IDs... This is false in some cases
+ * (Image is especially tricky here), editors' code is to handle refcount (id->us) itself then. */
+ if (remap_editor_id_reference_cb) {
+ remap_editor_id_reference_cb(old_id, new_id);
+ }
+
+ skipped_direct = id_remap_data.skipped_direct;
+ skipped_refcounted = id_remap_data.skipped_refcounted;
+
+ /* If old_id was used by some ugly 'user_one' stuff (like Image or Clip editors...), and user count has actually
+ * been incremented for that, we have to decrease once more its user count... unless we had to skip
+ * some 'user_one' cases. */
+ if ((old_id->tag & LIB_TAG_EXTRAUSER_SET) && !(id_remap_data.status & ID_REMAP_IS_USER_ONE_SKIPPED)) {
+ id_us_min(old_id);
+ old_id->tag &= ~LIB_TAG_EXTRAUSER_SET;
+ }
+
+ BLI_assert(old_id->us - skipped_refcounted >= 0);
+ UNUSED_VARS_NDEBUG(skipped_refcounted);
+
+ if (skipped_direct == 0) {
+ /* old_id is assumed to not be used directly anymore... */
+ if (old_id->lib && (old_id->tag & LIB_TAG_EXTERN)) {
+ old_id->tag &= ~LIB_TAG_EXTERN;
+ old_id->tag |= LIB_TAG_INDIRECT;
+ }
+ }
+
+ /* Some after-process updates.
+ * This is a bit ugly, but cannot see a way to avoid it. Maybe we should do a per-ID callback for this instead?
+ */
+ switch (GS(old_id->name)) {
+ case ID_OB:
+ {
+ Object *old_ob = (Object *)old_id;
+ Object *new_ob = (Object *)new_id;
+
+ if (old_ob->flag & OB_FROMGROUP) {
+ /* Note that for Scene's BaseObject->flag, either we:
+ * - unlinked old_ob (i.e. new_ob is NULL), in which case scenes' bases have been removed already.
+ * - remaped old_ob by new_ob, in which case scenes' bases are still valid as is.
+ * So in any case, no need to update them here. */
+ if (BKE_group_object_find(NULL, old_ob) == NULL) {
+ old_ob->flag &= ~OB_FROMGROUP;
+ }
+ if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */
+ Group *group;
+ for (group = bmain->group.first; group; group = group->id.next) {
+ BKE_group_object_unlink(group, NULL, NULL, NULL);
+ }
+ }
+ else {
+ new_ob->flag |= OB_FROMGROUP;
+ }
+ }
+ break;
+ }
+ case ID_GR:
+ if (new_id == NULL) { /* Only affects us in case group was unlinked. */
+ for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+ /* Note that here we assume no object has no base (i.e. all objects are assumed instanced
+ * in one scene...). */
+ for (Base *base = sce->base.first; base; base = base->next) {
+ if (base->flag & OB_FROMGROUP) {
+ Object *ob = base->object;
+
+ if (ob->flag & OB_FROMGROUP) {
+ Group *grp = BKE_group_object_find(NULL, ob);
+
+ /* Unlinked group (old_id) is still in bmain... */
+ if (grp && (&grp->id == old_id)) {
+ grp = BKE_group_object_find(grp, ob);
+ }
+ if (!grp) {
+ ob->flag &= ~OB_FROMGROUP;
+ }
+ }
+ if (!(ob->flag & OB_FROMGROUP)) {
+ base->flag &= ~OB_FROMGROUP;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Full rebuild of DAG! */
+ DAG_relations_tag_update(bmain);
+}
+
+void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
+{
+ BKE_main_lock(bmain);
+
+ BKE_libblock_remap_locked(bmain, old_idv, new_idv, remap_flags);
+
+ BKE_main_unlock(bmain);
+}
+
+/**
+ * Unlink given \a id from given \a bmain (does not touch to indirect, i.e. library, usages of the ID).
+ *
+ * \param do_flag_never_null: If true, all IDs using \a idv in a 'non-NULL' way are flagged by \a LIB_TAG_DOIT flag
+ * (quite obviously, 'non-NULL' usages can never be unlinked by this function...).
+ */
+void BKE_libblock_unlink(Main *bmain, void *idv, const bool do_flag_never_null)
+{
+ const short remap_flags = ID_REMAP_SKIP_INDIRECT_USAGE | (do_flag_never_null ? ID_REMAP_FLAG_NEVER_NULL_USAGE : 0);
+
+ BKE_main_lock(bmain);
+
+ BKE_libblock_remap_locked(bmain, idv, NULL, remap_flags);
+
+ BKE_main_unlock(bmain);
+}
+
+/** Similar to libblock_remap, but only affects IDs used by given \a idv ID.
+ *
+ * \param old_idv: Unlike BKE_libblock_remap, can be NULL,
+ * in which case all ID usages by given \a idv will be cleared.
+ * \param us_min_never_null: If \a true and new_id is NULL,
+ * 'NEVER_NULL' ID usages keep their old id, but this one still gets its user count decremented
+ * (needed when given \a idv is going to be deleted right after being unlinked).
+ */
+/* Should be able to replace all _relink() funcs (constraints, rigidbody, etc.) ? */
+/* XXX Arg! Naming... :(
+ * _relink? avoids confusion with _remap, but is confusing with _unlink
+ * _remap_used_ids?
+ * _remap_datablocks?
+ * BKE_id_remap maybe?
+ * ... sigh
+ */
+void BKE_libblock_relink_ex(
+ void *idv, void *old_idv, void *new_idv, const bool us_min_never_null)
+{
+ ID *id = idv;
+ ID *old_id = old_idv;
+ ID *new_id = new_idv;
+ int remap_flags = us_min_never_null ? 0 : ID_REMAP_SKIP_NEVER_NULL_USAGE;
+
+ /* No need to lock here, we are only affecting given ID. */
+
+ BLI_assert(id);
+ if (old_id) {
+ BLI_assert((new_id == NULL) || GS(old_id->name) == GS(new_id->name));
+ BLI_assert(old_id != new_id);
+ }
+ else {
+ BLI_assert(new_id == NULL);
+ }
+
+ libblock_remap_data(NULL, id, old_id, new_id, remap_flags, NULL);
+}
+
+static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
+{
+ ChannelDriver *driver;
+ FCurve *fcu;
+
+ /* find the driver this belongs to and update it */
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ driver = fcu->driver;
+
+ if (driver) {
+ DriverVar *dvar;
+ for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ if (dtar->id == userdata)
+ dtar->id = NULL;
+ }
+ DRIVER_TARGETS_LOOPER_END
+ }
+ }
+ }
+}
+
+void BKE_libblock_free_data(Main *bmain, ID *id)
+{
+ if (id->properties) {
+ IDP_FreeProperty(id->properties);
+ MEM_freeN(id->properties);
+ }
+
+ /* this ID may be a driver target! */
+ BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id);
+}
+
+/**
+ * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
+ *
+ * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv.
+ */
+void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user)
+{
+ ID *id = idv;
+ short type = GS(id->name);
+ ListBase *lb = which_libbase(bmain, type);
+
+ DAG_id_type_tag(bmain, type);
+
+#ifdef WITH_PYTHON
+ BPY_id_release(id);
+#endif
+
+ if (do_id_user) {
+ BKE_libblock_relink_ex(id, NULL, NULL, true);
+ }
+
+ switch (type) {
+ case ID_SCE:
+ BKE_scene_free((Scene *)id);
+ break;
+ case ID_LI:
+ BKE_library_free((Library *)id);
+ break;
+ case ID_OB:
+ BKE_object_free((Object *)id);
+ break;
+ case ID_ME:
+ BKE_mesh_free((Mesh *)id);
+ break;
+ case ID_CU:
+ BKE_curve_free((Curve *)id);
+ break;
+ case ID_MB:
+ BKE_mball_free((MetaBall *)id);
+ break;
+ case ID_MA:
+ BKE_material_free((Material *)id);
+ break;
+ case ID_TE:
+ BKE_texture_free((Tex *)id);
+ break;
+ case ID_IM:
+ BKE_image_free((Image *)id);
+ break;
+ case ID_LT:
+ BKE_lattice_free((Lattice *)id);
+ break;
+ case ID_LA:
+ BKE_lamp_free((Lamp *)id);
+ break;
+ case ID_CA:
+ BKE_camera_free((Camera *) id);
+ break;
+ case ID_IP: /* Deprecated. */
+ BKE_ipo_free((Ipo *)id);
+ break;
+ case ID_KE:
+ BKE_key_free((Key *)id);
+ break;
+ case ID_WO:
+ BKE_world_free((World *)id);
+ break;
+ case ID_SCR:
+ BKE_screen_free((bScreen *)id);
+ break;
+ case ID_VF:
+ BKE_vfont_free((VFont *)id);
+ break;
+ case ID_TXT:
+ BKE_text_free((Text *)id);
+ break;
+ case ID_SPK:
+ BKE_speaker_free((Speaker *)id);
+ break;
+ case ID_SO:
+ BKE_sound_free((bSound *)id);
+ break;
+ case ID_GR:
+ BKE_group_free((Group *)id);
+ break;
+ case ID_AR:
+ BKE_armature_free((bArmature *)id);
+ break;
+ case ID_AC:
+ BKE_action_free((bAction *)id);
+ break;
+ case ID_NT:
+ ntreeFreeTree((bNodeTree *)id);
+ break;
+ case ID_BR:
+ BKE_brush_free((Brush *)id);
+ break;
+ case ID_PA:
+ BKE_particlesettings_free((ParticleSettings *)id);
+ break;
+ case ID_WM:
+ if (free_windowmanager_cb)
+ free_windowmanager_cb(NULL, (wmWindowManager *)id);
+ break;
+ case ID_GD:
+ BKE_gpencil_free((bGPdata *)id);
+ break;
+ case ID_MC:
+ BKE_movieclip_free((MovieClip *)id);
+ break;
+ case ID_MSK:
+ BKE_mask_free((Mask *)id);
+ break;
+ case ID_LS:
+ BKE_linestyle_free((FreestyleLineStyle *)id);
+ break;
+ case ID_PAL:
+ BKE_palette_free((Palette *)id);
+ break;
+ case ID_PC:
+ BKE_paint_curve_free((PaintCurve *)id);
+ break;
+ }
+
+ /* avoid notifying on removed data */
+ BKE_main_lock(bmain);
+
+ if (free_notifier_reference_cb) {
+ free_notifier_reference_cb(id);
+ }
+
+ if (remap_editor_id_reference_cb) {
+ remap_editor_id_reference_cb(id, NULL);
+ }
+
+ BLI_remlink(lb, id);
+
+ BKE_libblock_free_data(bmain, id);
+ BKE_main_unlock(bmain);
+
+ MEM_freeN(id);
+}
+
+void BKE_libblock_free(Main *bmain, void *idv)
+{
+ BKE_libblock_free_ex(bmain, idv, true);
+}
+
+void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */
+{
+ ID *id = idv;
+
+ id_us_min(id);
+
+ /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding groups when deleting an object.
+ * Since only 'user_one' usage of objects is groups, and only 'real user' usage of objects is scenes,
+ * removing that 'user_one' tag when there is no more real (scene) users of an object ensures it gets
+ * fully unlinked.
+ * Otherwise, there is no real way to get rid of an object anymore - better handling of this is TODO.
+ */
+ if ((GS(id->name) == ID_OB) && (id->us == 1)) {
+ id_us_clear_real(id);
+ }
+
+ if (id->us == 0) {
+ BKE_libblock_unlink(bmain, id, false);
+
+ BKE_libblock_free(bmain, id);
+ }
+}
+
+void BKE_libblock_delete(Main *bmain, void *idv)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int base_count, i;
+
+ base_count = set_listbasepointers(bmain, lbarray);
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ /* First tag all datablocks directly from target lib.
+ * Note that we go forward here, since we want to check dependencies before users (e.g. meshes before objects).
+ * Avoids to have to loop twice. */
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id;
+
+ for (id = lb->first; id; id = id->next) {
+ /* Note: in case we delete a library, we also delete all its datablocks! */
+ if ((id == (ID *)idv) || (id->lib == (Library *)idv) || (id->tag & LIB_TAG_DOIT)) {
+ id->tag |= LIB_TAG_DOIT;
+ /* Will tag 'never NULL' users of this ID too.
+ * Note that we cannot use BKE_libblock_unlink() here, since it would ignore indirect (and proxy!)
+ * links, this can lead to nasty crashing here in second, actual deleting loop.
+ * Also, this will also flag users of deleted data that cannot be unlinked
+ * (object using deleted obdata, etc.), so that they also get deleted. */
+ BKE_libblock_remap(bmain, id, NULL, ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE);
+ }
+ }
+ }
+
+ /* In usual reversed order, such that all usage of a given ID, even 'never NULL' ones, have been already cleared
+ * when we reach it (e.g. Objects being processed before meshes, they'll have already released their 'reference'
+ * over meshes when we come to freeing obdata). */
+ for (i = base_count; i--; ) {
+ ListBase *lb = lbarray[i];
+ ID *id, *id_next;
+
+ for (id = lb->first; id; id = id_next) {
+ id_next = id->next;
+ if (id->tag & LIB_TAG_DOIT) {
+ if (id->us != 0) {
+#ifdef DEBUG_PRINT
+ printf("%s: deleting %s (%d)\n", __func__, id->name, id->us);
+#endif
+ BLI_assert(id->us == 0);
+ }
+ BKE_libblock_free(bmain, id);
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 5a1dfc04045..30dc48819e9 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -125,26 +125,25 @@ FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name)
return linestyle;
}
+/** Free (or release) any data used by this linestyle (does not free the linestyle itself). */
void BKE_linestyle_free(FreestyleLineStyle *linestyle)
{
LineStyleModifier *m;
-
- MTex *mtex;
int a;
+ BKE_animdata_free(&linestyle->id, false);
+
for (a = 0; a < MAX_MTEX; a++) {
- mtex = linestyle->mtex[a];
- if (mtex && mtex->tex)
- id_us_min(&mtex->tex->id);
- if (mtex)
- MEM_freeN(mtex);
+ MEM_SAFE_FREE(linestyle->mtex[a]);
}
+
+ /* is no lib link block, but linestyle extension */
if (linestyle->nodetree) {
ntreeFreeTree(linestyle->nodetree);
MEM_freeN(linestyle->nodetree);
+ linestyle->nodetree = NULL;
}
- BKE_animdata_free(&linestyle->id);
while ((m = (LineStyleModifier *)linestyle->color_modifiers.first))
BKE_linestyle_color_modifier_remove(linestyle, m);
while ((m = (LineStyleModifier *)linestyle->alpha_modifiers.first))
@@ -1452,33 +1451,6 @@ char *BKE_linestyle_path_to_color_ramp(FreestyleLineStyle *linestyle, ColorBand
return NULL;
}
-void BKE_linestyle_target_object_unlink(FreestyleLineStyle *linestyle, struct Object *ob)
-{
- LineStyleModifier *m;
-
- for (m = (LineStyleModifier *)linestyle->color_modifiers.first; m; m = m->next) {
- if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
- if (((LineStyleColorModifier_DistanceFromObject *)m)->target == ob) {
- ((LineStyleColorModifier_DistanceFromObject *)m)->target = NULL;
- }
- }
- }
- for (m = (LineStyleModifier *)linestyle->alpha_modifiers.first; m; m = m->next) {
- if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
- if (((LineStyleAlphaModifier_DistanceFromObject *)m)->target == ob) {
- ((LineStyleAlphaModifier_DistanceFromObject *)m)->target = NULL;
- }
- }
- }
- for (m = (LineStyleModifier *)linestyle->thickness_modifiers.first; m; m = m->next) {
- if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
- if (((LineStyleThicknessModifier_DistanceFromObject *)m)->target == ob) {
- ((LineStyleThicknessModifier_DistanceFromObject *)m)->target = NULL;
- }
- }
- }
-}
-
bool BKE_linestyle_use_textures(FreestyleLineStyle *linestyle, const bool use_shading_nodes)
{
if (use_shading_nodes) {
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 930a3c487ec..94e53755ac4 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -1010,63 +1010,10 @@ void BKE_mask_layer_free_list(ListBase *masklayers)
}
}
-/** free for temp copy, but don't manage unlinking from other pointers */
-void BKE_mask_free_nolib(Mask *mask)
+/** Free (or release) any data used by this mask (does not free the mask itself). */
+void BKE_mask_free(Mask *mask)
{
- BKE_mask_layer_free_list(&mask->masklayers);
-}
-
-void BKE_mask_free(Main *bmain, Mask *mask)
-{
- bScreen *scr;
- ScrArea *area;
- SpaceLink *sl;
- Scene *scene;
-
- for (scr = bmain->screen.first; scr; scr = scr->id.next) {
- for (area = scr->areabase.first; area; area = area->next) {
- for (sl = area->spacedata.first; sl; sl = sl->next) {
- switch (sl->spacetype) {
- case SPACE_CLIP:
- {
- SpaceClip *sc = (SpaceClip *)sl;
-
- if (sc->mask_info.mask == mask) {
- sc->mask_info.mask = NULL;
- }
- break;
- }
- case SPACE_IMAGE:
- {
- SpaceImage *sima = (SpaceImage *)sl;
-
- if (sima->mask_info.mask == mask) {
- sima->mask_info.mask = NULL;
- }
- break;
- }
- }
- }
- }
- }
-
- for (scene = bmain->scene.first; scene; scene = scene->id.next) {
- if (scene->ed) {
- Sequence *seq;
-
- SEQ_BEGIN (scene->ed, seq)
- {
- if (seq->mask == mask) {
- seq->mask = NULL;
- }
- }
- SEQ_END
- }
- }
-
- FOREACH_NODETREE(bmain, ntree, id) {
- BKE_node_tree_unlink_id((ID *)mask, ntree);
- } FOREACH_NODETREE_END
+ BKE_animdata_free((ID *)mask, false);
/* free mask data */
BKE_mask_layer_free_list(&mask->masklayers);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 30f82a50ed9..db5ac54ada9 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -81,47 +81,33 @@ void init_def_material(void)
BKE_material_init(&defmaterial);
}
-/* not material itself */
+/** Free (or release) any data used by this material (does not free the material itself). */
void BKE_material_free(Material *ma)
{
- BKE_material_free_ex(ma, true);
-}
-
-/* not material itself */
-void BKE_material_free_ex(Material *ma, bool do_id_user)
-{
- MTex *mtex;
int a;
+
+ BKE_animdata_free((ID *)ma, false);
for (a = 0; a < MAX_MTEX; a++) {
- mtex = ma->mtex[a];
- if (do_id_user && mtex && mtex->tex)
- id_us_min(&mtex->tex->id);
- if (mtex)
- MEM_freeN(mtex);
+ MEM_SAFE_FREE(ma->mtex[a]);
}
- if (ma->ramp_col) MEM_freeN(ma->ramp_col);
- if (ma->ramp_spec) MEM_freeN(ma->ramp_spec);
-
- BKE_animdata_free((ID *)ma);
-
- if (ma->preview)
- BKE_previewimg_free(&ma->preview);
- BKE_icon_id_delete((struct ID *)ma);
- ma->id.icon_id = 0;
+ MEM_SAFE_FREE(ma->ramp_col);
+ MEM_SAFE_FREE(ma->ramp_spec);
/* is no lib link block, but material extension */
if (ma->nodetree) {
- ntreeFreeTree_ex(ma->nodetree, do_id_user);
+ ntreeFreeTree(ma->nodetree);
MEM_freeN(ma->nodetree);
+ ma->nodetree = NULL;
}
- if (ma->texpaintslot)
- MEM_freeN(ma->texpaintslot);
+ MEM_SAFE_FREE(ma->texpaintslot);
+
+ GPU_material_free(&ma->gpumaterial);
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
+ BKE_icon_id_delete((ID *)ma);
+ BKE_previewimg_free(&ma->preview);
}
void BKE_material_init(Material *ma)
@@ -1840,7 +1826,7 @@ void free_matcopybuf(void)
matcopybuf.ramp_spec = NULL;
if (matcopybuf.nodetree) {
- ntreeFreeTree_ex(matcopybuf.nodetree, false);
+ ntreeFreeTree(matcopybuf.nodetree);
MEM_freeN(matcopybuf.nodetree);
matcopybuf.nodetree = NULL;
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index d7019aa8458..685cd35fc20 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -66,28 +66,13 @@
/* Functions */
-void BKE_mball_unlink(MetaBall *mb)
+/** Free (or release) any data used by this mball (does not free the mball itself). */
+void BKE_mball_free(MetaBall *mb)
{
- int a;
-
- for (a = 0; a < mb->totcol; a++) {
- if (mb->mat[a])
- id_us_min(&mb->mat[a]->id);
- mb->mat[a] = NULL;
- }
-}
+ BKE_animdata_free((ID *)mb, false);
+ MEM_SAFE_FREE(mb->mat);
-/* do not free mball itself */
-void BKE_mball_free(MetaBall *mb)
-{
- BKE_mball_unlink(mb);
-
- if (mb->adt) {
- BKE_animdata_free((ID *)mb);
- mb->adt = NULL;
- }
- if (mb->mat) MEM_freeN(mb->mat);
BLI_freelistN(&mb->elems);
if (mb->disp.first) BKE_displist_free(&mb->disp);
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 2af78cca79f..4e47dfcce74 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -432,33 +432,11 @@ bool BKE_mesh_has_custom_loop_normals(Mesh *me)
* we need a more generic method, like the expand() functions in
* readfile.c */
-void BKE_mesh_unlink(Mesh *me)
-{
- int a;
-
- if (me == NULL) return;
-
- if (me->mat) {
- for (a = 0; a < me->totcol; a++) {
- if (me->mat[a])
- id_us_min(&me->mat[a]->id);
- me->mat[a] = NULL;
- }
- }
- if (me->key) {
- id_us_min(&me->key->id);
- }
- me->key = NULL;
-
- if (me->texcomesh) me->texcomesh = NULL;
-}
-
-/* do not free mesh itself */
-void BKE_mesh_free(Mesh *me, int unlink)
+/** Free (or release) any data used by this mesh (does not free the mesh itself). */
+void BKE_mesh_free(Mesh *me)
{
- if (unlink)
- BKE_mesh_unlink(me);
+ BKE_animdata_free(&me->id, false);
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
@@ -466,16 +444,10 @@ void BKE_mesh_free(Mesh *me, int unlink)
CustomData_free(&me->ldata, me->totloop);
CustomData_free(&me->pdata, me->totpoly);
- if (me->adt) {
- BKE_animdata_free(&me->id);
- me->adt = NULL;
- }
-
- if (me->mat) MEM_freeN(me->mat);
-
- if (me->bb) MEM_freeN(me->bb);
- if (me->mselect) MEM_freeN(me->mselect);
- if (me->edit_btmesh) MEM_freeN(me->edit_btmesh);
+ MEM_SAFE_FREE(me->mat);
+ MEM_SAFE_FREE(me->bb);
+ MEM_SAFE_FREE(me->mselect);
+ MEM_SAFE_FREE(me->edit_btmesh);
}
static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index d2bfcfb0887..5f667732b04 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -1248,7 +1248,7 @@ static void free_buffers(MovieClip *clip)
clip->anim = NULL;
}
- BKE_animdata_free((ID *) clip);
+ BKE_animdata_free((ID *) clip, false);
}
void BKE_movieclip_clear_cache(MovieClip *clip)
@@ -1482,8 +1482,10 @@ void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, stru
}
}
+/** Free (or release) any data used by this movie clip (does not free the clip itself). */
void BKE_movieclip_free(MovieClip *clip)
{
+ /* Also frees animdata. */
free_buffers(clip);
BKE_tracking_free(&clip->tracking);
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 2b381f6ff0b..d78ddc41e97 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1782,21 +1782,21 @@ static void free_localized_node_groups(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP && node->id) {
bNodeTree *ngroup = (bNodeTree *)node->id;
- ntreeFreeTree_ex(ngroup, false);
+ ntreeFreeTree(ngroup);
MEM_freeN(ngroup);
}
}
}
-/* do not free ntree itself here, BKE_libblock_free calls this function too */
-void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user)
+/** Free (or release) any data used by this nodetree (does not free the nodetree itself). */
+void ntreeFreeTree(bNodeTree *ntree)
{
bNodeTree *tntree;
bNode *node, *next;
bNodeSocket *sock, *nextsock;
-
- if (ntree == NULL) return;
-
+
+ BKE_animdata_free((ID *)ntree, false);
+
/* XXX hack! node trees should not store execution graphs at all.
* This should be removed when old tree types no longer require it.
* Currently the execution data for texture nodes remains in the tree
@@ -1820,29 +1820,10 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user)
/* unregister associated RNA types */
ntreeInterfaceTypeFree(ntree);
- BKE_animdata_free((ID *)ntree);
-
- id_us_min((ID *)ntree->gpd);
-
BLI_freelistN(&ntree->links); /* do first, then unlink_node goes fast */
for (node = ntree->nodes.first; node; node = next) {
next = node->next;
-
- /* ntreeUserIncrefID inline */
-
- /* XXX, this is correct, however when freeing the entire database
- * this ends up accessing freed data which isn't properly unlinking
- * its self from scene nodes, SO - for now prefer invalid usercounts
- * on free rather then bad memory access - Campbell */
-#if 0
- if (do_id_user) {
- id_us_min(node->id);
- }
-#else
- (void)do_id_user;
-#endif
-
node_free_node_ex(ntree, node, false, false);
}
@@ -1874,11 +1855,6 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user)
BKE_libblock_free_data(G.main, &ntree->id);
}
}
-/* same as ntreeFreeTree_ex but always manage users */
-void ntreeFreeTree(bNodeTree *ntree)
-{
- ntreeFreeTree_ex(ntree, true);
-}
void ntreeFreeCache(bNodeTree *ntree)
{
@@ -2165,7 +2141,7 @@ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
if (ntree->typeinfo->local_merge)
ntree->typeinfo->local_merge(localtree, ntree);
- ntreeFreeTree_ex(localtree, false);
+ ntreeFreeTree(localtree);
MEM_freeN(localtree);
}
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 65ee153e00b..d4ba70ee0a6 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -317,14 +317,14 @@ void BKE_object_free_derived_caches(Object *ob)
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
- if (me->bb) {
+ if (me && me->bb) {
me->bb->flag |= BOUNDBOX_DIRTY;
}
}
else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
Curve *cu = ob->data;
- if (cu->bb) {
+ if (cu && cu->bb) {
cu->bb->flag |= BOUNDBOX_DIRTY;
}
}
@@ -393,77 +393,52 @@ void BKE_object_free_caches(Object *object)
}
}
-/* do not free object itself */
-void BKE_object_free_ex(Object *ob, bool do_id_user)
+/** Free (or release) any data used by this object (does not free the object itself). */
+void BKE_object_free(Object *ob)
{
- int a;
-
+ BKE_animdata_free((ID *)ob, false);
+
BKE_object_free_modifiers(ob);
-
- /* disconnect specific data, but not for lib data (might be indirect data, can get relinked) */
- if (ob->data) {
- ID *id = ob->data;
- id_us_min(id);
- if (id->us == 0 && id->lib == NULL) {
- switch (ob->type) {
- case OB_MESH:
- BKE_mesh_unlink((Mesh *)id);
- break;
- case OB_CURVE:
- BKE_curve_unlink((Curve *)id);
- break;
- case OB_MBALL:
- BKE_mball_unlink((MetaBall *)id);
- break;
- }
- }
- ob->data = NULL;
- }
- if (ob->mat) {
- for (a = 0; a < ob->totcol; a++) {
- if (ob->mat[a])
- id_us_min(&ob->mat[a]->id);
- }
- MEM_freeN(ob->mat);
+ MEM_SAFE_FREE(ob->mat);
+ MEM_SAFE_FREE(ob->matbits);
+ MEM_SAFE_FREE(ob->iuser);
+ MEM_SAFE_FREE(ob->bb);
+
+ BLI_freelistN(&ob->defbase);
+ if (ob->pose) {
+ BKE_pose_free_ex(ob->pose, false);
+ ob->pose = NULL;
}
- if (ob->matbits) MEM_freeN(ob->matbits);
- ob->mat = NULL;
- ob->matbits = NULL;
- if (ob->iuser) MEM_freeN(ob->iuser);
- ob->iuser = NULL;
- if (ob->bb) MEM_freeN(ob->bb);
- ob->bb = NULL;
- if (ob->adt) BKE_animdata_free((ID *)ob);
- if (ob->poselib)
- id_us_min(&ob->poselib->id);
- if (ob->gpd)
- id_us_min(&ob->gpd->id);
- if (ob->defbase.first)
- BLI_freelistN(&ob->defbase);
- if (ob->pose)
- BKE_pose_free_ex(ob->pose, do_id_user);
- if (ob->mpath)
+ if (ob->mpath) {
animviz_free_motionpath(ob->mpath);
+ ob->mpath = NULL;
+ }
BKE_bproperty_free_list(&ob->prop);
-
+
free_sensors(&ob->sensors);
free_controllers(&ob->controllers);
free_actuators(&ob->actuators);
- BKE_constraints_free_ex(&ob->constraints, do_id_user);
+ BKE_constraints_free_ex(&ob->constraints, false);
free_partdeflect(ob->pd);
BKE_rigidbody_free_object(ob);
BKE_rigidbody_free_constraint(ob);
- if (ob->soft) sbFree(ob->soft);
- if (ob->bsoft) bsbFree(ob->bsoft);
- if (ob->gpulamp.first) GPU_lamp_free(ob);
+ if (ob->soft) {
+ sbFree(ob->soft);
+ ob->soft = NULL;
+ }
+ if (ob->bsoft) {
+ bsbFree(ob->bsoft);
+ ob->bsoft = NULL;
+ }
+ GPU_lamp_free(ob);
BKE_sculptsession_free(ob);
- if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids);
+ BLI_freelistN(&ob->pc_ids);
BLI_freelistN(&ob->lodlevels);
@@ -473,398 +448,12 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
if (ob->curve_cache->path)
free_path(ob->curve_cache->path);
MEM_freeN(ob->curve_cache);
+ ob->curve_cache = NULL;
}
BKE_previewimg_free(&ob->preview);
}
-void BKE_object_free(Object *ob)
-{
- BKE_object_free_ex(ob, true);
-}
-
-static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin, int UNUSED(cd_flag))
-{
- Object *unlinkOb = userData;
-
- if (*obpoin == unlinkOb) {
- *obpoin = NULL;
- // XXX: should this just be OB_RECALC_DATA?
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- }
-}
-
-void BKE_object_unlink(Main *bmain, Object *ob)
-{
- Object *obt;
- Material *mat;
- World *wrld;
- bScreen *sc;
- Scene *sce;
- SceneRenderLayer *srl;
- FreestyleLineSet *lineset;
- bNodeTree *ntree;
- Curve *cu;
- Tex *tex;
- Group *group;
- Camera *camera;
- bConstraint *con;
- //bActionStrip *strip; // XXX animsys
- ModifierData *md;
- ARegion *ar;
- RegionView3D *rv3d;
- LodLevel *lod;
- int a, found;
-
- unlink_controllers(&ob->controllers);
- unlink_actuators(&ob->actuators);
-
- /* check all objects: parents en bevels and fields, also from libraries */
- /* FIXME: need to check all animation blocks (drivers) */
- obt = bmain->object.first;
- while (obt) {
- if (obt->proxy == ob)
- obt->proxy = NULL;
- if (obt->proxy_from == ob) {
- obt->proxy_from = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_OB);
- }
- if (obt->proxy_group == ob)
- obt->proxy_group = NULL;
-
- if (obt->parent == ob) {
- obt->parent = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- }
-
- modifiers_foreachObjectLink(obt, unlink_object__unlinkModifierLinks, ob);
-
- if (ELEM(obt->type, OB_CURVE, OB_FONT)) {
- cu = obt->data;
-
- if (cu->bevobj == ob) {
- cu->bevobj = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- }
- if (cu->taperobj == ob) {
- cu->taperobj = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- }
- if (cu->textoncurve == ob) {
- cu->textoncurve = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- }
- }
- else if (obt->type == OB_ARMATURE && obt->pose) {
- bPoseChannel *pchan;
- for (pchan = obt->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == ob) {
- ct->tar = NULL;
- ct->subtarget[0] = '\0';
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- if (pchan->custom == ob)
- pchan->custom = NULL;
- }
- }
- else if (ELEM(OB_MBALL, ob->type, obt->type)) {
- if (BKE_mball_is_basis_for(obt, ob))
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- }
-
- sca_remove_ob_poin(obt, ob);
-
- for (con = obt->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == ob) {
- ct->tar = NULL;
- ct->subtarget[0] = '\0';
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
-
- /* object is deflector or field */
- if (ob->pd) {
- if (obt->soft)
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
-
- /* cloth */
- for (md = obt->modifiers.first; md; md = md->next)
- if (md->type == eModifierType_Cloth)
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- }
-
- /* strips */
-#if 0 // XXX old animation system
- for (strip = obt->nlastrips.first; strip; strip = strip->next) {
- if (strip->object == ob)
- strip->object = NULL;
-
- if (strip->modifiers.first) {
- bActionModifier *amod;
- for (amod = strip->modifiers.first; amod; amod = amod->next)
- if (amod->ob == ob)
- amod->ob = NULL;
- }
- }
-#endif // XXX old animation system
-
- /* particle systems */
- if (obt->particlesystem.first) {
- ParticleSystem *tpsys = obt->particlesystem.first;
- for (; tpsys; tpsys = tpsys->next) {
- BoidState *state = NULL;
- BoidRule *rule = NULL;
-
- ParticleTarget *pt = tpsys->targets.first;
- for (; pt; pt = pt->next) {
- if (pt->ob == ob) {
- pt->ob = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- break;
- }
- }
-
- if (tpsys->target_ob == ob) {
- tpsys->target_ob = NULL;
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- }
-
- if (tpsys->part->dup_ob == ob)
- tpsys->part->dup_ob = NULL;
-
- if (tpsys->part->phystype == PART_PHYS_BOIDS) {
- ParticleData *pa;
- BoidParticle *bpa;
- int p;
-
- for (p = 0, pa = tpsys->particles; p < tpsys->totpart; p++, pa++) {
- bpa = pa->boid;
- if (bpa->ground == ob)
- bpa->ground = NULL;
- }
- }
- if (tpsys->part->boids) {
- for (state = tpsys->part->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- if (rule->type == eBoidRuleType_Avoid) {
- BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
- if (gabr->ob == ob)
- gabr->ob = NULL;
- }
- else if (rule->type == eBoidRuleType_FollowLeader) {
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
- if (flbr->ob == ob)
- flbr->ob = NULL;
- }
- }
- }
- }
-
- if (tpsys->parent == ob)
- tpsys->parent = NULL;
- }
- if (ob->pd)
- DAG_id_tag_update(&obt->id, OB_RECALC_DATA);
- }
-
- /* levels of detail */
- for (lod = obt->lodlevels.first; lod; lod = lod->next) {
- if (lod->source == ob)
- lod->source = NULL;
- }
-
- obt = obt->id.next;
- }
-
- /* materials */
- for (mat = bmain->mat.first; mat; mat = mat->id.next) {
- if (mat->nodetree) {
- ntreeSwitchID(mat->nodetree, &ob->id, NULL);
- }
- for (a = 0; a < MAX_MTEX; a++) {
- if (mat->mtex[a] && ob == mat->mtex[a]->object) {
- /* actually, test for lib here... to do */
- mat->mtex[a]->object = NULL;
- }
- }
- }
-
- /* node trees */
- for (ntree = bmain->nodetree.first; ntree; ntree = ntree->id.next) {
- if (ntree->type == NTREE_SHADER)
- ntreeSwitchID(ntree, &ob->id, NULL);
- }
-
- /* textures */
- for (tex = bmain->tex.first; tex; tex = tex->id.next) {
- if (tex->env && (ob == tex->env->object)) tex->env->object = NULL;
- if (tex->pd && (ob == tex->pd->object)) tex->pd->object = NULL;
- if (tex->vd && (ob == tex->vd->object)) tex->vd->object = NULL;
- }
-
- /* worlds */
- wrld = bmain->world.first;
- while (wrld) {
- if (wrld->id.lib == NULL) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (wrld->mtex[a] && ob == wrld->mtex[a]->object)
- wrld->mtex[a]->object = NULL;
- }
- }
-
- wrld = wrld->id.next;
- }
-
- /* scenes */
- sce = bmain->scene.first;
- while (sce) {
- if (sce->id.lib == NULL) {
- if (sce->camera == ob) sce->camera = NULL;
- if (sce->toolsettings->skgen_template == ob) sce->toolsettings->skgen_template = NULL;
- if (sce->toolsettings->particle.object == ob) sce->toolsettings->particle.object = NULL;
- if (sce->toolsettings->particle.shape_object == ob) sce->toolsettings->particle.shape_object = NULL;
-
-#ifdef DURIAN_CAMERA_SWITCH
- {
- TimeMarker *m;
-
- for (m = sce->markers.first; m; m = m->next) {
- if (m->camera == ob)
- m->camera = NULL;
- }
- }
-#endif
- if (sce->ed) {
- Sequence *seq;
- SEQ_BEGIN(sce->ed, seq)
- {
- if (seq->scene_camera == ob) {
- seq->scene_camera = NULL;
- }
- }
- SEQ_END
- }
-
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- for (lineset = (FreestyleLineSet *)srl->freestyleConfig.linesets.first;
- lineset; lineset = lineset->next)
- {
- if (lineset->linestyle) {
- BKE_linestyle_target_object_unlink(lineset->linestyle, ob);
- }
- }
- }
- }
-
- sce = sce->id.next;
- }
-
- /* screens */
- sc = bmain->screen.first;
- while (sc) {
- ScrArea *sa = sc->areabase.first;
- while (sa) {
- SpaceLink *sl;
-
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *) sl;
-
- /* found doesn't need to be set here */
- if (v3d->ob_centre == ob) {
- v3d->ob_centre = NULL;
- v3d->ob_centre_bone[0] = '\0';
- }
- if (v3d->localvd && v3d->localvd->ob_centre == ob) {
- v3d->localvd->ob_centre = NULL;
- v3d->localvd->ob_centre_bone[0] = '\0';
- }
-
- found = 0;
- if (v3d->camera == ob) {
- v3d->camera = NULL;
- found = 1;
- }
- if (v3d->localvd && v3d->localvd->camera == ob) {
- v3d->localvd->camera = NULL;
- found += 2;
- }
-
- if (found) {
- if (sa->spacetype == SPACE_VIEW3D) {
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- rv3d = (RegionView3D *)ar->regiondata;
- if (found == 1 || found == 3) {
- if (rv3d->persp == RV3D_CAMOB)
- rv3d->persp = RV3D_PERSP;
- }
- if (found == 2 || found == 3) {
- if (rv3d->localvd && rv3d->localvd->persp == RV3D_CAMOB)
- rv3d->localvd->persp = RV3D_PERSP;
- }
- }
- }
- }
- }
- }
-#if 0
- else if (ELEM(sl->spacetype, SPACE_OUTLINER, SPACE_BUTS, SPACE_NODE)) {
- /* now handled by WM_main_remove_editor_id_reference */
- }
-#endif
- }
-
- sa = sa->next;
- }
- sc = sc->id.next;
- }
-
- /* groups */
- group = bmain->group.first;
- while (group) {
- BKE_group_object_unlink(group, ob, NULL, NULL);
- group = group->id.next;
- }
-
- /* cameras */
- camera = bmain->camera.first;
- while (camera) {
- if (camera->dof_ob == ob) {
- camera->dof_ob = NULL;
- }
- camera = camera->id.next;
- }
-}
-
/* actual check for internal data, not context or flags */
bool BKE_object_is_in_editmode(Object *ob)
{
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 3a2663c5d48..8c1502643c5 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -298,13 +298,11 @@ void BKE_paint_brush_set(Paint *p, Brush *br)
}
}
+/** Free (or release) any data used by this paint curve (does not free the pcurve itself). */
void BKE_paint_curve_free(PaintCurve *pc)
{
- if (pc->points) {
- MEM_freeN(pc->points);
- pc->points = NULL;
- pc->tot_points = 0;
- }
+ MEM_SAFE_FREE(pc->points);
+ pc->tot_points = 0;
}
PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name)
@@ -378,6 +376,7 @@ Palette *BKE_palette_add(Main *bmain, const char *name)
return palette;
}
+/** Free (or release) any data used by this palette (does not free the palette itself). */
void BKE_palette_free(Palette *palette)
{
BLI_freelistN(&palette->colors);
@@ -493,8 +492,6 @@ void BKE_paint_init(Scene *sce, PaintMode mode, const char col[3])
void BKE_paint_free(Paint *paint)
{
- id_us_min((ID *)paint->brush);
- id_us_min((ID *)paint->palette);
curvemapping_free(paint->cavity_curve);
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 25dd7fff380..633227d68f3 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -376,12 +376,17 @@ static void fluid_free_settings(SPHFluidSettings *fluid)
MEM_freeN(fluid);
}
+/** Free (or release) any data used by this particle settings (does not free the partsett itself). */
void BKE_particlesettings_free(ParticleSettings *part)
{
- MTex *mtex;
int a;
- BKE_animdata_free(&part->id);
+
+ BKE_animdata_free((ID *)part, false);
+ for (a = 0; a < MAX_MTEX; a++) {
+ MEM_SAFE_FREE(part->mtex[a]);
+ }
+
if (part->clumpcurve)
curvemapping_free(part->clumpcurve);
if (part->roughcurve)
@@ -390,21 +395,12 @@ void BKE_particlesettings_free(ParticleSettings *part)
free_partdeflect(part->pd);
free_partdeflect(part->pd2);
- if (part->effector_weights)
- MEM_freeN(part->effector_weights);
+ MEM_SAFE_FREE(part->effector_weights);
BLI_freelistN(&part->dupliweights);
boid_free_settings(part->boids);
fluid_free_settings(part->fluid);
-
- for (a = 0; a < MAX_MTEX; a++) {
- mtex = part->mtex[a];
- if (mtex && mtex->tex)
- id_us_min(&mtex->tex->id);
- if (mtex)
- MEM_freeN(mtex);
- }
}
void free_hair(Object *UNUSED(ob), ParticleSystem *psys, int dynamics)
@@ -573,10 +569,7 @@ void psys_free(Object *ob, ParticleSystem *psys)
if (!nr)
ob->transflag &= ~OB_DUPLIPARTS;
- if (psys->part) {
- id_us_min(&psys->part->id);
- psys->part = NULL;
- }
+ psys->part = NULL;
BKE_ptcache_free_list(&psys->ptcaches);
psys->pointcache = NULL;
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index e90a39e8c0e..a468420f87d 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -653,77 +653,6 @@ void set_sca_new_poins(void)
}
}
-void sca_remove_ob_poin(Object *obt, Object *ob)
-{
- bSensor *sens;
- bMessageSensor *ms;
- bActuator *act;
- bCameraActuator *ca;
- bObjectActuator *oa;
- bSceneActuator *sa;
- bEditObjectActuator *eoa;
- bPropertyActuator *pa;
- bMessageActuator *ma;
- bParentActuator *para;
- bArmatureActuator *aa;
- bSteeringActuator *sta;
-
-
- sens= obt->sensors.first;
- while (sens) {
- switch (sens->type) {
- case SENS_MESSAGE:
- ms= sens->data;
- if (ms->fromObject==ob) ms->fromObject= NULL;
- }
- sens= sens->next;
- }
-
- act= obt->actuators.first;
- while (act) {
- switch (act->type) {
- case ACT_CAMERA:
- ca= act->data;
- if (ca->ob==ob) ca->ob= NULL;
- break;
- case ACT_OBJECT:
- oa= act->data;
- if (oa->reference==ob) oa->reference= NULL;
- break;
- case ACT_PROPERTY:
- pa= act->data;
- if (pa->ob==ob) pa->ob= NULL;
- break;
- case ACT_SCENE:
- sa= act->data;
- if (sa->camera==ob) sa->camera= NULL;
- break;
- case ACT_EDIT_OBJECT:
- eoa= act->data;
- if (eoa->ob==ob) eoa->ob= NULL;
- break;
- case ACT_MESSAGE:
- ma= act->data;
- if (ma->toObject==ob) ma->toObject= NULL;
- break;
- case ACT_PARENT:
- para = act->data;
- if (para->ob==ob) para->ob = NULL;
- break;
- case ACT_ARMATURE:
- aa = act->data;
- if (aa->target == ob) aa->target = NULL;
- if (aa->subtarget == ob) aa->subtarget = NULL;
- break;
- case ACT_STEERING:
- sta = act->data;
- if (sta->navmesh == ob) sta->navmesh = NULL;
- if (sta->target == ob) sta->target = NULL;
- }
- act= act->next;
- }
-}
-
/* ******************** INTERFACE ******************* */
void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up)
{
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index a3393b6b9c0..0e8efca04d0 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -357,41 +357,34 @@ void BKE_scene_groups_relink(Scene *sce)
BKE_rigidbody_world_groups_relink(sce->rigidbody_world);
}
-/* do not free scene itself */
+/** Free (or release) any data used by this scene (does not free the scene itself). */
void BKE_scene_free(Scene *sce)
{
- Base *base;
SceneRenderLayer *srl;
+ BKE_animdata_free((ID *)sce, false);
+
/* check all sequences */
BKE_sequencer_clear_scene_in_allseqs(G.main, sce);
- base = sce->base.first;
- while (base) {
- id_us_min(&base->object->id);
- base = base->next;
- }
- /* do not free objects! */
-
- if (sce->gpd) {
-#if 0 /* removed since this can be invalid memory when freeing everything */
- /* since the grease pencil data is freed before the scene.
- * since grease pencil data is not (yet?), shared between objects
- * its probably safe not to do this, some save and reload will free this. */
- id_us_min(&sce->gpd->id);
-#endif
- sce->gpd = NULL;
- }
-
+ sce->basact = NULL;
BLI_freelistN(&sce->base);
BKE_sequencer_editing_free(sce);
- BKE_animdata_free((ID *)sce);
BKE_keyingsets_free(&sce->keyingsets);
-
- if (sce->rigidbody_world)
+
+ /* is no lib link block, but scene extension */
+ if (sce->nodetree) {
+ ntreeFreeTree(sce->nodetree);
+ MEM_freeN(sce->nodetree);
+ sce->nodetree = NULL;
+ }
+
+ if (sce->rigidbody_world) {
BKE_rigidbody_free_world(sce->rigidbody_world);
-
+ sce->rigidbody_world = NULL;
+ }
+
if (sce->r.avicodecdata) {
free_avicodecdata(sce->r.avicodecdata);
MEM_freeN(sce->r.avicodecdata);
@@ -444,15 +437,8 @@ void BKE_scene_free(Scene *sce)
if (sce->depsgraph)
DEG_graph_free(sce->depsgraph);
- if (sce->nodetree) {
- ntreeFreeTree(sce->nodetree);
- MEM_freeN(sce->nodetree);
- }
-
- if (sce->stats)
- MEM_freeN(sce->stats);
- if (sce->fps_info)
- MEM_freeN(sce->fps_info);
+ MEM_SAFE_FREE(sce->stats);
+ MEM_SAFE_FREE(sce->fps_info);
BKE_sound_destroy_scene(sce);
@@ -904,40 +890,6 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
return NULL;
}
-void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
-{
- Scene *sce1;
- bScreen *screen;
-
- /* check all sets */
- for (sce1 = bmain->scene.first; sce1; sce1 = sce1->id.next)
- if (sce1->set == sce)
- sce1->set = NULL;
-
- for (sce1 = bmain->scene.first; sce1; sce1 = sce1->id.next) {
- bNode *node;
-
- if (sce1 == sce || !sce1->nodetree)
- continue;
-
- for (node = sce1->nodetree->nodes.first; node; node = node->next) {
- if (node->id == &sce->id)
- node->id = NULL;
- }
- }
-
- /* all screens */
- for (screen = bmain->screen.first; screen; screen = screen->id.next) {
- if (screen->scene == sce) {
- screen->scene = newsce;
- }
-
- /* editors are handled by WM_main_remove_editor_id_reference */
- }
-
- BKE_libblock_free(bmain, sce);
-}
-
/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
Scene **scene, int val, Base **base, Object **ob)
@@ -1193,6 +1145,8 @@ void BKE_scene_base_unlink(Scene *sce, Base *base)
BKE_rigidbody_remove_object(sce, base->object);
BLI_remlink(&sce->base, base);
+ if (sce->basact == base)
+ sce->basact = NULL;
}
void BKE_scene_base_deselect_all(Scene *sce)
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 139c6670f74..857bd5447c8 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -273,17 +273,18 @@ void BKE_spacedata_draw_locks(int set)
}
}
-static void (*spacedata_id_unref_cb)(struct SpaceLink *sl, const struct ID *id) = NULL;
+static void (*spacedata_id_remap_cb)(struct ScrArea *sa, struct SpaceLink *sl, ID *old_id, ID *new_id) = NULL;
-void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *))
+void BKE_spacedata_callback_id_remap_set(void (*func)(ScrArea *sa, SpaceLink *sl, ID *, ID *))
{
- spacedata_id_unref_cb = func;
+ spacedata_id_remap_cb = func;
}
-void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id)
+/* UNUSED!!! */
+void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID *id)
{
- if (spacedata_id_unref_cb) {
- spacedata_id_unref_cb(sl, id);
+ if (spacedata_id_remap_cb) {
+ spacedata_id_remap_cb(sa, sl, id, NULL);
}
}
@@ -358,11 +359,13 @@ void BKE_screen_area_free(ScrArea *sa)
BLI_freelistN(&sa->actionzones);
}
-/* don't free screen itself */
+/** Free (or release) any data used by this screen (does not free the screen itself). */
void BKE_screen_free(bScreen *sc)
{
ScrArea *sa, *san;
ARegion *ar;
+
+ /* No animdata here. */
for (ar = sc->regionbase.first; ar; ar = ar->next)
BKE_area_region_free(NULL, ar);
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index c82f3a3af23..5ef502e0182 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -3092,7 +3092,7 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr
BKE_maskrasterize_handle_init(mr_handle, mask_temp, context->rectx, context->recty, true, true, true);
- BKE_mask_free_nolib(mask_temp);
+ BKE_mask_free(mask_temp);
MEM_freeN(mask_temp);
BKE_maskrasterize_buffer(mr_handle, context->rectx, context->recty, maskbuf);
@@ -5154,7 +5154,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
info = AUD_getInfo(sound->playback_handle);
if (info.specs.channels == AUD_CHANNELS_INVALID) {
- BKE_sound_delete(bmain, sound);
+ BKE_libblock_free(bmain, sound);
#if 0
if (op)
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index b016f8a49ed..414be73e234 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -123,8 +123,11 @@ bSound *BKE_sound_new_file_exists(struct Main *bmain, const char *filepath)
return BKE_sound_new_file_exists_ex(bmain, filepath, NULL);
}
+/** Free (or release) any data used by this sound (does not free the sound itself). */
void BKE_sound_free(bSound *sound)
{
+ /* No animdata here. */
+
if (sound->packedfile) {
freePackedFile(sound->packedfile);
sound->packedfile = NULL;
@@ -148,8 +151,7 @@ void BKE_sound_free(bSound *sound)
BLI_spin_end(sound->spinlock);
MEM_freeN(sound->spinlock);
sound->spinlock = NULL;
- }
-
+ }
#endif /* WITH_AUDASPACE */
}
@@ -315,15 +317,6 @@ bSound *BKE_sound_new_limiter(struct Main *bmain, bSound *source, float start, f
}
#endif
-void BKE_sound_delete(struct Main *bmain, bSound *sound)
-{
- if (sound) {
- BKE_sound_free(sound);
-
- BKE_libblock_free(bmain, sound);
- }
-}
-
void BKE_sound_cache(bSound *sound)
{
sound->flags |= SOUND_FLAGS_CACHING;
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index c452065fbad..e5075a2d382 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -141,8 +141,5 @@ void BKE_speaker_make_local(Speaker *spk)
void BKE_speaker_free(Speaker *spk)
{
- if (spk->sound)
- id_us_min(&spk->sound->id);
-
- BKE_animdata_free((ID *)spk);
+ BKE_animdata_free((ID *)spk, false);
}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 6def9e3e503..594f9dffbee 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -171,14 +171,17 @@ void BKE_text_free_lines(Text *text)
text->curl = text->sell = NULL;
}
+/** Free (or release) any data used by this text (does not free the text itself). */
void BKE_text_free(Text *text)
{
+ /* No animdata here. */
+
BKE_text_free_lines(text);
- if (text->name) MEM_freeN(text->name);
- MEM_freeN(text->undo_buf);
+ MEM_SAFE_FREE(text->name);
+ MEM_SAFE_FREE(text->undo_buf);
#ifdef WITH_PYTHON
- if (text->compiled) BPY_text_free_code(text);
+ BPY_text_free_code(text);
#endif
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index d353042b711..9326ece7a4b 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -557,23 +557,38 @@ int colorband_element_remove(struct ColorBand *coba, int index)
/* ******************* TEX ************************ */
+/** Free (or release) any data used by this texture (does not free the texure itself). */
void BKE_texture_free(Tex *tex)
{
- if (tex->coba) MEM_freeN(tex->coba);
- if (tex->env) BKE_texture_envmap_free(tex->env);
- if (tex->pd) BKE_texture_pointdensity_free(tex->pd);
- if (tex->vd) BKE_texture_voxeldata_free(tex->vd);
- if (tex->ot) BKE_texture_ocean_free(tex->ot);
- BKE_animdata_free((struct ID *)tex);
-
- BKE_previewimg_free(&tex->preview);
- BKE_icon_id_delete((struct ID *)tex);
- tex->id.icon_id = 0;
-
+ BKE_animdata_free((ID *)tex, false);
+
+ /* is no lib link block, but texture extension */
if (tex->nodetree) {
ntreeFreeTree(tex->nodetree);
MEM_freeN(tex->nodetree);
+ tex->nodetree = NULL;
}
+
+ MEM_SAFE_FREE(tex->coba);
+ if (tex->env) {
+ BKE_texture_envmap_free(tex->env);
+ tex->env = NULL;
+ }
+ if (tex->pd) {
+ BKE_texture_pointdensity_free(tex->pd);
+ tex->pd = NULL;
+ }
+ if (tex->vd) {
+ BKE_texture_voxeldata_free(tex->vd);
+ tex->vd = NULL;
+ }
+ if (tex->ot) {
+ BKE_texture_ocean_free(tex->ot);
+ tex->ot = NULL;
+ }
+
+ BKE_icon_id_delete((ID *)tex);
+ BKE_previewimg_free(&tex->preview);
}
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 17a2e7f14fd..ec021586be5 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -52,38 +52,28 @@
#include "GPU_material.h"
-void BKE_world_free_ex(World *wrld, bool do_id_user)
+/** Free (or release) any data used by this world (does not free the world itself). */
+void BKE_world_free(World *wrld)
{
- MTex *mtex;
int a;
-
+
+ BKE_animdata_free((ID *)wrld, false);
+
for (a = 0; a < MAX_MTEX; a++) {
- mtex = wrld->mtex[a];
- if (do_id_user && mtex && mtex->tex)
- id_us_min(&mtex->tex->id);
- if (mtex)
- MEM_freeN(mtex);
+ MEM_SAFE_FREE(wrld->mtex[a]);
}
- BKE_previewimg_free(&wrld->preview);
-
- BKE_animdata_free((ID *)wrld);
/* is no lib link block, but world extension */
if (wrld->nodetree) {
- ntreeFreeTree_ex(wrld->nodetree, do_id_user);
+ ntreeFreeTree(wrld->nodetree);
MEM_freeN(wrld->nodetree);
+ wrld->nodetree = NULL;
}
- if (wrld->gpumaterial.first)
- GPU_material_free(&wrld->gpumaterial);
+ GPU_material_free(&wrld->gpumaterial);
BKE_icon_id_delete((struct ID *)wrld);
- wrld->id.icon_id = 0;
-}
-
-void BKE_world_free(World *wrld)
-{
- BKE_world_free_ex(wrld, true);
+ BKE_previewimg_free(&wrld->preview);
}
void BKE_world_init(World *wrld)
diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp
index 220b4e908a6..d6e5fdf86bb 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_MaskOperation.cpp
@@ -94,7 +94,7 @@ void MaskOperation::initExecution()
frame_iter += frame_step;
}
- BKE_mask_free_nolib(mask_temp);
+ BKE_mask_free(mask_temp);
MEM_freeN(mask_temp);
}
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 8822c8511de..c98470fb194 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -2119,7 +2119,7 @@ static int animchannels_clean_empty_exec(bContext *C, wmOperator *UNUSED(op))
/* remove AnimData? */
if (action_empty && nla_empty && drivers_empty) {
- BKE_animdata_free(id);
+ BKE_animdata_free(id, true);
}
}
diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h
index 9a987d7618c..64c16605dec 100644
--- a/source/blender/editors/include/ED_buttons.h
+++ b/source/blender/editors/include/ED_buttons.h
@@ -37,6 +37,4 @@ bool ED_texture_context_check_particles(const struct bContext *C);
bool ED_texture_context_check_linestyle(const struct bContext *C);
bool ED_texture_context_check_others(const struct bContext *C);
-void ED_buttons_id_unref(struct SpaceButs *sbuts, const struct ID *id);
-
#endif /* __ED_BUTTONS_H__ */
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 7fe9a0c320c..f7b9d6b4f9e 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -103,8 +103,6 @@ void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNod
void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree, struct Scene *scene_owner);
-void ED_node_id_unref(struct SpaceNode *snode, const ID *id);
-
/* node_ops.c */
void ED_operatormacros_node(void);
diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h
index af4af8e2f5d..73ee2542247 100644
--- a/source/blender/editors/include/ED_outliner.h
+++ b/source/blender/editors/include/ED_outliner.h
@@ -27,10 +27,4 @@
#ifndef __ED_OUTLINER_H__
#define __ED_OUTLINER_H__
-struct ID;
-struct SpaceOops;
-
-/* Used to check whether a given texture context is valid in current context. */
-void ED_outliner_id_unref(struct SpaceOops *so, const struct ID *id);
-
#endif /* __ED_OUTLINER_H__ */
diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h
index f143ea478c6..b6b80b93e0b 100644
--- a/source/blender/editors/include/ED_util.h
+++ b/source/blender/editors/include/ED_util.h
@@ -43,7 +43,7 @@ void ED_editors_exit(struct bContext *C);
bool ED_editors_flush_edits(const struct bContext *C, bool for_render);
-void ED_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id);
+void ED_spacedata_id_remap(struct ScrArea *sa, struct SpaceLink *sl, struct ID *old_id, struct ID *new_id);
void ED_OT_flush_edits(struct wmOperatorType *ot);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index c23c2eed890..baab6b6100d 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -403,4 +403,6 @@ void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View
#define V3D_IS_ZBUF(v3d) \
(((v3d)->flag & V3D_ZBUF_SELECT) && ((v3d)->drawtype > OB_WIRE))
+void ED_view3d_id_remap(struct View3D *v3d, const struct ID *old_id, struct ID *new_id);
+
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 8b16b2a977e..62656d75b9a 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -637,7 +637,7 @@ static void free_undo(void *um_v)
MEM_freeN(me->key);
}
- BKE_mesh_free(me, false);
+ BKE_mesh_free(me);
MEM_freeN(me);
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 09c9442db54..f85c76291cd 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1112,7 +1112,6 @@ void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
BKE_scene_base_unlink(scene, base);
object_delete_check_glsl_update(base->object);
BKE_libblock_free_us(bmain, base->object);
- if (scene->basact == base) scene->basact = NULL;
MEM_freeN(base);
}
@@ -1288,7 +1287,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
basen->object = ob;
/* make sure apply works */
- BKE_animdata_free(&ob->id);
+ BKE_animdata_free(&ob->id, true);
ob->adt = NULL;
/* Proxies are not to be copied. */
@@ -1380,7 +1379,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
}
- /* The same how BKE_object_unlink detects which object proxies to clear. */
if (base->object->transflag & OB_DUPLIGROUP && base->object->dup_group) {
for (object = bmain->object.first; object; object = object->id.next) {
if (object->proxy_group == base->object) {
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 76a8a68c42d..2b87a890f0f 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -43,6 +43,7 @@
#include "BKE_depsgraph.h"
#include "BKE_group.h"
#include "BKE_library.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_object.h"
@@ -527,7 +528,8 @@ static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op))
if (!group)
return OPERATOR_CANCELLED;
- BKE_group_unlink(bmain, group);
+ BKE_libblock_unlink(bmain, group, false);
+ BKE_libblock_free(bmain, group);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index f4260a0cd33..132c3fa5438 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -70,6 +70,7 @@
#include "BKE_icons.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
@@ -830,7 +831,7 @@ static void shader_preview_free(void *customdata)
/* get rid of copied material */
BLI_remlink(&pr_main->mat, sp->matcopy);
- BKE_material_free_ex(sp->matcopy, false);
+ BKE_material_free(sp->matcopy);
properties = IDP_GetProperties((ID *)sp->matcopy, false);
if (properties) {
@@ -862,7 +863,9 @@ static void shader_preview_free(void *customdata)
/* get rid of copied world */
BLI_remlink(&pr_main->world, sp->worldcopy);
- BKE_world_free_ex(sp->worldcopy, true); /* [#32865] - we need to unlink the texture copies, unlike for materials */
+ /* T32865 - we need to unlink the texture copies, unlike for materials */
+ BKE_libblock_relink_ex(sp->worldcopy, NULL, NULL, true);
+ BKE_world_free(sp->worldcopy);
properties = IDP_GetProperties((ID *)sp->worldcopy, false);
if (properties) {
@@ -878,6 +881,7 @@ static void shader_preview_free(void *customdata)
/* get rid of copied lamp */
BLI_remlink(&pr_main->lamp, sp->lampcopy);
+ BKE_libblock_relink_ex(sp->lampcopy, NULL, NULL, true);
BKE_lamp_free(sp->lampcopy);
properties = IDP_GetProperties((ID *)sp->lampcopy, false);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index a459f982ada..62aeca4b9d1 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -45,6 +45,7 @@
#include "BKE_image.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_screen.h"
@@ -1755,7 +1756,9 @@ bool ED_screen_delete_scene(bContext *C, Scene *scene)
ED_screen_set_scene(C, CTX_wm_screen(C), newscene);
- BKE_scene_unlink(bmain, scene, newscene);
+ BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
+
+ BKE_libblock_free(bmain, scene);
return true;
}
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index a4d9a920cbb..4931426d62e 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -116,7 +116,7 @@ static int sound_open_exec(bContext *C, wmOperator *op)
info = AUD_getInfo(sound->playback_handle);
if (info.specs.channels == AUD_CHANNELS_INVALID) {
- BKE_sound_delete(bmain, sound);
+ BKE_libblock_free(bmain, sound);
if (op->customdata) MEM_freeN(op->customdata);
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 60240109432..671d6bb083e 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -33,6 +33,7 @@
#include <stdio.h>
#include "DNA_action_types.h"
+#include "DNA_group_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -614,6 +615,19 @@ static void action_refresh(const bContext *C, ScrArea *sa)
// XXX re-sizing y-extents of tot should go here?
}
+static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceAction *sact = (SpaceAction *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_GR)) {
+ return;
+ }
+
+ if ((ID *)sact->ads.filter_grp == old_id) {
+ sact->ads.filter_grp = (Group *)new_id;
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_action(void)
{
@@ -631,7 +645,8 @@ void ED_spacetype_action(void)
st->keymap = action_keymap;
st->listener = action_listener;
st->refresh = action_refresh;
-
+ st->id_remap = action_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 42e2d6b90f0..5b03bdd7761 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -1180,33 +1180,3 @@ ID *buttons_context_id_path(const bContext *C)
return NULL;
}
-
-void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id)
-{
- if (sbuts->pinid == id) {
- sbuts->pinid = NULL;
- sbuts->flag &= ~SB_PIN_CONTEXT;
- }
-
- if (sbuts->path) {
- ButsContextPath *path = sbuts->path;
- int i;
-
- for (i = 0; i < path->len; i++) {
- if (path->ptr[i].id.data == id) {
- break;
- }
- }
-
- if (i == path->len) {
- /* pass */
- }
- else if (i == 0) {
- MEM_SAFE_FREE(sbuts->path);
- }
- else {
- memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
- path->len = i;
- }
- }
-}
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 126a27c36cb..e4c23ad74f8 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -45,6 +45,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "RNA_access.h"
+
#include "buttons_intern.h" /* own include */
/* ******************** default callbacks for buttons space ***************** */
@@ -389,6 +391,59 @@ static void buttons_area_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *
ED_area_tag_redraw(sa);
}
+static void buttons_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceButs *sbuts = (SpaceButs *)slink;
+
+ if (sbuts->pinid == old_id) {
+ sbuts->pinid = new_id;
+ if (new_id == NULL) {
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
+ }
+
+ if (sbuts->path) {
+ ButsContextPath *path = sbuts->path;
+ int i;
+
+ for (i = 0; i < path->len; i++) {
+ if (path->ptr[i].id.data == old_id) {
+ break;
+ }
+ }
+
+ if (i == path->len) {
+ /* pass */
+ }
+ else if (new_id == NULL) {
+ if (i == 0) {
+ MEM_SAFE_FREE(sbuts->path);
+ }
+ else {
+ memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
+ path->len = i;
+ }
+ }
+ else {
+ RNA_id_pointer_create(new_id, &path->ptr[i]);
+ /* There is no easy way to check/make path downwards valid, just nullify it.
+ * Next redraw will rebuild this anyway. */
+ i++;
+ memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i));
+ path->len = i;
+ }
+ }
+
+ if (sbuts->texuser) {
+ ButsContextTexture *ct = sbuts->texuser;
+ if ((ID *)ct->texture == old_id) {
+ ct->texture = (Tex *)new_id;
+ }
+ BLI_freelistN(&ct->users);
+ ct->user = NULL;
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_buttons(void)
{
@@ -406,7 +461,8 @@ void ED_spacetype_buttons(void)
st->keymap = buttons_keymap;
st->listener = buttons_area_listener;
st->context = buttons_context;
-
+ st->id_remap = buttons_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index e1d4e4fabc5..415839ab761 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -45,6 +45,7 @@
#include "BKE_context.h"
#include "BKE_screen.h"
+#include "BKE_library.h"
#include "BKE_movieclip.h"
#include "BKE_tracking.h"
@@ -1512,6 +1513,25 @@ static void clip_properties_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED
/********************* registration ********************/
+static void clip_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceClip *sclip = (SpaceClip *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_MC, ID_MSK)) {
+ return;
+ }
+
+ if ((ID *)sclip->clip == old_id) {
+ sclip->clip = (MovieClip *)new_id;
+ id_us_ensure_real(new_id);
+ }
+
+ if ((ID *)sclip->mask_info.mask == old_id) {
+ sclip->mask_info.mask = (Mask *)new_id;
+ id_us_ensure_real(new_id);
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_clip(void)
{
@@ -1531,6 +1551,7 @@ void ED_spacetype_clip(void)
st->context = clip_context;
st->dropboxes = clip_dropboxes;
st->refresh = clip_refresh;
+ st->id_remap = clip_id_remap;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype clip region");
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index c6a8a9753d1..a7284694f64 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -33,6 +33,7 @@
#include <stdio.h>
#include "DNA_anim_types.h"
+#include "DNA_group_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -627,6 +628,19 @@ static void graph_refresh(const bContext *C, ScrArea *sa)
}
}
+static void graph_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceIpo *sgraph = (SpaceIpo *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_GR)) {
+ return;
+ }
+
+ if ((ID *)sgraph->ads->filter_grp == old_id) {
+ sgraph->ads->filter_grp = (Group *)new_id;
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_ipo(void)
{
@@ -644,7 +658,8 @@ void ED_spacetype_ipo(void)
st->keymap = graphedit_keymap;
st->listener = graph_listener;
st->refresh = graph_refresh;
-
+ st->id_remap = graph_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 168f9c0dfdf..35a658eac23 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -28,6 +28,7 @@
* \ingroup spimage
*/
+#include "DNA_gpencil_types.h"
#include "DNA_mesh_types.h"
#include "DNA_mask_types.h"
#include "DNA_meshdata_types.h"
@@ -44,6 +45,7 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_image.h"
+#include "BKE_library.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -981,6 +983,31 @@ static void image_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa
}
}
+static void image_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceImage *simg = (SpaceImage *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_IM, ID_GD, ID_MSK)) {
+ return;
+ }
+
+ if ((ID *)simg->image == old_id) {
+ simg->image = (Image *)new_id;
+ id_us_ensure_real(new_id);
+ }
+
+ if ((ID *)simg->gpd == old_id) {
+ simg->gpd = (bGPdata *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+
+ if ((ID *)simg->mask_info.mask == old_id) {
+ simg->mask_info.mask = (Mask *)new_id;
+ id_us_ensure_real(new_id);
+ }
+}
+
/**************************** spacetype *****************************/
/* only called once, from space/spacetypes.c */
@@ -1002,7 +1029,8 @@ void ED_spacetype_image(void)
st->refresh = image_refresh;
st->listener = image_listener;
st->context = image_context;
-
+ st->id_remap = image_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c
index 243a522011b..69966e9bf34 100644
--- a/source/blender/editors/space_logic/space_logic.c
+++ b/source/blender/editors/space_logic/space_logic.c
@@ -38,7 +38,10 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "DNA_gpencil_types.h"
+
#include "BKE_context.h"
+#include "BKE_library.h"
#include "BKE_screen.h"
#include "ED_space_api.h"
@@ -300,6 +303,21 @@ static void logic_header_region_draw(const bContext *C, ARegion *ar)
/**************************** spacetype *****************************/
+static void logic_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceLogic *slog = (SpaceLogic *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_GD)) {
+ return;
+ }
+
+ if ((ID *)slog->gpd == old_id) {
+ slog->gpd = (bGPdata *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_logic(void)
{
@@ -317,7 +335,8 @@ void ED_spacetype_logic(void)
st->keymap = logic_keymap;
st->refresh = logic_refresh;
st->context = logic_context;
-
+ st->id_remap = logic_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype logic region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index e2b36c5b5ae..3b5604087b9 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -33,6 +33,7 @@
#include <stdio.h>
#include "DNA_anim_types.h"
+#include "DNA_group_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -501,6 +502,19 @@ static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
}
}
+static void nla_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceNla *snla = (SpaceNla *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_GR)) {
+ return;
+ }
+
+ if ((ID *)snla->ads->filter_grp == old_id) {
+ snla->ads->filter_grp = (Group *)new_id;
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_nla(void)
{
@@ -517,7 +531,8 @@ void ED_spacetype_nla(void)
st->operatortypes = nla_operatortypes;
st->listener = nla_listener;
st->keymap = nla_keymap;
-
+ st->id_remap = nla_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 6ae72e2a164..ffe510016ff 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -740,34 +740,6 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
}
}
-void ED_node_id_unref(SpaceNode *snode, const ID *id)
-{
- if (GS(id->name) == ID_SCE) {
- if (snode->id == id) {
- /* nasty DNA logic for SpaceNode:
- * ideally should be handled by editor code, but would be bad level call
- */
- bNodeTreePath *path, *path_next;
- for (path = snode->treepath.first; path; path = path_next) {
- path_next = path->next;
- MEM_freeN(path);
- }
- BLI_listbase_clear(&snode->treepath);
-
- snode->id = NULL;
- snode->from = NULL;
- snode->nodetree = NULL;
- snode->edittree = NULL;
- }
- }
- else if (GS(id->name) == ID_OB) {
- if (snode->from == id) {
- snode->flag &= ~SNODE_PIN;
- snode->from = NULL;
- }
- }
-}
-
void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree))
{
/* XXX This does not work due to layout functions relying on node->block,
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index df484724fc5..4ef703c8994 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -28,6 +28,7 @@
* \ingroup spnode
*/
+#include "DNA_gpencil_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -821,6 +822,41 @@ static int node_context(const bContext *C, const char *member, bContextDataResul
return 0;
}
+static void node_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceNode *snode = (SpaceNode *)slink;
+
+ if (GS(old_id->name) == ID_SCE) {
+ if (snode->id == old_id) {
+ /* nasty DNA logic for SpaceNode:
+ * ideally should be handled by editor code, but would be bad level call
+ */
+ BLI_freelistN(&snode->treepath);
+
+ /* XXX Untested in case new_id != NULL... */
+ snode->id = new_id;
+ snode->from = NULL;
+ snode->nodetree = NULL;
+ snode->edittree = NULL;
+ }
+ }
+ else if (GS(old_id->name) == ID_OB) {
+ if (snode->from == old_id) {
+ if (new_id == NULL) {
+ snode->flag &= ~SNODE_PIN;
+ }
+ snode->from = new_id;
+ }
+ }
+ else if (GS(old_id->name) == ID_GD) {
+ if ((ID *)snode->gpd == old_id) {
+ snode->gpd = (bGPdata *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+ }
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_node(void)
{
@@ -840,6 +876,7 @@ void ED_spacetype_node(void)
st->refresh = node_area_refresh;
st->context = node_context;
st->dropboxes = node_dropboxes;
+ st->id_remap = node_id_remap;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 554009da8be..43e9c262172 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -502,6 +502,11 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
BKE_reportf(CTX_wm_reports(C), RPT_ERROR,
"Library path '%s' does not exist, correct this before saving", expanded);
}
+ else if (lib->id.tag & LIB_TAG_MISSING) {
+ BKE_reportf(CTX_wm_reports(C), RPT_INFO,
+ "Library path '%s' is now valid, please reload the library", expanded);
+ lib->id.tag &= ~LIB_TAG_MISSING;
+ }
}
}
else {
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 2627b978b40..8cee696b2ac 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -2079,36 +2079,3 @@ void OUTLINER_OT_group_link(wmOperatorType *ot)
/* properties */
RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object");
}
-
-/******** Utils to clear any ref to freed ID... **********/
-
-void ED_outliner_id_unref(SpaceOops *so, const ID *id)
-{
- /* Some early out checks. */
- if (!TREESTORE_ID_TYPE(id)) {
- return; /* ID type is not used by outilner... */
- }
-
- if (so->search_tse.id == id) {
- so->search_tse.id = NULL;
- }
-
- if (so->treestore) {
- TreeStoreElem *tselem;
- BLI_mempool_iter iter;
- bool changed = false;
-
- BLI_mempool_iternew(so->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- if (tselem->id == id) {
- tselem->id = NULL;
- changed = true;
- }
- }
- if (so->treehash && changed) {
- /* rebuild hash table, because it depends on ids too */
- /* postpone a full rebuild because this can be called many times on-free */
- so->storeflag |= SO_TREESTORE_REBUILD;
- }
- }
-}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index dc81be7a8e0..2e46ffa6437 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -230,6 +230,7 @@ void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
void OUTLINER_OT_group_operation(struct wmOperatorType *ot);
void OUTLINER_OT_lib_operation(struct wmOperatorType *ot);
void OUTLINER_OT_id_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_id_remap(struct wmOperatorType *ot);
void OUTLINER_OT_data_operation(struct wmOperatorType *ot);
void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 83677b6bd86..2a210e382a2 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -57,6 +57,7 @@
#include "BKE_fcurve.h"
#include "BKE_group.h"
#include "BKE_library.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -230,7 +231,8 @@ static void unlink_group_cb(
}
else {
Main *bmain = CTX_data_main(C);
- BKE_group_unlink(bmain, group);
+ BKE_libblock_unlink(bmain, group, false);
+ BKE_libblock_free(bmain, group);
}
}
@@ -246,7 +248,7 @@ static void unlink_world_cb(bContext *UNUSED(C), Scene *UNUSED(scene), TreeEleme
}
static void outliner_do_libdata_operation(
- bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb,
+ bContext *C, Scene *scene, SpaceOops *soops, ListBase *lb,
void (*operation_cb)(bContext *C, Scene *scene, TreeElement *, TreeStoreElem *, TreeStoreElem *, void *),
void *user_data)
{
@@ -522,8 +524,7 @@ static void group_instance_cb(bContext *C, Scene *scene, TreeElement *UNUSED(te)
*/
void outliner_do_object_operation_ex(
bContext *C, Scene *scene_act, SpaceOops *soops, ListBase *lb,
- void (*operation_cb)(bContext *C, Scene *scene, TreeElement *,
- TreeStoreElem *, TreeStoreElem *, void *),
+ void (*operation_cb)(bContext *, Scene *, TreeElement *, TreeStoreElem *, TreeStoreElem *, void *),
bool select_recurse)
{
TreeElement *te;
@@ -565,7 +566,7 @@ void outliner_do_object_operation(
static void clear_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te),
TreeStoreElem *tselem, void *UNUSED(arg))
{
- BKE_animdata_free(tselem->id);
+ BKE_animdata_free(tselem->id, true);
}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 1dd66366e5d..76bf9c701ed 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -486,6 +486,39 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl)
return (SpaceLink *)soutlinern;
}
+static void outliner_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceOops *so = (SpaceOops *)slink;
+
+ /* Some early out checks. */
+ if (!TREESTORE_ID_TYPE(old_id)) {
+ return; /* ID type is not used by outilner... */
+ }
+
+ if (so->search_tse.id == old_id) {
+ so->search_tse.id = new_id;
+ }
+
+ if (so->treestore) {
+ TreeStoreElem *tselem;
+ BLI_mempool_iter iter;
+ bool changed = false;
+
+ BLI_mempool_iternew(so->treestore, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ if (tselem->id == old_id) {
+ tselem->id = new_id;
+ changed = true;
+ }
+ }
+ if (so->treehash && changed) {
+ /* rebuild hash table, because it depends on ids too */
+ /* postpone a full rebuild because this can be called many times on-free */
+ so->storeflag |= SO_TREESTORE_REBUILD;
+ }
+ }
+}
+
/* only called once, from space_api/spacetypes.c */
void ED_spacetype_outliner(void)
{
@@ -502,7 +535,8 @@ void ED_spacetype_outliner(void)
st->operatortypes = outliner_operatortypes;
st->keymap = outliner_keymap;
st->dropboxes = outliner_dropboxes;
-
+ st->id_remap = outliner_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index fce40f8ca59..a2a80297041 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -32,6 +32,7 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
@@ -41,6 +42,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_library.h"
#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_global.h"
@@ -687,6 +689,22 @@ static void sequencer_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUS
break;
}
}
+
+static void sequencer_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceSeq *sseq = (SpaceSeq *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_GD)) {
+ return;
+ }
+
+ if ((ID *)sseq->gpd == old_id) {
+ sseq->gpd = (bGPdata *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+}
+
/* ************************************* */
/* only called once, from space/spacetypes.c */
@@ -708,6 +726,7 @@ void ED_spacetype_sequencer(void)
st->dropboxes = sequencer_dropboxes;
st->refresh = sequencer_refresh;
st->listener = sequencer_listener;
+ st->id_remap = sequencer_id_remap;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 0a6a9a81e63..0dea59fd68c 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -38,6 +38,7 @@
#include "BLI_blenlib.h"
#include "BKE_context.h"
+#include "BKE_library.h"
#include "BKE_screen.h"
#include "BKE_text.h"
@@ -562,6 +563,20 @@ static void text_properties_region_draw(const bContext *C, ARegion *ar)
}
}
+static void text_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ SpaceText *stext = (SpaceText *)slink;
+
+ if (!ELEM(GS(old_id->name), ID_GD)) {
+ return;
+ }
+
+ if ((ID *)stext->text == old_id) {
+ stext->text = (Text *)new_id;
+ id_us_ensure_real(new_id);
+ }
+}
+
/********************* registration ********************/
/* only called once, from space/spacetypes.c */
@@ -582,7 +597,8 @@ void ED_spacetype_text(void)
st->listener = text_listener;
st->context = text_context;
st->dropboxes = text_dropboxes;
-
+ st->id_remap = text_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype text region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index fa14ca96fe2..96dda65b81d 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1400,6 +1400,66 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
return -1; /* found but not available */
}
+static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_id)
+{
+ View3D *v3d;
+ ARegion *ar;
+ bool is_local = false;
+
+ if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) {
+ return;
+ }
+
+ for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) {
+ if ((ID *)v3d->camera == old_id) {
+ v3d->camera = (Object *)new_id;
+ if (!new_id) {
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = is_local ? ((RegionView3D *)ar->regiondata)->localvd : ar->regiondata;
+ if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
+ rv3d->persp = RV3D_PERSP;
+ }
+ }
+ }
+ }
+ }
+ if ((ID *)v3d->ob_centre == old_id) {
+ v3d->ob_centre = (Object *)new_id;
+ if (new_id == NULL) { /* Otherwise, bonename may remain valid... We could be smart and check this, too? */
+ v3d->ob_centre_bone[0] = '\0';
+ }
+ }
+
+ if ((ID *)v3d->defmaterial == old_id) {
+ v3d->defmaterial = (Material *)new_id;
+ }
+#if 0 /* XXX Deprecated? */
+ if ((ID *)v3d->gpd == old_id) {
+ v3d->gpd = (bGPData *)new_id;
+ }
+#endif
+
+ if (ELEM(GS(old_id->name), ID_IM, ID_MC)) {
+ for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ if ((ID *)bgpic->ima == old_id) {
+ bgpic->ima = (Image *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+ if ((ID *)bgpic->clip == old_id) {
+ bgpic->clip = (MovieClip *)new_id;
+ id_us_min(old_id);
+ id_us_plus(new_id);
+ }
+ }
+ }
+
+ if (is_local) {
+ break;
+ }
+ }
+}
/* only called once, from space/spacetypes.c */
void ED_spacetype_view3d(void)
@@ -1419,7 +1479,8 @@ void ED_spacetype_view3d(void)
st->keymap = view3d_keymap;
st->dropboxes = view3d_dropboxes;
st->context = view3d_context;
-
+ st->id_remap = view3d_id_remap;
+
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region");
art->regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 1f4ce926f16..e2f60955c81 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -57,6 +57,7 @@
#include "BKE_multires.h"
#include "BKE_packedFile.h"
#include "BKE_paint.h"
+#include "BKE_screen.h"
#include "ED_armature.h"
#include "ED_buttons.h"
@@ -326,22 +327,14 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info
/**
* Use to free ID references within runtime data (stored outside of DNA)
*
- * \note Typically notifiers take care of this,
- * but there are times we have to free references immediately, see: T44376
+ * \param new_id may be NULL to unlink \a old_id.
*/
-void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id)
+void ED_spacedata_id_remap(struct ScrArea *sa, struct SpaceLink *sl, ID *old_id, ID *new_id)
{
+ SpaceType *st = BKE_spacetype_from_id(sl->spacetype);
- switch (sl->spacetype) {
- case SPACE_OUTLINER:
- ED_outliner_id_unref((SpaceOops *)sl, id);
- break;
- case SPACE_BUTS:
- ED_buttons_id_unref((SpaceButs *)sl, id);
- break;
- case SPACE_NODE:
- ED_node_id_unref((SpaceNode *)sl, id);
- break;
+ if (st && st->id_remap) {
+ st->id_remap(sa, sl, old_id, new_id);
}
}
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 63ea836e3de..de793054ca7 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -342,7 +342,7 @@ static AnimData * rna_ID_animation_data_create(ID *id, Main *bmain)
static void rna_ID_animation_data_free(ID *id, Main *bmain)
{
- BKE_animdata_free(id);
+ BKE_animdata_free(id, true);
DAG_relations_tag_update(bmain);
}
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 4b7ce640a56..679f20fab83 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -58,6 +58,7 @@
#include "BKE_armature.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
+#include "BKE_library_remap.h"
#include "BKE_object.h"
#include "BKE_material.h"
#include "BKE_icons.h"
@@ -160,7 +161,8 @@ static void rna_Main_scenes_remove(Main *bmain, bContext *C, ReportList *reports
}
- BKE_scene_unlink(bmain, scene, scene_new);
+ BKE_libblock_remap(bmain, scene, scene_new, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE);
+ BKE_libblock_free(bmain, scene);
RNA_POINTER_INVALIDATE(scene_ptr);
}
else {
@@ -226,7 +228,7 @@ static void rna_Main_objects_remove(Main *bmain, ReportList *reports, PointerRNA
{
Object *object = object_ptr->data;
if (ID_REAL_USERS(object) <= 0) {
- BKE_object_unlink(bmain, object); /* needed or ID pointers to this are not cleared */
+ BKE_libblock_unlink(bmain, object, false);
BKE_libblock_free(bmain, object);
RNA_POINTER_INVALIDATE(object_ptr);
}
@@ -542,7 +544,7 @@ static Group *rna_Main_groups_new(Main *bmain, const char *name)
static void rna_Main_groups_remove(Main *bmain, PointerRNA *group_ptr)
{
Group *group = group_ptr->data;
- BKE_group_unlink(bmain, group);
+ BKE_libblock_unlink(bmain, group, false);
BKE_libblock_free(bmain, group);
RNA_POINTER_INVALIDATE(group_ptr);
}
@@ -736,7 +738,6 @@ static Mask *rna_Main_mask_new(Main *bmain, const char *name)
static void rna_Main_masks_remove(Main *bmain, PointerRNA *mask_ptr)
{
Mask *mask = mask_ptr->data;
- BKE_mask_free(bmain, mask);
BKE_libblock_free(bmain, mask);
RNA_POINTER_INVALIDATE(mask_ptr);
}
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 5b65a2bbfd4..8523b7275bf 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -488,7 +488,7 @@ void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat, short compatibili
ntreeExecGPUNodes(exec, mat, 1, compatibility);
ntreeShaderEndExecTree(exec);
- ntreeFreeTree_ex(localtree, false);
+ ntreeFreeTree(localtree);
MEM_freeN(localtree);
}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index c88e3b36e27..4d711f86644 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -66,6 +66,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_node.h"
@@ -2267,7 +2268,8 @@ static void free_all_freestyle_renders(void)
if (freestyle_render) {
freestyle_scene = freestyle_render->scene;
RE_FreeRender(freestyle_render);
- BKE_scene_unlink(re1->freestyle_bmain, freestyle_scene, NULL);
+ BKE_libblock_unlink(re1->freestyle_bmain, freestyle_scene, false);
+ BKE_libblock_free(re1->freestyle_bmain, freestyle_scene);
}
}
BLI_freelistN(&re1->freestyle_renders);
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 8f61f4159e6..530ebc084be 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -3806,6 +3806,7 @@ void RE_sample_material_free(Material *mat)
MTex *mtex= mat->mtex[tex_nr];
if (mtex->tex) {
+ /* don't update user counts as we are freeing a duplicate */
BKE_texture_free(mtex->tex);
MEM_freeN(mtex->tex);
mtex->tex = NULL;
@@ -3814,7 +3815,7 @@ void RE_sample_material_free(Material *mat)
}
/* don't update user counts as we are freeing a duplicate */
- BKE_material_free_ex(mat, false);
+ BKE_material_free(mat);
MEM_freeN(mat);
}
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 388837af67a..9bb2462a4e9 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -191,7 +191,7 @@ void WM_ndof_deadzone_set(float deadzone);
void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference);
void WM_main_add_notifier(unsigned int type, void *reference);
void WM_main_remove_notifier_reference(const void *reference);
-void WM_main_remove_editor_id_reference(const struct ID *id);
+void WM_main_remap_editor_id_reference(struct ID *old_id, struct ID *new_id);
/* reports */
void WM_report_banner_show(void);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index f632dd9aff4..4515ae92f66 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -241,7 +241,7 @@ void WM_main_remove_notifier_reference(const void *reference)
}
}
-void WM_main_remove_editor_id_reference(const ID *id)
+void WM_main_remap_editor_id_reference(ID *old_id, ID *new_id)
{
Main *bmain = G.main;
bScreen *sc;
@@ -253,7 +253,7 @@ void WM_main_remove_editor_id_reference(const ID *id)
SpaceLink *sl;
for (sl = sa->spacedata.first; sl; sl = sl->next) {
- ED_spacedata_id_unref(sl, id);
+ ED_spacedata_id_remap(sa, sl, old_id, new_id);
}
}
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 917e2bf5913..a1ca89c6a8c 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -61,6 +61,7 @@
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_library.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_mball_tessellate.h"
#include "BKE_node.h"
@@ -160,9 +161,9 @@ void WM_init(bContext *C, int argc, const char **argv)
BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */
BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */
- BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference); /* library.c */
+ BKE_library_callback_remap_editor_id_reference_set(WM_main_remap_editor_id_reference); /* library.c */
BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */
- BKE_spacedata_callback_id_unref_set(ED_spacedata_id_unref); /* screen.c */
+ BKE_spacedata_callback_id_remap_set(ED_spacedata_id_remap); /* screen.c */
DAG_editors_update_cb(ED_render_id_flush_update,
ED_render_scene_update,
ED_render_scene_update_pre); /* depsgraph.c */