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:
authorBastien Montagne <montagne29@wanadoo.fr>2016-07-12 01:01:38 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2016-07-12 01:07:44 +0300
commitcfbd605567f48229a923df382baf6db98fbafc61 (patch)
treed4218c49672047d6c3b37517034660b3b5dcd966 /source/blender/blenkernel
parent71a57a37b2eebbed53b5335019287b4df9c30519 (diff)
parent7212ebd09f9720883581221be923ae5e97ff5d76 (diff)
Merge branch 'master' into blender2.8
Conflicts: intern/cycles/blender/addon/ui.py source/blender/blenkernel/BKE_particle.h source/blender/blenkernel/intern/dynamicpaint.c source/blender/blenkernel/intern/library.c source/blender/blenkernel/intern/object.c source/blender/blenkernel/intern/particle.c source/blender/blenkernel/intern/particle_distribute.c source/blender/blenkernel/intern/texture.c source/blender/editors/object/object_add.c source/blender/editors/object/object_relations.c source/blender/editors/physics/particle_edit.c source/blender/editors/physics/particle_object.c source/blender/editors/transform/transform_snap_object.c
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_action.h5
-rw-r--r--source/blender/blenkernel/BKE_animsys.h3
-rw-r--r--source/blender/blenkernel/BKE_armature.h4
-rw-r--r--source/blender/blenkernel/BKE_brush.h4
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h12
-rw-r--r--source/blender/blenkernel/BKE_camera.h4
-rw-r--r--source/blender/blenkernel/BKE_curve.h14
-rw-r--r--source/blender/blenkernel/BKE_global.h1
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h3
-rw-r--r--source/blender/blenkernel/BKE_group.h2
-rw-r--r--source/blender/blenkernel/BKE_image.h2
-rw-r--r--source/blender/blenkernel/BKE_key.h5
-rw-r--r--source/blender/blenkernel/BKE_lamp.h4
-rw-r--r--source/blender/blenkernel/BKE_lattice.h4
-rw-r--r--source/blender/blenkernel/BKE_library.h8
-rw-r--r--source/blender/blenkernel/BKE_library_query.h14
-rw-r--r--source/blender/blenkernel/BKE_library_remap.h10
-rw-r--r--source/blender/blenkernel/BKE_mask.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h8
-rw-r--r--source/blender/blenkernel/BKE_mball.h4
-rw-r--r--source/blender/blenkernel/BKE_mesh.h10
-rw-r--r--source/blender/blenkernel/BKE_node.h4
-rw-r--r--source/blender/blenkernel/BKE_object.h4
-rw-r--r--source/blender/blenkernel/BKE_scene.h2
-rw-r--r--source/blender/blenkernel/BKE_speaker.h4
-rw-r--r--source/blender/blenkernel/BKE_texture.h4
-rw-r--r--source/blender/blenkernel/BKE_world.h4
-rw-r--r--source/blender/blenkernel/intern/action.c87
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c48
-rw-r--r--source/blender/blenkernel/intern/armature.c59
-rw-r--r--source/blender/blenkernel/intern/armature_update.c2
-rw-r--r--source/blender/blenkernel/intern/bpath.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c81
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c71
-rw-r--r--source/blender/blenkernel/intern/camera.c58
-rw-r--r--source/blender/blenkernel/intern/colortools.c2
-rw-r--r--source/blender/blenkernel/intern/constraint.c4
-rw-r--r--source/blender/blenkernel/intern/curve.c146
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c6
-rw-r--r--source/blender/blenkernel/intern/gpencil.c5
-rw-r--r--source/blender/blenkernel/intern/group.c9
-rw-r--r--source/blender/blenkernel/intern/image.c163
-rw-r--r--source/blender/blenkernel/intern/key.c33
-rw-r--r--source/blender/blenkernel/intern/lamp.c71
-rw-r--r--source/blender/blenkernel/intern/lattice.c68
-rw-r--r--source/blender/blenkernel/intern/library.c138
-rw-r--r--source/blender/blenkernel/intern/library_query.c215
-rw-r--r--source/blender/blenkernel/intern/library_remap.c304
-rw-r--r--source/blender/blenkernel/intern/linestyle.c7
-rw-r--r--source/blender/blenkernel/intern/mask.c19
-rw-r--r--source/blender/blenkernel/intern/material.c226
-rw-r--r--source/blender/blenkernel/intern/mball.c67
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c4
-rw-r--r--source/blender/blenkernel/intern/mesh.c146
-rw-r--r--source/blender/blenkernel/intern/modifier.c2
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c8
-rw-r--r--source/blender/blenkernel/intern/nla.c4
-rw-r--r--source/blender/blenkernel/intern/node.c86
-rw-r--r--source/blender/blenkernel/intern/object.c118
-rw-r--r--source/blender/blenkernel/intern/object_update.c4
-rw-r--r--source/blender/blenkernel/intern/packedFile.c6
-rw-r--r--source/blender/blenkernel/intern/pbvh.c39
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c497
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h5
-rw-r--r--source/blender/blenkernel/intern/scene.c20
-rw-r--r--source/blender/blenkernel/intern/softbody.c2
-rw-r--r--source/blender/blenkernel/intern/speaker.c64
-rw-r--r--source/blender/blenkernel/intern/text.c5
-rw-r--r--source/blender/blenkernel/intern/texture.c178
-rw-r--r--source/blender/blenkernel/intern/world.c62
70 files changed, 1622 insertions, 1664 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index cb282b46bec..5874f95502b 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -58,13 +58,12 @@ extern "C" {
struct bAction *add_empty_action(struct Main *bmain, const char name[]);
/* Allocate a copy of the given Action and all its data */
-struct bAction *BKE_action_copy(struct bAction *src);
+struct bAction *BKE_action_copy(struct Main *bmain, struct bAction *src);
/* Deallocate all of the Action's data, but not the Action itself */
void BKE_action_free(struct bAction *act);
-// XXX is this needed?
-void BKE_action_make_local(struct bAction *act);
+void BKE_action_make_local(struct Main *bmain, struct bAction *act);
/* Action API ----------------- */
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 772e08589c1..983f3ce22b8 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -50,7 +50,8 @@ struct AnimMapper;
/* AnimData API */
/* Check if the given ID-block can have AnimData */
-bool id_type_can_have_animdata(struct ID *id);
+bool id_type_can_have_animdata(const short id_type);
+bool id_can_have_animdata(const struct ID *id);
/* Get AnimData from the given ID-block */
struct AnimData *BKE_animdata_from_id(struct ID *id);
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index cc082c084ce..326c335338f 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -76,8 +76,8 @@ struct bArmature *BKE_armature_from_object(struct Object *ob);
int BKE_armature_bonelist_count(struct ListBase *lb);
void BKE_armature_bonelist_free(struct ListBase *lb);
void BKE_armature_free(struct bArmature *arm);
-void BKE_armature_make_local(struct bArmature *arm);
-struct bArmature *BKE_armature_copy(struct bArmature *arm);
+void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm);
+struct bArmature *BKE_armature_copy(struct Main *bmain, struct bArmature *arm);
/* Bounding box. */
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index c663458963c..c7116bf2ef6 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -44,8 +44,8 @@ void BKE_brush_system_exit(void);
void BKE_brush_init(struct Brush *brush);
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
-struct Brush *BKE_brush_copy(struct Brush *brush);
-void BKE_brush_make_local(struct Brush *brush);
+struct Brush *BKE_brush_copy(struct Main *bmain, struct Brush *brush);
+void BKE_brush_make_local(struct Main *bmain, struct Brush *brush);
void BKE_brush_unlink(struct Main *bmain, struct Brush *brush);
void BKE_brush_free(struct Brush *brush);
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 7ec91b006b2..07db2217bac 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -46,8 +46,8 @@ struct MFace;
typedef struct LinkNode BVHCache;
/**
-* struct that kepts basic information about a BVHTree build from a editmesh
-*/
+ * struct that kepts basic information about a BVHTree build from a editmesh
+ */
typedef struct BVHTreeFromEditMesh {
struct BVHTree *tree;
@@ -122,6 +122,14 @@ BVHTree *bvhtree_from_mesh_verts_ex(
const bool vert_allocated, const BLI_bitmap *mask, int verts_num_active,
float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_editmesh_edges(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em,
+ float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_editmesh_edges_ex(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em,
+ const BLI_bitmap *edges_mask, int edges_num_active,
+ float epsilon, int tree_type, int axis);
+
BVHTree *bvhtree_from_mesh_edges(
struct BVHTreeFromMesh *data, struct DerivedMesh *mesh,
float epsilon, int tree_type, int axis);
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index d13a711c589..97f4b30894b 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -52,8 +52,8 @@ struct GPUFXSettings;
void BKE_camera_init(struct Camera *cam);
void *BKE_camera_add(struct Main *bmain, const char *name);
-struct Camera *BKE_camera_copy(struct Camera *cam);
-void BKE_camera_make_local(struct Camera *cam);
+struct Camera *BKE_camera_copy(struct Main *bmain, struct Camera *cam);
+void BKE_camera_make_local(struct Main *bmain, struct Camera *cam);
void BKE_camera_free(struct Camera *ca);
/* Camera Usage */
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 23b3128f328..89dbe246910 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -70,8 +70,8 @@ void BKE_curve_free(struct Curve *cu);
void BKE_curve_editfont_free(struct Curve *cu);
void BKE_curve_init(struct Curve *cu);
struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
-struct Curve *BKE_curve_copy(struct Curve *cu);
-void BKE_curve_make_local(struct Curve *cu);
+struct Curve *BKE_curve_copy(struct Main *bmain, struct Curve *cu);
+void BKE_curve_make_local(struct Main *bmain, struct Curve *cu);
short BKE_curve_type_get(struct Curve *cu);
void BKE_curve_type_test(struct Object *ob);
void BKE_curve_curve_dimension_update(struct Curve *cu);
@@ -150,6 +150,16 @@ void BKE_nurb_minmax(struct Nurb *nu, bool use_radius, float min[3], float max[3
void BKE_nurb_makeFaces(struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv);
void BKE_nurb_makeCurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride);
+unsigned int BKE_curve_calc_coords_axis_len(
+ const unsigned int bezt_array_len, const unsigned int resolu,
+ const bool is_cyclic, const bool use_cyclic_duplicate_endpoint);
+void BKE_curve_calc_coords_axis(
+ const struct BezTriple *bezt_array, const unsigned int bezt_array_len, const unsigned int resolu,
+ const bool is_cyclic, const bool use_cyclic_duplicate_endpoint,
+ /* array params */
+ const unsigned int axis, const unsigned int stride,
+ float *r_points);
+
void BKE_nurb_knot_calc_u(struct Nurb *nu);
void BKE_nurb_knot_calc_v(struct Nurb *nu);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 26a40597ca8..5ef5a807f63 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -178,6 +178,7 @@ enum {
#define G_FILE_MESH_COMPAT (1 << 26)
/* On write, restore paths after editing them (G_FILE_RELATIVE_REMAP) */
#define G_FILE_SAVE_COPY (1 << 27)
+#define G_FILE_GLSL_NO_ENV_LIGHTING (1 << 28)
#define G_FILE_FLAGS_RUNTIME (G_FILE_NO_UI | G_FILE_RELATIVE_REMAP | G_FILE_MESH_COMPAT | G_FILE_SAVE_COPY)
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 24e330d927f..6159531d8bd 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -36,6 +36,7 @@ struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
struct bGPDstroke;
+struct Main;
/* ------------ Grease-Pencil API ------------------ */
@@ -53,7 +54,7 @@ struct bGPdata *gpencil_data_addnew(const char name[]);
struct bGPDframe *gpencil_frame_duplicate(struct bGPDframe *src);
struct bGPDlayer *gpencil_layer_duplicate(struct bGPDlayer *src);
-struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd, bool internal_copy);
+struct bGPdata *gpencil_data_duplicate(struct Main *bmain, struct bGPdata *gpd, bool internal_copy);
void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index ae6e52b613b..4f2c89070cb 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -42,7 +42,7 @@ struct Scene;
void BKE_group_free(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
-struct Group *BKE_group_copy(struct Group *group);
+struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index eb98268c9f0..0895feef983 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -108,7 +108,7 @@ struct anim *openanim_noload(const char *name, int flags, int streamindex, char
void BKE_image_de_interlace(struct Image *ima, int odd);
-void BKE_image_make_local(struct Image *ima);
+void BKE_image_make_local(struct Main *bmain, struct Image *ima);
void BKE_image_tag_time(struct Image *ima);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index 1edbb455ca4..f30f9eac4e8 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -39,6 +39,7 @@ struct ListBase;
struct Curve;
struct Object;
struct Lattice;
+struct Main;
struct Mesh;
struct WeightsArrayCache;
@@ -50,9 +51,9 @@ extern "C" {
void BKE_key_free(struct Key *sc);
void BKE_key_free_nolib(struct Key *key);
struct Key *BKE_key_add(struct ID *id);
-struct Key *BKE_key_copy(struct Key *key);
+struct Key *BKE_key_copy(struct Main *bmain, struct Key *key);
struct Key *BKE_key_copy_nolib(struct Key *key);
-void BKE_key_make_local(struct Key *key);
+void BKE_key_make_local(struct Main *bmain, struct Key *key);
void BKE_key_sort(struct Key *key);
void key_curve_position_weights(float t, float data[4], int type);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index d830c19651f..49b43550e67 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -44,9 +44,9 @@ struct Scene;
void BKE_lamp_init(struct Lamp *la);
struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
-struct Lamp *BKE_lamp_copy(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
+struct Lamp *BKE_lamp_copy(struct Main *bmain, struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
-void BKE_lamp_make_local(struct Lamp *la);
+void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la);
void BKE_lamp_free(struct Lamp *la);
void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 828a40de1c9..606df9dcec8 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -47,9 +47,9 @@ struct MDeformVert;
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb);
void BKE_lattice_init(struct Lattice *lt);
struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
-struct Lattice *BKE_lattice_copy(struct Lattice *lt);
+struct Lattice *BKE_lattice_copy(struct Main *bmain, struct Lattice *lt);
void BKE_lattice_free(struct Lattice *lt);
-void BKE_lattice_make_local(struct Lattice *lt);
+void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
struct LatticeDeformData;
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 2e225775af0..cb39b2e53ee 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -52,9 +52,8 @@ struct PropertyRNA;
void *BKE_libblock_alloc_notest(short type);
void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BKE_libblock_init_empty(struct ID *id);
-void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void *BKE_libblock_copy(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void *BKE_libblock_copy_nolib(struct ID *id, const bool do_action) ATTR_NONNULL();
-void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
void BKE_libblock_relink(struct ID *id);
void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL();
@@ -81,10 +80,11 @@ void id_us_min(struct ID *id);
void id_fake_user_set(struct ID *id);
void id_fake_user_clear(struct ID *id);
-bool id_make_local(struct ID *id, bool test);
+bool id_make_local(struct Main *bmain, 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_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
+void BKE_id_expand_local(struct ID *id);
bool new_id(struct ListBase *lb, struct ID *id, const char *name);
void id_clear_lib_data(struct Main *bmain, struct ID *id);
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index c89dce99caa..c5f575c8c0f 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -41,6 +41,12 @@ enum {
IDWALK_NEVER_SELF = (1 << 1),
/**
+ * Indicates whether this is direct (i.e. by local data) or indirect (i.e. by linked data) usage.
+ * \note Object proxies are half-local, half-linked...
+ */
+ IDWALK_INDIRECT_USAGE = (1 << 2),
+
+ /**
* Adjusts #ID.us reference-count.
* \note keep in sync with 'newlibadr_us' use in readfile.c
*/
@@ -53,7 +59,7 @@ enum {
enum {
IDWALK_RET_NOP = 0,
- IDWALK_RET_STOP_ITER = 1 << 0, /* Completly top iteration. */
+ IDWALK_RET_STOP_ITER = 1 << 0, /* Completly stop iteration. */
IDWALK_RET_STOP_RECURSION = 1 << 1, /* Stop recursion, that is, do not loop over ID used by current one. */
};
@@ -76,4 +82,10 @@ void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const
int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
+bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id_type_used);
+
+bool BKE_library_ID_is_locally_used(struct Main *bmain, void *idv);
+bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv);
+void BKE_library_ID_test_usages(struct Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked);
+
#endif /* __BKE_LIBRARY_QUERY_H__ */
diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h
index e85a3e60751..e974b79ee66 100644
--- a/source/blender/blenkernel/BKE_library_remap.h
+++ b/source/blender/blenkernel/BKE_library_remap.h
@@ -56,9 +56,13 @@ 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_unlink(
+ struct Main *bmain, void *idv,
+ const bool do_flag_never_null, const bool do_skip_indirect) ATTR_NONNULL();
-void BKE_libblock_relink_ex(void *idv, void *old_idv, void *new_idv, const bool us_min_never_null) ATTR_NONNULL(1);
+void BKE_libblock_relink_ex(
+ struct Main *bmain, void *idv, void *old_idv, void *new_idv,
+ const bool us_min_never_null) ATTR_NONNULL(1, 2);
typedef void (*BKE_library_free_window_manager_cb)(struct bContext *, struct wmWindowManager *);
@@ -73,4 +77,4 @@ void BKE_library_callback_remap_editor_id_reference_set(BKE_library_remap_editor
}
#endif
-#endif /* __BKE_LIBRARY_REMAP_H__ */ \ No newline at end of file
+#endif /* __BKE_LIBRARY_REMAP_H__ */
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index f3d12b5a8cc..97bfd0f3f07 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -123,7 +123,7 @@ void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const eMask
/* general */
struct Mask *BKE_mask_new(struct Main *bmain, const char *name);
struct Mask *BKE_mask_copy_nolib(struct Mask *mask);
-struct Mask *BKE_mask_copy(struct Mask *mask);
+struct Mask *BKE_mask_copy(struct Main *bmain, struct Mask *mask);
void BKE_mask_free(struct Mask *mask);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 852564c8d90..0bc54ee4a16 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -47,17 +47,17 @@ struct Scene;
void init_def_material(void);
void BKE_material_free(struct Material *ma);
void BKE_material_free_ex(struct Material *ma, bool do_id_user);
-void test_object_materials(struct Main *bmain, struct ID *id);
+void test_object_materials(struct Object *ob, struct ID *id);
+void test_all_objects_materials(struct Main *bmain, struct ID *id);
void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
void BKE_material_init(struct Material *ma);
void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
-struct Material *BKE_material_copy(struct Material *ma);
+struct Material *BKE_material_copy(struct Main *bmain, struct Material *ma);
struct Material *localize_material(struct Material *ma);
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
-void BKE_material_make_local(struct Material *ma);
-void extern_local_matarar(struct Material **matar, short totcol);
+void BKE_material_make_local(struct Main *bmain, struct Material *ma);
/* UNUSED */
// void automatname(struct Material *);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index b8258455c65..42704c1b2db 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -41,9 +41,9 @@ struct MetaElem;
void BKE_mball_free(struct MetaBall *mb);
void BKE_mball_init(struct MetaBall *mb);
struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name);
-struct MetaBall *BKE_mball_copy(struct MetaBall *mb);
+struct MetaBall *BKE_mball_copy(struct Main *bmain, struct MetaBall *mb);
-void BKE_mball_make_local(struct MetaBall *mb);
+void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb);
bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
bool BKE_mball_is_basis(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 9330f41d19a..d3bb34d7a41 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -32,6 +32,7 @@
*/
struct ID;
+struct BMeshCreateParams;
struct BoundBox;
struct EdgeHash;
struct ListBase;
@@ -69,7 +70,9 @@ extern "C" {
/* *** mesh.c *** */
-struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob, const bool add_key_index);
+struct BMesh *BKE_mesh_to_bmesh(
+ struct Mesh *me, struct Object *ob,
+ const bool add_key_index, const struct BMeshCreateParams *params);
int poly_find_loop_from_vert(
const struct MPoly *poly,
@@ -84,12 +87,11 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
void BKE_mesh_free(struct Mesh *me);
void BKE_mesh_init(struct Mesh *me);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
-struct Mesh *BKE_mesh_copy_ex(struct Main *bmain, struct Mesh *me);
-struct Mesh *BKE_mesh_copy(struct Mesh *me);
+struct Mesh *BKE_mesh_copy(struct Main *bmain, struct Mesh *me);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
-void BKE_mesh_make_local(struct Mesh *me);
+void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me);
void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_calc(struct Mesh *me);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index bf198c9b86b..b44cb226f0d 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -336,7 +336,7 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char
/* copy/free funcs, need to manage ID users */
void ntreeFreeTree(struct bNodeTree *ntree);
struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user);
-struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree);
+struct bNodeTree *ntreeCopyTree(struct Main *bmain, struct bNodeTree *ntree);
void ntreeSwitchID_ex(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to, const bool do_id_user);
void ntreeSwitchID(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to);
/* node->id user count */
@@ -346,7 +346,7 @@ void ntreeUserDecrefID(struct bNodeTree *ntree);
struct bNodeTree *ntreeFromID(struct ID *id);
-void ntreeMakeLocal(struct bNodeTree *ntree, bool id_in_mainlist);
+void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist);
struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type);
bool ntreeHasType(const struct bNodeTree *ntree, int type);
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 612c758139a..2c4df9620c2 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -103,8 +103,8 @@ struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene)
struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches);
-struct Object *BKE_object_copy(struct Object *ob);
-void BKE_object_make_local(struct Object *ob);
+struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob);
+void BKE_object_make_local(struct Main *bmain, struct Object *ob);
bool BKE_object_is_libdata(struct Object *ob);
bool BKE_object_obdata_is_libdata(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index ccb7dc8e015..03af0b7d6c9 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -98,7 +98,7 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene);
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
-struct Scene *BKE_scene_copy(struct Scene *sce, int type);
+struct Scene *BKE_scene_copy(struct Main *bmain, struct Scene *sce, int type);
void BKE_scene_groups_relink(struct Scene *sce);
struct Object *BKE_scene_camera_find(struct Scene *sc);
diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h
index 5f30df1d6e3..89b948a2126 100644
--- a/source/blender/blenkernel/BKE_speaker.h
+++ b/source/blender/blenkernel/BKE_speaker.h
@@ -33,8 +33,8 @@ struct Speaker;
void BKE_speaker_init(struct Speaker *spk);
void *BKE_speaker_add(struct Main *bmain, const char *name);
-struct Speaker *BKE_speaker_copy(struct Speaker *spk);
-void BKE_speaker_make_local(struct Speaker *spk);
+struct Speaker *BKE_speaker_copy(struct Main *bmain, struct Speaker *spk);
+void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk);
void BKE_speaker_free(struct Speaker *spk);
#endif
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 43378551449..52b1906a78b 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -68,10 +68,10 @@ void colorband_update_sort(struct ColorBand *coba);
void BKE_texture_free(struct Tex *tex);
void BKE_texture_default(struct Tex *tex);
-struct Tex *BKE_texture_copy(struct Tex *tex);
+struct Tex *BKE_texture_copy(struct Main *bmain, struct Tex *tex);
struct Tex *BKE_texture_add(struct Main *bmain, const char *name);
struct Tex *BKE_texture_localize(struct Tex *tex);
-void BKE_texture_make_local(struct Tex *tex);
+void BKE_texture_make_local(struct Main *bmain, struct Tex *tex);
void BKE_texture_type_set(struct Tex *tex, int type);
void BKE_texture_mtex_default(struct MTex *mtex);
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
index 0be61fe0229..da5cca09b27 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -39,9 +39,9 @@ struct World;
void BKE_world_free(struct World *sc);
void BKE_world_init(struct World *wrld);
struct World *add_world(struct Main *bmian, const char *name);
-struct World *BKE_world_copy(struct World *wrld);
+struct World *BKE_world_copy(struct Main *bmain, struct World *wrld);
struct World *localize_world(struct World *wrld);
-void BKE_world_make_local(struct World *wrld);
+void BKE_world_make_local(struct Main *bmain, struct World *wrld);
#endif
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 46ee8a4d888..f7ff1261c8a 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -59,6 +59,8 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_object.h"
@@ -92,68 +94,34 @@ bAction *add_empty_action(Main *bmain, const char name[])
/* .................................. */
-/* temp data for BKE_action_make_local */
-typedef struct tMakeLocalActionContext {
- bAction *act; /* original action */
- bAction *act_new; /* new action */
-
- bool is_lib; /* some action users were libraries */
- bool is_local; /* some action users were not libraries */
-} tMakeLocalActionContext;
-
-/* helper function for BKE_action_make_local() - local/lib init step */
-static void make_localact_init_cb(ID *id, AnimData *adt, void *mlac_ptr)
+// does copy_fcurve...
+void BKE_action_make_local(Main *bmain, bAction *act)
{
- tMakeLocalActionContext *mlac = (tMakeLocalActionContext *)mlac_ptr;
-
- if (adt->action == mlac->act) {
- if (id->lib) mlac->is_lib = true;
- else mlac->is_local = true;
- }
-}
+ bool is_local = false, is_lib = false;
-/* helper function for BKE_action_make_local() - change references */
-static void make_localact_apply_cb(ID *id, AnimData *adt, void *mlac_ptr)
-{
- tMakeLocalActionContext *mlac = (tMakeLocalActionContext *)mlac_ptr;
-
- if (adt->action == mlac->act) {
- if (id->lib == NULL) {
- adt->action = mlac->act_new;
-
- id_us_plus(&mlac->act_new->id);
- id_us_min(&mlac->act->id);
- }
- }
-}
+ /* - only lib users: do nothing
+ * - only local users: set flag
+ * - mixed: make copy
+ */
-// does copy_fcurve...
-void BKE_action_make_local(bAction *act)
-{
- tMakeLocalActionContext mlac = {act, NULL, false, false};
- Main *bmain = G.main;
-
- if (act->id.lib == NULL)
- return;
-
- /* XXX: double-check this; it used to be just single-user check, but that was when fake-users were still default */
- if ((act->id.flag & LIB_FAKEUSER) && (act->id.us <= 1)) {
- id_clear_lib_data(bmain, &act->id);
+ if (!ID_IS_LINKED_DATABLOCK(act)) {
return;
}
-
- BKE_animdata_main_cb(bmain, make_localact_init_cb, &mlac);
-
- if (mlac.is_local && mlac.is_lib == false) {
- id_clear_lib_data(bmain, &act->id);
- }
- else if (mlac.is_local && mlac.is_lib) {
- mlac.act_new = BKE_action_copy(act);
- mlac.act_new->id.us = 0;
- BKE_id_lib_local_paths(bmain, act->id.lib, &mlac.act_new->id);
+ BKE_library_ID_test_usages(bmain, act, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &act->id);
+ BKE_id_expand_local(&act->id);
+ }
+ else {
+ bAction *act_new = BKE_action_copy(bmain, act);
+
+ act_new->id.us = 0;
- BKE_animdata_main_cb(bmain, make_localact_apply_cb, &mlac);
+ BKE_libblock_remap(bmain, act, act_new, ID_REMAP_SKIP_INDIRECT_USAGE);
+ }
}
}
@@ -176,7 +144,7 @@ void BKE_action_free(bAction *act)
/* .................................. */
-bAction *BKE_action_copy(bAction *src)
+bAction *BKE_action_copy(Main *bmain, bAction *src)
{
bAction *dst = NULL;
bActionGroup *dgrp, *sgrp;
@@ -184,7 +152,7 @@ bAction *BKE_action_copy(bAction *src)
if (src == NULL)
return NULL;
- dst = BKE_libblock_copy(&src->id);
+ dst = BKE_libblock_copy(bmain, &src->id);
/* duplicate the lists of groups and markers */
BLI_duplicatelist(&dst->groups, &src->groups);
@@ -213,8 +181,9 @@ bAction *BKE_action_copy(bAction *src)
}
}
- if (src->id.lib) {
- BKE_id_lib_local_paths(G.main, src->id.lib, &dst->id);
+ if (ID_IS_LINKED_DATABLOCK(src)) {
+ BKE_id_expand_local(&dst->id);
+ BKE_id_lib_local_paths(bmain, src->id.lib, &dst->id);
}
return dst;
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index b7e8bc62470..7f10f6833db 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -79,15 +79,11 @@
/* Getter/Setter -------------------------------------------- */
/* Check if ID can have AnimData */
-bool id_type_can_have_animdata(ID *id)
+bool id_type_can_have_animdata(const short id_type)
{
- /* sanity check */
- if (id == NULL)
- return false;
-
/* Only some ID-blocks have this info for now */
/* TODO: finish adding this for the other blocktypes */
- switch (GS(id->name)) {
+ switch (id_type) {
/* has AnimData */
case ID_OB:
case ID_ME: case ID_MB: case ID_CU: case ID_AR: case ID_LT:
@@ -100,9 +96,7 @@ bool id_type_can_have_animdata(ID *id)
case ID_MC:
case ID_MSK:
case ID_GD:
- {
return true;
- }
/* no AnimData */
default:
@@ -110,6 +104,14 @@ bool id_type_can_have_animdata(ID *id)
}
}
+bool id_can_have_animdata(const ID *id)
+{
+ /* sanity check */
+ if (id == NULL)
+ return false;
+
+ return id_type_can_have_animdata(GS(id->name));
+}
/* Get AnimData from the given ID-block. In order for this to work, we assume that
* the AnimData pointer is stored immediately after the given ID-block in the struct,
@@ -121,7 +123,7 @@ AnimData *BKE_animdata_from_id(ID *id)
* types that do to be of type IdAdtTemplate, and extract the
* AnimData that way
*/
- if (id_type_can_have_animdata(id)) {
+ if (id_can_have_animdata(id)) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
return iat->adt;
}
@@ -139,7 +141,7 @@ AnimData *BKE_animdata_add_id(ID *id)
* types that do to be of type IdAdtTemplate, and add the AnimData
* to it using the template
*/
- if (id_type_can_have_animdata(id)) {
+ if (id_can_have_animdata(id)) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
/* check if there's already AnimData, in which case, don't add */
@@ -220,7 +222,7 @@ 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
*/
- if (id_type_can_have_animdata(id)) {
+ if (id_can_have_animdata(id)) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
AnimData *adt = iat->adt;
@@ -265,8 +267,8 @@ AnimData *BKE_animdata_copy(AnimData *adt, const bool do_action)
/* make a copy of action - at worst, user has to delete copies... */
if (do_action) {
- dadt->action = BKE_action_copy(adt->action);
- dadt->tmpact = BKE_action_copy(adt->tmpact);
+ dadt->action = BKE_action_copy(G.main, adt->action);
+ dadt->tmpact = BKE_action_copy(G.main, adt->tmpact);
}
else {
id_us_plus((ID *)dadt->action);
@@ -310,11 +312,11 @@ void BKE_animdata_copy_id_action(ID *id)
if (adt) {
if (adt->action) {
id_us_min((ID *)adt->action);
- adt->action = BKE_action_copy(adt->action);
+ adt->action = BKE_action_copy(G.main, adt->action);
}
if (adt->tmpact) {
id_us_min((ID *)adt->tmpact);
- adt->tmpact = BKE_action_copy(adt->tmpact);
+ adt->tmpact = BKE_action_copy(G.main, adt->tmpact);
}
}
}
@@ -338,8 +340,8 @@ void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes a
/* handle actions... */
if (action_mode == ADT_MERGECOPY_SRC_COPY) {
/* make a copy of the actions */
- dst->action = BKE_action_copy(src->action);
- dst->tmpact = BKE_action_copy(src->tmpact);
+ dst->action = BKE_action_copy(G.main, src->action);
+ dst->tmpact = BKE_action_copy(G.main, src->tmpact);
}
else if (action_mode == ADT_MERGECOPY_SRC_REF) {
/* make a reference to it */
@@ -397,8 +399,8 @@ static void make_local_strips(ListBase *strips)
NlaStrip *strip;
for (strip = strips->first; strip; strip = strip->next) {
- if (strip->act) BKE_action_make_local(strip->act);
- if (strip->remap && strip->remap->target) BKE_action_make_local(strip->remap->target);
+ if (strip->act) BKE_action_make_local(G.main, strip->act);
+ if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target);
make_local_strips(&strip->strips);
}
@@ -410,10 +412,10 @@ void BKE_animdata_make_local(AnimData *adt)
NlaTrack *nlt;
/* Actions - Active and Temp */
- if (adt->action) BKE_action_make_local(adt->action);
- if (adt->tmpact) BKE_action_make_local(adt->tmpact);
+ if (adt->action) BKE_action_make_local(G.main, adt->action);
+ if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact);
/* Remaps */
- if (adt->remap && adt->remap->target) BKE_action_make_local(adt->remap->target);
+ if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target);
/* Drivers */
/* TODO: need to remap the ID-targets too? */
@@ -1048,7 +1050,7 @@ void BKE_animdata_fix_paths_remove(ID *id, const char *prefix)
*/
NlaTrack *nlt;
- if (id_type_can_have_animdata(id)) {
+ if (id_can_have_animdata(id)) {
IdAdtTemplate *iat = (IdAdtTemplate *)id;
AnimData *adt = iat->adt;
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index b59618f46b2..5f564e1c4d2 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -67,6 +67,8 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_object.h"
@@ -142,46 +144,32 @@ void BKE_armature_free(bArmature *arm)
}
}
-void BKE_armature_make_local(bArmature *arm)
+void BKE_armature_make_local(Main *bmain, bArmature *arm)
{
- Main *bmain = G.main;
bool is_local = false, is_lib = false;
- Object *ob;
- if (arm->id.lib == NULL)
- return;
- if (arm->id.us == 1) {
- id_clear_lib_data(bmain, &arm->id);
+ /* - only lib users: do nothing
+ * - only local users: set flag
+ * - mixed: make copy
+ */
+
+ if (!ID_IS_LINKED_DATABLOCK(arm)) {
return;
}
- for (ob = bmain->object.first; ob && ELEM(0, is_lib, is_local); ob = ob->id.next) {
- if (ob->data == arm) {
- if (ob->id.lib)
- is_lib = true;
- else
- is_local = true;
- }
- }
+ BKE_library_ID_test_usages(bmain, arm, &is_local, &is_lib);
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &arm->id);
- }
- else if (is_local && is_lib) {
- bArmature *arm_new = BKE_armature_copy(arm);
- arm_new->id.us = 0;
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &arm->id);
+ BKE_id_expand_local(&arm->id);
+ }
+ else {
+ bArmature *arm_new = BKE_armature_copy(bmain, arm);
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, arm->id.lib, &arm_new->id);
+ arm_new->id.us = 0;
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (ob->data == arm) {
- if (ob->id.lib == NULL) {
- ob->data = arm_new;
- id_us_plus(&arm_new->id);
- id_us_min(&arm->id);
- }
- }
+ BKE_libblock_remap(bmain, arm, arm_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
@@ -208,13 +196,13 @@ static void copy_bonechildren(Bone *newBone, Bone *oldBone, Bone *actBone, Bone
}
}
-bArmature *BKE_armature_copy(bArmature *arm)
+bArmature *BKE_armature_copy(Main *bmain, bArmature *arm)
{
bArmature *newArm;
Bone *oldBone, *newBone;
Bone *newActBone = NULL;
- newArm = BKE_libblock_copy(&arm->id);
+ newArm = BKE_libblock_copy(bmain, &arm->id);
BLI_duplicatelist(&newArm->bonebase, &arm->bonebase);
/* Duplicate the childrens' lists */
@@ -231,8 +219,9 @@ bArmature *BKE_armature_copy(bArmature *arm)
newArm->act_edbone = NULL;
newArm->sketch = NULL;
- if (arm->id.lib) {
- BKE_id_lib_local_paths(G.main, arm->id.lib, &newArm->id);
+ if (ID_IS_LINKED_DATABLOCK(arm)) {
+ BKE_id_expand_local(&newArm->id);
+ BKE_id_lib_local_paths(bmain, arm->id.lib, &newArm->id);
}
return newArm;
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 826bb12a912..ece17335fa0 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -696,7 +696,7 @@ void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx),
void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob)
{
- BLI_assert(ob->id.lib != NULL && ob->proxy_from != NULL);
+ BLI_assert(ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from != NULL);
DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index e338974eca6..f3ff0f253e5 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -423,7 +423,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
{
const char *absbase = (flag & BKE_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL;
- if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && id->lib) {
+ if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && ID_IS_LINKED_DATABLOCK(id)) {
return;
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 44cacffb71f..20621feac6c 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -38,6 +38,8 @@
#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_paint.h"
#include "BKE_texture.h"
@@ -170,11 +172,11 @@ struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode)
return NULL;
}
-Brush *BKE_brush_copy(Brush *brush)
+Brush *BKE_brush_copy(Main *bmain, Brush *brush)
{
Brush *brushn;
- brushn = BKE_libblock_copy(&brush->id);
+ brushn = BKE_libblock_copy(bmain, &brush->id);
if (brush->mtex.tex)
id_us_plus((ID *)brush->mtex.tex);
@@ -195,8 +197,9 @@ Brush *BKE_brush_copy(Brush *brush)
/* enable fake user by default */
id_fake_user_set(&brush->id);
- if (brush->id.lib) {
- BKE_id_lib_local_paths(G.main, brush->id.lib, &brushn->id);
+ if (ID_IS_LINKED_DATABLOCK(brush)) {
+ BKE_id_expand_local(&brushn->id);
+ BKE_id_lib_local_paths(bmain, brush->id.lib, &brushn->id);
}
return brushn;
@@ -216,63 +219,40 @@ void BKE_brush_free(Brush *brush)
BKE_previewimg_free(&(brush->preview));
}
-static void extern_local_brush(Brush *brush)
-{
- id_lib_extern((ID *)brush->mtex.tex);
- id_lib_extern((ID *)brush->mask_mtex.tex);
- id_lib_extern((ID *)brush->clone.image);
- id_lib_extern((ID *)brush->toggle_brush);
- id_lib_extern((ID *)brush->paint_curve);
-}
-
-void BKE_brush_make_local(Brush *brush)
+void BKE_brush_make_local(Main *bmain, Brush *brush)
{
+ bool is_local = false, is_lib = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
- Main *bmain = G.main;
- Scene *scene;
- bool is_local = false, is_lib = false;
-
- if (brush->id.lib == NULL) return;
+ if (!ID_IS_LINKED_DATABLOCK(brush)) {
+ return;
+ }
if (brush->clone.image) {
- /* special case: ima always local immediately. Clone image should only
- * have one user anyway. */
- id_clear_lib_data(bmain, &brush->clone.image->id);
- extern_local_brush(brush);
+ /* Special case: ima always local immediately. Clone image should only have one user anyway. */
+ id_make_local(bmain, &brush->clone.image->id, false);
}
- for (scene = bmain->scene.first; scene && ELEM(0, is_lib, is_local); scene = scene->id.next) {
- if (BKE_paint_brush(&scene->toolsettings->imapaint.paint) == brush) {
- if (scene->id.lib) is_lib = true;
- else is_local = true;
+ BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &brush->id);
+ BKE_id_expand_local(&brush->id);
+
+ /* enable fake user by default */
+ id_fake_user_set(&brush->id);
}
- }
+ else {
+ Brush *brush_new = BKE_brush_copy(bmain, brush); /* Ensures FAKE_USER is set */
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &brush->id);
- extern_local_brush(brush);
+ brush_new->id.us = 0;
- /* enable fake user by default */
- id_fake_user_set(&brush->id);
- }
- else if (is_local && is_lib) {
- Brush *brush_new = BKE_brush_copy(brush); /* Ensures FAKE_USER is set */
- id_us_min(&brush_new->id); /* Remove user added by standard BKE_libblock_copy(). */
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, brush->id.lib, &brush_new->id);
-
- for (scene = bmain->scene.first; scene; scene = scene->id.next) {
- if (BKE_paint_brush(&scene->toolsettings->imapaint.paint) == brush) {
- if (scene->id.lib == NULL) {
- BKE_paint_brush_set(&scene->toolsettings->imapaint.paint, brush_new);
- }
- }
+ BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
@@ -469,6 +449,7 @@ void BKE_brush_curve_preset(Brush *b, int preset)
curvemapping_changed(b->curve, false);
}
+/* XXX Unused function. */
int BKE_brush_texture_set_nr(Brush *brush, int nr)
{
ID *idtest, *id = NULL;
@@ -477,7 +458,7 @@ int BKE_brush_texture_set_nr(Brush *brush, int nr)
idtest = (ID *)BLI_findlink(&G.main->tex, nr - 1);
if (idtest == NULL) { /* new tex */
- if (id) idtest = (ID *)BKE_texture_copy((Tex *)id);
+ if (id) idtest = (ID *)BKE_texture_copy(G.main, (Tex *)id);
else idtest = (ID *)BKE_texture_add(G.main, "Tex");
id_us_min(idtest);
}
@@ -816,9 +797,7 @@ void BKE_brush_color_set(struct Scene *scene, struct Brush *brush, const float c
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
-
- size = (int)((float)size / U.pixelsize);
-
+
/* make sure range is sane */
CLAMP(size, 1, MAX_BRUSH_PIXEL_RADIUS);
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index a3cfe3f80b4..264d87b86f3 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -590,6 +590,77 @@ BVHTree *bvhtree_from_mesh_verts_ex(
/** \name Edge Builder
* \{ */
+static BVHTree *bvhtree_from_editmesh_edges_create_tree(
+ float epsilon, int tree_type, int axis,
+ BMEditMesh *em, const int edges_num,
+ const BLI_bitmap *edges_mask, int edges_num_active)
+{
+ BVHTree *tree = NULL;
+ int i;
+ BM_mesh_elem_table_ensure(em->bm, BM_EDGE);
+ if (edges_mask) {
+ BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edges_num));
+ }
+ else {
+ edges_num_active = edges_num;
+ }
+
+ tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
+
+ if (tree) {
+ BMIter iter;
+ BMEdge *eed;
+ BM_ITER_MESH_INDEX (eed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
+ if (edges_mask && !BLI_BITMAP_TEST_BOOL(edges_mask, i)) {
+ continue;
+ }
+ float co[2][3];
+ copy_v3_v3(co[0], eed->v1->co);
+ copy_v3_v3(co[1], eed->v2->co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 2);
+ }
+ BLI_assert(BLI_bvhtree_get_size(tree) == edges_num_active);
+ BLI_bvhtree_balance(tree);
+ }
+
+ return tree;
+}
+
+/* Builds a bvh tree where nodes are the edges of the given em */
+BVHTree *bvhtree_from_editmesh_edges_ex(
+ BVHTreeFromEditMesh *data, BMEditMesh *em,
+ const BLI_bitmap *edges_mask, int edges_num_active,
+ float epsilon, int tree_type, int axis)
+{
+ int edge_num = em->bm->totedge;
+
+ BVHTree *tree = bvhtree_from_editmesh_edges_create_tree(
+ epsilon, tree_type, axis,
+ em, edge_num, edges_mask, edges_num_active);
+
+ if (tree) {
+ memset(data, 0, sizeof(*data));
+ data->tree = tree;
+ data->em = em;
+ data->nearest_callback = NULL; /* TODO */
+ data->raycast_callback = NULL; /* TODO */
+ /* TODO: not urgent however since users currently define own callbacks */
+ data->nearest_to_ray_callback = NULL;
+ }
+
+ return tree;
+}
+BVHTree *bvhtree_from_editmesh_edges(
+ BVHTreeFromEditMesh *data, BMEditMesh *em,
+ float epsilon, int tree_type, int axis)
+{
+ return bvhtree_from_editmesh_edges_ex(
+ data, em,
+ NULL, -1,
+ epsilon, tree_type, axis);
+}
+
/* Builds a bvh tree where nodes are the edges of the given dm */
BVHTree *bvhtree_from_mesh_edges(
BVHTreeFromMesh *data, DerivedMesh *dm,
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index eabee742327..ae7aac8b54f 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -49,6 +49,8 @@
#include "BKE_object.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -91,64 +93,46 @@ void *BKE_camera_add(Main *bmain, const char *name)
return cam;
}
-Camera *BKE_camera_copy(Camera *cam)
+Camera *BKE_camera_copy(Main *bmain, Camera *cam)
{
Camera *camn;
- camn = BKE_libblock_copy(&cam->id);
+ camn = BKE_libblock_copy(bmain, &cam->id);
- id_lib_extern((ID *)camn->dof_ob);
-
- if (cam->id.lib) {
- BKE_id_lib_local_paths(G.main, cam->id.lib, &camn->id);
+ if (ID_IS_LINKED_DATABLOCK(cam)) {
+ BKE_id_expand_local(&camn->id);
+ BKE_id_lib_local_paths(bmain, cam->id.lib, &camn->id);
}
return camn;
}
-void BKE_camera_make_local(Camera *cam)
+void BKE_camera_make_local(Main *bmain, Camera *cam)
{
- Main *bmain = G.main;
- Object *ob;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
-
- if (cam->id.lib == NULL) return;
- if (cam->id.us == 1) {
- id_clear_lib_data(bmain, &cam->id);
+
+ if (!ID_IS_LINKED_DATABLOCK(cam)) {
return;
}
-
- for (ob = bmain->object.first; ob && ELEM(0, is_lib, is_local); ob = ob->id.next) {
- if (ob->data == cam) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
- }
- }
-
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &cam->id);
- }
- else if (is_local && is_lib) {
- Camera *cam_new = BKE_camera_copy(cam);
- cam_new->id.us = 0;
+ BKE_library_ID_test_usages(bmain, cam, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &cam->id);
+ BKE_id_expand_local(&cam->id);
+ }
+ else {
+ Camera *cam_new = BKE_camera_copy(bmain, cam);
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, cam->id.lib, &cam_new->id);
+ cam_new->id.us = 0;
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (ob->data == cam) {
- if (ob->id.lib == NULL) {
- ob->data = cam_new;
- id_us_plus(&cam_new->id);
- id_us_min(&cam->id);
- }
- }
+ BKE_libblock_remap(bmain, cam, cam_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index c1f1f0128f5..2932939b208 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -1322,7 +1322,7 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
.cm_processor = cm_processor, .display_buffer = display_buffer, .ycc_mode = ycc_mode,
.bin_lum = bin_lum, .bin_r = bin_r, .bin_g = bin_g, .bin_b = bin_b, .bin_a = bin_a,
};
- ScopesUpdateDataChunk data_chunk = {0};
+ ScopesUpdateDataChunk data_chunk = {{0}};
INIT_MINMAX(data_chunk.min, data_chunk.max);
BLI_task_parallel_range_finalize(0, ibuf->y, &data, &data_chunk, sizeof(data_chunk),
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index a591d536b43..4c9ddd495e3 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -2195,7 +2195,7 @@ static void actcon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintT
}
else if (cob->type == CONSTRAINT_OBTYPE_BONE) {
Object workob;
- bPose pose = {0};
+ bPose pose = {{0}};
bPoseChannel *pchan, *tchan;
/* make a copy of the bone of interest in the temp pose before evaluating action, so that it can get set
@@ -4649,7 +4649,7 @@ void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, void *use
/* helper for BKE_constraints_copy(), to be used for making sure that ID's are valid */
static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, bool UNUSED(is_reference), void *UNUSED(userData))
{
- if (*idpoin && (*idpoin)->lib)
+ if (*idpoin && ID_IS_LINKED_DATABLOCK(*idpoin))
id_lib_extern(*idpoin);
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index dec6ff22360..0e634e21ea3 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -58,6 +58,8 @@
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_material.h"
@@ -172,12 +174,13 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
return cu;
}
-Curve *BKE_curve_copy(Curve *cu)
+Curve *BKE_curve_copy(Main *bmain, Curve *cu)
{
Curve *cun;
int a;
- cun = BKE_libblock_copy(&cu->id);
+ cun = BKE_libblock_copy(bmain, &cu->id);
+
BLI_listbase_clear(&cun->nurb);
BKE_nurbList_duplicate(&(cun->nurb), &(cu->nurb));
@@ -191,45 +194,29 @@ Curve *BKE_curve_copy(Curve *cu)
cun->tb = MEM_dupallocN(cu->tb);
cun->bb = MEM_dupallocN(cu->bb);
- cun->key = BKE_key_copy(cu->key);
- if (cun->key) cun->key->from = (ID *)cun;
+ if (cu->key) {
+ cun->key = BKE_key_copy(bmain, cu->key);
+ cun->key->from = (ID *)cun;
+ }
cun->editnurb = NULL;
cun->editfont = NULL;
-#if 0 // XXX old animation system
- /* single user ipo too */
- if (cun->ipo) cun->ipo = copy_ipo(cun->ipo);
-#endif // XXX old animation system
-
id_us_plus((ID *)cun->vfont);
id_us_plus((ID *)cun->vfontb);
id_us_plus((ID *)cun->vfonti);
id_us_plus((ID *)cun->vfontbi);
- if (cu->id.lib) {
- BKE_id_lib_local_paths(G.main, cu->id.lib, &cun->id);
+ if (ID_IS_LINKED_DATABLOCK(cu)) {
+ BKE_id_expand_local(&cun->id);
+ BKE_id_lib_local_paths(bmain, cu->id.lib, &cun->id);
}
return cun;
}
-static void extern_local_curve(Curve *cu)
-{
- id_lib_extern((ID *)cu->vfont);
- id_lib_extern((ID *)cu->vfontb);
- id_lib_extern((ID *)cu->vfonti);
- id_lib_extern((ID *)cu->vfontbi);
-
- if (cu->mat) {
- extern_local_matarar(cu->mat, cu->totcol);
- }
-}
-
-void BKE_curve_make_local(Curve *cu)
+void BKE_curve_make_local(Main *bmain, Curve *cu)
{
- Main *bmain = G.main;
- Object *ob;
bool is_local = false, is_lib = false;
/* - when there are only lib users: don't do
@@ -237,40 +224,26 @@ void BKE_curve_make_local(Curve *cu)
* - mixed: do a copy
*/
- if (cu->id.lib == NULL)
- return;
-
- if (cu->id.us == 1) {
- id_clear_lib_data(bmain, &cu->id);
- extern_local_curve(cu);
+ if (!ID_IS_LINKED_DATABLOCK(cu)) {
return;
}
- for (ob = bmain->object.first; ob && ELEM(0, is_lib, is_local); ob = ob->id.next) {
- if (ob->data == cu) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
- }
- }
+ BKE_library_ID_test_usages(bmain, cu, &is_local, &is_lib);
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &cu->id);
- extern_local_curve(cu);
- }
- else if (is_local && is_lib) {
- Curve *cu_new = BKE_curve_copy(cu);
- cu_new->id.us = 0;
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &cu->id);
+ if (cu->key) {
+ BKE_key_make_local(bmain, cu->key);
+ }
+ BKE_id_expand_local(&cu->id);
+ }
+ else {
+ Curve *cu_new = BKE_curve_copy(bmain, cu);
- BKE_id_lib_local_paths(bmain, cu->id.lib, &cu_new->id);
+ cu_new->id.us = 0;
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (ob->data == cu) {
- if (ob->id.lib == NULL) {
- ob->data = cu_new;
- id_us_plus(&cu_new->id);
- id_us_min(&cu->id);
- }
- }
+ BKE_libblock_remap(bmain, cu, cu_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
@@ -1384,6 +1357,71 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float *
MEM_freeN(basisu);
}
+/**
+ * Calculate the length for arrays filled in by #BKE_curve_calc_coords_axis.
+ */
+unsigned int BKE_curve_calc_coords_axis_len(
+ const unsigned int bezt_array_len, const unsigned int resolu,
+ const bool is_cyclic, const bool use_cyclic_duplicate_endpoint)
+{
+ const unsigned int segments = bezt_array_len - (is_cyclic ? 0 : 1);
+ const unsigned int points_len = (segments * resolu) + (is_cyclic ? (use_cyclic_duplicate_endpoint) : 1);
+ return points_len;
+}
+
+/**
+ * Calculate an array for the entire curve (cyclic or non-cyclic).
+ * \note Call for each axis.
+ *
+ * \param use_cyclic_duplicate_endpoint: Duplicate values at the beginning & end of the array.
+ */
+void BKE_curve_calc_coords_axis(
+ const BezTriple *bezt_array, const unsigned int bezt_array_len, const unsigned int resolu,
+ const bool is_cyclic, const bool use_cyclic_duplicate_endpoint,
+ /* array params */
+ const unsigned int axis, const unsigned int stride,
+ float *r_points)
+{
+ const unsigned int points_len = BKE_curve_calc_coords_axis_len(
+ bezt_array_len, resolu, is_cyclic, use_cyclic_duplicate_endpoint);
+ float *r_points_offset = r_points;
+
+ const unsigned int resolu_stride = resolu * stride;
+ const unsigned int bezt_array_last = bezt_array_len - 1;
+
+ for (unsigned int i = 0; i < bezt_array_last; i++) {
+ const BezTriple *bezt_curr = &bezt_array[i];
+ const BezTriple *bezt_next = &bezt_array[i + 1];
+ BKE_curve_forward_diff_bezier(
+ bezt_curr->vec[1][axis], bezt_curr->vec[2][axis],
+ bezt_next->vec[0][axis], bezt_next->vec[1][axis],
+ r_points_offset, (int)resolu, stride);
+ r_points_offset = POINTER_OFFSET(r_points_offset, resolu_stride);
+ }
+
+ if (is_cyclic) {
+ const BezTriple *bezt_curr = &bezt_array[bezt_array_last];
+ const BezTriple *bezt_next = &bezt_array[0];
+ BKE_curve_forward_diff_bezier(
+ bezt_curr->vec[1][axis], bezt_curr->vec[2][axis],
+ bezt_next->vec[0][axis], bezt_next->vec[1][axis],
+ r_points_offset, (int)resolu, stride);
+ r_points_offset = POINTER_OFFSET(r_points_offset, resolu_stride);
+ if (use_cyclic_duplicate_endpoint) {
+ *r_points_offset = *r_points;
+ r_points_offset = POINTER_OFFSET(r_points_offset, stride);
+ }
+ }
+ else {
+ float *r_points_last = POINTER_OFFSET(r_points, bezt_array_last * resolu_stride);
+ *r_points_last = bezt_array[bezt_array_last].vec[1][axis];
+ r_points_offset = POINTER_OFFSET(r_points_offset, stride);
+ }
+
+ BLI_assert(POINTER_OFFSET(r_points, points_len * stride) == r_points_offset);
+ UNUSED_VARS_NDEBUG(points_len);
+}
+
/* forward differencing method for bezier curve */
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
{
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index d02041d6da8..82ea710b5b6 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2205,7 +2205,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *userdata, const in
/* tri index */
/* There is a low possibility of actually having a neighbor point which tri is
* already set from another neighbor in a separate thread here.
- * Cheking for both tri_index and neighbour_pixel above reduces that probability
+ * Checking for both tri_index and neighbour_pixel above reduces that probability
* but it remains possible.
* That atomic op (and its memory fence) ensures tPoint->neighbour_pixel is set
* to non--1 *before* its tri_index is set (i.e. that it cannot be used a neighbour).
@@ -3785,7 +3785,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
const float brush_radius = brush->paint_distance * surface->radius_scale;
int numOfVerts;
int ii;
- Bounds3D mesh_bb = {0};
+ Bounds3D mesh_bb = {{0}};
VolumeGrid *grid = bData->grid;
dm = CDDM_copy(brush->dm);
@@ -4475,7 +4475,7 @@ static void dynamic_paint_effect_drip_cb(void *userdata, const int index)
/* Sort of spinlock, but only for given ePoint.
* Since the odds a same ePoint is modified at the same time by several threads is very low, this is
- * much more eficient than a global spin lock. */
+ * much more efficient than a global spin lock. */
const unsigned int pointlock_idx = n_trgt / 8;
const uint8_t pointlock_bitmask = 1 << (n_trgt & 7); /* 7 == 0b111 */
while (atomic_fetch_and_or_uint8(&point_locks[pointlock_idx], pointlock_bitmask) & pointlock_bitmask);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index af1bcd0c545..ac4f566dc62 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -49,6 +49,7 @@
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
+#include "BKE_main.h"
/* ************************************************** */
@@ -358,7 +359,7 @@ bGPDlayer *gpencil_layer_duplicate(bGPDlayer *src)
}
/* make a copy of a given gpencil datablock */
-bGPdata *gpencil_data_duplicate(bGPdata *src, bool internal_copy)
+bGPdata *gpencil_data_duplicate(Main *bmain, bGPdata *src, bool internal_copy)
{
bGPDlayer *gpl, *gpld;
bGPdata *dst;
@@ -374,7 +375,7 @@ bGPdata *gpencil_data_duplicate(bGPdata *src, bool internal_copy)
}
else {
/* make a copy when others use this */
- dst = BKE_libblock_copy(&src->id);
+ dst = BKE_libblock_copy(bmain, &src->id);
}
/* copy layers */
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 95c7730431a..5a51d4797bb 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -86,18 +86,19 @@ Group *BKE_group_add(Main *bmain, const char *name)
return group;
}
-Group *BKE_group_copy(Group *group)
+Group *BKE_group_copy(Main *bmain, Group *group)
{
Group *groupn;
- groupn = BKE_libblock_copy(&group->id);
+ groupn = BKE_libblock_copy(bmain, &group->id);
BLI_duplicatelist(&groupn->gobject, &group->gobject);
/* Do not copy group's preview (same behavior as for objects). */
groupn->preview = NULL;
- if (group->id.lib) {
- BKE_id_lib_local_paths(G.main, group->id.lib, &groupn->id);
+ if (ID_IS_LINKED_DATABLOCK(group)) {
+ BKE_id_expand_local(&groupn->id);
+ BKE_id_lib_local_paths(bmain, group->id.lib, &groupn->id);
}
return groupn;
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 69384a70969..f6f38977402 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -72,6 +72,8 @@
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
@@ -457,25 +459,18 @@ Image *BKE_image_copy(Main *bmain, Image *ima)
nima->stereo3d_format = MEM_dupallocN(ima->stereo3d_format);
BLI_duplicatelist(&nima->views, &ima->views);
- if (ima->id.lib) {
+ nima->preview = BKE_previewimg_copy(ima->preview);
+
+ if (ID_IS_LINKED_DATABLOCK(ima)) {
+ BKE_id_expand_local(&nima->id);
BKE_id_lib_local_paths(bmain, ima->id.lib, &nima->id);
}
return nima;
}
-static void extern_local_image(Image *UNUSED(ima))
-{
- /* Nothing to do: images don't link to other IDs. This function exists to
- * match id_make_local pattern. */
-}
-
-void BKE_image_make_local(struct Image *ima)
+void BKE_image_make_local(Main *bmain, Image *ima)
{
- Main *bmain = G.main;
- Tex *tex;
- Brush *brush;
- Mesh *me;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
@@ -483,147 +478,23 @@ void BKE_image_make_local(struct Image *ima)
* - mixed: make copy
*/
- if (ima->id.lib == NULL) return;
-
- /* Can't take short cut here: must check meshes at least because of bogus
- * texface ID refs. - z0r */
-#if 0
- if (ima->id.us == 1) {
- id_clear_lib_data(bmain, &ima->id);
- extern_local_image(ima);
+ if (!ID_IS_LINKED_DATABLOCK(ima)) {
return;
}
-#endif
-
- for (tex = bmain->tex.first; tex; tex = tex->id.next) {
- if (tex->ima == ima) {
- if (tex->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- for (brush = bmain->brush.first; brush; brush = brush->id.next) {
- if (brush->clone.image == ima) {
- if (brush->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- for (me = bmain->mesh.first; me; me = me->id.next) {
- if (me->mtface) {
- MTFace *tface;
- int a, i;
- for (i = 0; i < me->fdata.totlayer; i++) {
- if (me->fdata.layers[i].type == CD_MTFACE) {
- tface = (MTFace *)me->fdata.layers[i].data;
+ BKE_library_ID_test_usages(bmain, ima, &is_local, &is_lib);
- for (a = 0; a < me->totface; a++, tface++) {
- if (tface->tpage == ima) {
- if (me->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- }
- }
- }
-
- if (me->mtpoly) {
- MTexPoly *mtpoly;
- int a, i;
-
- for (i = 0; i < me->pdata.totlayer; i++) {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- mtpoly = (MTexPoly *)me->pdata.layers[i].data;
-
- for (a = 0; a < me->totpoly; a++, mtpoly++) {
- if (mtpoly->tpage == ima) {
- if (me->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- }
- }
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &ima->id);
+ BKE_id_expand_local(&ima->id);
}
+ else {
+ Image *ima_new = BKE_image_copy(bmain, ima);
- }
-
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &ima->id);
- extern_local_image(ima);
- }
- else if (is_local && is_lib) {
- Image *ima_new = BKE_image_copy(bmain, ima);
-
- ima_new->id.us = 0;
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, ima->id.lib, &ima_new->id);
-
- tex = bmain->tex.first;
- while (tex) {
- if (tex->id.lib == NULL) {
- if (tex->ima == ima) {
- tex->ima = ima_new;
- id_us_plus(&ima_new->id);
- id_us_min(&ima->id);
- }
- }
- tex = tex->id.next;
- }
- brush = bmain->brush.first;
- while (brush) {
- if (brush->id.lib == NULL) {
- if (brush->clone.image == ima) {
- brush->clone.image = ima_new;
- id_us_plus(&ima_new->id);
- id_us_min(&ima->id);
- }
- }
- brush = brush->id.next;
- }
- /* Transfer references in texfaces. Texfaces don't add to image ID
- * user count *unless* there are no other users. See
- * readfile.c:lib_link_mtface. */
- me = bmain->mesh.first;
- while (me) {
- if (me->mtface) {
- MTFace *tface;
- int a, i;
-
- for (i = 0; i < me->fdata.totlayer; i++) {
- if (me->fdata.layers[i].type == CD_MTFACE) {
- tface = (MTFace *)me->fdata.layers[i].data;
-
- for (a = 0; a < me->totface; a++, tface++) {
- if (tface->tpage == ima) {
- tface->tpage = ima_new;
- id_us_ensure_real((ID *)ima_new);
- id_lib_extern((ID *)ima_new);
- }
- }
- }
- }
- }
-
- if (me->mtpoly) {
- MTexPoly *mtpoly;
- int a, i;
-
- for (i = 0; i < me->pdata.totlayer; i++) {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- mtpoly = (MTexPoly *)me->pdata.layers[i].data;
-
- for (a = 0; a < me->totpoly; a++, mtpoly++) {
- if (mtpoly->tpage == ima) {
- mtpoly->tpage = ima_new;
- id_us_ensure_real((ID *)ima_new);
- id_lib_extern((ID *)ima_new);
- }
- }
- }
- }
- }
+ ima_new->id.us = 0;
- me = me->id.next;
+ BKE_libblock_remap(bmain, ima, ima_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 2517e2cc197..e59facd3c39 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -58,6 +58,7 @@
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
#include "BKE_scene.h"
@@ -149,14 +150,12 @@ Key *BKE_key_add(ID *id) /* common function */
return key;
}
-Key *BKE_key_copy(Key *key)
+Key *BKE_key_copy(Main *bmain, Key *key)
{
Key *keyn;
KeyBlock *kbn, *kb;
- if (key == NULL) return NULL;
-
- keyn = BKE_libblock_copy(&key->id);
+ keyn = BKE_libblock_copy(bmain, &key->id);
BLI_duplicatelist(&keyn->block, &key->block);
@@ -171,22 +170,19 @@ Key *BKE_key_copy(Key *key)
kb = kb->next;
}
- if (key->id.lib) {
- BKE_id_lib_local_paths(G.main, key->id.lib, &keyn->id);
+ if (ID_IS_LINKED_DATABLOCK(key)) {
+ BKE_id_expand_local(&keyn->id);
+ BKE_id_lib_local_paths(bmain, key->id.lib, &keyn->id);
}
return keyn;
}
-
Key *BKE_key_copy_nolib(Key *key)
{
Key *keyn;
KeyBlock *kbn, *kb;
- if (key == NULL)
- return NULL;
-
keyn = MEM_dupallocN(key);
keyn->adt = NULL;
@@ -207,17 +203,16 @@ Key *BKE_key_copy_nolib(Key *key)
return keyn;
}
-void BKE_key_make_local(Key *key)
+void BKE_key_make_local(Main *bmain, Key *key)
{
+ /* Note that here for now we simply just make it local...
+ * Sounds fishy behavior, but since skeys are not *real* IDs... */
- /* - only lib users: do nothing
- * - only local users: set flag
- * - mixed: make copy
- */
- if (key == NULL) return;
-
- key->id.lib = NULL;
- new_id(NULL, &key->id, NULL);
+ if (!ID_IS_LINKED_DATABLOCK(key)) {
+ return;
+ }
+
+ id_clear_lib_data(bmain, &key->id);
}
/* Sort shape keys and Ipo curves after a change. This assumes that at most
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 692b703f721..003b154a70b 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -50,6 +50,8 @@
#include "BKE_global.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -114,12 +116,12 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name)
return la;
}
-Lamp *BKE_lamp_copy(Lamp *la)
+Lamp *BKE_lamp_copy(Main *bmain, Lamp *la)
{
Lamp *lan;
int a;
- lan = BKE_libblock_copy(&la->id);
+ lan = BKE_libblock_copy(bmain, &la->id);
for (a = 0; a < MAX_MTEX; a++) {
if (lan->mtex[a]) {
@@ -132,13 +134,13 @@ Lamp *BKE_lamp_copy(Lamp *la)
lan->curfalloff = curvemapping_copy(la->curfalloff);
if (la->nodetree)
- lan->nodetree = ntreeCopyTree(la->nodetree);
+ lan->nodetree = ntreeCopyTree(bmain, la->nodetree);
- if (la->preview)
- lan->preview = BKE_previewimg_copy(la->preview);
-
- if (la->id.lib) {
- BKE_id_lib_local_paths(G.main, la->id.lib, &lan->id);
+ lan->preview = BKE_previewimg_copy(la->preview);
+
+ if (ID_IS_LINKED_DATABLOCK(la)) {
+ BKE_id_expand_local(&lan->id);
+ BKE_id_lib_local_paths(bmain, la->id.lib, &lan->id);
}
return lan;
@@ -166,14 +168,12 @@ Lamp *localize_lamp(Lamp *la)
lan->nodetree = ntreeLocalize(la->nodetree);
lan->preview = NULL;
-
+
return lan;
}
-void BKE_lamp_make_local(Lamp *la)
+void BKE_lamp_make_local(Main *bmain, Lamp *la)
{
- Main *bmain = G.main;
- Object *ob;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
@@ -181,42 +181,23 @@ void BKE_lamp_make_local(Lamp *la)
* - mixed: make copy
*/
- if (la->id.lib == NULL) return;
- if (la->id.us == 1) {
- id_clear_lib_data(bmain, &la->id);
+ if (!ID_IS_LINKED_DATABLOCK(la)) {
return;
}
-
- ob = bmain->object.first;
- while (ob) {
- if (ob->data == la) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
+
+ BKE_library_ID_test_usages(bmain, la, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &la->id);
+ BKE_id_expand_local(&la->id);
}
- ob = ob->id.next;
- }
-
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &la->id);
- }
- else if (is_local && is_lib) {
- Lamp *la_new = BKE_lamp_copy(la);
- la_new->id.us = 0;
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, la->id.lib, &la_new->id);
-
- ob = bmain->object.first;
- while (ob) {
- if (ob->data == la) {
-
- if (ob->id.lib == NULL) {
- ob->data = la_new;
- id_us_plus(&la_new->id);
- id_us_min(&la->id);
- }
- }
- ob = ob->id.next;
+ else {
+ Lamp *la_new = BKE_lamp_copy(bmain, la);
+
+ la_new->id.us = 0;
+
+ BKE_libblock_remap(bmain, la, la_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 58c0a567116..67f49266efc 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -59,6 +59,8 @@
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -275,15 +277,17 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name)
return lt;
}
-Lattice *BKE_lattice_copy(Lattice *lt)
+Lattice *BKE_lattice_copy(Main *bmain, Lattice *lt)
{
Lattice *ltn;
- ltn = BKE_libblock_copy(&lt->id);
+ ltn = BKE_libblock_copy(bmain, &lt->id);
ltn->def = MEM_dupallocN(lt->def);
- ltn->key = BKE_key_copy(ltn->key);
- if (ltn->key) ltn->key->from = (ID *)ltn;
+ if (lt->key) {
+ ltn->key = BKE_key_copy(bmain, ltn->key);
+ ltn->key->from = (ID *)ltn;
+ }
if (lt->dvert) {
int tot = lt->pntsu * lt->pntsv * lt->pntsw;
@@ -293,8 +297,9 @@ Lattice *BKE_lattice_copy(Lattice *lt)
ltn->editlatt = NULL;
- if (lt->id.lib) {
- BKE_id_lib_local_paths(G.main, lt->id.lib, &ltn->id);
+ if (ID_IS_LINKED_DATABLOCK(lt)) {
+ BKE_id_expand_local(&ltn->id);
+ BKE_id_lib_local_paths(bmain, lt->id.lib, &ltn->id);
}
return ltn;
@@ -325,48 +330,35 @@ void BKE_lattice_free(Lattice *lt)
}
-void BKE_lattice_make_local(Lattice *lt)
+void BKE_lattice_make_local(Main *bmain, Lattice *lt)
{
- Main *bmain = G.main;
- Object *ob;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
-
- if (lt->id.lib == NULL) return;
- if (lt->id.us == 1) {
- id_clear_lib_data(bmain, &lt->id);
+
+ if (!ID_IS_LINKED_DATABLOCK(lt)) {
return;
}
-
- for (ob = bmain->object.first; ob && ELEM(false, is_lib, is_local); ob = ob->id.next) {
- if (ob->data == lt) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
- }
- }
-
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &lt->id);
- }
- else if (is_local && is_lib) {
- Lattice *lt_new = BKE_lattice_copy(lt);
- lt_new->id.us = 0;
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, lt->id.lib, &lt_new->id);
-
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (ob->data == lt) {
- if (ob->id.lib == NULL) {
- ob->data = lt_new;
- id_us_plus(&lt_new->id);
- id_us_min(&lt->id);
- }
+
+ BKE_library_ID_test_usages(bmain, lt, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &lt->id);
+ if (lt->key) {
+ BKE_key_make_local(bmain, lt->key);
}
+ BKE_id_expand_local(&lt->id);
+ }
+ else {
+ Lattice *lt_new = BKE_lattice_copy(bmain, lt);
+
+ lt_new->id.us = 0;
+
+ BKE_libblock_remap(bmain, lt, lt_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 5f7bded4262..978f1acefba 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -141,7 +141,7 @@ void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
void id_lib_extern(ID *id)
{
- if (id) {
+ if (id && ID_IS_LINKED_DATABLOCK(id)) {
BLI_assert(BKE_idcode_is_linkable(GS(id->name)));
if (id->tag & LIB_TAG_INDIRECT) {
id->tag -= LIB_TAG_INDIRECT;
@@ -250,9 +250,27 @@ void id_fake_user_clear(ID *id)
}
}
+static int id_expand_local_callback(
+ void *UNUSED(user_data), struct ID *UNUSED(id_self), struct ID **id_pointer, int UNUSED(cd_flag))
+{
+ if (*id_pointer) {
+ id_lib_extern(*id_pointer);
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+/**
+ * Expand ID usages of given id as 'extern' (and no more indirect) linked data. Used by ID copy/make_local functions.
+ */
+void BKE_id_expand_local(ID *id)
+{
+ BKE_library_foreach_ID_link(id, id_expand_local_callback, NULL, 0);
+}
+
/* calls the appropriate make_local method for the block, unless test. Returns true
* if the block can be made local. */
-bool id_make_local(ID *id, bool test)
+bool id_make_local(Main *bmain, ID *id, bool test)
{
if (id->tag & LIB_TAG_INDIRECT)
return false;
@@ -263,54 +281,45 @@ bool id_make_local(ID *id, bool test)
case ID_LI:
return false; /* can't be linked */
case ID_OB:
- if (!test) BKE_object_make_local((Object *)id);
+ if (!test) BKE_object_make_local(bmain, (Object *)id);
return true;
case ID_ME:
- if (!test) {
- BKE_mesh_make_local((Mesh *)id);
- BKE_key_make_local(((Mesh *)id)->key);
- }
+ if (!test) BKE_mesh_make_local(bmain, (Mesh *)id);
return true;
case ID_CU:
- if (!test) {
- BKE_curve_make_local((Curve *)id);
- BKE_key_make_local(((Curve *)id)->key);
- }
+ if (!test) BKE_curve_make_local(bmain, (Curve *)id);
return true;
case ID_MB:
- if (!test) BKE_mball_make_local((MetaBall *)id);
+ if (!test) BKE_mball_make_local(bmain, (MetaBall *)id);
return true;
case ID_MA:
- if (!test) BKE_material_make_local((Material *)id);
+ if (!test) BKE_material_make_local(bmain, (Material *)id);
return true;
case ID_TE:
- if (!test) BKE_texture_make_local((Tex *)id);
+ if (!test) BKE_texture_make_local(bmain, (Tex *)id);
return true;
case ID_IM:
- if (!test) BKE_image_make_local((Image *)id);
+ if (!test) BKE_image_make_local(bmain, (Image *)id);
return true;
case ID_LT:
- if (!test) {
- BKE_lattice_make_local((Lattice *)id);
- BKE_key_make_local(((Lattice *)id)->key);
- }
+ if (!test) BKE_lattice_make_local(bmain, (Lattice *)id);
return true;
case ID_LA:
- if (!test) BKE_lamp_make_local((Lamp *)id);
+ if (!test) BKE_lamp_make_local(bmain, (Lamp *)id);
return true;
case ID_CA:
- if (!test) BKE_camera_make_local((Camera *)id);
+ if (!test) BKE_camera_make_local(bmain, (Camera *)id);
return true;
case ID_SPK:
- if (!test) BKE_speaker_make_local((Speaker *)id);
+ if (!test) BKE_speaker_make_local(bmain, (Speaker *)id);
return true;
case ID_IP:
return false; /* deprecated */
case ID_KE:
- if (!test) BKE_key_make_local((Key *)id);
+ if (!test) BKE_key_make_local(bmain, (Key *)id);
return true;
case ID_WO:
- if (!test) BKE_world_make_local((World *)id);
+ if (!test) BKE_world_make_local(bmain, (World *)id);
return true;
case ID_SCR:
return false; /* can't be linked */
@@ -323,16 +332,16 @@ bool id_make_local(ID *id, bool test)
case ID_GR:
return false; /* not implemented */
case ID_AR:
- if (!test) BKE_armature_make_local((bArmature *)id);
+ if (!test) BKE_armature_make_local(bmain, (bArmature *)id);
return true;
case ID_AC:
- if (!test) BKE_action_make_local((bAction *)id);
+ if (!test) BKE_action_make_local(bmain, (bAction *)id);
return true;
case ID_NT:
- if (!test) ntreeMakeLocal((bNodeTree *)id, true);
+ if (!test) ntreeMakeLocal(bmain, (bNodeTree *)id, true);
return true;
case ID_BR:
- if (!test) BKE_brush_make_local((Brush *)id);
+ if (!test) BKE_brush_make_local(bmain, (Brush *)id);
return true;
case ID_WM:
return false; /* can't be linked */
@@ -349,9 +358,11 @@ bool id_make_local(ID *id, bool test)
* Invokes the appropriate copy method for the block and returns the result in
* newid, unless test. Returns true if the block can be copied.
*/
-bool id_copy(ID *id, ID **newid, bool test)
+bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
{
- if (!test) *newid = NULL;
+ if (!test) {
+ *newid = NULL;
+ }
/* conventions:
* - make shallow copy, only this ID block
@@ -362,80 +373,80 @@ bool id_copy(ID *id, ID **newid, bool test)
case ID_LI:
return false; /* can't be copied from here */
case ID_OB:
- if (!test) *newid = (ID *)BKE_object_copy((Object *)id);
+ if (!test) *newid = (ID *)BKE_object_copy(bmain, (Object *)id);
return true;
case ID_ME:
- if (!test) *newid = (ID *)BKE_mesh_copy((Mesh *)id);
+ if (!test) *newid = (ID *)BKE_mesh_copy(bmain, (Mesh *)id);
return true;
case ID_CU:
- if (!test) *newid = (ID *)BKE_curve_copy((Curve *)id);
+ if (!test) *newid = (ID *)BKE_curve_copy(bmain, (Curve *)id);
return true;
case ID_MB:
- if (!test) *newid = (ID *)BKE_mball_copy((MetaBall *)id);
+ if (!test) *newid = (ID *)BKE_mball_copy(bmain, (MetaBall *)id);
return true;
case ID_MA:
- if (!test) *newid = (ID *)BKE_material_copy((Material *)id);
+ if (!test) *newid = (ID *)BKE_material_copy(bmain, (Material *)id);
return true;
case ID_TE:
- if (!test) *newid = (ID *)BKE_texture_copy((Tex *)id);
+ if (!test) *newid = (ID *)BKE_texture_copy(bmain, (Tex *)id);
return true;
case ID_IM:
- if (!test) *newid = (ID *)BKE_image_copy(G.main, (Image *)id);
+ if (!test) *newid = (ID *)BKE_image_copy(bmain, (Image *)id);
return true;
case ID_LT:
- if (!test) *newid = (ID *)BKE_lattice_copy((Lattice *)id);
+ if (!test) *newid = (ID *)BKE_lattice_copy(bmain, (Lattice *)id);
return true;
case ID_LA:
- if (!test) *newid = (ID *)BKE_lamp_copy((Lamp *)id);
+ if (!test) *newid = (ID *)BKE_lamp_copy(bmain, (Lamp *)id);
return true;
case ID_SPK:
- if (!test) *newid = (ID *)BKE_speaker_copy((Speaker *)id);
+ if (!test) *newid = (ID *)BKE_speaker_copy(bmain, (Speaker *)id);
return true;
case ID_CA:
- if (!test) *newid = (ID *)BKE_camera_copy((Camera *)id);
+ if (!test) *newid = (ID *)BKE_camera_copy(bmain, (Camera *)id);
return true;
case ID_IP:
return false; /* deprecated */
case ID_KE:
- if (!test) *newid = (ID *)BKE_key_copy((Key *)id);
+ if (!test) *newid = (ID *)BKE_key_copy(bmain, (Key *)id);
return true;
case ID_WO:
- if (!test) *newid = (ID *)BKE_world_copy((World *)id);
+ if (!test) *newid = (ID *)BKE_world_copy(bmain, (World *)id);
return true;
case ID_SCR:
return false; /* can't be copied from here */
case ID_VF:
return false; /* not implemented */
case ID_TXT:
- if (!test) *newid = (ID *)BKE_text_copy(G.main, (Text *)id);
+ if (!test) *newid = (ID *)BKE_text_copy(bmain, (Text *)id);
return true;
case ID_SO:
return false; /* not implemented */
case ID_GR:
- if (!test) *newid = (ID *)BKE_group_copy((Group *)id);
+ if (!test) *newid = (ID *)BKE_group_copy(bmain, (Group *)id);
return true;
case ID_AR:
- if (!test) *newid = (ID *)BKE_armature_copy((bArmature *)id);
+ if (!test) *newid = (ID *)BKE_armature_copy(bmain, (bArmature *)id);
return true;
case ID_AC:
- if (!test) *newid = (ID *)BKE_action_copy((bAction *)id);
+ if (!test) *newid = (ID *)BKE_action_copy(bmain, (bAction *)id);
return true;
case ID_NT:
- if (!test) *newid = (ID *)ntreeCopyTree((bNodeTree *)id);
+ if (!test) *newid = (ID *)ntreeCopyTree(bmain, (bNodeTree *)id);
return true;
case ID_BR:
- if (!test) *newid = (ID *)BKE_brush_copy((Brush *)id);
+ if (!test) *newid = (ID *)BKE_brush_copy(bmain, (Brush *)id);
return true;
case ID_WM:
return false; /* can't be copied from here */
case ID_GD:
- if (!test) *newid = (ID *)gpencil_data_duplicate((bGPdata *)id, false);
+ if (!test) *newid = (ID *)gpencil_data_duplicate(bmain, (bGPdata *)id, false);
return true;
case ID_MSK:
- if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id);
+ if (!test) *newid = (ID *)BKE_mask_copy(bmain, (Mask *)id);
return true;
case ID_LS:
- if (!test) *newid = (ID *)BKE_linestyle_copy(G.main, (FreestyleLineStyle *)id);
+ if (!test) *newid = (ID *)BKE_linestyle_copy(bmain, (FreestyleLineStyle *)id);
return true;
}
@@ -450,7 +461,7 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
if (id) {
/* if property isn't editable, we're going to have an extra block hanging around until we save */
if (RNA_property_editable(ptr, prop)) {
- if (id_copy(id, &newid, false) && newid) {
+ if (id_copy(CTX_data_main(C), id, &newid, false) && newid) {
/* copy animation actions too */
BKE_animdata_copy_id_action(id);
/* us is 1 by convention, but RNA_property_pointer_set
@@ -621,7 +632,7 @@ void BKE_main_lib_objects_recalc_all(Main *bmain)
/* flag for full recalc */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (ob->id.lib) {
+ if (ID_IS_LINKED_DATABLOCK(ob)) {
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
}
@@ -969,7 +980,7 @@ void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action)
}
/* used everywhere in blenkernel */
-void *BKE_libblock_copy_ex(Main *bmain, ID *id)
+void *BKE_libblock_copy(Main *bmain, ID *id)
{
ID *idn;
size_t idn_len;
@@ -1021,11 +1032,6 @@ void *BKE_libblock_copy_nolib(ID *id, const bool do_action)
return idn;
}
-void *BKE_libblock_copy(ID *id)
-{
- return BKE_libblock_copy_ex(G.main, id);
-}
-
static int id_relink_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cd_flag)
{
ID *id = *id_pointer;
@@ -1045,7 +1051,7 @@ static int id_relink_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **i
void BKE_libblock_relink(ID *id)
{
- if (id->lib)
+ if (ID_IS_LINKED_DATABLOCK(id))
return;
BKE_library_foreach_ID_link(id, id_relink_looper, NULL, 0);
@@ -1259,7 +1265,7 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name)
for (idtest = lb->first; idtest; idtest = idtest->next) {
/* if idtest is not a lib */
- if (id != idtest && idtest->lib == NULL) {
+ if (id != idtest && !ID_IS_LINKED_DATABLOCK(idtest)) {
/* do not test alphabetic! */
/* optimized */
if (idtest->name[2] == name[0]) {
@@ -1319,7 +1325,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name)
for (idtest = lb->first; idtest; idtest = idtest->next) {
int nrtest;
if ( (id != idtest) &&
- (idtest->lib == NULL) &&
+ !ID_IS_LINKED_DATABLOCK(idtest) &&
(*name == *(idtest->name + 2)) &&
STREQLEN(name, idtest->name + 2, left_len) &&
(BLI_split_name_num(leftest, &nrtest, idtest->name + 2, '.') == left_len)
@@ -1401,7 +1407,7 @@ bool new_id(ListBase *lb, ID *id, const char *tname)
char name[MAX_ID_NAME - 2];
/* if library, don't rename */
- if (id->lib)
+ if (ID_IS_LINKED_DATABLOCK(id))
return false;
/* if no libdata given, look up based on ID */
@@ -1465,7 +1471,7 @@ void id_clear_lib_data_ex(Main *bmain, ID *id, bool id_in_mainlist)
ntree = ntreeFromID(id);
if (ntree) {
- ntreeMakeLocal(ntree, false);
+ ntreeMakeLocal(bmain, ntree, false);
}
if (GS(id->name) == ID_OB) {
@@ -1506,7 +1512,7 @@ static void lib_indirect_test_id(ID *id, const Library *lib)
#define LIBTAG(a) \
if (a && a->id.lib) { a->id.tag &= ~LIB_TAG_INDIRECT; a->id.tag |= LIB_TAG_EXTERN; } (void)0
- if (id->lib) {
+ if (ID_IS_LINKED_DATABLOCK(id)) {
/* datablocks that were indirectly related are now direct links
* without this, appending data that has a link to other data will fail to write */
if (lib && id->lib->parent == lib) {
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 7cb5bfd1360..b623cecb0ff 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -45,6 +45,7 @@
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
@@ -71,6 +72,7 @@
#include "BKE_fcurve.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
+#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_rigidbody.h"
#include "BKE_sca.h"
@@ -85,7 +87,7 @@
if (!((_data)->status & IDWALK_STOP)) { \
const int _flag = (_data)->flag; \
ID *old_id = *(id_pp); \
- const int callback_return = (_data)->callback((_data)->user_data, (_data)->self_id, id_pp, cb_flag); \
+ const int callback_return = (_data)->callback((_data)->user_data, (_data)->self_id, id_pp, cb_flag | (_data)->cd_flag); \
if (_flag & IDWALK_READONLY) { \
BLI_assert(*(id_pp) == old_id); \
} \
@@ -126,6 +128,7 @@ enum {
typedef struct LibraryForeachIDData {
ID *self_id;
int flag;
+ int cd_flag;
LibraryIDLinkCallback callback;
void *user_data;
int status;
@@ -285,6 +288,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
do {
data.self_id = id;
+ data.cd_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_INDIRECT_USAGE : 0;
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
@@ -400,7 +404,12 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
Object *object = (Object *) id;
+ /* Object is special, proxies make things hard... */
+ const int data_cd_flag = data.cd_flag;
+ const int proxy_cd_flag = (object->proxy || object->proxy_group) ? IDWALK_INDIRECT_USAGE : 0;
+
/* object data special case */
+ data.cd_flag |= proxy_cd_flag;
if (object->type == OB_EMPTY) {
/* empty can have NULL or Image */
CALLBACK_INVOKE_ID(object->data, IDWALK_USER);
@@ -411,6 +420,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
CALLBACK_INVOKE_ID(object->data, IDWALK_USER | IDWALK_NEVER_NULL);
}
}
+ data.cd_flag = data_cd_flag;
CALLBACK_INVOKE(object->parent, IDWALK_NOP);
CALLBACK_INVOKE(object->track, IDWALK_NOP);
@@ -419,9 +429,13 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP);
CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP);
CALLBACK_INVOKE(object->poselib, IDWALK_USER);
+
+ data.cd_flag |= proxy_cd_flag;
for (i = 0; i < object->totcol; i++) {
CALLBACK_INVOKE(object->mat[i], IDWALK_USER);
}
+ data.cd_flag = data_cd_flag;
+
CALLBACK_INVOKE(object->gpd, IDWALK_USER);
CALLBACK_INVOKE(object->dup_group, IDWALK_USER);
@@ -433,10 +447,13 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
if (object->pose) {
bPoseChannel *pchan;
+
+ data.cd_flag |= proxy_cd_flag;
for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) {
CALLBACK_INVOKE(pchan->custom, IDWALK_USER);
BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data);
}
+ data.cd_flag = data_cd_flag;
}
if (object->rigidbody_constraint) {
@@ -468,6 +485,31 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
for (i = 0; i < mesh->totcol; i++) {
CALLBACK_INVOKE(mesh->mat[i], IDWALK_USER);
}
+
+ /* XXX Really not happy with this - probably texface should rather use some kind of
+ * 'texture slots' and just set indices in each poly/face item - would also save some memory.
+ * Maybe a nice TODO for blender2.8? */
+ if (mesh->mtface || mesh->mtpoly) {
+ for (i = 0; i < mesh->pdata.totlayer; i++) {
+ if (mesh->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)mesh->pdata.layers[i].data;
+
+ for (int j = 0; j < mesh->totpoly; j++, txface++) {
+ CALLBACK_INVOKE(txface->tpage, IDWALK_USER_ONE);
+ }
+ }
+ }
+
+ for (i = 0; i < mesh->fdata.totlayer; i++) {
+ if (mesh->fdata.layers[i].type == CD_MTFACE) {
+ MTFace *tface = (MTFace *)mesh->fdata.layers[i].data;
+
+ for (int j = 0; j < mesh->totface; j++, tface++) {
+ CALLBACK_INVOKE(tface->tpage, IDWALK_USER_ONE);
+ }
+ }
+ }
+ }
break;
}
@@ -743,6 +785,80 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cd_flag)
}
}
+/**
+ * Say whether given \a id_type_owner can use (in any way) a datablock of \a id_type_used.
+ */
+/* This is a 'simplified' abstract version of BKE_library_foreach_ID_link() above, quite useful to reduce
+ * useless ietrations in some cases. */
+bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id_type_used)
+{
+ if (id_type_used == ID_AC) {
+ return id_type_can_have_animdata(id_type_owner);
+ }
+
+ switch (id_type_owner) {
+ case ID_LI:
+ return ELEM(id_type_used, ID_LI);
+ case ID_SCE:
+ return (ELEM(id_type_used, ID_OB, ID_WO, ID_SCE, ID_MC, ID_MA, ID_GR, ID_TXT,
+ ID_LS, ID_MSK, ID_SO, ID_GD, ID_BR, ID_PAL, ID_IM, ID_NT) ||
+ BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ case ID_OB:
+ /* Could be the following, but simpler to just always say 'yes' here. */
+#if 0
+ return ELEM(id_type_used, ID_ME, ID_CU, ID_MB, ID_LT, ID_SPK, ID_AR, ID_LA, ID_CA, /* obdata */
+ ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC
+ /* + constraints, modifiers and game logic ID types... */);
+#else
+ return true;
+#endif
+ case ID_ME:
+ return ELEM(id_type_used, ID_ME, ID_KE, ID_MA);
+ case ID_CU:
+ return ELEM(id_type_used, ID_OB, ID_KE, ID_MA, ID_VF);
+ case ID_MB:
+ return ELEM(id_type_used, ID_MA);
+ case ID_MA:
+ return (ELEM(id_type_used, ID_TE, ID_GR) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ case ID_TE:
+ return (ELEM(id_type_used, ID_IM, ID_OB) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ case ID_LT:
+ return ELEM(id_type_used, ID_KE);
+ case ID_LA:
+ return (ELEM(id_type_used, ID_TE) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ case ID_CA:
+ return ELEM(id_type_used, ID_OB);
+ case ID_KE:
+ return ELEM(id_type_used, ID_ME, ID_CU, ID_LT); /* Warning! key->from, could be more types in future? */
+ case ID_SCR:
+ return ELEM(id_type_used, ID_SCE);
+ case ID_WO:
+ return (ELEM(id_type_used, ID_TE) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ case ID_SPK:
+ return ELEM(id_type_used, ID_SO);
+ case ID_GR:
+ return ELEM(id_type_used, ID_OB);
+ case ID_NT:
+ /* Could be the following, but node.id has no type restriction... */
+#if 0
+ return ELEM(id_type_used, ID_GD /* + node.id types... */);
+#else
+ return true;
+#endif
+ case ID_BR:
+ return ELEM(id_type_used, ID_BR, ID_IM, ID_PC, ID_TE);
+ case ID_MC:
+ return ELEM(id_type_used, ID_GD, ID_IM);
+ case ID_MSK:
+ return ELEM(id_type_used, ID_MC); /* WARNING! mask->parent.id, not typed. */
+ case ID_LS:
+ return (ELEM(id_type_used, ID_TE, ID_OB) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used));
+ default:
+ return false;
+ }
+}
+
+
/* ***** ID users iterator. ***** */
typedef struct IDUsersIter {
ID *id;
@@ -751,7 +867,7 @@ typedef struct IDUsersIter {
int lb_idx;
ID *curr_id;
- int count; /* Set by callback. */
+ int count_direct, count_indirect; /* Set by callback. */
} IDUsersIter;
static int foreach_libblock_id_users_callback(void *user_data, ID *UNUSED(self_id), ID **id_p, int cb_flag)
@@ -760,13 +876,17 @@ static int foreach_libblock_id_users_callback(void *user_data, ID *UNUSED(self_i
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",
+ printf("%s uses %s (refcounted: %d, userone: %d, used_one: %d, used_one_active: %d, indirect_usage: %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);
+ (iter->id->tag & LIB_TAG_EXTRAUSER) ? 1 : 0, (iter->id->tag & LIB_TAG_EXTRAUSER_SET) ? 1 : 0,
+ (cb_flag & IDWALK_INDIRECT_USAGE) ? 1 : 0);
#endif
- iter->count++;
+ if (cb_flag & IDWALK_INDIRECT_USAGE) {
+ iter->count_indirect++;
+ }
+ else {
+ iter->count_direct++;
+ }
}
return IDWALK_RET_NOP;
@@ -789,9 +909,86 @@ int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
/* We do not care about iter.lb_array/lb_idx here... */
iter.id = id_used;
iter.curr_id = id_user;
- iter.count = 0;
+ iter.count_direct = iter.count_indirect = 0;
BKE_library_foreach_ID_link(iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_NOP);
- return iter.count;
+ return iter.count_direct + iter.count_indirect;
+}
+
+static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
+{
+ IDUsersIter iter;
+ ListBase *lb_array[MAX_LIBARRAY];
+ ID *id = idv;
+ int i = set_listbasepointers(bmain, lb_array);
+ bool is_defined = false;
+
+ iter.id = id;
+ iter.count_direct = iter.count_indirect = 0;
+ while (i-- && !is_defined) {
+ ID *id_curr = lb_array[i]->first;
+
+ if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(id->name))) {
+ continue;
+ }
+
+ for (; id_curr && !is_defined; id_curr = id_curr->next) {
+ iter.curr_id = id_curr;
+ BKE_library_foreach_ID_link(
+ id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP);
+
+ is_defined = ((check_linked ? iter.count_indirect : iter.count_direct) != 0);
+ }
+ }
+
+ return is_defined;
+}
+
+/**
+ * Check whether given ID is used locally (i.e. by another non-linked ID).
+ */
+bool BKE_library_ID_is_locally_used(Main *bmain, void *idv)
+{
+ return library_ID_is_used(bmain, idv, false);
+}
+
+/**
+ * Check whether given ID is used indirectly (i.e. by another linked ID).
+ */
+bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
+{
+ return library_ID_is_used(bmain, idv, true);
+}
+
+/**
+ * Combine \a BKE_library_ID_is_locally_used() and \a BKE_library_ID_is_indirectly_used() in a single call.
+ */
+void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked)
+{
+ IDUsersIter iter;
+ ListBase *lb_array[MAX_LIBARRAY];
+ ID *id = idv;
+ int i = set_listbasepointers(bmain, lb_array);
+ bool is_defined = false;
+
+ iter.id = id;
+ iter.count_direct = iter.count_indirect = 0;
+ while (i-- && !is_defined) {
+ ID *id_curr = lb_array[i]->first;
+
+ if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(id->name))) {
+ continue;
+ }
+
+ for (; id_curr && !is_defined; id_curr = id_curr->next) {
+ iter.curr_id = id_curr;
+ BKE_library_foreach_ID_link(id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP);
+
+ is_defined = (iter.count_direct != 0 && iter.count_indirect != 0);
+ }
+ }
+
+ *is_used_local = (iter.count_direct != 0);
+ *is_used_linked = (iter.count_indirect != 0);
}
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index e9598bee0df..62a6541529a 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -88,9 +88,11 @@
#include "BKE_mesh.h"
#include "BKE_material.h"
#include "BKE_main.h"
+#include "BKE_mask.h"
#include "BKE_mball.h"
+#include "BKE_modifier.h"
#include "BKE_movieclip.h"
-#include "BKE_mask.h"
+#include "BKE_multires.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -162,18 +164,22 @@ static int foreach_libblock_remap_callback(void *user_data, ID *UNUSED(id_self),
}
if (*id_p && (*id_p == old_id)) {
- const bool is_indirect = (id->lib != NULL);
+ const bool is_indirect = (cb_flag & IDWALK_INDIRECT_USAGE) != 0;
const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
/* 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));
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;
+#ifdef DEBUG_PRINT
+ printf("In %s: Remapping %s (%p) to %s (%p) (skip_indirect: %d)\n",
+ id->name, old_id->name, old_id, new_id ? new_id->name : "<NONE>", new_id, skip_indirect);
+#endif
+
if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_NEVER_NULL)) {
id->tag |= LIB_TAG_DOIT;
}
@@ -181,13 +187,16 @@ static int foreach_libblock_remap_callback(void *user_data, ID *UNUSED(id_self),
/* 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)))
+ (skip_indirect && is_indirect))
{
- if (!is_indirect && (is_never_null || is_proxy || is_obj_editmode)) {
+ if (is_indirect) {
+ id_remap_data->skipped_indirect++;
+ }
+ else if (is_never_null || is_obj_editmode) {
id_remap_data->skipped_direct++;
}
else {
- id_remap_data->skipped_indirect++;
+ BLI_assert(0);
}
if (cb_flag & IDWALK_USER) {
id_remap_data->skipped_refcounted++;
@@ -221,6 +230,145 @@ static int foreach_libblock_remap_callback(void *user_data, ID *UNUSED(id_self),
return IDWALK_RET_NOP;
}
+/* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */
+static void libblock_remap_data_preprocess_scene_base_unlink(
+ IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect)
+{
+ if (skip_indirect && is_indirect) {
+ r_id_remap_data->skipped_indirect++;
+ r_id_remap_data->skipped_refcounted++;
+ }
+ else {
+ id_us_min((ID *)base->object);
+ BKE_scene_base_unlink(sce, base);
+ MEM_freeN(base);
+ if (!is_indirect) {
+ r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
+ }
+ }
+}
+
+static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
+{
+ switch (GS(r_id_remap_data->id->name)) {
+ case ID_SCE:
+ {
+ Scene *sce = (Scene *)r_id_remap_data->id;
+
+ if (!r_id_remap_data->new_id) {
+ const bool is_indirect = (sce->id.lib != NULL);
+ const bool skip_indirect = (r_id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
+
+ /* In case we are unlinking... */
+ if (!r_id_remap_data->old_id) {
+ /* ... everything from scene. */
+ Base *base, *base_next;
+ for (base = sce->base.first; base; base = base_next) {
+ base_next = base->next;
+ libblock_remap_data_preprocess_scene_base_unlink(
+ r_id_remap_data, sce, base, skip_indirect, is_indirect);
+ }
+ }
+ else if (GS(r_id_remap_data->old_id->name) == ID_OB) {
+ /* ... a specific object from scene. */
+ Object *old_ob = (Object *)r_id_remap_data->old_id;
+ Base *base = BKE_scene_base_find(sce, old_ob);
+
+ if (base) {
+ libblock_remap_data_preprocess_scene_base_unlink(
+ r_id_remap_data, sce, base, skip_indirect, is_indirect);
+ }
+ }
+ }
+ break;
+ }
+ case ID_OB:
+ {
+ ID *old_id = r_id_remap_data->old_id;
+ if (!old_id || GS(old_id->name) == ID_AR) {
+ Object *ob = (Object *)r_id_remap_data->id;
+ /* Object's pose holds reference to armature bones... sic */
+ /* Note that in theory, we should have to bother about linked/non-linked/never-null/etc. flags/states.
+ * Fortunately, this is just a tag, so we can accept to 'over-tag' a bit for pose recalc, and avoid
+ * another complex and risky condition nightmare like the one we have in
+ * foreach_libblock_remap_callback()... */
+ if (ob->pose && (!old_id || ob->data == old_id)) {
+ BLI_assert(ob->type == OB_ARMATURE);
+ ob->pose->flag |= POSE_RECALC;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain, Object *old_ob, Object *new_ob)
+{
+ 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.
+ * - remapped 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... */
+ for (Group *group = bmain->group.first; group; group = group->id.next) {
+ BKE_group_object_unlink(group, NULL, NULL, NULL);
+ }
+ }
+ else {
+ new_ob->flag |= OB_FROMGROUP;
+ }
+ }
+}
+
+static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmain), Scene *sce, ID *old_id)
+{
+ /* 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->id.us == 0)) {
+ grp = BKE_group_object_find(grp, ob);
+ }
+ if (!grp) {
+ ob->flag &= ~OB_FROMGROUP;
+ }
+ }
+ if (!(ob->flag & OB_FROMGROUP)) {
+ base->flag &= ~OB_FROMGROUP;
+ }
+ }
+ }
+}
+
+static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), Object *ob, ID *new_id)
+{
+ if (ob->data == new_id) {
+ switch (GS(new_id->name)) {
+ case ID_ME:
+ multires_force_update(ob);
+ break;
+ case ID_CU:
+ BKE_curve_type_test(ob);
+ break;
+ default:
+ break;
+ }
+ test_object_modifiers(ob);
+ test_object_materials(ob, new_id);
+ }
+}
+
/**
* Execute the 'data' part of the remapping (that is, all ID pointers from other ID datablocks).
*
@@ -263,6 +411,7 @@ static void libblock_remap_data(
printf("\tchecking id %s (%p, %p)\n", id->name, id, id->lib);
#endif
r_id_remap_data->id = id;
+ libblock_remap_data_preprocess(r_id_remap_data);
BKE_library_foreach_ID_link(id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
}
else {
@@ -274,11 +423,16 @@ static void libblock_remap_data(
while (i--) {
ID *id_curr = lb_array[i]->first;
+ if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(old_id->name))) {
+ continue;
+ }
+
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;
+ libblock_remap_data_preprocess(r_id_remap_data);
BKE_library_foreach_ID_link(
id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
}
@@ -323,29 +477,6 @@ void BKE_libblock_remap_locked(
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) {
@@ -385,55 +516,21 @@ void BKE_libblock_remap_locked(
*/
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.
- * - remapped 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;
- }
- }
+ libblock_remap_data_postprocess_object_fromgroup_update(bmain, (Object *)old_id, (Object *)new_id);
break;
- }
case ID_GR:
- if (new_id == NULL) { /* Only affects us in case group was unlinked. */
+ if (!new_id) { /* 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;
- }
- }
- }
+ libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, old_id);
+ }
+ }
+ break;
+ case ID_ME:
+ case ID_CU:
+ case ID_MB:
+ if (new_id) { /* Only affects us in case obdata was relinked (changed). */
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ libblock_remap_data_postprocess_obdata_relink(bmain, ob, new_id);
}
}
break;
@@ -460,9 +557,10 @@ void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short r
* \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)
+void BKE_libblock_unlink(Main *bmain, void *idv, const bool do_flag_never_null, const bool do_skip_indirect)
{
- const short remap_flags = ID_REMAP_SKIP_INDIRECT_USAGE | (do_flag_never_null ? ID_REMAP_FLAG_NEVER_NULL_USAGE : 0);
+ const short remap_flags = (do_skip_indirect ? ID_REMAP_SKIP_INDIRECT_USAGE : 0) |
+ (do_flag_never_null ? ID_REMAP_FLAG_NEVER_NULL_USAGE : 0);
BKE_main_lock(bmain);
@@ -488,14 +586,14 @@ void BKE_libblock_unlink(Main *bmain, void *idv, const bool do_flag_never_null)
* ... sigh
*/
void BKE_libblock_relink_ex(
- void *idv, void *old_idv, void *new_idv, const bool us_min_never_null)
+ Main *bmain, 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. */
+ /* No need to lock here, we are only affecting given ID, not bmain database. */
BLI_assert(id);
if (old_id) {
@@ -507,6 +605,50 @@ void BKE_libblock_relink_ex(
}
libblock_remap_data(NULL, id, old_id, new_id, remap_flags, NULL);
+
+ /* 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(id->name)) {
+ case ID_SCE:
+ {
+ Scene *sce = (Scene *)id;
+
+ if (old_id) {
+ switch (GS(old_id->name)) {
+ case ID_OB:
+ {
+ libblock_remap_data_postprocess_object_fromgroup_update(
+ bmain, (Object *)old_id, (Object *)new_id);
+ break;
+ }
+ case ID_GR:
+ if (!new_id) { /* Only affects us in case group was unlinked. */
+ libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, old_id);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ /* No choice but to check whole objects/groups. */
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+ libblock_remap_data_postprocess_object_fromgroup_update(bmain, ob, NULL);
+ }
+ for (Group *grp = bmain->group.first; grp; grp = grp->id.next) {
+ libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, NULL);
+ }
+ }
+ }
+ case ID_OB:
+ if (new_id) { /* Only affects us in case obdata was relinked (changed). */
+ libblock_remap_data_postprocess_obdata_relink(bmain, (Object *)id, new_id);
+ }
+ break;
+ default:
+ break;
+ }
}
static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
@@ -561,7 +703,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user)
#endif
if (do_id_user) {
- BKE_libblock_relink_ex(id, NULL, NULL, true);
+ BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
}
switch (type) {
@@ -705,7 +847,7 @@ void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */
}
if (id->us == 0) {
- BKE_libblock_unlink(bmain, id, false);
+ BKE_libblock_unlink(bmain, id, false, false);
BKE_libblock_free(bmain, id);
}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 30dc48819e9..c4a0d0074fb 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -171,7 +171,7 @@ FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *l
}
}
if (linestyle->nodetree) {
- new_linestyle->nodetree = ntreeCopyTree(linestyle->nodetree);
+ new_linestyle->nodetree = ntreeCopyTree(bmain, linestyle->nodetree);
}
new_linestyle->r = linestyle->r;
@@ -218,8 +218,9 @@ FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *l
for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next)
BKE_linestyle_geometry_modifier_copy(new_linestyle, m);
- if (linestyle->id.lib) {
- BKE_id_lib_local_paths(G.main, linestyle->id.lib, &new_linestyle->id);
+ if (ID_IS_LINKED_DATABLOCK(linestyle)) {
+ BKE_id_expand_local(&new_linestyle->id);
+ BKE_id_lib_local_paths(bmain, linestyle->id.lib, &new_linestyle->id);
}
return new_linestyle;
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 94e53755ac4..9e070bbef22 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -533,7 +533,6 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float
MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
BezTriple *bezt = &point->bezt, *bezt_next;
- float q0[2], q1[2], q2[2], r0[2], r1[2];
bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
@@ -542,14 +541,7 @@ void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float
return;
}
- interp_v2_v2v2(q0, bezt->vec[1], bezt->vec[2], u);
- interp_v2_v2v2(q1, bezt->vec[2], bezt_next->vec[0], u);
- interp_v2_v2v2(q2, bezt_next->vec[0], bezt_next->vec[1], u);
-
- interp_v2_v2v2(r0, q0, q1, u);
- interp_v2_v2v2(r1, q1, q2, u);
-
- interp_v2_v2v2(co, r0, r1, u);
+ interp_v2_v2v2v2v2_cubic(co, bezt->vec[1], bezt->vec[2], bezt_next->vec[0], bezt_next->vec[1], u);
}
BLI_INLINE void orthogonal_direction_get(float vec[2], float result[2])
@@ -848,11 +840,11 @@ Mask *BKE_mask_copy_nolib(Mask *mask)
return mask_new;
}
-Mask *BKE_mask_copy(Mask *mask)
+Mask *BKE_mask_copy(Main *bmain, Mask *mask)
{
Mask *mask_new;
- mask_new = BKE_libblock_copy(&mask->id);
+ mask_new = BKE_libblock_copy(bmain, &mask->id);
BLI_listbase_clear(&mask_new->masklayers);
@@ -861,8 +853,9 @@ Mask *BKE_mask_copy(Mask *mask)
/* enable fake user by default */
id_fake_user_set(&mask->id);
- if (mask->id.lib) {
- BKE_id_lib_local_paths(G.main, mask->id.lib, &mask_new->id);
+ if (ID_IS_LINKED_DATABLOCK(mask)) {
+ BKE_id_expand_local(&mask_new->id);
+ BKE_id_lib_local_paths(bmain, mask->id.lib, &mask_new->id);
}
return mask_new;
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index db5ac54ada9..17811893c03 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -61,6 +61,8 @@
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -217,12 +219,12 @@ Material *BKE_material_add(Main *bmain, const char *name)
}
/* XXX keep synced with next function */
-Material *BKE_material_copy(Material *ma)
+Material *BKE_material_copy(Main *bmain, Material *ma)
{
Material *man;
int a;
- man = BKE_libblock_copy(&ma->id);
+ man = BKE_libblock_copy(bmain, &ma->id);
id_lib_extern((ID *)man->group);
@@ -237,16 +239,17 @@ Material *BKE_material_copy(Material *ma)
if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col);
if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec);
- if (ma->preview) man->preview = BKE_previewimg_copy(ma->preview);
-
if (ma->nodetree) {
- man->nodetree = ntreeCopyTree(ma->nodetree);
+ man->nodetree = ntreeCopyTree(bmain, ma->nodetree);
}
+ man->preview = BKE_previewimg_copy(ma->preview);
+
BLI_listbase_clear(&man->gpumaterial);
-
- if (ma->id.lib) {
- BKE_id_lib_local_paths(G.main, ma->id.lib, &man->id);
+
+ if (ID_IS_LINKED_DATABLOCK(ma)) {
+ BKE_id_expand_local(&man->id);
+ BKE_id_lib_local_paths(bmain, ma->id.lib, &man->id);
}
return man;
@@ -282,180 +285,33 @@ Material *localize_material(Material *ma)
return man;
}
-static void extern_local_material(Material *ma)
-{
- int i;
- for (i = 0; i < MAX_MTEX; i++) {
- if (ma->mtex[i]) id_lib_extern((ID *)ma->mtex[i]->tex);
- }
-}
-
-void BKE_material_make_local(Material *ma)
+void BKE_material_make_local(Main *bmain, Material *ma)
{
- Main *bmain = G.main;
- Object *ob;
- Mesh *me;
- Curve *cu;
- MetaBall *mb;
- int a;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
-
- if (ma->id.lib == NULL) return;
- /* One local user; set flag and return. */
- if (ma->id.us == 1) {
- id_clear_lib_data(bmain, &ma->id);
- extern_local_material(ma);
+ if (!ID_IS_LINKED_DATABLOCK(ma)) {
return;
}
- /* Check which other IDs reference this one to determine if it's used by
- * lib or local */
- /* test objects */
- ob = bmain->object.first;
- while (ob) {
- if (ob->mat) {
- for (a = 0; a < ob->totcol; a++) {
- if (ob->mat[a] == ma) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- }
- ob = ob->id.next;
- }
- /* test meshes */
- me = bmain->mesh.first;
- while (me) {
- if (me->mat) {
- for (a = 0; a < me->totcol; a++) {
- if (me->mat[a] == ma) {
- if (me->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- }
- me = me->id.next;
- }
- /* test curves */
- cu = bmain->curve.first;
- while (cu) {
- if (cu->mat) {
- for (a = 0; a < cu->totcol; a++) {
- if (cu->mat[a] == ma) {
- if (cu->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- }
- cu = cu->id.next;
- }
- /* test mballs */
- mb = bmain->mball.first;
- while (mb) {
- if (mb->mat) {
- for (a = 0; a < mb->totcol; a++) {
- if (mb->mat[a] == ma) {
- if (mb->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- }
- mb = mb->id.next;
- }
-
- /* Only local users. */
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &ma->id);
- extern_local_material(ma);
- }
- /* Both user and local, so copy. */
- else if (is_local && is_lib) {
- Material *ma_new = BKE_material_copy(ma);
+ BKE_library_ID_test_usages(bmain, ma, &is_local, &is_lib);
- ma_new->id.us = 0;
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &ma->id);
+ BKE_id_expand_local(&ma->id);
+ }
+ else {
+ Material *ma_new = BKE_material_copy(bmain, ma);
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, ma->id.lib, &ma_new->id);
+ ma_new->id.us = 0;
- /* do objects */
- ob = bmain->object.first;
- while (ob) {
- if (ob->mat) {
- for (a = 0; a < ob->totcol; a++) {
- if (ob->mat[a] == ma) {
- if (ob->id.lib == NULL) {
- ob->mat[a] = ma_new;
- id_us_plus(&ma_new->id);
- id_us_min(&ma->id);
- }
- }
- }
- }
- ob = ob->id.next;
+ BKE_libblock_remap(bmain, ma, ma_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
- /* do meshes */
- me = bmain->mesh.first;
- while (me) {
- if (me->mat) {
- for (a = 0; a < me->totcol; a++) {
- if (me->mat[a] == ma) {
- if (me->id.lib == NULL) {
- me->mat[a] = ma_new;
- id_us_plus(&ma_new->id);
- id_us_min(&ma->id);
- }
- }
- }
- }
- me = me->id.next;
- }
- /* do curves */
- cu = bmain->curve.first;
- while (cu) {
- if (cu->mat) {
- for (a = 0; a < cu->totcol; a++) {
- if (cu->mat[a] == ma) {
- if (cu->id.lib == NULL) {
- cu->mat[a] = ma_new;
- id_us_plus(&ma_new->id);
- id_us_min(&ma->id);
- }
- }
- }
- }
- cu = cu->id.next;
- }
- /* do mballs */
- mb = bmain->mball.first;
- while (mb) {
- if (mb->mat) {
- for (a = 0; a < mb->totcol; a++) {
- if (mb->mat[a] == ma) {
- if (mb->id.lib == NULL) {
- mb->mat[a] = ma_new;
- id_us_plus(&ma_new->id);
- id_us_min(&ma->id);
- }
- }
- }
- }
- mb = mb->id.next;
- }
- }
-}
-
-/* for curve, mball, mesh types */
-void extern_local_matarar(struct Material **matar, short totcol)
-{
- short i;
- for (i = 0; i < totcol; i++) {
- id_lib_extern((ID *)matar[i]);
}
}
@@ -611,7 +467,7 @@ void BKE_material_append_id(ID *id, Material *ma)
(*matar)[(*totcol)++] = ma;
id_us_plus((ID *)ma);
- test_object_materials(G.main, id);
+ test_all_objects_materials(G.main, id);
}
}
@@ -637,7 +493,7 @@ Material *BKE_material_pop_id(ID *id, int index_i, bool update_data)
(*totcol)--;
*matar = MEM_reallocN(*matar, sizeof(void *) * (*totcol));
- test_object_materials(G.main, id);
+ test_all_objects_materials(G.main, id);
}
if (update_data) {
@@ -776,7 +632,19 @@ void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user)
if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
}
-void test_object_materials(Main *bmain, ID *id)
+void test_object_materials(Object *ob, ID *id)
+{
+ /* make the ob mat-array same size as 'ob->data' mat-array */
+ const short *totcol;
+
+ if (id == NULL || (totcol = give_totcolp_id(id)) == NULL) {
+ return;
+ }
+
+ BKE_material_resize_object(ob, *totcol, false);
+}
+
+void test_all_objects_materials(Main *bmain, ID *id)
{
/* make the ob mat-array same size as 'ob->data' mat-array */
Object *ob;
@@ -839,7 +707,7 @@ void assign_material_id(ID *id, Material *ma, short act)
if (ma)
id_us_plus(&ma->id);
- test_object_materials(G.main, id);
+ test_all_objects_materials(G.main, id);
}
void assign_material(Object *ob, Material *ma, short act, int assign_type)
@@ -852,8 +720,8 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type)
if (act < 1) act = 1;
/* prevent crashing when using accidentally */
- BLI_assert(ob->id.lib == NULL);
- if (ob->id.lib) return;
+ BLI_assert(!ID_IS_LINKED_DATABLOCK(ob));
+ if (ID_IS_LINKED_DATABLOCK(ob)) return;
/* test arraylens */
@@ -924,7 +792,7 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type)
if (ma)
id_us_plus(&ma->id);
- test_object_materials(G.main, ob->data);
+ test_object_materials(ob, ob->data);
}
@@ -1121,7 +989,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
Group *group;
for (group = G.main->group.first; group; group = group->id.next) {
- if (!group->id.lib && STREQ(group->id.name, ma->group->id.name)) {
+ if (!ID_IS_LINKED_DATABLOCK(group) && STREQ(group->id.name, ma->group->id.name)) {
ma->group = group;
}
}
@@ -2158,7 +2026,7 @@ static void convert_tfacematerial(Main *main, Material *ma)
}
/* create a new material */
else {
- mat_new = BKE_material_copy(ma);
+ mat_new = BKE_material_copy(main, ma);
if (mat_new) {
/* rename the material*/
BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
@@ -2230,7 +2098,7 @@ int do_version_tface(Main *main)
/* 1st part: marking mesh materials to update */
for (me = main->mesh.first; me; me = me->id.next) {
- if (me->id.lib) continue;
+ if (ID_IS_LINKED_DATABLOCK(me)) continue;
/* get the active tface layer */
index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
@@ -2284,7 +2152,7 @@ int do_version_tface(Main *main)
* at doversion time: direct_link might not have happened on it,
* so ma->mtex is not pointing to valid memory yet.
* later we could, but it's better not */
- else if (ma->id.lib)
+ else if (ID_IS_LINKED_DATABLOCK(ma))
continue;
/* material already marked as disputed */
@@ -2349,7 +2217,7 @@ int do_version_tface(Main *main)
/* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
- if (ma->id.lib) continue;
+ if (ID_IS_LINKED_DATABLOCK(ma)) continue;
/* disputed material */
if (ma->game.flag == MAT_BGE_DISPUTED) {
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 685cd35fc20..9a0a6e3540c 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -59,6 +59,8 @@
#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_displist.h"
#include "BKE_mball.h"
#include "BKE_object.h"
@@ -100,12 +102,12 @@ MetaBall *BKE_mball_add(Main *bmain, const char *name)
return mb;
}
-MetaBall *BKE_mball_copy(MetaBall *mb)
+MetaBall *BKE_mball_copy(Main *bmain, MetaBall *mb)
{
MetaBall *mbn;
int a;
- mbn = BKE_libblock_copy(&mb->id);
+ mbn = BKE_libblock_copy(bmain, &mb->id);
BLI_duplicatelist(&mbn->elems, &mb->elems);
@@ -117,65 +119,40 @@ MetaBall *BKE_mball_copy(MetaBall *mb)
mbn->editelems = NULL;
mbn->lastelem = NULL;
- if (mb->id.lib) {
- BKE_id_lib_local_paths(G.main, mb->id.lib, &mbn->id);
+ if (ID_IS_LINKED_DATABLOCK(mb)) {
+ BKE_id_expand_local(&mbn->id);
+ BKE_id_lib_local_paths(bmain, mb->id.lib, &mbn->id);
}
return mbn;
}
-static void extern_local_mball(MetaBall *mb)
+void BKE_mball_make_local(Main *bmain, MetaBall *mb)
{
- if (mb->mat) {
- extern_local_matarar(mb->mat, mb->totcol);
- }
-}
-
-void BKE_mball_make_local(MetaBall *mb)
-{
- Main *bmain = G.main;
- Object *ob;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
-
- if (mb->id.lib == NULL) return;
- if (mb->id.us == 1) {
- id_clear_lib_data(bmain, &mb->id);
- extern_local_mball(mb);
-
+
+ if (!ID_IS_LINKED_DATABLOCK(mb)) {
return;
}
- for (ob = G.main->object.first; ob && ELEM(0, is_lib, is_local); ob = ob->id.next) {
- if (ob->data == mb) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
+ BKE_library_ID_test_usages(bmain, mb, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &mb->id);
+ BKE_id_expand_local(&mb->id);
}
- }
-
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &mb->id);
- extern_local_mball(mb);
- }
- else if (is_local && is_lib) {
- MetaBall *mb_new = BKE_mball_copy(mb);
- mb_new->id.us = 0;
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, mb->id.lib, &mb_new->id);
-
- for (ob = G.main->object.first; ob; ob = ob->id.next) {
- if (ob->data == mb) {
- if (ob->id.lib == NULL) {
- ob->data = mb_new;
- id_us_plus(&mb_new->id);
- id_us_min(&mb->id);
- }
- }
+ else {
+ MetaBall *mb_new = BKE_mball_copy(bmain, mb);
+
+ mb_new->id.us = 0;
+
+ BKE_libblock_remap(bmain, mb, mb_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index e8418e876bb..2068854421f 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -1159,7 +1159,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
new_ml->imat = BLI_memarena_alloc(process->pgn_elements, 4 * 4 * sizeof(float));
/* too big stiffness seems only ugly due to linear interpolation
- * no need to have possibility for too big stiffness */
+ * no need to have possibility for too big stiffness */
if (ml->s > 10.0f) new_ml->s = 10.0f;
else new_ml->s = ml->s;
@@ -1294,7 +1294,7 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob,
build_bvh_spatial(&process, &process.metaball_bvh, 0, process.totelem, &process.allbb);
/* don't polygonize metaballs with too high resolution (base mball to small)
- * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */
+ * note: Eps was 0.0001f but this was giving problems for blood animation for durian, using 0.00001f */
if (ob->size[0] > 0.00001f * (process.allbb.max[0] - process.allbb.min[0]) ||
ob->size[1] > 0.00001f * (process.allbb.max[1] - process.allbb.min[1]) ||
ob->size[2] > 0.00001f * (process.allbb.max[2] - process.allbb.min[2]))
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index f82e5cf61b3..787b9905734 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -49,6 +49,8 @@
#include "BKE_mesh.h"
#include "BKE_displist.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
@@ -491,15 +493,13 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name)
return me;
}
-Mesh *BKE_mesh_copy_ex(Main *bmain, Mesh *me)
+Mesh *BKE_mesh_copy(Main *bmain, Mesh *me)
{
Mesh *men;
- MTFace *tface;
- MTexPoly *txface;
- int a, i;
+ int a;
const int do_tessface = ((me->totface != 0) && (me->totpoly == 0)); /* only do tessface if we have no polys */
- men = BKE_libblock_copy_ex(bmain, &me->id);
+ men = BKE_libblock_copy(bmain, &me->id);
men->mat = MEM_dupallocN(me->mat);
for (a = 0; a < men->totcol; a++) {
@@ -520,53 +520,32 @@ Mesh *BKE_mesh_copy_ex(Main *bmain, Mesh *me)
BKE_mesh_update_customdata_pointers(men, do_tessface);
- /* ensure indirect linked data becomes lib-extern */
- for (i = 0; i < me->fdata.totlayer; i++) {
- if (me->fdata.layers[i].type == CD_MTFACE) {
- tface = (MTFace *)me->fdata.layers[i].data;
-
- for (a = 0; a < me->totface; a++, tface++)
- if (tface->tpage)
- id_lib_extern((ID *)tface->tpage);
- }
- }
-
- for (i = 0; i < me->pdata.totlayer; i++) {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- txface = (MTexPoly *)me->pdata.layers[i].data;
-
- for (a = 0; a < me->totpoly; a++, txface++)
- if (txface->tpage)
- id_lib_extern((ID *)txface->tpage);
- }
- }
-
men->edit_btmesh = NULL;
men->mselect = MEM_dupallocN(men->mselect);
men->bb = MEM_dupallocN(men->bb);
-
- men->key = BKE_key_copy(me->key);
- if (men->key) men->key->from = (ID *)men;
- if (me->id.lib) {
+ if (me->key) {
+ men->key = BKE_key_copy(bmain, me->key);
+ men->key->from = (ID *)men;
+ }
+
+ if (ID_IS_LINKED_DATABLOCK(me)) {
+ BKE_id_expand_local(&men->id);
BKE_id_lib_local_paths(bmain, me->id.lib, &men->id);
}
return men;
}
-Mesh *BKE_mesh_copy(Mesh *me)
-{
- return BKE_mesh_copy_ex(G.main, me);
-}
-
-BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob, const bool add_key_index)
+BMesh *BKE_mesh_to_bmesh(
+ Mesh *me, Object *ob,
+ const bool add_key_index, const struct BMeshCreateParams *params)
{
BMesh *bm;
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me);
- bm = BM_mesh_create(&allocsize);
+ bm = BM_mesh_create(&allocsize, params);
BM_mesh_bm_from_me(
bm, me, (&(struct BMeshFromMeshParams){
@@ -576,49 +555,8 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob, const bool add_key_index)
return bm;
}
-static void expand_local_mesh(Mesh *me)
-{
- id_lib_extern((ID *)me->texcomesh);
-
- if (me->mtface || me->mtpoly) {
- int a, i;
-
- for (i = 0; i < me->pdata.totlayer; i++) {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
-
- for (a = 0; a < me->totpoly; a++, txface++) {
- /* special case: ima always local immediately */
- if (txface->tpage) {
- id_lib_extern((ID *)txface->tpage);
- }
- }
- }
- }
-
- for (i = 0; i < me->fdata.totlayer; i++) {
- if (me->fdata.layers[i].type == CD_MTFACE) {
- MTFace *tface = (MTFace *)me->fdata.layers[i].data;
-
- for (a = 0; a < me->totface; a++, tface++) {
- /* special case: ima always local immediately */
- if (tface->tpage) {
- id_lib_extern((ID *)tface->tpage);
- }
- }
- }
- }
- }
-
- if (me->mat) {
- extern_local_matarar(me->mat, me->totcol);
- }
-}
-
-void BKE_mesh_make_local(Mesh *me)
+void BKE_mesh_make_local(Main *bmain, Mesh *me)
{
- Main *bmain = G.main;
- Object *ob;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
@@ -626,38 +564,26 @@ void BKE_mesh_make_local(Mesh *me)
* - mixed: make copy
*/
- if (me->id.lib == NULL) return;
- if (me->id.us == 1) {
- id_clear_lib_data(bmain, &me->id);
- expand_local_mesh(me);
+ if (!ID_IS_LINKED_DATABLOCK(me)) {
return;
}
- for (ob = bmain->object.first; ob && ELEM(0, is_lib, is_local); ob = ob->id.next) {
- if (me == ob->data) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
- }
- }
-
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &me->id);
- expand_local_mesh(me);
- }
- else if (is_local && is_lib) {
- Mesh *me_new = BKE_mesh_copy(me);
- me_new->id.us = 0;
+ BKE_library_ID_test_usages(bmain, me, &is_local, &is_lib);
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &me->id);
+ if (me->key) {
+ BKE_key_make_local(bmain, me->key);
+ }
+ BKE_id_expand_local(&me->id);
+ }
+ else {
+ Mesh *me_new = BKE_mesh_copy(bmain, me);
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, me->id.lib, &me_new->id);
+ me_new->id.us = 0;
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (me == ob->data) {
- if (ob->id.lib == NULL) {
- BKE_mesh_assign_object(ob, me_new);
- }
- }
+ BKE_libblock_remap(bmain, me, me_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
@@ -1008,7 +934,7 @@ void BKE_mesh_assign_object(Object *ob, Mesh *me)
id_us_plus((ID *)me);
}
- test_object_materials(G.main, (ID *)me);
+ test_object_materials(ob, (ID *)me);
test_object_modifiers(ob);
}
@@ -2338,7 +2264,7 @@ Mesh *BKE_mesh_new_from_object(
BKE_object_free_modifiers(tmpobj);
/* copies the data */
- copycu = tmpobj->data = BKE_curve_copy((Curve *) ob->data);
+ copycu = tmpobj->data = BKE_curve_copy(bmain, (Curve *) ob->data);
/* temporarily set edit so we get updates from edit mode, but
* also because for text datablocks copying it while in edit
@@ -2419,7 +2345,7 @@ Mesh *BKE_mesh_new_from_object(
/* copies object and modifiers (but not the data) */
if (cage) {
/* copies the data */
- tmpmesh = BKE_mesh_copy_ex(bmain, ob->data);
+ tmpmesh = BKE_mesh_copy(bmain, ob->data);
/* if not getting the original caged mesh, get final derived mesh */
}
else {
@@ -2516,8 +2442,8 @@ Mesh *BKE_mesh_new_from_object(
BKE_mesh_tessface_ensure(tmpmesh);
}
- /* make sure materials get updated in objects */
- test_object_materials(bmain, &tmpmesh->id);
+ /* make sure materials get updated in object */
+ test_object_materials(tmpobj ? tmpobj : ob, &tmpmesh->id);
return tmpmesh;
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 59eeb5dd96a..936b014cca3 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -700,7 +700,7 @@ void test_object_modifiers(Object *ob)
*/
const char *modifier_path_relbase(Object *ob)
{
- if (G.relbase_valid || ob->id.lib) {
+ if (G.relbase_valid || ID_IS_LINKED_DATABLOCK(ob)) {
return ID_BLEND_PATH(G.main, &ob->id);
}
else {
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
index 18f3db6bd15..0838630a6cb 100644
--- a/source/blender/blenkernel/intern/modifiers_bmesh.c
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -211,7 +211,9 @@ BMEditMesh *DM_to_editbmesh(DerivedMesh *dm, BMEditMesh *existing, const bool do
bm = em->bm;
}
else {
- bm = BM_mesh_create(&bm_mesh_allocsize_default);
+ bm = BM_mesh_create(
+ &bm_mesh_allocsize_default,
+ &((struct BMeshCreateParams){.use_toolflags = false,}));
}
DM_to_bmesh_ex(dm, bm, do_tessellate);
@@ -233,7 +235,9 @@ BMesh *DM_to_bmesh(DerivedMesh *dm, const bool calc_face_normal)
BMesh *bm;
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_DM(dm);
- bm = BM_mesh_create(&allocsize);
+ bm = BM_mesh_create(
+ &allocsize,
+ &((struct BMeshCreateParams){.use_toolflags = false,}));
DM_to_bmesh_ex(dm, bm, calc_face_normal);
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 0527df67033..c321bc92a71 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -183,7 +183,7 @@ NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action)
}
else {
/* use a copy of the action instead (user count shouldn't have changed yet) */
- strip_d->act = BKE_action_copy(strip_d->act);
+ strip_d->act = BKE_action_copy(G.main, strip_d->act);
}
}
@@ -1291,7 +1291,7 @@ void BKE_nlastrip_recalculate_bounds(NlaStrip *strip)
if (IS_EQF(mapping, 0.0f) == 0)
strip->end = (actlen * mapping) + strip->start;
- /* make sure we don't overlap our neighbours */
+ /* make sure we don't overlap our neighbors */
nlastrip_fix_resize_overlaps(strip);
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index d78ddc41e97..296a00388c4 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -58,6 +58,8 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -1205,7 +1207,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool ski
/* is ntree part of library? */
if (bmain && !skip_database && BLI_findindex(&bmain->nodetree, ntree) >= 0) {
- newtree = BKE_libblock_copy(&ntree->id);
+ newtree = BKE_libblock_copy(bmain, &ntree->id);
}
else {
newtree = BKE_libblock_copy_nolib(&ntree->id, true);
@@ -1289,7 +1291,8 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool ski
/* node tree will generate its own interface type */
newtree->interface_type = NULL;
- if (ntree->id.lib) {
+ if (ID_IS_LINKED_DATABLOCK(ntree)) {
+ BKE_id_expand_local(&newtree->id);
BKE_id_lib_local_paths(bmain, ntree->id.lib, &newtree->id);
}
@@ -1300,9 +1303,9 @@ bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user
{
return ntreeCopyTree_internal(ntree, bmain, false, do_id_user, true, true);
}
-bNodeTree *ntreeCopyTree(bNodeTree *ntree)
+bNodeTree *ntreeCopyTree(Main *bmain, bNodeTree *ntree)
{
- return ntreeCopyTree_ex(ntree, G.main, true);
+ return ntreeCopyTree_ex(ntree, bmain, true);
}
/* use when duplicating scenes */
@@ -1948,70 +1951,33 @@ bNodeTree *ntreeFromID(ID *id)
}
}
-static void extern_local_ntree(bNodeTree *ntree)
+void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist)
{
- for (bNode *node = ntree->nodes.first; node; node = node->next) {
- if (node->id) {
- id_lib_extern(node->id);
- }
- }
-}
-
-void ntreeMakeLocal(bNodeTree *ntree, bool id_in_mainlist)
-{
- Main *bmain = G.main;
- bool lib = false, local = false;
+ bool is_lib = false, is_local = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
-
- if (ntree->id.lib == NULL) return;
- if (ntree->id.us == 1) {
- id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist);
- extern_local_ntree(ntree);
+
+ if (!ID_IS_LINKED_DATABLOCK(ntree)) {
return;
}
-
- /* now check users of groups... again typedepending, callback... */
- FOREACH_NODETREE(G.main, tntree, owner_id) {
- bNode *node;
- /* find if group is in tree */
- for (node = tntree->nodes.first; node; node = node->next) {
- if (node->id == (ID *)ntree) {
- if (owner_id->lib)
- lib = true;
- else
- local = true;
- }
+
+ BKE_library_ID_test_usages(bmain, ntree, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist);
+ BKE_id_expand_local(&ntree->id);
+ }
+ else {
+ bNodeTree *ntree_new = ntreeCopyTree(bmain, ntree);
+
+ ntree_new->id.us = 0;
+
+ BKE_libblock_remap(bmain, ntree, ntree_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
- } FOREACH_NODETREE_END
-
- /* if all users are local, we simply make tree local */
- if (local && !lib) {
- id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist);
- extern_local_ntree(ntree);
- }
- else if (local && lib) {
- /* this is the mixed case, we copy the tree and assign it to local users */
- bNodeTree *newtree = ntreeCopyTree(ntree);
-
- newtree->id.us = 0;
-
- FOREACH_NODETREE(G.main, tntree, owner_id) {
- bNode *node;
- /* find if group is in tree */
- for (node = tntree->nodes.first; node; node = node->next) {
- if (node->id == (ID *)ntree) {
- if (owner_id->lib == NULL) {
- node->id = (ID *)newtree;
- id_us_plus(&newtree->id);
- id_us_min(&ntree->id);
- }
- }
- }
- } FOREACH_NODETREE_END
}
}
@@ -2715,7 +2681,7 @@ void BKE_node_clipboard_add_node(bNode *node)
node_info->id = node->id;
if (node->id) {
BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name));
- if (node->id->lib) {
+ if (ID_IS_LINKED_DATABLOCK(node->id)) {
BLI_strncpy(node_info->library_name, node->id->lib->filepath, sizeof(node_info->library_name));
}
else {
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 357f01e0961..00c25bed1f7 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -95,6 +95,8 @@
#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_editmesh.h"
@@ -931,7 +933,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
ModifierData *md;
int a;
- obn = BKE_libblock_copy_ex(bmain, &ob->id);
+ obn = BKE_libblock_copy(bmain, &ob->id);
if (ob->totcol) {
obn->mat = MEM_dupallocN(ob->mat);
@@ -1001,11 +1003,11 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
copy_object_lod(obn, ob);
-
/* Copy runtime surve data. */
obn->curve_cache = NULL;
- if (ob->id.lib) {
+ if (ID_IS_LINKED_DATABLOCK(ob)) {
+ BKE_id_expand_local(&obn->id);
BKE_id_lib_local_paths(bmain, ob->id.lib, &obn->id);
}
@@ -1016,41 +1018,13 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
}
/* copy objects, will re-initialize cached simulation data */
-Object *BKE_object_copy(Object *ob)
+Object *BKE_object_copy(Main *bmain, Object *ob)
{
- return BKE_object_copy_ex(G.main, ob, false);
+ return BKE_object_copy_ex(bmain, ob, false);
}
-static void extern_local_object__modifiersForeachIDLink(
- void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag))
+void BKE_object_make_local(Main *bmain, Object *ob)
{
- if (*idpoin) {
- /* intentionally omit ID_OB */
- if (ELEM(GS((*idpoin)->name), ID_IM, ID_TE)) {
- id_lib_extern(*idpoin);
- }
- }
-}
-
-static void extern_local_object(Object *ob)
-{
- id_lib_extern((ID *)ob->data);
- id_lib_extern((ID *)ob->dup_group);
- id_lib_extern((ID *)ob->poselib);
- id_lib_extern((ID *)ob->gpd);
-
- extern_local_matarar(ob->mat, ob->totcol);
-
- modifiers_foreachIDLink(ob, extern_local_object__modifiersForeachIDLink, NULL);
-
- ob->preview = NULL;
-}
-
-void BKE_object_make_local(Object *ob)
-{
- Main *bmain = G.main;
- Scene *sce;
- Base *base;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
@@ -1058,74 +1032,40 @@ void BKE_object_make_local(Object *ob)
* - mixed: make copy
*/
- if (ob->id.lib == NULL) return;
-
- ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
-
- if (ob->id.us == 1) {
- id_clear_lib_data(bmain, &ob->id);
- extern_local_object(ob);
+ if (!ID_IS_LINKED_DATABLOCK(ob)) {
+ return;
}
- else {
- for (sce = bmain->scene.first; sce && ELEM(0, is_lib, is_local); sce = sce->id.next) {
- if (BKE_scene_base_find(sce, ob)) {
- if (sce->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- if (is_local && is_lib == false) {
+ BKE_library_ID_test_usages(bmain, ob, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
id_clear_lib_data(bmain, &ob->id);
- extern_local_object(ob);
+ BKE_id_expand_local(&ob->id);
}
- else if (is_local && is_lib) {
- Object *ob_new = BKE_object_copy(ob);
+ else {
+ Object *ob_new = BKE_object_copy(bmain, ob);
ob_new->id.us = 0;
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, ob->id.lib, &ob_new->id);
-
- sce = bmain->scene.first;
- while (sce) {
- if (sce->id.lib == NULL) {
- base = sce->base.first;
- while (base) {
- if (base->object == ob) {
- base->object = ob_new;
- id_us_plus(&ob_new->id);
- id_us_min(&ob->id);
- }
- base = base->next;
- }
- }
- sce = sce->id.next;
- }
+ ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = NULL;
+
+ BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
-/*
- * Returns true if the Object is a from an external blend file (libdata)
- */
+/* Returns true if the Object is from an external blend file (libdata) */
bool BKE_object_is_libdata(Object *ob)
{
- if (!ob) return false;
- if (ob->proxy) return false;
- if (ob->id.lib) return true;
- return false;
+ return (ob && ID_IS_LINKED_DATABLOCK(ob));
}
-/* Returns true if the Object data is a from an external blend file (libdata) */
+/* Returns true if the Object data is from an external blend file (libdata) */
bool BKE_object_obdata_is_libdata(Object *ob)
{
- if (!ob) return false;
- if (ob->proxy && (ob->data == NULL || ((ID *)ob->data)->lib == NULL)) return false;
- if (ob->id.lib) return true;
- if (ob->data == NULL) return false;
- if (((ID *)ob->data)->lib) return true;
-
- return false;
+ /* Linked objects with local obdata are forbidden! */
+ BLI_assert(!ob || !ob->data || (ID_IS_LINKED_DATABLOCK(ob) ? ID_IS_LINKED_DATABLOCK(ob->data) : true));
+ return (ob && ob->data && ID_IS_LINKED_DATABLOCK(ob->data));
}
/* *************** PROXY **************** */
@@ -1172,7 +1112,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
/* only on local objects because this causes indirect links
* 'a -> b -> c', blend to point directly to a.blend
* when a.blend has a proxy thats linked into c.blend */
- if (ob->id.lib == NULL)
+ if (!ID_IS_LINKED_DATABLOCK(ob))
id_lib_extern((ID *)dtar->id);
}
}
@@ -1190,7 +1130,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
{
/* paranoia checks */
- if (ob->id.lib || target->id.lib == NULL) {
+ if (ID_IS_LINKED_DATABLOCK(ob) || !ID_IS_LINKED_DATABLOCK(target)) {
printf("cannot make proxy\n");
return;
}
@@ -2567,7 +2507,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
printf("recalcob %s\n", ob->id.name + 2);
/* handle proxy copy for target */
- if (ob->id.lib && ob->proxy_from) {
+ if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from) {
// printf("ob proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
if (ob->proxy_from->proxy_group) { /* transform proxy into group space */
Object *obg = ob->proxy_from->proxy_group;
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 8df501bd106..b5cb59da7d2 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -203,7 +203,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
break;
}
case OB_ARMATURE:
- if (ob->id.lib && ob->proxy_from) {
+ if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from) {
if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
@@ -268,7 +268,7 @@ void BKE_object_eval_uber_transform(EvaluationContext *UNUSED(eval_ctx),
// XXX: it's almost redundant now...
/* Handle proxy copy for target, */
- if (ob->id.lib && ob->proxy_from) {
+ if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from) {
if (ob->proxy_from->proxy_group) {
/* Transform proxy into group space. */
Object *obg = ob->proxy_from->proxy_group;
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 1c318dfd115..489fc2f3710 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -232,7 +232,7 @@ void packAll(Main *bmain, ReportList *reports, bool verbose)
int tot = 0;
for (ima = bmain->image.first; ima; ima = ima->id.next) {
- if (BKE_image_has_packedfile(ima) == false && ima->id.lib == NULL) {
+ if (BKE_image_has_packedfile(ima) == false && !ID_IS_LINKED_DATABLOCK(ima)) {
if (ima->source == IMA_SRC_FILE) {
BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
tot ++;
@@ -245,14 +245,14 @@ void packAll(Main *bmain, ReportList *reports, bool verbose)
}
for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next) {
- if (vfont->packedfile == NULL && vfont->id.lib == NULL && BKE_vfont_is_builtin(vfont) == false) {
+ if (vfont->packedfile == NULL && !ID_IS_LINKED_DATABLOCK(vfont) && BKE_vfont_is_builtin(vfont) == false) {
vfont->packedfile = newPackedFile(reports, vfont->name, bmain->name);
tot ++;
}
}
for (sound = bmain->sound.first; sound; sound = sound->id.next) {
- if (sound->packedfile == NULL && sound->id.lib == NULL) {
+ if (sound->packedfile == NULL && !ID_IS_LINKED_DATABLOCK(sound)) {
sound->packedfile = newPackedFile(reports, sound->name, bmain->name);
tot++;
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 58ec75dc706..ff69f381b06 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -276,16 +276,14 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
/* reserve size is rough guess */
GHash *map = BLI_ghash_int_new_ex("build_mesh_leaf_node gh", 2 * totface);
- int (*face_vert_indices)[4] = MEM_callocN(sizeof(int[4]) * totface,
+ int (*face_vert_indices)[3] = MEM_mallocN(sizeof(int[3]) * totface,
"bvh node face vert indices");
- node->face_vert_indices = (const int (*)[4])face_vert_indices;
+ node->face_vert_indices = (const int (*)[3])face_vert_indices;
for (int i = 0; i < totface; ++i) {
const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]];
- const int sides = 3;
-
- for (int j = 0; j < sides; ++j) {
+ for (int j = 0; j < 3; ++j) {
face_vert_indices[i][j] =
map_insert_vert(bvh, map, &node->face_verts,
&node->uniq_verts, bvh->mloop[lt->tri[j]].v);
@@ -690,8 +688,7 @@ static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, bool revisiting)
{
if (UNLIKELY(iter->stacksize == iter->stackspace)) {
iter->stackspace *= 2;
-
- if (iter->stackspace != STACK_FIXED_DEPTH) {
+ if (iter->stackspace != (STACK_FIXED_DEPTH * 2)) {
iter->stack = MEM_reallocN(iter->stack, sizeof(PBVHStack) * iter->stackspace);
}
else {
@@ -1496,12 +1493,18 @@ typedef struct {
static bool ray_aabb_intersect(PBVHNode *node, void *data_v)
{
RaycastData *rcd = data_v;
- float bb_min[3], bb_max[3];
+ const float *bb_min, *bb_max;
- if (rcd->original)
- BKE_pbvh_node_get_original_BB(node, bb_min, bb_max);
- else
- BKE_pbvh_node_get_BB(node, bb_min, bb_max);
+ if (rcd->original) {
+ /* BKE_pbvh_node_get_original_BB */
+ bb_min = node->orig_vb.bmin;
+ bb_max = node->orig_vb.bmax;
+ }
+ else {
+ /* BKE_pbvh_node_get_BB */
+ bb_min = node->vb.bmin;
+ bb_max = node->vb.bmax;
+ }
return isect_ray_aabb_v3(&rcd->ray, bb_min, bb_max, &node->tmin);
}
@@ -1801,17 +1804,21 @@ static PlaneAABBIsect test_planes_aabb(const float bb_min[3],
bool BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data)
{
- float bb_min[3], bb_max[3];
+ const float *bb_min, *bb_max;
+ /* BKE_pbvh_node_get_BB */
+ bb_min = node->vb.bmin;
+ bb_max = node->vb.bmax;
- BKE_pbvh_node_get_BB(node, bb_min, bb_max);
return test_planes_aabb(bb_min, bb_max, data) != ISECT_OUTSIDE;
}
bool BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data)
{
- float bb_min[3], bb_max[3];
+ const float *bb_min, *bb_max;
+ /* BKE_pbvh_node_get_BB */
+ bb_min = node->vb.bmin;
+ bb_max = node->vb.bmax;
- BKE_pbvh_node_get_BB(node, bb_min, bb_max);
return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 88dc63d6cb2..55f9f384081 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -69,11 +69,134 @@
static void pbvh_bmesh_verify(PBVH *bvh);
#endif
+/** \name BMesh Utility API
+ *
+ * Use some local functions which assume triangles.
+ * \{ */
+
+/**
+ * Typically using BM_LOOPS_OF_VERT and BM_FACES_OF_VERT iterators are fine,
+ * however this is an area where performance matters so do it in-line.
+ *
+ * Take care since 'break' won't works as expected within these macros!
+ */
+
+#define BM_LOOPS_OF_VERT_ITER_BEGIN(l_iter_radial_, v_) \
+{ \
+ struct { BMVert *v; BMEdge *e_iter, *e_first; BMLoop *l_iter_radial; } _iter; \
+ _iter.v = v_; \
+ if (_iter.v->e) { \
+ _iter.e_iter = _iter.e_first = _iter.v->e; \
+ do { \
+ if (_iter.e_iter->l) { \
+ _iter.l_iter_radial = _iter.e_iter->l; \
+ do { \
+ if (_iter.l_iter_radial->v == _iter.v) { \
+ l_iter_radial_ = _iter.l_iter_radial;
+
+#define BM_LOOPS_OF_VERT_ITER_END \
+ } \
+ } while ((_iter.l_iter_radial = _iter.l_iter_radial->radial_next) != _iter.e_iter->l); \
+ } \
+ } while ((_iter.e_iter = BM_DISK_EDGE_NEXT(_iter.e_iter, _iter.v)) != _iter.e_first); \
+ } \
+} ((void)0)
+
+#define BM_FACES_OF_VERT_ITER_BEGIN(f_iter_, v_) \
+{ \
+ BMLoop *l_iter_radial_; \
+ BM_LOOPS_OF_VERT_ITER_BEGIN(l_iter_radial_, v_) { \
+ f_iter_ = l_iter_radial_->f; \
+
+#define BM_FACES_OF_VERT_ITER_END \
+ } \
+ BM_LOOPS_OF_VERT_ITER_END; \
+}
+
+static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3])
+{
+ e_tri[0] = BM_edge_create(bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
+ e_tri[1] = BM_edge_create(bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
+ e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE);
+}
+
+BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3])
+{
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+
+ BLI_assert(f->len == 3);
+
+ r_index[0] = BM_elem_index_get(l->v); l = l->next;
+ r_index[1] = BM_elem_index_get(l->v); l = l->next;
+ r_index[2] = BM_elem_index_get(l->v);
+}
+
+/**
+ * A version of #BM_face_exists, optimized for triangles
+ * when we know the loop and the opposite vertex.
+ *
+ * Check if any triangle is formed by (l_radial_first->v, l_radial_first->next->v, v_opposite),
+ * at either winding (since its a triangle no special checks are needed).
+ *
+ * <pre>
+ * l_radial_first->v & l_radial_first->next->v
+ * +---+
+ * | /
+ * | /
+ * + v_opposite
+ * </pre>
+ *
+ * Its assumed that \a l_radial_first is never forming the target face.
+ */
+static bool bm_face_exists_tri_from_loop_vert(
+ BMLoop *l_radial_first, BMVert *v_opposite, BMFace **r_face_existing)
+{
+ BLI_assert(!ELEM(v_opposite, l_radial_first->v, l_radial_first->next->v, l_radial_first->prev->v));
+ if (l_radial_first->radial_next != l_radial_first) {
+ BMLoop *l_radial_iter = l_radial_first->radial_next;
+ do {
+ BLI_assert(l_radial_iter->f->len == 3);
+ if (l_radial_iter->prev->v == v_opposite) {
+ *r_face_existing = l_radial_iter->f;
+ return true;
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
+ }
+ return false;
+}
+
+/**
+ * Uses a map of vertices to lookup the final target.
+ * References can't point to previous items (would cause infinite loop).
+ */
+static BMVert *bm_vert_hash_lookup_chain(GHash *deleted_verts, BMVert *v)
+{
+ while (true) {
+ BMVert **v_next_p = (BMVert **)BLI_ghash_lookup_p(deleted_verts, v);
+ if (v_next_p == NULL) {
+ /* not remapped*/
+ return v;
+ }
+ else if (*v_next_p == NULL) {
+ /* removed and not remapped */
+ return NULL;
+ }
+ else {
+ /* remapped */
+ v = *v_next_p;
+ }
+ }
+}
+
+/** \} */
+
/****************************** Building ******************************/
/* Update node data after splitting */
-static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index, const int cd_vert_node_offset, const int cd_face_node_offset)
+static void pbvh_bmesh_node_finalize(
+ PBVH *bvh, const int node_index,
+ const int cd_vert_node_offset, const int cd_face_node_offset)
{
GSetIterator gs_iter;
PBVHNode *n = &bvh->nodes[node_index];
@@ -200,7 +323,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
break;
}
}
-
+
/* Clear this node */
/* Mark this node's unique verts as unclaimed */
@@ -224,18 +347,18 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
if (n->layer_disp)
MEM_freeN(n->layer_disp);
-
+
n->bm_faces = NULL;
n->bm_unique_verts = NULL;
n->bm_other_verts = NULL;
n->layer_disp = NULL;
-
+
if (n->draw_buffers) {
GPU_free_pbvh_buffers(n->draw_buffers);
n->draw_buffers = NULL;
}
n->flag &= ~PBVH_Leaf;
-
+
/* Recurse */
pbvh_bmesh_node_split(bvh, bbc_array, children);
pbvh_bmesh_node_split(bvh, bbc_array, children + 1);
@@ -292,6 +415,7 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
/**********************************************************************/
+#if 0
static int pbvh_bmesh_node_offset_from_elem(PBVH *bvh, BMElem *ele)
{
switch (ele->head.htype) {
@@ -304,7 +428,7 @@ static int pbvh_bmesh_node_offset_from_elem(PBVH *bvh, BMElem *ele)
}
-static int pbvh_bmesh_node_lookup_index(PBVH *bvh, void *key)
+static int pbvh_bmesh_node_index_from_elem(PBVH *bvh, void *key)
{
const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(bvh, key);
const int node_index = BM_ELEM_CD_GET_INT((BMElem *)key, cd_node_offset);
@@ -316,18 +440,45 @@ static int pbvh_bmesh_node_lookup_index(PBVH *bvh, void *key)
return node_index;
}
-static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, void *key)
+static PBVHNode *pbvh_bmesh_node_from_elem(PBVH *bvh, void *key)
{
- return &bvh->nodes[pbvh_bmesh_node_lookup_index(bvh, key)];
+ return &bvh->nodes[pbvh_bmesh_node_index_from_elem(bvh, key)];
}
/* typecheck */
-#define pbvh_bmesh_node_lookup_index(bvh, key) ( \
+#define pbvh_bmesh_node_index_from_elem(bvh, key) ( \
CHECK_TYPE_ANY(key, BMFace *, BMVert *), \
- pbvh_bmesh_node_lookup_index(bvh, key))
-#define pbvh_bmesh_node_lookup(bvh, key) ( \
+ pbvh_bmesh_node_index_from_elem(bvh, key))
+#define pbvh_bmesh_node_from_elem(bvh, key) ( \
CHECK_TYPE_ANY(key, BMFace *, BMVert *), \
- pbvh_bmesh_node_lookup(bvh, key))
+ pbvh_bmesh_node_from_elem(bvh, key))
+#endif
+
+BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *bvh, const BMVert *key)
+{
+ const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, bvh->cd_vert_node_offset);
+ BLI_assert(node_index != DYNTOPO_NODE_NONE);
+ BLI_assert(node_index < bvh->totnode);
+ return node_index;
+}
+
+BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *bvh, const BMFace *key)
+{
+ const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, bvh->cd_face_node_offset);
+ BLI_assert(node_index != DYNTOPO_NODE_NONE);
+ BLI_assert(node_index < bvh->totnode);
+ return node_index;
+}
+
+BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *bvh, const BMVert *key)
+{
+ return &bvh->nodes[pbvh_bmesh_node_index_from_vert(bvh, key)];
+}
+
+BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *bvh, const BMFace *key)
+{
+ return &bvh->nodes[pbvh_bmesh_node_index_from_face(bvh, key)];
+}
static BMVert *pbvh_bmesh_vert_create(
@@ -357,6 +508,9 @@ static BMVert *pbvh_bmesh_vert_create(
return v;
}
+/**
+ * \note Callers are responsible for checking if the face exists before adding.
+ */
static BMFace *pbvh_bmesh_face_create(
PBVH *bvh, int node_index,
BMVert *v_tri[3], BMEdge *e_tri[3],
@@ -367,7 +521,7 @@ static BMFace *pbvh_bmesh_face_create(
/* ensure we never add existing face */
BLI_assert(BM_face_exists(v_tri, 3, NULL) == false);
- BMFace *f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NO_DOUBLE);
+ BMFace *f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
f->head.hflag = f_example->head.hflag;
BLI_gset_insert(node->bm_faces, f);
@@ -387,16 +541,16 @@ static BMFace *pbvh_bmesh_face_create(
#if 0
static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
{
- BMIter bm_iter;
BMFace *f;
int count = 0;
- BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f);
+ BM_FACES_OF_VERT_ITER_BEGIN(f, v) {
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
if (f_node == node) {
count++;
}
}
+ BM_FACES_OF_VERT_ITER_END;
return count;
}
@@ -407,19 +561,19 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
static int pbvh_bmesh_node_vert_use_count_ex(PBVH *bvh, PBVHNode *node, BMVert *v, const int count_max)
{
- BMIter bm_iter;
- BMFace *f;
int count = 0;
+ BMFace *f;
- BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f);
+ BM_FACES_OF_VERT_ITER_BEGIN(f, v) {
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
if (f_node == node) {
count++;
if (count == count_max) {
- break;
+ return count;
}
}
}
+ BM_FACES_OF_VERT_ITER_END;
return count;
}
@@ -427,16 +581,17 @@ static int pbvh_bmesh_node_vert_use_count_ex(PBVH *bvh, PBVHNode *node, BMVert *
/* Return a node that uses vertex 'v' other than its current owner */
static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v)
{
- BMIter bm_iter;
+ PBVHNode *current_node = pbvh_bmesh_node_from_vert(bvh, v);
BMFace *f;
- PBVHNode *current_node = pbvh_bmesh_node_lookup(bvh, v);
- BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f);
+ BM_FACES_OF_VERT_ITER_BEGIN(f, v) {
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
- if (f_node != current_node)
+ if (f_node != current_node) {
return f_node;
+ }
}
+ BM_FACES_OF_VERT_ITER_END;
return NULL;
}
@@ -445,7 +600,7 @@ static void pbvh_bmesh_vert_ownership_transfer(
PBVH *bvh, PBVHNode *new_owner,
BMVert *v)
{
- PBVHNode *current_owner = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *current_owner = pbvh_bmesh_node_from_vert(bvh, v);
/* mark node for update */
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
@@ -469,36 +624,36 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
/* never match for first time */
int f_node_index_prev = DYNTOPO_NODE_NONE;
- PBVHNode *v_node = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *v_node = pbvh_bmesh_node_from_vert(bvh, v);
BLI_gset_remove(v_node->bm_unique_verts, v, NULL);
BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
/* Have to check each neighboring face's node */
- BMIter bm_iter;
BMFace *f;
- BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- const int f_node_index = pbvh_bmesh_node_lookup_index(bvh, f);
+ BM_FACES_OF_VERT_ITER_BEGIN(f, v) {
+ const int f_node_index = pbvh_bmesh_node_index_from_face(bvh, f);
/* faces often share the same node,
* quick check to avoid redundant #BLI_gset_remove calls */
- if (f_node_index_prev == f_node_index)
- continue;
- f_node_index_prev = f_node_index;
+ if (f_node_index_prev != f_node_index) {
+ f_node_index_prev = f_node_index;
- PBVHNode *f_node = &bvh->nodes[f_node_index];
- f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
+ PBVHNode *f_node = &bvh->nodes[f_node_index];
+ f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
- /* Remove current ownership */
- BLI_gset_remove(f_node->bm_other_verts, v, NULL);
+ /* Remove current ownership */
+ BLI_gset_remove(f_node->bm_other_verts, v, NULL);
- BLI_assert(!BLI_gset_haskey(f_node->bm_unique_verts, v));
- BLI_assert(!BLI_gset_haskey(f_node->bm_other_verts, v));
+ BLI_assert(!BLI_gset_haskey(f_node->bm_unique_verts, v));
+ BLI_assert(!BLI_gset_haskey(f_node->bm_other_verts, v));
+ }
}
+ BM_FACES_OF_VERT_ITER_END;
}
static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
{
- PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
/* Check if any of this face's vertices need to be removed
* from the node */
@@ -923,13 +1078,6 @@ static void short_edge_queue_create(
/*************************** Topology update **************************/
-static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3])
-{
- e_tri[0] = BM_edge_create(bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
- e_tri[1] = BM_edge_create(bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
- e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE);
-}
-
static void pbvh_bmesh_split_edge(
EdgeQueueContext *eq_ctx, PBVH *bvh,
BMEdge *e, BLI_Buffer *edge_loops)
@@ -1101,15 +1249,16 @@ static bool pbvh_bmesh_subdivide_long_edges(
static void pbvh_bmesh_collapse_edge(
PBVH *bvh, BMEdge *e,
BMVert *v1, BMVert *v2,
- GSet *deleted_verts,
+ GHash *deleted_verts,
BLI_Buffer *deleted_faces,
EdgeQueueContext *eq_ctx)
{
BMVert *v_del, *v_conn;
- float mask_v1 = BM_ELEM_CD_GET_FLOAT(v1, eq_ctx->cd_vert_mask_offset);
/* one of the two vertices may be masked, select the correct one for deletion */
- if (mask_v1 < 1.0f) {
+ if (BM_ELEM_CD_GET_FLOAT(v1, eq_ctx->cd_vert_mask_offset) <
+ BM_ELEM_CD_GET_FLOAT(v2, eq_ctx->cd_vert_mask_offset))
+ {
v_del = v1;
v_conn = v2;
}
@@ -1141,33 +1290,43 @@ static void pbvh_bmesh_collapse_edge(
* really buy anything. */
BLI_buffer_empty(deleted_faces);
- BMIter bm_iter;
- BMFace *f;
+ BMLoop *l;
- BM_ITER_ELEM (f, &bm_iter, v_del, BM_FACES_OF_VERT) {
- BMVert *v_tri[3];
+ BM_LOOPS_OF_VERT_ITER_BEGIN(l, v_del) {
BMFace *existing_face;
/* Get vertices, replace use of v_del with v_conn */
// BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3);
+ BMFace *f = l->f;
+#if 0
+ BMVert *v_tri[3];
BM_face_as_array_vert_tri(f, v_tri);
for (int i = 0; i < 3; i++) {
if (v_tri[i] == v_del) {
v_tri[i] = v_conn;
}
}
+#endif
/* Check if a face using these vertices already exists. If so,
* skip adding this face and mark the existing one for
* deletion as well. Prevents extraneous "flaps" from being
* created. */
- if (BM_face_exists(v_tri, 3, &existing_face)) {
+#if 0
+ if (UNLIKELY(BM_face_exists(v_tri, 3, &existing_face)))
+#else
+ if (UNLIKELY(bm_face_exists_tri_from_loop_vert(l->next, v_conn, &existing_face)))
+#endif
+ {
BLI_assert(existing_face);
BLI_buffer_append(deleted_faces, BMFace *, existing_face);
}
else {
+ BMVert *v_tri[3] = {v_conn, l->next->v, l->prev->v};
+
+ BLI_assert(BM_face_exists(v_tri, 3, NULL) == false);
BMEdge *e_tri[3];
- PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f);
+ PBVHNode *n = pbvh_bmesh_node_from_face(bvh, f);
int ni = n - bvh->nodes;
bm_edges_from_tri(bvh->bm, v_tri, e_tri);
pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f);
@@ -1180,6 +1339,7 @@ static void pbvh_bmesh_collapse_edge(
BLI_buffer_append(deleted_faces, BMFace *, f);
}
+ BM_LOOPS_OF_VERT_ITER_END;
/* Delete the tagged faces */
for (int i = 0; i < deleted_faces->count; i++) {
@@ -1209,10 +1369,14 @@ static void pbvh_bmesh_collapse_edge(
* remove them from the PBVH */
for (int j = 0; j < 3; j++) {
if ((v_tri[j] != v_del) && (v_tri[j]->e == NULL)) {
- BLI_gset_insert(deleted_verts, v_tri[j]);
pbvh_bmesh_vert_remove(bvh, v_tri[j]);
BM_log_vert_removed(bvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset);
+
+ if (v_tri[j] == v_conn) {
+ v_conn = NULL;
+ }
+ BLI_ghash_insert(deleted_verts, v_tri[j], NULL);
BM_vert_kill(bvh->bm, v_tri[j]);
}
}
@@ -1220,17 +1384,26 @@ static void pbvh_bmesh_collapse_edge(
/* Move v_conn to the midpoint of v_conn and v_del (if v_conn still exists, it
* may have been deleted above) */
- if (!BLI_gset_haskey(deleted_verts, v_conn)) {
+ if (v_conn != NULL) {
BM_log_vert_before_modified(bvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset);
mid_v3_v3v3(v_conn->co, v_conn->co, v_del->co);
add_v3_v3(v_conn->no, v_del->no);
normalize_v3(v_conn->no);
+
+ /* update boundboxes attached to the connected vertex
+ * note that we can often get-away without this but causes T48779 */
+ BM_LOOPS_OF_VERT_ITER_BEGIN(l, v_conn) {
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, l->f);
+ f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateBB;
+ }
+ BM_LOOPS_OF_VERT_ITER_END;
}
/* Delete v_del */
BLI_assert(!BM_vert_face_check(v_del));
- BLI_gset_insert(deleted_verts, v_del);
BM_log_vert_removed(bvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset);
+ /* v_conn == NULL is OK */
+ BLI_ghash_insert(deleted_verts, v_del, v_conn);
BM_vert_kill(bvh->bm, v_del);
}
@@ -1241,17 +1414,19 @@ static bool pbvh_bmesh_collapse_short_edges(
{
const float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
bool any_collapsed = false;
- GSet *deleted_verts = BLI_gset_ptr_new("deleted_verts");
+ /* deleted verts point to vertices they were merged into, or NULL when removed. */
+ GHash *deleted_verts = BLI_ghash_ptr_new("deleted_verts");
while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
- BMVert *v1 = pair[0], *v2 = pair[1];
+ BMVert *v1 = pair[0], *v2 = pair[1];
BLI_mempool_free(eq_ctx->pool, pair);
pair = NULL;
/* Check the verts still exist */
- if (BLI_gset_haskey(deleted_verts, v1) ||
- BLI_gset_haskey(deleted_verts, v2))
+ if (!(v1 = bm_vert_hash_lookup_chain(deleted_verts, v1)) ||
+ !(v2 = bm_vert_hash_lookup_chain(deleted_verts, v2)) ||
+ (v1 == v2))
{
continue;
}
@@ -1285,7 +1460,7 @@ static bool pbvh_bmesh_collapse_short_edges(
deleted_faces, eq_ctx);
}
- BLI_gset_free(deleted_verts, NULL);
+ BLI_ghash_free(deleted_verts, NULL, NULL);
return any_collapsed;
}
@@ -1406,18 +1581,23 @@ void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
}
}
-typedef struct FastNodeBuildInfo {
+struct FastNodeBuildInfo {
int totface; /* number of faces */
int start; /* start of faces in array */
struct FastNodeBuildInfo *child1;
struct FastNodeBuildInfo *child2;
-} FastNodeBuildInfo;
+};
-/* Recursively split the node if it exceeds the leaf_limit. This function is multithreadabe since each invocation applies
- * to a sub part of the arrays */
-static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, FastNodeBuildInfo *node, MemArena *arena)
+/**
+ * Recursively split the node if it exceeds the leaf_limit.
+ * This function is multithreadabe since each invocation applies
+ * to a sub part of the arrays
+ */
+static void pbvh_bmesh_node_limit_ensure_fast(
+ PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node,
+ MemArena *arena)
{
- FastNodeBuildInfo *child1, *child2;
+ struct FastNodeBuildInfo *child1, *child2;
if (node->totface <= bvh->leaf_limit) {
return;
@@ -1497,8 +1677,8 @@ static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC
* each sequential part belonging to one node only */
BLI_assert((num_child1 + num_child2) == node->totface);
- node->child1 = child1 = BLI_memarena_alloc(arena, sizeof(FastNodeBuildInfo));
- node->child2 = child2 = BLI_memarena_alloc(arena, sizeof(FastNodeBuildInfo));
+ node->child1 = child1 = BLI_memarena_alloc(arena, sizeof(struct FastNodeBuildInfo));
+ node->child2 = child2 = BLI_memarena_alloc(arena, sizeof(struct FastNodeBuildInfo));
child1->totface = num_child1;
child1->start = node->start;
@@ -1510,7 +1690,9 @@ static void pbvh_bmesh_node_limit_ensure_fast(PBVH *bvh, BMFace **nodeinfo, BBC
pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child2, arena);
}
-static void pbvh_bmesh_create_nodes_fast_recursive(PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, FastNodeBuildInfo *node, int node_index)
+static void pbvh_bmesh_create_nodes_fast_recursive(
+ PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array,
+ struct FastNodeBuildInfo *node, int node_index)
{
PBVHNode *n = bvh->nodes + node_index;
/* two cases, node does not have children or does have children */
@@ -1651,7 +1833,7 @@ void BKE_pbvh_build_bmesh(
bm->elem_index_dirty |= BM_FACE;
/* setup root node */
- FastNodeBuildInfo rootnode = {0};
+ struct FastNodeBuildInfo rootnode = {0};
rootnode.totface = bm->totface;
/* start recursion, assign faces to nodes accordingly */
@@ -1693,12 +1875,14 @@ bool BKE_pbvh_bmesh_update_topology(
if (mode & PBVH_Collapse) {
EdgeQueue q;
BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP);
- EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset};
+ EdgeQueueContext eq_ctx = {
+ &q, queue_pool, bvh->bm,
+ cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset,
+ };
short_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius);
- modified |= !BLI_heap_is_empty(q.heap);
- pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh,
- &deleted_faces);
+ modified |= pbvh_bmesh_collapse_short_edges(
+ &eq_ctx, bvh, &deleted_faces);
BLI_heap_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
}
@@ -1706,15 +1890,18 @@ bool BKE_pbvh_bmesh_update_topology(
if (mode & PBVH_Subdivide) {
EdgeQueue q;
BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 0, 128, BLI_MEMPOOL_NOP);
- EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset};
+ EdgeQueueContext eq_ctx = {
+ &q, queue_pool, bvh->bm,
+ cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset,
+ };
long_edge_queue_create(&eq_ctx, bvh, center, view_normal, radius);
- modified |= !BLI_heap_is_empty(q.heap);
- pbvh_bmesh_subdivide_long_edges(&eq_ctx, bvh, &edge_loops);
+ modified |= pbvh_bmesh_subdivide_long_edges(
+ &eq_ctx, bvh, &edge_loops);
BLI_heap_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
}
-
+
/* Unmark nodes */
for (int n = 0; n < bvh->totnode; n++) {
PBVHNode *node = &bvh->nodes[n];
@@ -1735,16 +1922,6 @@ bool BKE_pbvh_bmesh_update_topology(
return modified;
}
-BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3])
-{
- BMLoop *l = BM_FACE_FIRST_LOOP(f);
-
- BLI_assert(f->len == 3);
-
- r_index[0] = BM_elem_index_get(l->v); l = l->next;
- r_index[1] = BM_elem_index_get(l->v); l = l->next;
- r_index[2] = BM_elem_index_get(l->v);
-}
/* In order to perform operations on the original node coordinates
* (currently just raycast), store the node's triangles and vertices.
@@ -1858,8 +2035,8 @@ static void pbvh_bmesh_print(PBVH *bvh)
BMFace *f;
BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
fprintf(stderr, " %d -> %d\n",
- BM_elem_index_get(v),
- pbvh_bmesh_node_lookup_index(bvh, f));
+ BM_elem_index_get(f),
+ pbvh_bmesh_node_index_from_face(bvh, f));
}
fprintf(stderr, "bm_vert_to_node:\n");
@@ -1867,7 +2044,7 @@ static void pbvh_bmesh_print(PBVH *bvh)
BM_ITER_MESH(v, &iter, bvh->bm, BM_FACES_OF_MESH) {
fprintf(stderr, " %d -> %d\n",
BM_elem_index_get(v),
- pbvh_bmesh_node_lookup_index(bvh, v));
+ pbvh_bmesh_node_index_from_vert(bvh, v));
}
for (int n = 0; n < bvh->totnode; n++) {
@@ -1909,17 +2086,23 @@ static void pbvh_bmesh_verify(PBVH *bvh)
{
/* build list of faces & verts to lookup */
GSet *faces_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totface);
- BMFace *f;
BMIter iter;
- BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
- BLI_gset_insert(faces_all, f);
+
+ {
+ BMFace *f;
+ BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
+ BLI_assert(BM_ELEM_CD_GET_INT(f, bvh->cd_face_node_offset) != DYNTOPO_NODE_NONE);
+ BLI_gset_insert(faces_all, f);
+ }
}
GSet *verts_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totvert);
- BMVert *v;
- BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
- if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
- BLI_gset_insert(verts_all, v);
+ {
+ BMVert *v;
+ BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
+ if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
+ BLI_gset_insert(verts_all, v);
+ }
}
}
@@ -1936,76 +2119,83 @@ static void pbvh_bmesh_verify(PBVH *bvh)
BLI_assert(totvert == BLI_gset_size(verts_all));
}
- BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
- BMIter bm_iter;
- BMVert *v;
- PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f);
+ {
+ BMFace *f;
+ BM_ITER_MESH(f, &iter, bvh->bm, BM_FACES_OF_MESH) {
+ BMIter bm_iter;
+ BMVert *v;
+ PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f);
- /* Check that the face's node is a leaf */
- BLI_assert(n->flag & PBVH_Leaf);
+ /* Check that the face's node is a leaf */
+ BLI_assert(n->flag & PBVH_Leaf);
- /* Check that the face's node knows it owns the face */
- BLI_assert(BLI_gset_haskey(n->bm_faces, f));
+ /* Check that the face's node knows it owns the face */
+ BLI_assert(BLI_gset_haskey(n->bm_faces, f));
- /* Check the face's vertices... */
- BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
- PBVHNode *nv;
+ /* Check the face's vertices... */
+ BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
+ PBVHNode *nv;
- /* Check that the vertex is in the node */
- BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v) ^
- BLI_gset_haskey(n->bm_other_verts, v));
+ /* Check that the vertex is in the node */
+ BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v) ^
+ BLI_gset_haskey(n->bm_other_verts, v));
- /* Check that the vertex has a node owner */
- nv = pbvh_bmesh_node_lookup(bvh, v);
+ /* Check that the vertex has a node owner */
+ nv = pbvh_bmesh_node_lookup(bvh, v);
- /* Check that the vertex's node knows it owns the vert */
- BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v));
+ /* Check that the vertex's node knows it owns the vert */
+ BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v));
- /* Check that the vertex isn't duplicated as an 'other' vert */
- BLI_assert(!BLI_gset_haskey(nv->bm_other_verts, v));
+ /* Check that the vertex isn't duplicated as an 'other' vert */
+ BLI_assert(!BLI_gset_haskey(nv->bm_other_verts, v));
+ }
}
}
/* Check verts */
- BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
- /* vertex isn't tracked */
- if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
- continue;
- }
+ {
+ BMVert *v;
+ BM_ITER_MESH(v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
+ /* vertex isn't tracked */
+ if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
+ continue;
+ }
- PBVHNode *n = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *n = pbvh_bmesh_node_lookup(bvh, v);
- /* Check that the vert's node is a leaf */
- BLI_assert(n->flag & PBVH_Leaf);
+ /* Check that the vert's node is a leaf */
+ BLI_assert(n->flag & PBVH_Leaf);
- /* Check that the vert's node knows it owns the vert */
- BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v));
+ /* Check that the vert's node knows it owns the vert */
+ BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v));
- /* Check that the vertex isn't duplicated as an 'other' vert */
- BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v));
+ /* Check that the vertex isn't duplicated as an 'other' vert */
+ BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v));
- /* Check that the vert's node also contains one of the vert's
- * adjacent faces */
- bool found = false;
- BMIter bm_iter;
- BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- if (pbvh_bmesh_node_lookup(bvh, f) == n) {
- found = true;
- break;
+ /* Check that the vert's node also contains one of the vert's
+ * adjacent faces */
+ bool found = false;
+ BMIter bm_iter;
+ BMFace *f = NULL;
+ BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
+ if (pbvh_bmesh_node_lookup(bvh, f) == n) {
+ found = true;
+ break;
+ }
}
- }
- BLI_assert(found);
+ BLI_assert(found || f == NULL);
#if 1
- /* total freak stuff, check if node exists somewhere else */
- /* Slow */
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n_other = &bvh->nodes[i];
- if ((n != n_other) && (n_other->bm_unique_verts)) {
- BLI_assert(!BLI_gset_haskey(n_other->bm_unique_verts, v));
+ /* total freak stuff, check if node exists somewhere else */
+ /* Slow */
+ for (int i = 0; i < bvh->totnode; i++) {
+ PBVHNode *n_other = &bvh->nodes[i];
+ if ((n != n_other) && (n_other->bm_unique_verts)) {
+ BLI_assert(!BLI_gset_haskey(n_other->bm_unique_verts, v));
+ }
}
- }
#endif
+ }
}
#if 0
@@ -2049,7 +2239,8 @@ static void pbvh_bmesh_verify(PBVH *bvh)
GSET_ITER (gs_iter, n->bm_other_verts) {
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
- BLI_assert(!BM_vert_face_check(v));
+ /* this happens sometimes and seems harmless */
+ // BLI_assert(!BM_vert_face_check(v));
BLI_assert(BLI_gset_haskey(verts_all, v));
}
}
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 4d2307c3e12..19d3b31bd31 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -83,12 +83,11 @@ struct PBVHNode {
* array. The array is sized to match 'totprim', and each of
* the face's corners gets an index into the vert_indices
* array, in the same order as the corners in the original
- * MFace. The fourth value should not be used if the original
- * face is a triangle.
+ * MLoopTri.
*
* Used for leaf nodes in a mesh-based PBVH (not multires.)
*/
- const int (*face_vert_indices)[4];
+ const int (*face_vert_indices)[3];
/* Indicates whether this node is a leaf or not; also used for
* marking various updates that need to be applied. */
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 4a649c2ea6d..572d23b39c7 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -150,7 +150,7 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
-Scene *BKE_scene_copy(Scene *sce, int type)
+Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
{
Scene *scen;
SceneRenderLayer *srl, *new_srl;
@@ -161,7 +161,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
if (type == SCE_COPY_EMPTY) {
ListBase rl, rv;
/* XXX. main should become an arg */
- scen = BKE_scene_add(G.main, sce->id.name + 2);
+ scen = BKE_scene_add(bmain, sce->id.name + 2);
rl = scen->r.layers;
rv = scen->r.views;
@@ -182,10 +182,10 @@ Scene *BKE_scene_copy(Scene *sce, int type)
BKE_sound_destroy_scene(scen);
}
else {
- scen = BKE_libblock_copy(&sce->id);
+ scen = BKE_libblock_copy(bmain, &sce->id);
BLI_duplicatelist(&(scen->base), &(sce->base));
- BKE_main_id_clear_newpoins(G.main);
+ BKE_main_id_clear_newpoins(bmain);
id_us_plus((ID *)scen->world);
id_us_plus((ID *)scen->set);
@@ -209,7 +209,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
if (sce->nodetree) {
/* ID's are managed on both copy and switch */
- scen->nodetree = ntreeCopyTree(sce->nodetree);
+ scen->nodetree = ntreeCopyTree(bmain, sce->nodetree);
ntreeSwitchID(scen->nodetree, &sce->id, &scen->id);
}
@@ -237,7 +237,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
if (lineset->linestyle) {
id_us_plus((ID *)lineset->linestyle);
- lineset->linestyle = BKE_linestyle_copy(G.main, lineset->linestyle);
+ lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle);
}
}
}
@@ -319,7 +319,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
if (type == SCE_COPY_FULL) {
if (scen->world) {
id_us_plus((ID *)scen->world);
- scen->world = BKE_world_copy(scen->world);
+ scen->world = BKE_world_copy(bmain, scen->world);
BKE_animdata_copy_id_action((ID *)scen->world);
}
@@ -333,7 +333,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
/* grease pencil */
if (scen->gpd) {
if (type == SCE_COPY_FULL) {
- scen->gpd = gpencil_data_duplicate(scen->gpd, false);
+ scen->gpd = gpencil_data_duplicate(bmain, scen->gpd, false);
}
else if (type == SCE_COPY_EMPTY) {
scen->gpd = NULL;
@@ -343,9 +343,7 @@ Scene *BKE_scene_copy(Scene *sce, int type)
}
}
- if (sce->preview) {
- scen->preview = BKE_previewimg_copy(sce->preview);
- }
+ scen->preview = BKE_previewimg_copy(sce->preview);
return scen;
}
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 25b32cc40aa..fc3daa132c6 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -2243,7 +2243,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
.. keeping G.debug_value==17 0x11 option for old files 'needing' the bug*/
/* rule we never alter free variables :bp->vec bp->pos in here !
- * this will ruin adaptive stepsize AKA heun! (BM)
+ * this will ruin adaptive stepsize AKA heun! (BM)
*/
SoftBody *sb= ob->soft; /* is supposed to be there */
BodyPoint *bp;
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index e5075a2d382..a91d8657179 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -34,6 +34,8 @@
#include "BKE_animsys.h"
#include "BKE_global.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_speaker.h"
@@ -66,30 +68,25 @@ void *BKE_speaker_add(Main *bmain, const char *name)
return spk;
}
-Speaker *BKE_speaker_copy(Speaker *spk)
+Speaker *BKE_speaker_copy(Main *bmain, Speaker *spk)
{
Speaker *spkn;
- spkn = BKE_libblock_copy(&spk->id);
+ spkn = BKE_libblock_copy(bmain, &spk->id);
+
if (spkn->sound)
id_us_plus(&spkn->sound->id);
- if (spk->id.lib) {
+ if (ID_IS_LINKED_DATABLOCK(spk)) {
+ BKE_id_expand_local(&spkn->id);
BKE_id_lib_local_paths(G.main, spk->id.lib, &spkn->id);
}
return spkn;
}
-static void extern_local_speaker(Speaker *spk)
-{
- id_lib_extern((ID *)spk->sound);
-}
-
-void BKE_speaker_make_local(Speaker *spk)
+void BKE_speaker_make_local(Main *bmain, Speaker *spk)
{
- Main *bmain = G.main;
- Object *ob;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
@@ -97,44 +94,23 @@ void BKE_speaker_make_local(Speaker *spk)
* - mixed: make copy
*/
- if (spk->id.lib == NULL) return;
- if (spk->id.us == 1) {
- id_clear_lib_data(bmain, &spk->id);
- extern_local_speaker(spk);
+ if (!ID_IS_LINKED_DATABLOCK(spk)) {
return;
}
- ob = bmain->object.first;
- while (ob) {
- if (ob->data == spk) {
- if (ob->id.lib) is_lib = true;
- else is_local = true;
+ BKE_library_ID_test_usages(bmain, spk, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &spk->id);
+ BKE_id_expand_local(&spk->id);
}
- ob = ob->id.next;
- }
+ else {
+ Speaker *spk_new = BKE_speaker_copy(bmain, spk);
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &spk->id);
- extern_local_speaker(spk);
- }
- else if (is_local && is_lib) {
- Speaker *spk_new = BKE_speaker_copy(spk);
- spk_new->id.us = 0;
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, spk->id.lib, &spk_new->id);
-
- ob = bmain->object.first;
- while (ob) {
- if (ob->data == spk) {
-
- if (ob->id.lib == NULL) {
- ob->data = spk_new;
- id_us_plus(&spk_new->id);
- id_us_min(&spk->id);
- }
- }
- ob = ob->id.next;
+ spk_new->id.us = 0;
+
+ BKE_libblock_remap(bmain, spk, spk_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index fdc2edba57f..269d6d32b31 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -452,7 +452,7 @@ Text *BKE_text_copy(Main *bmain, Text *ta)
Text *tan;
TextLine *line, *tmp;
- tan = BKE_libblock_copy(&ta->id);
+ tan = BKE_libblock_copy(bmain, &ta->id);
/* file name can be NULL */
if (ta->name) {
@@ -491,7 +491,8 @@ Text *BKE_text_copy(Main *bmain, Text *ta)
init_undo_text(tan);
- if (ta->id.lib) {
+ if (ID_IS_LINKED_DATABLOCK(ta)) {
+ BKE_id_expand_local(&tan->id);
BKE_id_lib_local_paths(bmain, ta->id.lib, &tan->id);
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 3e4f13a2c8f..dcd60aaa702 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -58,6 +58,8 @@
#include "BKE_main.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_image.h"
#include "BKE_material.h"
#include "BKE_texture.h"
@@ -843,11 +845,11 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot)
/* ------------------------------------------------------------------------- */
-Tex *BKE_texture_copy(Tex *tex)
+Tex *BKE_texture_copy(Main *bmain, Tex *tex)
{
Tex *texn;
- texn = BKE_libblock_copy(&tex->id);
+ texn = BKE_libblock_copy(bmain, &tex->id);
if (BKE_texture_is_image_user(tex)) {
id_us_plus((ID *)texn->ima);
}
@@ -866,11 +868,14 @@ Tex *BKE_texture_copy(Tex *tex)
if (tex->nodetree->execdata) {
ntreeTexEndExecTree(tex->nodetree->execdata);
}
- texn->nodetree = ntreeCopyTree(tex->nodetree);
+ texn->nodetree = ntreeCopyTree(bmain, tex->nodetree);
}
- if (tex->id.lib) {
- BKE_id_lib_local_paths(G.main, tex->id.lib, &texn->id);
+ texn->preview = BKE_previewimg_copy(tex->preview);
+
+ if (ID_IS_LINKED_DATABLOCK(tex)) {
+ BKE_id_expand_local(&texn->id);
+ BKE_id_lib_local_paths(bmain, tex->id.lib, &texn->id);
}
return texn;
@@ -912,169 +917,32 @@ Tex *BKE_texture_localize(Tex *tex)
/* ------------------------------------------------------------------------- */
-static void extern_local_texture(Tex *tex)
+void BKE_texture_make_local(Main *bmain, Tex *tex)
{
- id_lib_extern((ID *)tex->ima);
-}
-
-void BKE_texture_make_local(Tex *tex)
-{
- Main *bmain = G.main;
- Material *ma;
- World *wrld;
- Lamp *la;
- Brush *br;
- FreestyleLineStyle *ls;
- int a;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
-
- if (tex->id.lib == NULL) return;
- if (tex->id.us == 1) {
- id_clear_lib_data(bmain, &tex->id);
- extern_local_texture(tex);
+ if (!ID_IS_LINKED_DATABLOCK(tex)) {
return;
}
-
- ma = bmain->mat.first;
- while (ma) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a] && ma->mtex[a]->tex == tex) {
- if (ma->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- ma = ma->id.next;
- }
- la = bmain->lamp.first;
- while (la) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (la->mtex[a] && la->mtex[a]->tex == tex) {
- if (la->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- la = la->id.next;
- }
- wrld = bmain->world.first;
- while (wrld) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (wrld->mtex[a] && wrld->mtex[a]->tex == tex) {
- if (wrld->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- wrld = wrld->id.next;
- }
- br = bmain->brush.first;
- while (br) {
- if (br->mtex.tex == tex) {
- if (br->id.lib) is_lib = true;
- else is_local = true;
- }
- if (br->mask_mtex.tex == tex) {
- if (br->id.lib) is_lib = true;
- else is_local = true;
- }
- br = br->id.next;
- }
- ls = bmain->linestyle.first;
- while (ls) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (ls->mtex[a] && ls->mtex[a]->tex == tex) {
- if (ls->id.lib) is_lib = true;
- else is_local = true;
- }
- }
- ls = ls->id.next;
- }
-
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &tex->id);
- extern_local_texture(tex);
- }
- else if (is_local && is_lib) {
- Tex *tex_new = BKE_texture_copy(tex);
- tex_new->id.us = 0;
+ BKE_library_ID_test_usages(bmain, tex, &is_local, &is_lib);
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, tex->id.lib, &tex_new->id);
-
- ma = bmain->mat.first;
- while (ma) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a] && ma->mtex[a]->tex == tex) {
- if (ma->id.lib == NULL) {
- ma->mtex[a]->tex = tex_new;
- id_us_plus(&tex_new->id);
- id_us_min(&tex->id);
- }
- }
- }
- ma = ma->id.next;
- }
- la = bmain->lamp.first;
- while (la) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (la->mtex[a] && la->mtex[a]->tex == tex) {
- if (la->id.lib == NULL) {
- la->mtex[a]->tex = tex_new;
- id_us_plus(&tex_new->id);
- id_us_min(&tex->id);
- }
- }
- }
- la = la->id.next;
- }
- wrld = bmain->world.first;
- while (wrld) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (wrld->mtex[a] && wrld->mtex[a]->tex == tex) {
- if (wrld->id.lib == NULL) {
- wrld->mtex[a]->tex = tex_new;
- id_us_plus(&tex_new->id);
- id_us_min(&tex->id);
- }
- }
- }
- wrld = wrld->id.next;
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &tex->id);
+ BKE_id_expand_local(&tex->id);
}
- br = bmain->brush.first;
- while (br) {
- if (br->mtex.tex == tex) {
- if (br->id.lib == NULL) {
- br->mtex.tex = tex_new;
- id_us_plus(&tex_new->id);
- id_us_min(&tex->id);
- }
- }
- if (br->mask_mtex.tex == tex) {
- if (br->id.lib == NULL) {
- br->mask_mtex.tex = tex_new;
- id_us_plus(&tex_new->id);
- id_us_min(&tex->id);
- }
- }
- br = br->id.next;
- }
- ls = bmain->linestyle.first;
- while (ls) {
- for (a = 0; a < MAX_MTEX; a++) {
- if (ls->mtex[a] && ls->mtex[a]->tex == tex) {
- if (ls->id.lib == NULL) {
- ls->mtex[a]->tex = tex_new;
- id_us_plus(&tex_new->id);
- id_us_min(&tex->id);
- }
- }
- }
- ls = ls->id.next;
+ else {
+ Tex *tex_new = BKE_texture_copy(bmain, tex);
+
+ tex_new->id.us = 0;
+
+ BKE_libblock_remap(bmain, tex, tex_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index ec021586be5..9795a8174f8 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -46,6 +46,8 @@
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
+#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_world.h"
@@ -117,12 +119,12 @@ World *add_world(Main *bmain, const char *name)
return wrld;
}
-World *BKE_world_copy(World *wrld)
+World *BKE_world_copy(Main *bmain, World *wrld)
{
World *wrldn;
int a;
- wrldn = BKE_libblock_copy(&wrld->id);
+ wrldn = BKE_libblock_copy(bmain, &wrld->id);
for (a = 0; a < MAX_MTEX; a++) {
if (wrld->mtex[a]) {
@@ -133,16 +135,16 @@ World *BKE_world_copy(World *wrld)
}
if (wrld->nodetree) {
- wrldn->nodetree = ntreeCopyTree(wrld->nodetree);
+ wrldn->nodetree = ntreeCopyTree(bmain, wrld->nodetree);
}
- if (wrld->preview)
- wrldn->preview = BKE_previewimg_copy(wrld->preview);
+ wrldn->preview = BKE_previewimg_copy(wrld->preview);
BLI_listbase_clear(&wrldn->gpumaterial);
- if (wrld->id.lib) {
- BKE_id_lib_local_paths(G.main, wrld->id.lib, &wrldn->id);
+ if (ID_IS_LINKED_DATABLOCK(wrld)) {
+ BKE_id_expand_local(&wrldn->id);
+ BKE_id_lib_local_paths(bmain, wrld->id.lib, &wrldn->id);
}
return wrldn;
@@ -174,48 +176,32 @@ World *localize_world(World *wrld)
return wrldn;
}
-void BKE_world_make_local(World *wrld)
+void BKE_world_make_local(Main *bmain, World *wrld)
{
- Main *bmain = G.main;
- Scene *sce;
bool is_local = false, is_lib = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
-
- if (wrld->id.lib == NULL) return;
- if (wrld->id.us == 1) {
- id_clear_lib_data(bmain, &wrld->id);
+
+ if (!ID_IS_LINKED_DATABLOCK(wrld)) {
return;
}
-
- for (sce = bmain->scene.first; sce && ELEM(false, is_lib, is_local); sce = sce->id.next) {
- if (sce->world == wrld) {
- if (sce->id.lib) is_lib = true;
- else is_local = true;
+
+ BKE_library_ID_test_usages(bmain, wrld, &is_local, &is_lib);
+
+ if (is_local) {
+ if (!is_lib) {
+ id_clear_lib_data(bmain, &wrld->id);
+ BKE_id_expand_local(&wrld->id);
}
- }
+ else {
+ World *wrld_new = BKE_world_copy(bmain, wrld);
- if (is_local && is_lib == false) {
- id_clear_lib_data(bmain, &wrld->id);
- }
- else if (is_local && is_lib) {
- World *wrld_new = BKE_world_copy(wrld);
- wrld_new->id.us = 0;
-
- /* Remap paths of new ID using old library as base. */
- BKE_id_lib_local_paths(bmain, wrld->id.lib, &wrld_new->id);
-
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- if (sce->world == wrld) {
- if (sce->id.lib == NULL) {
- sce->world = wrld_new;
- id_us_plus(&wrld_new->id);
- id_us_min(&wrld->id);
- }
- }
+ wrld_new->id.us = 0;
+
+ BKE_libblock_remap(bmain, wrld, wrld_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
}
}