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>2017-01-31 12:47:43 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2017-01-31 12:47:43 +0300
commit3e9ade6e31c395252189e077b8edd0c846799694 (patch)
tree4eaad80cb0b61e819879c9cae41b714fe4d0e161 /source/blender
parent85174329d9f5701ed1499d7205dd153ec81d0e00 (diff)
parentb5682a6fdd8a3ebbea1fd4a75c72fe8c9c3326c5 (diff)
Merge branch 'master' into blender2.8
Conflicts: source/blender/blenkernel/intern/depsgraph.c source/blender/blenkernel/intern/library_query.c
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_library.h5
-rw-r--r--source/blender/blenkernel/BKE_library_query.h29
-rw-r--r--source/blender/blenkernel/BKE_main.h23
-rw-r--r--source/blender/blenkernel/BKE_modifier.h4
-rw-r--r--source/blender/blenkernel/BKE_object.h5
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h2
-rw-r--r--source/blender/blenkernel/BKE_sca.h6
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c15
-rw-r--r--source/blender/blenkernel/intern/brush.c2
-rw-r--r--source/blender/blenkernel/intern/cachefile.c8
-rw-r--r--source/blender/blenkernel/intern/library.c252
-rw-r--r--source/blender/blenkernel/intern/library_query.c340
-rw-r--r--source/blender/blenkernel/intern/library_remap.c32
-rw-r--r--source/blender/blenkernel/intern/object.c53
-rw-r--r--source/blender/blenkernel/intern/particle_system.c10
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c8
-rw-r--r--source/blender/blenkernel/intern/sca.c44
-rw-r--r--source/blender/blenlib/BLI_math_geom.h4
-rw-r--r--source/blender/blenlib/intern/math_geom.c28
-rw-r--r--source/blender/blenloader/intern/readfile.c6
-rw-r--r--source/blender/blenloader/intern/versioning_270.c4
-rw-r--r--source/blender/collada/ArmatureExporter.cpp14
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc2
-rw-r--r--source/blender/editors/animation/anim_filter.c2
-rw-r--r--source/blender/editors/object/object_relations.c6
-rw-r--r--source/blender/editors/transform/transform_snap.c8
-rw-r--r--source/blender/editors/transform/transform_snap_object.c1128
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl4
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c2
-rw-r--r--source/blender/modifiers/intern/MOD_array.c8
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c2
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c2
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c4
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c2
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c11
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c4
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c8
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c2
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c2
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c2
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c2
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c2
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c2
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c2
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c4
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c10
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c4
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c4
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c8
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c4
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c6
-rw-r--r--source/blender/python/intern/bpy_rna_id_collection.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c8
59 files changed, 1198 insertions, 971 deletions
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 2d9c35f7fd0..72ae2cf4efa 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -86,7 +86,7 @@ bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const boo
bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
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);
+void BKE_id_expand_local(struct Main *bmain, struct ID *id);
void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id);
bool new_id(struct ListBase *lb, struct ID *id, const char *name);
@@ -105,6 +105,9 @@ void BKE_main_free(struct Main *mainvar);
void BKE_main_lock(struct Main *bmain);
void BKE_main_unlock(struct Main *bmain);
+void BKE_main_relations_create(struct Main *bmain);
+void BKE_main_relations_free(struct Main *bmain);
+
struct BlendThumbnail *BKE_main_thumbnail_from_imbuf(struct Main *bmain, struct ImBuf *img);
struct ImBuf *BKE_main_thumbnail_to_imbuf(struct Main *bmain, struct BlendThumbnail *data);
void BKE_main_thumbnail_create(struct Main *bmain);
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index a7470107c24..1258e2fa72e 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -36,25 +36,28 @@ struct Main;
/* Tips for the callback for cases it's gonna to modify the pointer. */
enum {
- IDWALK_NOP = 0,
- IDWALK_NEVER_NULL = (1 << 0),
- IDWALK_NEVER_SELF = (1 << 1),
+ IDWALK_CB_NOP = 0,
+ IDWALK_CB_NEVER_NULL = (1 << 0),
+ IDWALK_CB_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),
+ IDWALK_CB_INDIRECT_USAGE = (1 << 2),
+
+ /** That ID is used as mere sub-data by its owner
+ * (only case currently: those f***ing nodetrees in materials etc.).
+ * This means callback shall not *do* anything, only use this as informative data if it needs it. */
+ IDWALK_CB_PRIVATE = (1 << 3),
/**
* Adjusts #ID.us reference-count.
* \note keep in sync with 'newlibadr_us' use in readfile.c
*/
- IDWALK_USER = (1 << 8),
- /**
- * Ensure #ID.us is at least 1 on use.
- */
- IDWALK_USER_ONE = (1 << 9),
+ IDWALK_CB_USER = (1 << 8),
+ /** Ensure #ID.us is at least 1 on use. */
+ IDWALK_CB_USER_ONE = (1 << 9),
};
enum {
@@ -68,17 +71,19 @@ enum {
*
* \return a set of flags to control further iteration (0 to keep going).
*/
-typedef int (*LibraryIDLinkCallback) (void *user_data, struct ID *id_self, struct ID **id_pointer, int cd_flag);
+typedef int (*LibraryIDLinkCallback) (void *user_data, struct ID *id_self, struct ID **id_pointer, int cb_flag);
/* Flags for the foreach function itself. */
enum {
+ IDWALK_NOP = 0,
IDWALK_READONLY = (1 << 0),
IDWALK_RECURSE = (1 << 1), /* Also implies IDWALK_READONLY. */
};
/* Loop over all of the ID's this datablock links to. */
-void BKE_library_foreach_ID_link(struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
-void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cd_flag);
+void BKE_library_foreach_ID_link(
+ struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
+void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int cb_flag);
int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used);
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index a4f5c425282..387045878f3 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -51,6 +51,8 @@ extern "C" {
struct EvaluationContext;
struct Library;
struct MainLock;
+struct GHash;
+struct BLI_mempool;
/* Blender thumbnail, as written on file (width, height, and data as char RGBA). */
/* We pack pixel data after that struct. */
@@ -59,6 +61,22 @@ typedef struct BlendThumbnail {
char rect[0];
} BlendThumbnail;
+/* Structs caching relations between data-blocks in a given Main. */
+typedef struct MainIDRelationsEntry {
+ struct MainIDRelationsEntry *next;
+ /* WARNING! for user_to_used, that pointer is really an ID** one, but for used_to_user, it’s only an ID* one! */
+ struct ID **id_pointer;
+ int usage_flag; /* Using IDWALK_ enums, in BKE_library_query.h */
+} MainIDRelationsEntry;
+
+typedef struct MainIDRelations {
+ struct GHash *id_user_to_used;
+ struct GHash *id_used_to_user;
+
+ /* Private... */
+ struct BLI_mempool *entry_pool;
+} MainIDRelations;
+
typedef struct Main {
struct Main *next, *prev;
char name[1024]; /* 1024 = FILE_MAX */
@@ -111,6 +129,11 @@ typedef struct Main {
/* Evaluation context used by viewport */
struct EvaluationContext *eval_ctx;
+ /* Must be generated, used and freed by same code - never assume this is valid data unless you know
+ * when, who and how it was created.
+ * Used by code doing a lot of remapping etc. at once to speed things up. */
+ struct MainIDRelations *relations;
+
struct MainLock *lock;
} Main;
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 92b186d7329..7a522cba282 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -106,8 +106,8 @@ typedef enum {
} ModifierTypeFlag;
/* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */
-typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cd_flag);
-typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cd_flag);
+typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin, int cb_flag);
+typedef void (*IDWalkFunc)(void *userData, struct Object *ob, struct ID **idpoin, int cb_flag);
typedef void (*TexWalkFunc)(void *userData, struct Object *ob, struct ModifierData *md, const char *propname);
typedef enum ModifierApplyFlag {
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 8413d266078..b1e218d3e5f 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -136,14 +136,9 @@ void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float
/* possibly belong in own moduke? */
struct BoundBox *BKE_boundbox_alloc_unit(void);
void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], const float max[3]);
-bool BKE_boundbox_ray_hit_check(
- const struct BoundBox *bb,
- const float ray_start[3], const float ray_normal[3],
- float *r_lambda);
void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]);
void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]);
-void BKE_boundbox_scale(struct BoundBox *bb_dst, const struct BoundBox *bb_src, float scale);
struct BoundBox *BKE_boundbox_ensure_minimum_dimensions(
struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index b3e3968ca9b..e5967be0bc7 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -384,7 +384,7 @@ void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleDa
void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
/* Callback format for performing operations on ID-pointers for particle systems */
-typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cd_flag);
+typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cb_flag);
void BKE_particlesystem_id_loop(struct ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 965a97f08ba..443c3b2b5b2 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -53,7 +53,7 @@ struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
/* Callback format for performing operations on ID-pointers for rigidbody world. */
-typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cd_flag);
+typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cb_flag);
void BKE_rigidbody_world_id_loop(struct RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata);
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index a504f1bac3d..1579a0c7bb3 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -77,9 +77,9 @@ void sca_move_controller(struct bController *cont_to_move, struct Object *ob, in
void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up);
/* Callback format for performing operations on ID-pointers for sensors/controllers/actuators. */
-typedef void (*SCASensorIDFunc)(struct bSensor *sensor, struct ID **idpoin, void *userdata, int cd_flag);
-typedef void (*SCAControllerIDFunc)(struct bController *controller, struct ID **idpoin, void *userdata, int cd_flag);
-typedef void (*SCAActuatorIDFunc)(struct bActuator *actuator, struct ID **idpoin, void *userdata, int cd_flag);
+typedef void (*SCASensorIDFunc)(struct bSensor *sensor, struct ID **idpoin, void *userdata, int cb_flag);
+typedef void (*SCAControllerIDFunc)(struct bController *controller, struct ID **idpoin, void *userdata, int cb_flag);
+typedef void (*SCAActuatorIDFunc)(struct bActuator *actuator, struct ID **idpoin, void *userdata, int cb_flag);
void BKE_sca_sensors_id_loop(struct ListBase *senslist, SCASensorIDFunc func, void *userdata);
void BKE_sca_controllers_id_loop(struct ListBase *contlist, SCAControllerIDFunc func, void *userdata);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index e0bbe345fc4..39f1db0b886 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2216,6 +2216,12 @@ static void mesh_calc_modifiers(
}
}
+ /* Some modifiers, like datatransfer, may generate those data as temp layer, we do not want to keep them,
+ * as they are used by display code when available (i.e. even if autosmooth is disabled). */
+ if (!do_loop_normals && CustomData_has_layer(&finaldm->loopData, CD_NORMAL)) {
+ CustomData_free_layers(&finaldm->loopData, CD_NORMAL, finaldm->numLoopData);
+ }
+
#ifdef WITH_GAMEENGINE
/* NavMesh - this is a hack but saves having a NavMesh modifier */
if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) {
@@ -2551,6 +2557,15 @@ static void editbmesh_calc_modifiers(
/* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
if (!do_loop_normals) {
dm_ensure_display_normals(*r_final);
+
+ /* Some modifiers, like datatransfer, may generate those data, we do not want to keep them,
+ * as they are used by display code when available (i.e. even if autosmooth is disabled). */
+ if (CustomData_has_layer(&(*r_final)->loopData, CD_NORMAL)) {
+ CustomData_free_layers(&(*r_final)->loopData, CD_NORMAL, (*r_final)->numLoopData);
+ }
+ if (r_cage && CustomData_has_layer(&(*r_cage)->loopData, CD_NORMAL)) {
+ CustomData_free_layers(&(*r_cage)->loopData, CD_NORMAL, (*r_cage)->numLoopData);
+ }
}
/* add an orco layer if needed */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 0d509ecea06..57b707a31d3 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -239,7 +239,7 @@ void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local)
if (lib_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &brush->id);
- BKE_id_expand_local(&brush->id);
+ BKE_id_expand_local(bmain, &brush->id);
/* enable fake user by default */
id_fake_user_set(&brush->id);
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index deeb35bd880..3dce08eb756 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -215,7 +215,9 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
if (cache_file == mcmd->cache_file) {
#ifdef WITH_ALEMBIC
- CacheReader_free(mcmd->reader);
+ if (mcmd->reader != NULL) {
+ CacheReader_free(mcmd->reader);
+ }
#endif
mcmd->reader = NULL;
mcmd->object_path[0] = '\0';
@@ -231,7 +233,9 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
if (cache_file == data->cache_file) {
#ifdef WITH_ALEMBIC
- CacheReader_free(data->reader);
+ if (data->reader != NULL) {
+ CacheReader_free(data->reader);
+ }
#endif
data->reader = NULL;
data->object_path[0] = '\0';
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index de35d1e0eac..2398c6724ed 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -76,6 +76,7 @@
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
+#include "BLI_mempool.h"
#include "BLI_string_utils.h"
#include "BLI_threads.h"
@@ -273,8 +274,12 @@ void BKE_id_clear_newpoin(ID *id)
}
static int id_expand_local_callback(
- void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int UNUSED(cd_flag))
+ void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int cb_flag)
{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
/* Can hapen that we get unlinkable ID here, e.g. with shapekey referring to itself (through drivers)...
* Just skip it, shape key can only be either indirectly linked, or fully local, period.
* And let's curse one more time that stupid useless shapekey ID type! */
@@ -288,9 +293,9 @@ static int id_expand_local_callback(
/**
* 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)
+void BKE_id_expand_local(Main *bmain, ID *id)
{
- BKE_library_foreach_ID_link(id, id_expand_local_callback, NULL, 0);
+ BKE_library_foreach_ID_link(bmain, id, id_expand_local_callback, NULL, IDWALK_READONLY);
}
/**
@@ -299,7 +304,7 @@ void BKE_id_expand_local(ID *id)
void BKE_id_copy_ensure_local(Main *bmain, ID *old_id, ID *new_id)
{
if (ID_IS_LINKED_DATABLOCK(old_id)) {
- BKE_id_expand_local(new_id);
+ BKE_id_expand_local(bmain, new_id);
BKE_id_lib_local_paths(bmain, old_id->lib, new_id);
}
}
@@ -326,7 +331,7 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c
if (lib_local || is_local) {
if (!is_lib) {
id_clear_lib_data_ex(bmain, id, id_in_mainlist);
- BKE_id_expand_local(id);
+ BKE_id_expand_local(bmain, id);
}
else {
ID *id_new;
@@ -1252,6 +1257,10 @@ void BKE_main_free(Main *mainvar)
}
}
+ if (mainvar->relations) {
+ BKE_main_relations_free(mainvar);
+ }
+
BLI_spin_end((SpinLock *)mainvar->lock);
MEM_freeN(mainvar->lock);
DEG_evaluation_context_free(mainvar->eval_ctx);
@@ -1268,6 +1277,78 @@ void BKE_main_unlock(struct Main *bmain)
BLI_spin_unlock((SpinLock *) bmain->lock);
}
+
+static int main_relations_create_cb(void *user_data, ID *id_self, ID **id_pointer, int cb_flag)
+{
+ MainIDRelations *rel = user_data;
+
+ if (*id_pointer) {
+ MainIDRelationsEntry *entry, **entry_p;
+
+ entry = BLI_mempool_alloc(rel->entry_pool);
+ if (BLI_ghash_ensure_p(rel->id_user_to_used, id_self, (void ***)&entry_p)) {
+ entry->next = *entry_p;
+ }
+ else {
+ entry->next = NULL;
+ }
+ entry->id_pointer = id_pointer;
+ entry->usage_flag = cb_flag;
+ *entry_p = entry;
+
+ entry = BLI_mempool_alloc(rel->entry_pool);
+ if (BLI_ghash_ensure_p(rel->id_used_to_user, *id_pointer, (void ***)&entry_p)) {
+ entry->next = *entry_p;
+ }
+ else {
+ entry->next = NULL;
+ }
+ entry->id_pointer = (ID **)id_self;
+ entry->usage_flag = cb_flag;
+ *entry_p = entry;
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+/** Generate the mappings between used IDs and their users, and vice-versa. */
+void BKE_main_relations_create(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ ID *id;
+ int a;
+
+ if (bmain->relations != NULL) {
+ BKE_main_relations_free(bmain);
+ }
+
+ bmain->relations = MEM_mallocN(sizeof(*bmain->relations), __func__);
+ bmain->relations->id_used_to_user = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ bmain->relations->id_user_to_used = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ bmain->relations->entry_pool = BLI_mempool_create(sizeof(MainIDRelationsEntry), 128, 128, BLI_MEMPOOL_NOP);
+
+ for (a = set_listbasepointers(bmain, lbarray); a--; ) {
+ for (id = lbarray[a]->first; id; id = id->next) {
+ BKE_library_foreach_ID_link(NULL, id, main_relations_create_cb, bmain->relations, IDWALK_READONLY);
+ }
+ }
+}
+
+void BKE_main_relations_free(Main *bmain)
+{
+ if (bmain->relations) {
+ if (bmain->relations->id_used_to_user) {
+ BLI_ghash_free(bmain->relations->id_used_to_user, NULL, NULL);
+ }
+ if (bmain->relations->id_user_to_used) {
+ BLI_ghash_free(bmain->relations->id_user_to_used, NULL, NULL);
+ }
+ BLI_mempool_destroy(bmain->relations->entry_pool);
+ MEM_freeN(bmain->relations);
+ bmain->relations = NULL;
+ }
+}
+
/**
* Generates a raw .blend file thumbnail data from given image.
*
@@ -1623,6 +1704,53 @@ void BKE_main_id_clear_newpoins(Main *bmain)
}
}
+
+static void library_make_local_copying_check(ID *id, GSet *loop_tags, MainIDRelations *id_relations, GSet *done_ids)
+{
+ if (BLI_gset_haskey(done_ids, id)) {
+ return; /* Already checked, nothing else to do. */
+ }
+
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id);
+ BLI_gset_insert(loop_tags, id);
+ for (; entry != NULL; entry = entry->next) {
+ ID *par_id = (ID *)entry->id_pointer; /* used_to_user stores ID pointer, not pointer to ID pointer... */
+
+ /* Shapekeys are considered 'private' to their owner ID here, and never tagged (since they cannot be linked),
+ * so we have to switch effective parent to their owner. */
+ if (GS(par_id->name) == ID_KE) {
+ par_id = ((Key *)par_id)->from;
+ }
+
+ if (par_id->lib == NULL) {
+ /* Local user, early out to avoid some gset querying... */
+ continue;
+ }
+ if (!BLI_gset_haskey(done_ids, par_id)) {
+ if (BLI_gset_haskey(loop_tags, par_id)) {
+ /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it.
+ * Note that this is the situation that can lead to archipelagoes of linked data-blocks
+ * (since all of them have non-local users, they would all be duplicated, leading to a loop of unused
+ * linked data-blocks that cannot be freed since they all use each other...). */
+ continue;
+ }
+ /* Else, recursively check that user ID. */
+ library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids);
+ }
+
+ if (par_id->tag & LIB_TAG_DOIT) {
+ /* This user will be fully local in future, so far so good, nothing to do here but check next user. */
+ }
+ else {
+ /* This user won't be fully local in future, so current ID won't be either. And we are done checking it. */
+ id->tag &= ~LIB_TAG_DOIT;
+ break;
+ }
+ }
+ BLI_gset_add(done_ids, id);
+ BLI_gset_remove(loop_tags, id, NULL);
+}
+
/** Make linked datablocks local.
*
* \param bmain Almost certainly G.main.
@@ -1633,11 +1761,10 @@ void BKE_main_id_clear_newpoins(Main *bmain)
/* Note: Old (2.77) version was simply making (tagging) datablocks as local, without actually making any check whether
* they were also indirectly used or not...
*
- * Current version uses regular id_make_local callback, which is not super-efficient since this ends up
- * duplicating some IDs and then removing original ones (due to missing knowledge of which ID uses some other ID).
- *
- * However, we now have a first check that allows us to use 'direct localization' of a lot of IDs, so performances
- * are now *reasonably* OK.
+ * Current version uses regular id_make_local callback, with advanced pre-processing step to detect all cases of
+ * IDs currently indirectly used, but which will be used by local data only once this function is finished.
+ * This allows to avoid any uneeded duplication of IDs, and hence all time lost afterwards to remove
+ * orphaned linked data-blocks...
*/
void BKE_library_make_local(
Main *bmain, const Library *lib, GHash *old_to_new_ids, const bool untagged_only, const bool set_fake)
@@ -1648,9 +1775,12 @@ void BKE_library_make_local(
LinkNode *todo_ids = NULL;
LinkNode *copied_ids = NULL;
- LinkNode *linked_loop_candidates = NULL;
MemArena *linklist_mem = BLI_memarena_new(512 * sizeof(*todo_ids), __func__);
+ BKE_main_relations_create(bmain);
+
+ GSet *done_ids = BLI_gset_ptr_new(__func__);
+
/* Step 1: Detect datablocks to make local. */
for (a = set_listbasepointers(bmain, lbarray); a--; ) {
id = lbarray[a]->first;
@@ -1660,16 +1790,25 @@ void BKE_library_make_local(
const bool do_skip = (id && !BKE_idcode_is_linkable(GS(id->name)));
for (; id; id = id->next) {
+ ID *ntree = (ID *)ntreeFromID(id);
+
id->tag &= ~LIB_TAG_DOIT;
+ if (ntree != NULL) {
+ ntree->tag &= ~LIB_TAG_DOIT;
+ }
if (id->lib == NULL) {
id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW);
}
- /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so its
- * possible to tag data you don't want to be made local, used for
- * appending data, so any libdata already linked wont become local
- * (very nasty to discover all your links are lost after appending).
+ /* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so its possible to tag data you don't want to
+ * be made local, used for appending data, so any libdata already linked wont become local (very nasty
+ * to discover all your links are lost after appending).
* Also, never ever make proxified objects local, would not make any sense. */
+ /* Some more notes:
+ * - Shapekeys are never tagged here (since they are not linkable).
+ * - Nodetrees used in materials etc. have to be tagged manually, since they do not exist in Main (!).
+ * This is ok-ish on 'make local' side of things (since those are handled by their 'owner' IDs),
+ * but complicates slightly the pre-processing of relations between IDs at step 2... */
else if (!do_skip && id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) &&
ELEM(lib, NULL, id->lib) &&
!(GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) &&
@@ -1677,13 +1816,32 @@ void BKE_library_make_local(
{
BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem);
id->tag |= LIB_TAG_DOIT;
+
+ /* Tag those nasty non-ID nodetrees, but do not add them to todo list, making them local is handled
+ * by 'owner' ID. This is needed for library_make_local_copying_check() to work OK at step 2. */
+ if (ntree != NULL) {
+ ntree->tag |= LIB_TAG_DOIT;
+ }
+ }
+ else {
+ /* Linked ID that we won't be making local (needed info for step 2, see below). */
+ BLI_gset_add(done_ids, id);
}
}
}
/* Step 2: Check which datablocks we can directly make local (because they are only used by already, or future,
- * local data), others will need to be duplicated and further processed later. */
- BKE_library_indirectly_used_data_tag_clear(bmain);
+ * local data), others will need to be duplicated. */
+ GSet *loop_tags = BLI_gset_ptr_new(__func__);
+ for (LinkNode *it = todo_ids; it; it = it->next) {
+ library_make_local_copying_check(it->link, loop_tags, bmain->relations, done_ids);
+ BLI_assert(BLI_gset_size(loop_tags) == 0);
+ }
+ BLI_gset_free(loop_tags, NULL);
+ BLI_gset_free(done_ids, NULL);
+
+ /* Next step will most likely add new IDs, better to get rid of this mapping now. */
+ BKE_main_relations_free(bmain);
/* Step 3: Make IDs local, either directly (quick and simple), or using generic process,
* which involves more complex checks and might instead create a local copy of original linked ID. */
@@ -1693,10 +1851,10 @@ void BKE_library_make_local(
if (id->tag & LIB_TAG_DOIT) {
/* We know all users of this object are local or will be made fully local, even if currently there are
- * some indirect usages. So instead of making a copy that se'll likely get rid of later, directly make
+ * some indirect usages. So instead of making a copy that we'll likely get rid of later, directly make
* that data block local. Saves a tremendous amount of time with complex scenes... */
id_clear_lib_data_ex(bmain, id, true);
- BKE_id_expand_local(id);
+ BKE_id_expand_local(bmain, id);
id->tag &= ~LIB_TAG_DOIT;
}
else {
@@ -1732,6 +1890,9 @@ void BKE_library_make_local(
/* Step 4: We have to remap local usages of old (linked) ID to new (local) id in a separated loop,
* as lbarray ordering is not enough to ensure us we did catch all dependencies
* (e.g. if making local a parent object before its child...). See T48907. */
+ /* TODO This is now the biggest step by far (in term of processing time). We may be able to gain here by
+ * using again main->relations mapping, but... this implies BKE_libblock_remap & co to be able to update
+ * main->relations on the fly. Have to think about it a bit more, and see whether new code is OK first, anyway. */
for (LinkNode *it = copied_ids; it; it = it->next) {
id = it->link;
@@ -1750,6 +1911,53 @@ void BKE_library_make_local(
}
}
+ /* Note: Keeping both version of the code (old one being safer, since it still has checks against unused IDs)
+ * for now, we can remove old one once it has been tested for some time in master... */
+#if 1
+ /* Step 5: proxy 'remapping' hack. */
+ for (LinkNode *it = copied_ids; it; it = it->next) {
+ /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
+ * from another blend file into this one, even when that blend file contains proxified
+ * armatures that have local references. Since the proxified object needs to be linked
+ * (not local), this will only work when the "Localize all" checkbox is disabled.
+ * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
+ if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
+ Object *ob = (Object *)id;
+ Object *ob_new = (Object *)id->newid;
+ bool is_local = false, is_lib = false;
+
+ /* Proxies only work when the proxified object is linked-in from a library. */
+ if (ob->proxy->id.lib == NULL) {
+ printf("Warning, proxy object %s will loose its link to %s, because the "
+ "proxified object is local.\n", id->newid->name, ob->proxy->id.name);
+ continue;
+ }
+
+ BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
+
+ /* We can only switch the proxy'ing to a made-local proxy if it is no longer
+ * referred to from a library. Not checking for local use; if new local proxy
+ * was not used locally would be a nasty bug! */
+ if (is_local || is_lib) {
+ printf("Warning, made-local proxy object %s will loose its link to %s, "
+ "because the linked-in proxy is referenced (is_local=%i, is_lib=%i).\n",
+ id->newid->name, ob->proxy->id.name, is_local, is_lib);
+ }
+ else {
+ /* we can switch the proxy'ing from the linked-in to the made-local proxy.
+ * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
+ * was already allocated by BKE_object_make_local_ex() (which called BKE_object_copy_ex). */
+ ob_new->proxy = ob->proxy;
+ ob_new->proxy_group = ob->proxy_group;
+ ob_new->proxy_from = ob->proxy_from;
+ ob_new->proxy->proxy_from = ob_new;
+ ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
+ }
+ }
+ }
+#else
+ LinkNode *linked_loop_candidates = NULL;
+
/* Step 5: remove datablocks that have been copied to be localized and are no more used in the end...
* Note that we may have to loop more than once here, to tackle dependencies between linked objects... */
bool do_loop = true;
@@ -1800,6 +2008,8 @@ void BKE_library_make_local(
if (!is_local) {
if (!is_lib) { /* Not used at all, we can free it! */
+ BLI_assert(!"Unused linked data copy remaining from MakeLibLocal process, should not happen anymore");
+ printf("\t%s (from %s)\n", id->name, id->lib->id.name);
BKE_libblock_free(bmain, id);
it->link = NULL;
do_loop = true;
@@ -1813,7 +2023,7 @@ void BKE_library_make_local(
/* Grrrrrrr... those half-datablocks-stuff... grrrrrrrrrrr...
* Here we have to also tag them as potential candidates, otherwise they would falsy report
- * ID they used as 'directly used' in fourth step. */
+ * ID they used as 'directly used' in sixth step. */
ID *ntree = (ID *)ntreeFromID(id);
if (ntree != NULL) {
ntree->tag |= LIB_TAG_DOIT;
@@ -1838,6 +2048,7 @@ void BKE_library_make_local(
/* Note: in theory here we are only handling datablocks forming exclusive linked dependency-cycles-based
* archipelagos, so no need to check again after we have deleted one, as done in previous step. */
if (id->tag & LIB_TAG_DOIT) {
+ BLI_assert(!"Unused linked data copy remaining from MakeLibLocal process (archipelago case), should not happen anymore");
/* Object's deletion rely on valid ob->data, but ob->data may have already been freed here...
* Setting it to NULL may not be 100% correct, but should be safe and do the work. */
if (GS(id->name) == ID_OB) {
@@ -1858,6 +2069,7 @@ void BKE_library_make_local(
it->link = NULL;
}
}
+#endif
BKE_main_id_clear_newpoins(bmain);
BLI_memarena_free(linklist_mem);
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index bfc26fcac0f..9685f1f5af6 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -63,6 +63,7 @@
#include "DNA_world_types.h"
#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
#include "BLI_ghash.h"
#include "BLI_linklist_stack.h"
@@ -83,11 +84,12 @@
#define FOREACH_FINALIZE _finalize
#define FOREACH_FINALIZE_VOID FOREACH_FINALIZE: (void)0
-#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, cb_flag) \
+#define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, _cb_flag) \
+ CHECK_TYPE(id_pp, ID **); \
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 | (_data)->cd_flag); \
+ const int callback_return = (_data)->callback((_data)->user_data, (_data)->self_id, id_pp, _cb_flag | (_data)->cb_flag); \
if (_flag & IDWALK_READONLY) { \
BLI_assert(*(id_pp) == old_id); \
} \
@@ -128,7 +130,7 @@ enum {
typedef struct LibraryForeachIDData {
ID *self_id;
int flag;
- int cd_flag;
+ int cb_flag;
LibraryIDLinkCallback callback;
void *user_data;
int status;
@@ -139,19 +141,19 @@ typedef struct LibraryForeachIDData {
} LibraryForeachIDData;
static void library_foreach_rigidbodyworldSceneLooper(
- struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cd_flag)
+ struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_modifiersForeachIDLink(
- void *user_data, Object *UNUSED(object), ID **id_pointer, int cd_flag)
+ void *user_data, Object *UNUSED(object), ID **id_pointer, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
@@ -160,44 +162,44 @@ static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID
bool is_reference, void *user_data)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- const int cd_flag = is_reference ? IDWALK_USER : IDWALK_NOP;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ const int cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_particlesystemsObjectLooper(
- ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cd_flag)
+ ParticleSystem *UNUSED(psys), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_sensorsObjectLooper(
- bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cd_flag)
+ bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_controllersObjectLooper(
- bController *UNUSED(controller), ID **id_pointer, void *user_data, int cd_flag)
+ bController *UNUSED(controller), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_actuatorsObjectLooper(
- bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cd_flag)
+ bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cb_flag)
{
LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
- FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cd_flag);
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag);
FOREACH_FINALIZE_VOID;
}
@@ -206,7 +208,7 @@ static void library_foreach_nla_strip(LibraryForeachIDData *data, NlaStrip *stri
{
NlaStrip *substrip;
- FOREACH_CALLBACK_INVOKE(data, strip->act, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, strip->act, IDWALK_CB_USER);
for (substrip = strip->strips.first; substrip; substrip = substrip->next) {
library_foreach_nla_strip(data, substrip);
@@ -229,14 +231,14 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *
/* only used targets */
DRIVER_TARGETS_USED_LOOPER(dvar)
{
- FOREACH_CALLBACK_INVOKE_ID(data, dtar->id, IDWALK_NOP);
+ FOREACH_CALLBACK_INVOKE_ID(data, dtar->id, IDWALK_CB_NOP);
}
DRIVER_TARGETS_LOOPER_END
}
}
- FOREACH_CALLBACK_INVOKE(data, adt->action, IDWALK_USER);
- FOREACH_CALLBACK_INVOKE(data, adt->tmpact, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, adt->action, IDWALK_CB_USER);
+ FOREACH_CALLBACK_INVOKE(data, adt->tmpact, IDWALK_CB_USER);
for (nla_track = adt->nla_tracks.first; nla_track; nla_track = nla_track->next) {
for (nla_strip = nla_track->strips.first; nla_strip; nla_strip = nla_strip->next) {
@@ -249,23 +251,28 @@ static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *
static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex)
{
- FOREACH_CALLBACK_INVOKE(data, mtex->object, IDWALK_NOP);
- FOREACH_CALLBACK_INVOKE(data, mtex->tex, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, mtex->object, IDWALK_CB_NOP);
+ FOREACH_CALLBACK_INVOKE(data, mtex->tex, IDWALK_CB_USER);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint)
{
- FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_USER);
- FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_USER);
+ FOREACH_CALLBACK_INVOKE(data, paint->brush, IDWALK_CB_USER);
+ FOREACH_CALLBACK_INVOKE(data, paint->palette, IDWALK_CB_USER);
FOREACH_FINALIZE_VOID;
}
static void library_foreach_ID_as_subdata_link(
- ID *id, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
+ ID **id_pp, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
{
+ /* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */
+ ID *id = *id_pp;
+ FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pp, IDWALK_CB_PRIVATE);
+ BLI_assert(id == *id_pp);
+
if (flag & IDWALK_RECURSE) {
/* Defer handling into main loop, recursively calling BKE_library_foreach_ID_link in IDWALK_RECURSE case is
* troublesome, see T49553. */
@@ -275,8 +282,10 @@ static void library_foreach_ID_as_subdata_link(
}
}
else {
- BKE_library_foreach_ID_link(id, callback, user_data, flag);
+ BKE_library_foreach_ID_link(NULL, id, callback, user_data, flag);
}
+
+ FOREACH_FINALIZE_VOID;
}
/**
@@ -284,7 +293,7 @@ static void library_foreach_ID_as_subdata_link(
*
* \note: May be extended to be recursive in the future.
*/
-void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
+void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
{
LibraryForeachIDData data;
int i;
@@ -312,9 +321,21 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
#define CALLBACK_INVOKE(check_id_super, cb_flag) \
FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag)
- do {
+ for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) {
data.self_id = id;
- data.cd_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_INDIRECT_USAGE : 0;
+ data.cb_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_CB_INDIRECT_USAGE : 0;
+
+ if (bmain != NULL && bmain->relations != NULL && (flag & IDWALK_READONLY)) {
+ /* Note that this is minor optimization, even in worst cases (like id being an object with lots of
+ * drivers and constraints and modifiers, or material etc. with huge node tree),
+ * but we might as well use it (Main->relations is always assumed valid, it's responsability of code
+ * creating it to free it, especially if/when it starts modifying Main database). */
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id);
+ for (; entry != NULL; entry = entry->next) {
+ FOREACH_CALLBACK_INVOKE_ID_PP(&data, entry->id_pointer, entry->usage_flag);
+ }
+ continue;
+ }
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
@@ -325,7 +346,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_LI:
{
Library *lib = (Library *) id;
- CALLBACK_INVOKE(lib->parent, IDWALK_NOP);
+ CALLBACK_INVOKE(lib->parent, IDWALK_CB_NOP);
break;
}
case ID_SCE:
@@ -335,39 +356,39 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
SceneRenderLayer *srl;
Base *base;
- CALLBACK_INVOKE(scene->camera, IDWALK_NOP);
- CALLBACK_INVOKE(scene->world, IDWALK_USER);
- CALLBACK_INVOKE(scene->set, IDWALK_NOP);
- CALLBACK_INVOKE(scene->clip, IDWALK_USER);
+ CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(scene->world, IDWALK_CB_USER);
+ CALLBACK_INVOKE(scene->set, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(scene->clip, IDWALK_CB_USER);
if (scene->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)scene->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&scene->nodetree, callback, user_data, flag, &data);
}
/* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later,
* since basact is just a pointer to one of those items. */
- CALLBACK_INVOKE(scene->obedit, IDWALK_NOP);
+ CALLBACK_INVOKE(scene->obedit, IDWALK_CB_NOP);
for (srl = scene->r.layers.first; srl; srl = srl->next) {
FreestyleModuleConfig *fmc;
FreestyleLineSet *fls;
if (srl->mat_override) {
- CALLBACK_INVOKE(srl->mat_override, IDWALK_USER);
+ CALLBACK_INVOKE(srl->mat_override, IDWALK_CB_USER);
}
if (srl->light_override) {
- CALLBACK_INVOKE(srl->light_override, IDWALK_USER);
+ CALLBACK_INVOKE(srl->light_override, IDWALK_CB_USER);
}
for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
if (fmc->script) {
- CALLBACK_INVOKE(fmc->script, IDWALK_NOP);
+ CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP);
}
}
for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
if (fls->group) {
- CALLBACK_INVOKE(fls->group, IDWALK_USER);
+ CALLBACK_INVOKE(fls->group, IDWALK_CB_USER);
}
if (fls->linestyle) {
- CALLBACK_INVOKE(fls->linestyle, IDWALK_USER);
+ CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER);
}
}
}
@@ -376,38 +397,39 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Sequence *seq;
SEQP_BEGIN(scene->ed, seq)
{
- CALLBACK_INVOKE(seq->scene, IDWALK_NOP);
- CALLBACK_INVOKE(seq->scene_camera, IDWALK_NOP);
- CALLBACK_INVOKE(seq->clip, IDWALK_USER);
- CALLBACK_INVOKE(seq->mask, IDWALK_USER);
- CALLBACK_INVOKE(seq->sound, IDWALK_USER);
+ CALLBACK_INVOKE(seq->scene, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(seq->scene_camera, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER);
+ CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER);
+ CALLBACK_INVOKE(seq->sound, IDWALK_CB_USER);
for (SequenceModifierData *smd = seq->modifiers.first; smd; smd = smd->next) {
- CALLBACK_INVOKE(smd->mask_id, IDWALK_USER);
+ CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER);
}
}
SEQ_END
}
- CALLBACK_INVOKE(scene->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
for (base = scene->base.first; base; base = base->next) {
- CALLBACK_INVOKE(base->object, IDWALK_USER);
+ CALLBACK_INVOKE(base->object, IDWALK_CB_USER);
}
for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) {
- CALLBACK_INVOKE(marker->camera, IDWALK_NOP);
+ CALLBACK_INVOKE(marker->camera, IDWALK_CB_NOP);
}
if (toolsett) {
- CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_CB_NOP);
+
+ CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(toolsett->particle.object, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_CB_NOP);
- CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_NOP);
- CALLBACK_INVOKE(toolsett->particle.object, IDWALK_NOP);
- CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_NOP);
library_foreach_paint(&data, &toolsett->imapaint.paint);
- CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_USER);
- CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_USER);
- CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_USER);
+ CALLBACK_INVOKE(toolsett->imapaint.stencil, IDWALK_CB_USER);
+ CALLBACK_INVOKE(toolsett->imapaint.clone, IDWALK_CB_USER);
+ CALLBACK_INVOKE(toolsett->imapaint.canvas, IDWALK_CB_USER);
if (toolsett->vpaint) {
library_foreach_paint(&data, &toolsett->vpaint->paint);
@@ -417,7 +439,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (toolsett->sculpt) {
library_foreach_paint(&data, &toolsett->sculpt->paint);
- CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_NOP);
+ CALLBACK_INVOKE(toolsett->sculpt->gravity_object, IDWALK_CB_NOP);
}
if (toolsett->uvsculpt) {
library_foreach_paint(&data, &toolsett->uvsculpt->paint);
@@ -428,7 +450,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
BKE_rigidbody_world_id_loop(scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, &data);
}
- CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_NOP);
+ CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_CB_NOP);
break;
}
@@ -439,75 +461,75 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
ParticleSystem *psys;
/* 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;
+ const int data_cb_flag = data.cb_flag;
+ const int proxy_cb_flag = (object->proxy || object->proxy_group) ? IDWALK_CB_INDIRECT_USAGE : 0;
/* object data special case */
- data.cd_flag |= proxy_cd_flag;
+ data.cb_flag |= proxy_cb_flag;
if (object->type == OB_EMPTY) {
/* empty can have NULL or Image */
- CALLBACK_INVOKE_ID(object->data, IDWALK_USER);
+ CALLBACK_INVOKE_ID(object->data, IDWALK_CB_USER);
}
else {
/* when set, this can't be NULL */
if (object->data) {
- CALLBACK_INVOKE_ID(object->data, IDWALK_USER | IDWALK_NEVER_NULL);
+ CALLBACK_INVOKE_ID(object->data, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
}
}
- data.cd_flag = data_cd_flag;
+ data.cb_flag = data_cb_flag;
- CALLBACK_INVOKE(object->parent, IDWALK_NOP);
- CALLBACK_INVOKE(object->track, IDWALK_NOP);
+ CALLBACK_INVOKE(object->parent, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(object->track, IDWALK_CB_NOP);
/* object->proxy is refcounted, but not object->proxy_group... *sigh* */
- CALLBACK_INVOKE(object->proxy, IDWALK_USER);
- CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP);
+ CALLBACK_INVOKE(object->proxy, IDWALK_CB_USER);
+ CALLBACK_INVOKE(object->proxy_group, IDWALK_CB_NOP);
/* Special case!
* Since this field is set/owned by 'user' of this ID (and not ID itself), it is only indirect usage
* if proxy object is linked... Twisted. */
if (object->proxy_from) {
- data.cd_flag = ID_IS_LINKED_DATABLOCK(object->proxy_from) ? IDWALK_INDIRECT_USAGE : 0;
+ data.cb_flag = ID_IS_LINKED_DATABLOCK(object->proxy_from) ? IDWALK_CB_INDIRECT_USAGE : 0;
}
- CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP);
- data.cd_flag = data_cd_flag;
+ CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_NOP);
+ data.cb_flag = data_cb_flag;
- CALLBACK_INVOKE(object->poselib, IDWALK_USER);
+ CALLBACK_INVOKE(object->poselib, IDWALK_CB_USER);
- data.cd_flag |= proxy_cd_flag;
+ data.cb_flag |= proxy_cb_flag;
for (i = 0; i < object->totcol; i++) {
- CALLBACK_INVOKE(object->mat[i], IDWALK_USER);
+ CALLBACK_INVOKE(object->mat[i], IDWALK_CB_USER);
}
- data.cd_flag = data_cd_flag;
+ data.cb_flag = data_cb_flag;
- CALLBACK_INVOKE(object->gpd, IDWALK_USER);
- CALLBACK_INVOKE(object->dup_group, IDWALK_USER);
+ CALLBACK_INVOKE(object->gpd, IDWALK_CB_USER);
+ CALLBACK_INVOKE(object->dup_group, IDWALK_CB_USER);
if (object->pd) {
- CALLBACK_INVOKE(object->pd->tex, IDWALK_USER);
- CALLBACK_INVOKE(object->pd->f_source, IDWALK_NOP);
+ CALLBACK_INVOKE(object->pd->tex, IDWALK_CB_USER);
+ CALLBACK_INVOKE(object->pd->f_source, IDWALK_CB_NOP);
}
/* Note that ob->effect is deprecated, so no need to handle it here. */
if (object->pose) {
bPoseChannel *pchan;
- data.cd_flag |= proxy_cd_flag;
+ data.cb_flag |= proxy_cb_flag;
for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) {
- CALLBACK_INVOKE(pchan->custom, IDWALK_USER);
+ CALLBACK_INVOKE(pchan->custom, IDWALK_CB_USER);
BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data);
}
- data.cd_flag = data_cd_flag;
+ data.cb_flag = data_cb_flag;
}
if (object->rigidbody_constraint) {
- CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_NOP);
- CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_NOP);
+ CALLBACK_INVOKE(object->rigidbody_constraint->ob1, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(object->rigidbody_constraint->ob2, IDWALK_CB_NOP);
}
if (object->lodlevels.first) {
LodLevel *level;
for (level = object->lodlevels.first; level; level = level->next) {
- CALLBACK_INVOKE(level->source, IDWALK_NOP);
+ CALLBACK_INVOKE(level->source, IDWALK_CB_NOP);
}
}
@@ -519,10 +541,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (object->soft) {
- CALLBACK_INVOKE(object->soft->collision_group, IDWALK_NOP);
+ CALLBACK_INVOKE(object->soft->collision_group, IDWALK_CB_NOP);
if (object->soft->effector_weights) {
- CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_NOP);
+ CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_CB_NOP);
}
}
@@ -535,10 +557,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_ME:
{
Mesh *mesh = (Mesh *) id;
- CALLBACK_INVOKE(mesh->texcomesh, IDWALK_USER);
- CALLBACK_INVOKE(mesh->key, IDWALK_USER);
+ CALLBACK_INVOKE(mesh->texcomesh, IDWALK_CB_USER);
+ CALLBACK_INVOKE(mesh->key, IDWALK_CB_USER);
for (i = 0; i < mesh->totcol; i++) {
- CALLBACK_INVOKE(mesh->mat[i], IDWALK_USER);
+ CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER);
}
/* XXX Really not happy with this - probably texface should rather use some kind of
@@ -550,7 +572,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
MTexPoly *txface = (MTexPoly *)mesh->pdata.layers[i].data;
for (int j = 0; j < mesh->totpoly; j++, txface++) {
- CALLBACK_INVOKE(txface->tpage, IDWALK_USER_ONE);
+ CALLBACK_INVOKE(txface->tpage, IDWALK_CB_USER_ONE);
}
}
}
@@ -560,7 +582,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
MTFace *tface = (MTFace *)mesh->fdata.layers[i].data;
for (int j = 0; j < mesh->totface; j++, tface++) {
- CALLBACK_INVOKE(tface->tpage, IDWALK_USER_ONE);
+ CALLBACK_INVOKE(tface->tpage, IDWALK_CB_USER_ONE);
}
}
}
@@ -571,17 +593,17 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_CU:
{
Curve *curve = (Curve *) id;
- CALLBACK_INVOKE(curve->bevobj, IDWALK_NOP);
- CALLBACK_INVOKE(curve->taperobj, IDWALK_NOP);
- CALLBACK_INVOKE(curve->textoncurve, IDWALK_NOP);
- CALLBACK_INVOKE(curve->key, IDWALK_USER);
+ CALLBACK_INVOKE(curve->bevobj, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(curve->taperobj, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(curve->textoncurve, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(curve->key, IDWALK_CB_USER);
for (i = 0; i < curve->totcol; i++) {
- CALLBACK_INVOKE(curve->mat[i], IDWALK_USER);
+ CALLBACK_INVOKE(curve->mat[i], IDWALK_CB_USER);
}
- CALLBACK_INVOKE(curve->vfont, IDWALK_USER);
- CALLBACK_INVOKE(curve->vfontb, IDWALK_USER);
- CALLBACK_INVOKE(curve->vfonti, IDWALK_USER);
- CALLBACK_INVOKE(curve->vfontbi, IDWALK_USER);
+ CALLBACK_INVOKE(curve->vfont, IDWALK_CB_USER);
+ CALLBACK_INVOKE(curve->vfontb, IDWALK_CB_USER);
+ CALLBACK_INVOKE(curve->vfonti, IDWALK_CB_USER);
+ CALLBACK_INVOKE(curve->vfontbi, IDWALK_CB_USER);
break;
}
@@ -589,7 +611,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
MetaBall *metaball = (MetaBall *) id;
for (i = 0; i < metaball->totcol; i++) {
- CALLBACK_INVOKE(metaball->mat[i], IDWALK_USER);
+ CALLBACK_INVOKE(metaball->mat[i], IDWALK_CB_USER);
}
break;
}
@@ -604,9 +626,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (material->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)material->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data);
}
- CALLBACK_INVOKE(material->group, IDWALK_USER);
+ CALLBACK_INVOKE(material->group, IDWALK_CB_USER);
break;
}
@@ -615,26 +637,26 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Tex *texture = (Tex *) id;
if (texture->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)texture->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&texture->nodetree, callback, user_data, flag, &data);
}
- CALLBACK_INVOKE(texture->ima, IDWALK_USER);
+ CALLBACK_INVOKE(texture->ima, IDWALK_CB_USER);
if (texture->env) {
- CALLBACK_INVOKE(texture->env->object, IDWALK_NOP);
- CALLBACK_INVOKE(texture->env->ima, IDWALK_USER);
+ CALLBACK_INVOKE(texture->env->object, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(texture->env->ima, IDWALK_CB_USER);
}
if (texture->pd)
- CALLBACK_INVOKE(texture->pd->object, IDWALK_NOP);
+ CALLBACK_INVOKE(texture->pd->object, IDWALK_CB_NOP);
if (texture->vd)
- CALLBACK_INVOKE(texture->vd->object, IDWALK_NOP);
+ CALLBACK_INVOKE(texture->vd->object, IDWALK_CB_NOP);
if (texture->ot)
- CALLBACK_INVOKE(texture->ot->object, IDWALK_NOP);
+ CALLBACK_INVOKE(texture->ot->object, IDWALK_CB_NOP);
break;
}
case ID_LT:
{
Lattice *lattice = (Lattice *) id;
- CALLBACK_INVOKE(lattice->key, IDWALK_USER);
+ CALLBACK_INVOKE(lattice->key, IDWALK_CB_USER);
break;
}
@@ -648,7 +670,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (lamp->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)lamp->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&lamp->nodetree, callback, user_data, flag, &data);
}
break;
}
@@ -656,7 +678,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_CA:
{
Camera *camera = (Camera *) id;
- CALLBACK_INVOKE(camera->dof_ob, IDWALK_NOP);
+ CALLBACK_INVOKE(camera->dof_ob, IDWALK_CB_NOP);
break;
}
@@ -667,14 +689,14 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
* (see also foreach_libblock_id_users_callback).
*/
Key *key = (Key *) id;
- CALLBACK_INVOKE_ID(key->from, IDWALK_NOP);
+ CALLBACK_INVOKE_ID(key->from, IDWALK_CB_NOP);
break;
}
case ID_SCR:
{
bScreen *screen = (bScreen *) id;
- CALLBACK_INVOKE(screen->scene, IDWALK_USER_ONE);
+ CALLBACK_INVOKE(screen->scene, IDWALK_CB_USER_ONE);
break;
}
@@ -688,7 +710,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (world->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)world->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&world->nodetree, callback, user_data, flag, &data);
}
break;
}
@@ -696,7 +718,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_SPK:
{
Speaker *speaker = (Speaker *) id;
- CALLBACK_INVOKE(speaker->sound, IDWALK_USER);
+ CALLBACK_INVOKE(speaker->sound, IDWALK_CB_USER);
break;
}
@@ -705,7 +727,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
Group *group = (Group *) id;
GroupObject *gob;
for (gob = group->gobject.first; gob; gob = gob->next) {
- CALLBACK_INVOKE(gob->ob, IDWALK_USER_ONE);
+ CALLBACK_INVOKE(gob->ob, IDWALK_CB_USER_ONE);
}
break;
}
@@ -714,9 +736,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
{
bNodeTree *ntree = (bNodeTree *) id;
bNode *node;
- CALLBACK_INVOKE(ntree->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER);
for (node = ntree->nodes.first; node; node = node->next) {
- CALLBACK_INVOKE_ID(node->id, IDWALK_USER);
+ CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER);
}
break;
}
@@ -724,9 +746,9 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_BR:
{
Brush *brush = (Brush *) id;
- CALLBACK_INVOKE(brush->toggle_brush, IDWALK_NOP);
- CALLBACK_INVOKE(brush->clone.image, IDWALK_NOP);
- CALLBACK_INVOKE(brush->paint_curve, IDWALK_USER);
+ CALLBACK_INVOKE(brush->toggle_brush, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(brush->clone.image, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(brush->paint_curve, IDWALK_CB_USER);
library_foreach_mtex(&data, &brush->mtex);
library_foreach_mtex(&data, &brush->mask_mtex);
break;
@@ -735,10 +757,10 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
case ID_PA:
{
ParticleSettings *psett = (ParticleSettings *) id;
- CALLBACK_INVOKE(psett->dup_group, IDWALK_NOP);
- CALLBACK_INVOKE(psett->dup_ob, IDWALK_NOP);
- CALLBACK_INVOKE(psett->bb_ob, IDWALK_NOP);
- CALLBACK_INVOKE(psett->collision_group, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->dup_group, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(psett->dup_ob, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(psett->bb_ob, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(psett->collision_group, IDWALK_CB_NOP);
for (i = 0; i < MAX_MTEX; i++) {
if (psett->mtex[i]) {
@@ -747,16 +769,16 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (psett->effector_weights) {
- CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->effector_weights->group, IDWALK_CB_NOP);
}
if (psett->pd) {
- CALLBACK_INVOKE(psett->pd->tex, IDWALK_USER);
- CALLBACK_INVOKE(psett->pd->f_source, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->pd->tex, IDWALK_CB_USER);
+ CALLBACK_INVOKE(psett->pd->f_source, IDWALK_CB_NOP);
}
if (psett->pd2) {
- CALLBACK_INVOKE(psett->pd2->tex, IDWALK_USER);
- CALLBACK_INVOKE(psett->pd2->f_source, IDWALK_NOP);
+ CALLBACK_INVOKE(psett->pd2->tex, IDWALK_CB_USER);
+ CALLBACK_INVOKE(psett->pd2->f_source, IDWALK_CB_NOP);
}
if (psett->boids) {
@@ -767,11 +789,11 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
for (rule = state->rules.first; rule; rule = rule->next) {
if (rule->type == eBoidRuleType_Avoid) {
BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
- CALLBACK_INVOKE(gabr->ob, IDWALK_NOP);
+ CALLBACK_INVOKE(gabr->ob, IDWALK_CB_NOP);
}
else if (rule->type == eBoidRuleType_FollowLeader) {
BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
- CALLBACK_INVOKE(flbr->ob, IDWALK_NOP);
+ CALLBACK_INVOKE(flbr->ob, IDWALK_CB_NOP);
}
}
}
@@ -787,19 +809,19 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
MovieTrackingTrack *track;
MovieTrackingPlaneTrack *plane_track;
- CALLBACK_INVOKE(clip->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(clip->gpd, IDWALK_CB_USER);
for (track = tracking->tracks.first; track; track = track->next) {
- CALLBACK_INVOKE(track->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(track->gpd, IDWALK_CB_USER);
}
for (object = tracking->objects.first; object; object = object->next) {
for (track = object->tracks.first; track; track = track->next) {
- CALLBACK_INVOKE(track->gpd, IDWALK_USER);
+ CALLBACK_INVOKE(track->gpd, IDWALK_CB_USER);
}
}
for (plane_track = tracking->plane_tracks.first; plane_track; plane_track = plane_track->next) {
- CALLBACK_INVOKE(plane_track->image, IDWALK_USER);
+ CALLBACK_INVOKE(plane_track->image, IDWALK_CB_USER);
}
break;
}
@@ -814,7 +836,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
for (mask_spline = mask_layer->splines.first; mask_spline; mask_spline = mask_spline->next) {
for (i = 0; i < mask_spline->tot_point; i++) {
MaskSplinePoint *point = &mask_spline->points[i];
- CALLBACK_INVOKE_ID(point->parent.id, IDWALK_USER);
+ CALLBACK_INVOKE_ID(point->parent.id, IDWALK_CB_USER);
}
}
}
@@ -832,14 +854,14 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
}
if (linestyle->nodetree) {
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
- library_foreach_ID_as_subdata_link((ID *)linestyle->nodetree, callback, user_data, flag, &data);
+ library_foreach_ID_as_subdata_link((ID **)&linestyle->nodetree, callback, user_data, flag, &data);
}
for (lsm = linestyle->color_modifiers.first; lsm; lsm = lsm->next) {
if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
LineStyleColorModifier_DistanceFromObject *p = (LineStyleColorModifier_DistanceFromObject *)lsm;
if (p->target) {
- CALLBACK_INVOKE(p->target, IDWALK_NOP);
+ CALLBACK_INVOKE(p->target, IDWALK_CB_NOP);
}
}
}
@@ -847,7 +869,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
LineStyleAlphaModifier_DistanceFromObject *p = (LineStyleAlphaModifier_DistanceFromObject *)lsm;
if (p->target) {
- CALLBACK_INVOKE(p->target, IDWALK_NOP);
+ CALLBACK_INVOKE(p->target, IDWALK_CB_NOP);
}
}
}
@@ -855,7 +877,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
if (lsm->type == LS_MODIFIER_DISTANCE_FROM_OBJECT) {
LineStyleThicknessModifier_DistanceFromObject *p = (LineStyleThicknessModifier_DistanceFromObject *)lsm;
if (p->target) {
- CALLBACK_INVOKE(p->target, IDWALK_NOP);
+ CALLBACK_INVOKE(p->target, IDWALK_CB_NOP);
}
}
}
@@ -866,7 +888,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
bAction *act = (bAction *) id;
for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
- CALLBACK_INVOKE(marker->camera, IDWALK_NOP);
+ CALLBACK_INVOKE(marker->camera, IDWALK_CB_NOP);
}
break;
}
@@ -889,7 +911,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u
break;
}
- } while ((id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL));
+ }
FOREACH_FINALIZE:
if (data.ids_handled) {
@@ -907,13 +929,13 @@ FOREACH_FINALIZE:
/**
* re-usable function, use when replacing ID's
*/
-void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cd_flag)
+void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
{
- if (cd_flag & IDWALK_USER) {
+ if (cb_flag & IDWALK_CB_USER) {
id_us_min(id_src);
id_us_plus(id_dst);
}
- else if (cd_flag & IDWALK_USER_ONE) {
+ else if (cb_flag & IDWALK_CB_USER_ONE) {
id_us_ensure_real(id_dst);
}
}
@@ -943,7 +965,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id
/* 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
+ ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_PA, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC
/* + constraints, modifiers and game logic ID types... */);
#else
return true;
@@ -1047,7 +1069,7 @@ static int foreach_libblock_id_users_callback(void *user_data, ID *self_id, ID *
(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
- if (cb_flag & IDWALK_INDIRECT_USAGE) {
+ if (cb_flag & IDWALK_CB_INDIRECT_USAGE) {
iter->count_indirect++;
}
else {
@@ -1078,7 +1100,7 @@ int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
iter.curr_id = id_user;
iter.count_direct = iter.count_indirect = 0;
- BKE_library_foreach_ID_link(iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_NOP);
+ BKE_library_foreach_ID_link(NULL, iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_READONLY);
return iter.count_direct + iter.count_indirect;
}
@@ -1107,7 +1129,7 @@ static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
}
iter.curr_id = id_curr;
BKE_library_foreach_ID_link(
- id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP);
+ bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY);
is_defined = ((check_linked ? iter.count_indirect : iter.count_direct) != 0);
}
@@ -1158,7 +1180,7 @@ void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, boo
continue;
}
iter.curr_id = id_curr;
- BKE_library_foreach_ID_link(id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_NOP);
+ BKE_library_foreach_ID_link(bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY);
is_defined = (iter.count_direct != 0 && iter.count_indirect != 0);
}
@@ -1235,7 +1257,8 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
/* Unused ID (so far), no need to check it further. */
continue;
}
- BKE_library_foreach_ID_link(id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_NOP);
+ BKE_library_foreach_ID_link(
+ bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
}
}
}
@@ -1262,7 +1285,8 @@ void BKE_library_indirectly_used_data_tag_clear(Main *bmain)
/* Local or non-indirectly-used ID (so far), no need to check it further. */
continue;
}
- BKE_library_foreach_ID_link(id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_NOP);
+ BKE_library_foreach_ID_link(
+ bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
}
}
}
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index d7d566a9ec0..a408b498f18 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -158,6 +158,10 @@ enum {
static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id_p, int cb_flag)
{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
IDRemap *id_remap_data = user_data;
ID *old_id = id_remap_data->old_id;
ID *new_id = id_remap_data->new_id;
@@ -169,14 +173,14 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
}
if (*id_p && (*id_p == old_id)) {
- const bool is_indirect = (cb_flag & IDWALK_INDIRECT_USAGE) != 0;
+ const bool is_indirect = (cb_flag & IDWALK_CB_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_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
- const bool is_never_null = ((cb_flag & IDWALK_NEVER_NULL) && (new_id == NULL) &&
+ const bool is_never_null = ((cb_flag & IDWALK_CB_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;
@@ -185,7 +189,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
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)) {
+ if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_CB_NEVER_NULL)) {
id->tag |= LIB_TAG_DOIT;
}
@@ -203,10 +207,10 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
else {
BLI_assert(0);
}
- if (cb_flag & IDWALK_USER) {
+ if (cb_flag & IDWALK_CB_USER) {
id_remap_data->skipped_refcounted++;
}
- else if (cb_flag & IDWALK_USER_ONE) {
+ else if (cb_flag & IDWALK_CB_USER_ONE) {
/* No need to count number of times this happens, just a flag is enough. */
id_remap_data->status |= ID_REMAP_IS_USER_ONE_SKIPPED;
}
@@ -216,13 +220,13 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
*id_p = new_id;
DAG_id_tag_update_ex(id_remap_data->bmain, id_self, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
- if (cb_flag & IDWALK_USER) {
+ if (cb_flag & IDWALK_CB_USER) {
id_us_min(old_id);
/* We do not want to handle LIB_TAG_INDIRECT/LIB_TAG_EXTERN here. */
if (new_id)
new_id->us++;
}
- else if (cb_flag & IDWALK_USER_ONE) {
+ else if (cb_flag & IDWALK_CB_USER_ONE) {
id_us_ensure_real(new_id);
/* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET) are assumed to be set as needed,
* that extra user is processed in final handling... */
@@ -434,7 +438,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
#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);
+ BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
}
else {
i = set_listbasepointers(bmain, lb_array);
@@ -456,7 +460,7 @@ ATTR_NONNULL(1) static void libblock_remap_data(
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);
+ NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP);
}
}
}
@@ -685,13 +689,17 @@ void BKE_libblock_relink_ex(
}
}
-static int id_relink_to_newid_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cd_flag)
+static int id_relink_to_newid_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cb_flag)
{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
ID *id = *id_pointer;
if (id) {
/* See: NEW_ID macro */
if (id->newid) {
- BKE_library_update_ID_link_user(id->newid, id, cd_flag);
+ BKE_library_update_ID_link_user(id->newid, id, cb_flag);
*id_pointer = id->newid;
}
else if (id->tag & LIB_TAG_NEW) {
@@ -711,7 +719,7 @@ void BKE_libblock_relink_to_newid(ID *id)
if (ID_IS_LINKED_DATABLOCK(id))
return;
- BKE_library_foreach_ID_link(id, id_relink_to_newid_looper, NULL, 0);
+ BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0);
}
void BKE_libblock_free_data(Main *UNUSED(bmain), ID *id)
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index e93bfcdda83..ff8be5892e9 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1204,7 +1204,7 @@ void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, con
if (lib_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &ob->id);
- BKE_id_expand_local(&ob->id);
+ BKE_id_expand_local(bmain, &ob->id);
if (clear_proxy) {
if (ob->proxy_from != NULL) {
ob->proxy_from->proxy = NULL;
@@ -2236,18 +2236,6 @@ void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3],
}
}
-void BKE_boundbox_scale(struct BoundBox *bb_dst, const struct BoundBox *bb_src, float scale)
-{
- float cent[3];
- BKE_boundbox_calc_center_aabb(bb_src, cent);
-
- for (int i = 0; i < ARRAY_SIZE(bb_dst->vec); i++) {
- bb_dst->vec[i][0] = ((bb_src->vec[i][0] - cent[0]) * scale) + cent[0];
- bb_dst->vec[i][1] = ((bb_src->vec[i][1] - cent[1]) * scale) + cent[1];
- bb_dst->vec[i][2] = ((bb_src->vec[i][2] - cent[2]) * scale) + cent[2];
- }
-}
-
/**
* Returns a BBox which each dimensions are at least epsilon.
* \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range.
@@ -2816,45 +2804,6 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc,
return 1;
}
-/*
- * Test a bounding box for ray intersection
- * assumes the ray is already local to the boundbox space
- */
-bool BKE_boundbox_ray_hit_check(
- const struct BoundBox *bb,
- const float ray_start[3], const float ray_normal[3],
- float *r_lambda)
-{
- const int triangle_indexes[12][3] = {
- {0, 1, 2}, {0, 2, 3},
- {3, 2, 6}, {3, 6, 7},
- {1, 2, 6}, {1, 6, 5},
- {5, 6, 7}, {4, 5, 7},
- {0, 3, 7}, {0, 4, 7},
- {0, 1, 5}, {0, 4, 5}};
-
- bool result = false;
- int i;
-
- for (i = 0; i < 12 && (!result || r_lambda); i++) {
- float lambda;
- int v1, v2, v3;
- v1 = triangle_indexes[i][0];
- v2 = triangle_indexes[i][1];
- v3 = triangle_indexes[i][2];
- if (isect_ray_tri_v3(ray_start, ray_normal, bb->vec[v1], bb->vec[v2], bb->vec[v3], &lambda, NULL) &&
- (!r_lambda || *r_lambda > lambda))
- {
- result = true;
- if (r_lambda) {
- *r_lambda = lambda;
- }
- }
- }
-
- return result;
-}
-
static int pc_cmp(const void *a, const void *b)
{
const LinkData *ad = a, *bd = b;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index ee435051151..943dc781246 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4328,12 +4328,12 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
{
ParticleTarget *pt;
- func(psys, (ID **)&psys->part, userdata, IDWALK_USER | IDWALK_NEVER_NULL);
- func(psys, (ID **)&psys->target_ob, userdata, IDWALK_NOP);
- func(psys, (ID **)&psys->parent, userdata, IDWALK_NOP);
+ func(psys, (ID **)&psys->part, userdata, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
+ func(psys, (ID **)&psys->target_ob, userdata, IDWALK_CB_NOP);
+ func(psys, (ID **)&psys->parent, userdata, IDWALK_CB_NOP);
for (pt = psys->targets.first; pt; pt = pt->next) {
- func(psys, (ID **)&pt->ob, userdata, IDWALK_NOP);
+ func(psys, (ID **)&pt->ob, userdata, IDWALK_CB_NOP);
}
/* Even though psys->part should never be NULL, this can happen as an exception during deletion.
@@ -4343,7 +4343,7 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
int p;
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
- func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_NOP);
+ func(psys, (ID **)&pa->boid->ground, userdata, IDWALK_CB_NOP);
}
}
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 6f86c68dc07..73fe5ae6cb8 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -974,14 +974,14 @@ void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw)
void BKE_rigidbody_world_id_loop(RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata)
{
- func(rbw, (ID **)&rbw->group, userdata, IDWALK_NOP);
- func(rbw, (ID **)&rbw->constraints, userdata, IDWALK_NOP);
- func(rbw, (ID **)&rbw->effector_weights->group, userdata, IDWALK_NOP);
+ func(rbw, (ID **)&rbw->group, userdata, IDWALK_CB_NOP);
+ func(rbw, (ID **)&rbw->constraints, userdata, IDWALK_CB_NOP);
+ func(rbw, (ID **)&rbw->effector_weights->group, userdata, IDWALK_CB_NOP);
if (rbw->objects) {
int i;
for (i = 0; i < rbw->numbodies; i++) {
- func(rbw, (ID **)&rbw->objects[i], userdata, IDWALK_NOP);
+ func(rbw, (ID **)&rbw->objects[i], userdata, IDWALK_CB_NOP);
}
}
}
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index fa221348932..7920d8b5696 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -992,19 +992,19 @@ void BKE_sca_sensors_id_loop(ListBase *senslist, SCASensorIDFunc func, void *use
bSensor *sensor;
for (sensor = senslist->first; sensor; sensor = sensor->next) {
- func(sensor, (ID **)&sensor->ob, userdata, IDWALK_NOP);
+ func(sensor, (ID **)&sensor->ob, userdata, IDWALK_CB_NOP);
switch (sensor->type) {
case SENS_TOUCH: /* DEPRECATED */
{
bTouchSensor *ts = sensor->data;
- func(sensor, (ID **)&ts->ma, userdata, IDWALK_NOP);
+ func(sensor, (ID **)&ts->ma, userdata, IDWALK_CB_NOP);
break;
}
case SENS_MESSAGE:
{
bMessageSensor *ms = sensor->data;
- func(sensor, (ID **)&ms->fromObject, userdata, IDWALK_NOP);
+ func(sensor, (ID **)&ms->fromObject, userdata, IDWALK_CB_NOP);
break;
}
case SENS_ALWAYS:
@@ -1035,7 +1035,7 @@ void BKE_sca_controllers_id_loop(ListBase *contlist, SCAControllerIDFunc func, v
case CONT_PYTHON:
{
bPythonCont *pc = controller->data;
- func(controller, (ID **)&pc->text, userdata, IDWALK_NOP);
+ func(controller, (ID **)&pc->text, userdata, IDWALK_CB_NOP);
break;
}
case CONT_LOGIC_AND:
@@ -1056,89 +1056,89 @@ void BKE_sca_actuators_id_loop(ListBase *actlist, SCAActuatorIDFunc func, void *
bActuator *actuator;
for (actuator = actlist->first; actuator; actuator = actuator->next) {
- func(actuator, (ID **)&actuator->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&actuator->ob, userdata, IDWALK_CB_NOP);
switch (actuator->type) {
case ACT_ADD_OBJECT: /* DEPRECATED */
{
bAddObjectActuator *aoa = actuator->data;
- func(actuator, (ID **)&aoa->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&aoa->ob, userdata, IDWALK_CB_NOP);
break;
}
case ACT_ACTION:
{
bActionActuator *aa = actuator->data;
- func(actuator, (ID **)&aa->act, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&aa->act, userdata, IDWALK_CB_NOP);
break;
}
case ACT_SOUND:
{
bSoundActuator *sa = actuator->data;
- func(actuator, (ID **)&sa->sound, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&sa->sound, userdata, IDWALK_CB_NOP);
break;
}
case ACT_EDIT_OBJECT:
{
bEditObjectActuator *eoa = actuator->data;
- func(actuator, (ID **)&eoa->ob, userdata, IDWALK_NOP);
- func(actuator, (ID **)&eoa->me, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&eoa->ob, userdata, IDWALK_CB_NOP);
+ func(actuator, (ID **)&eoa->me, userdata, IDWALK_CB_NOP);
break;
}
case ACT_SCENE:
{
bSceneActuator *sa = actuator->data;
- func(actuator, (ID **)&sa->scene, userdata, IDWALK_NOP);
- func(actuator, (ID **)&sa->camera, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&sa->scene, userdata, IDWALK_CB_NOP);
+ func(actuator, (ID **)&sa->camera, userdata, IDWALK_CB_NOP);
break;
}
case ACT_PROPERTY:
{
bPropertyActuator *pa = actuator->data;
- func(actuator, (ID **)&pa->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&pa->ob, userdata, IDWALK_CB_NOP);
break;
}
case ACT_OBJECT:
{
bObjectActuator *oa = actuator->data;
- func(actuator, (ID **)&oa->reference, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&oa->reference, userdata, IDWALK_CB_NOP);
break;
}
case ACT_CAMERA:
{
bCameraActuator *ca = actuator->data;
- func(actuator, (ID **)&ca->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&ca->ob, userdata, IDWALK_CB_NOP);
break;
}
case ACT_MESSAGE:
{
bMessageActuator *ma = actuator->data;
- func(actuator, (ID **)&ma->toObject, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&ma->toObject, userdata, IDWALK_CB_NOP);
break;
}
case ACT_2DFILTER:
{
bTwoDFilterActuator *tdfa = actuator->data;
- func(actuator, (ID **)&tdfa->text, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&tdfa->text, userdata, IDWALK_CB_NOP);
break;
}
case ACT_PARENT:
{
bParentActuator *pa = actuator->data;
- func(actuator, (ID **)&pa->ob, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&pa->ob, userdata, IDWALK_CB_NOP);
break;
}
case ACT_ARMATURE:
{
bArmatureActuator *aa = actuator->data;
- func(actuator, (ID **)&aa->target, userdata, IDWALK_NOP);
- func(actuator, (ID **)&aa->subtarget, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&aa->target, userdata, IDWALK_CB_NOP);
+ func(actuator, (ID **)&aa->subtarget, userdata, IDWALK_CB_NOP);
break;
}
case ACT_STEERING:
{
bSteeringActuator *sa = actuator->data;
- func(actuator, (ID **)&sa->target, userdata, IDWALK_NOP);
- func(actuator, (ID **)&sa->navmesh, userdata, IDWALK_NOP);
+ func(actuator, (ID **)&sa->target, userdata, IDWALK_CB_NOP);
+ func(actuator, (ID **)&sa->navmesh, userdata, IDWALK_CB_NOP);
break;
}
/* Note: some types seems to be non-implemented? ACT_LAMP, ACT_MATERIAL... */
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index e3635be671f..4a85e859c16 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -293,6 +293,10 @@ void isect_ray_aabb_v3_precalc(
bool isect_ray_aabb_v3(
const struct IsectRayAABB_Precalc *data,
const float bb_min[3], const float bb_max[3], float *tmin);
+bool isect_ray_aabb_v3_simple(
+ const float orig[3], const float dir[3],
+ const float bb_min[3], const float bb_max[3],
+ float *tmin, float *tmax);
struct NearestRayToAABB_Precalc {
float ray_origin[3];
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 8f5d84dfa08..aeb6a550cd9 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2309,6 +2309,34 @@ bool isect_ray_aabb_v3(
return true;
}
+/*
+ * Test a bounding box (AABB) for ray intersection
+ * assumes the ray is already local to the boundbox space
+ */
+bool isect_ray_aabb_v3_simple(
+ const float orig[3], const float dir[3],
+ const float bb_min[3], const float bb_max[3],
+ float *tmin, float *tmax)
+{
+ double t[7];
+ float hit_dist[2];
+ t[1] = (double)(bb_min[0] - orig[0]) / dir[0];
+ t[2] = (double)(bb_max[0] - orig[0]) / dir[0];
+ t[3] = (double)(bb_min[1] - orig[1]) / dir[1];
+ t[4] = (double)(bb_max[1] - orig[1]) / dir[1];
+ t[5] = (double)(bb_min[2] - orig[2]) / dir[2];
+ t[6] = (double)(bb_max[2] - orig[2]) / dir[2];
+ hit_dist[0] = (float)fmax(fmax(fmin(t[1], t[2]), fmin(t[3], t[4])), fmin(t[5], t[6]));
+ hit_dist[1] = (float)fmin(fmin(fmax(t[1], t[2]), fmax(t[3], t[4])), fmax(t[5], t[6]));
+ if ((hit_dist[1] < 0 || hit_dist[0] > hit_dist[1]))
+ return false;
+ else {
+ if (tmin) *tmin = hit_dist[0];
+ if (tmax) *tmax = hit_dist[1];
+ return true;
+ }
+}
+
void dist_squared_ray_to_aabb_v3_precalc(
struct NearestRayToAABB_Precalc *data,
const float ray_origin[3], const float ray_direction[3])
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index b5dd1910f01..060d290df32 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4709,12 +4709,12 @@ static void direct_link_latt(FileData *fd, Lattice *lt)
/* ************ READ OBJECT ***************** */
static void lib_link_modifiers__linkModifiers(
- void *userData, Object *ob, ID **idpoin, int cd_flag)
+ void *userData, Object *ob, ID **idpoin, int cb_flag)
{
FileData *fd = userData;
*idpoin = newlibadr(fd, ob->id.lib, *idpoin);
- if (*idpoin != NULL && (cd_flag & IDWALK_USER) != 0) {
+ if (*idpoin != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
id_us_plus_no_lib(*idpoin);
}
}
@@ -9308,7 +9308,7 @@ static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
}
static void expand_object_expandModifiers(
- void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag))
+ void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cb_flag))
{
struct { FileData *fd; Main *mainvar; } *data= userData;
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 477382d8c5b..3bd84c5f5cf 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -216,6 +216,10 @@ static void anim_change_prop_name(FCurve *fcu,
static void do_version_hue_sat_node(bNodeTree *ntree, bNode *node)
{
+ if (node->storage == NULL) {
+ return;
+ }
+
/* Make sure new sockets are properly created. */
node_verify_socket_templates(ntree, node);
/* Convert value from old storage to new sockets. */
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 4f5cf83f5ca..9c26ba83b44 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -69,17 +69,21 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce,
// write bone nodes
bArmature * armature = (bArmature *)ob_arm->data;
- ED_armature_to_edit(armature);
+ bool is_edited = armature->edbo != NULL;
- bArmature *arm = (bArmature *)ob_arm->data;
- for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
+ if (!is_edited)
+ ED_armature_to_edit(armature);
+
+ for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) {
// start from root bones
if (!bone->parent)
add_bone_node(bone, ob_arm, sce, se, child_objects);
}
- ED_armature_from_edit(armature);
- ED_armature_edit_free(armature);
+ if (!is_edited) {
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
+ }
}
void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 4b73dfa1ec3..9fea68fc941 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -121,7 +121,7 @@ struct BuilderWalkUserData {
static void modifier_walk(void *user_data,
struct Object * /*ob*/,
struct Object **obpoin,
- int /*cd_flag*/)
+ int /*cb_flag*/)
{
BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
if (*obpoin) {
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index c12a050e9ba..2f73eb6b71c 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -2223,7 +2223,7 @@ typedef struct tAnimFilterModifiersContext {
/* dependency walker callback for modifier dependencies */
-static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cd_flag))
+static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cb_flag))
{
tAnimFilterModifiersContext *afm = (tAnimFilterModifiersContext *)afm_ptr;
ID *owner_id = &ob->id;
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index d30022c01f8..b5fbe4ba586 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2133,7 +2133,7 @@ enum {
};
static int tag_localizable_looper(
- void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cd_flag))
+ void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int UNUSED(cb_flag))
{
if (*id_pointer) {
(*id_pointer)->tag &= ~LIB_TAG_DOIT;
@@ -2170,12 +2170,12 @@ static void tag_localizable_objects(bContext *C, const int mode)
*/
for (Object *object = bmain->object.first; object; object = object->id.next) {
if ((object->id.tag & LIB_TAG_DOIT) == 0) {
- BKE_library_foreach_ID_link(&object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
+ BKE_library_foreach_ID_link(NULL, &object->id, tag_localizable_looper, NULL, IDWALK_READONLY);
}
if (object->data) {
ID *data_id = (ID *) object->data;
if ((data_id->tag & LIB_TAG_DOIT) == 0) {
- BKE_library_foreach_ID_link(data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
+ BKE_library_foreach_ID_link(NULL, data_id, tag_localizable_looper, NULL, IDWALK_READONLY);
}
}
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index f8bb124e943..87ac54b2bd9 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -569,7 +569,9 @@ static void initSnappingMode(TransInfo *t)
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
(obedit == NULL) ) // Object Mode
{
- t->tsnap.modeSelect = SNAP_NOT_SELECTED;
+ /* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632)
+ * TODO: perform self snap in gpencil_strokes */
+ t->tsnap.modeSelect = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_ALL : SNAP_NOT_SELECTED;
}
else {
/* Grid if snap is not possible */
@@ -1214,7 +1216,7 @@ bool snapObjectsTransform(
t->tsnap.object_context,
t->scene->toolsettings->snap_mode,
&(const struct SnapObjectParams){
- .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect,
+ .snap_select = t->tsnap.modeSelect,
.use_object_edit_cage = (t->flag & T_EDIT) != 0,
},
mval, dist_px, NULL,
@@ -1304,7 +1306,7 @@ bool peelObjectsTransform(
t->tsnap.object_context,
mval,
&(const struct SnapObjectParams){
- .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect,
+ .snap_select = t->tsnap.modeSelect,
.use_object_edit_cage = (t->flag & T_EDIT) != 0,
},
use_peel_object,
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 02900d7022c..bed451a32d8 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -59,6 +59,24 @@
#include "transform.h"
+enum eViewProj {
+ VIEW_PROJ_NONE = -1,
+ VIEW_PROJ_ORTHO = 0,
+ VIEW_PROJ_PERSP = -1,
+};
+
+typedef struct SnapData {
+ short snap_to;
+ float mval[2];
+ float ray_origin[3];
+ float ray_start[3];
+ float ray_dir[3];
+ float pmat[4][4]; /* perspective matrix */
+ float win_half[2];/* win x and y */
+ enum eViewProj view_proj;
+ float depth_range[2];
+} SnapData;
+
typedef struct SnapObjectData {
enum {
SNAP_MESH = 1,
@@ -110,12 +128,6 @@ struct SnapObjectContext {
};
-enum eViewProj {
- VIEW_PROJ_NONE = -1,
- VIEW_PROJ_ORTHO = 0,
- VIEW_PROJ_PERSP = -1,
-};
-
static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
@@ -223,6 +235,12 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
/** \Common utilities
* \{ */
+MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
+{
+ float dvec[3];
+ sub_v3_v3v3(dvec, co, ray_start);
+ return dot_v3v3(dvec, ray_dir);
+}
/**
* Struct that kepts basic information about a BVHTree build from a editmesh.
@@ -232,60 +250,40 @@ typedef struct BVHTreeFromMeshType {
char type;
} BVHTreeFromMeshType;
-typedef struct PreDefProject {
- float pmat[4][4]; /* perspective matrix multiplied by object matrix */
- float win_half[2];
- float dist_px_sq;
-} PreDefProject;
-
-static void precalc_project(
- PreDefProject *projectdefs, const ARegion *ar,
- const float dist_px, float obmat[4][4])
-{
- float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat;
- if (obmat) {
- mul_m4_m4m4(projectdefs->pmat, pmat, obmat);
- }
- else {
- copy_m4_m4(projectdefs->pmat, pmat);
- }
- projectdefs->win_half[0] = ar->winx / 2;
- projectdefs->win_half[1] = ar->winy / 2;
- projectdefs->dist_px_sq = SQUARE(dist_px);
-}
-
/**
- * From a threshold (maximum distance to snap in pixels) returns:
+ * Generates a struct with the immutable parameters that will be used on all objects.
*
- * - The *real* distance (3D) if you are in orthographic-view.
- * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view.
+ * \param snap_to: Element to snap, Vertice, Edge or Face.
+ * \param view_proj: ORTHO or PERSP.
+ * Currently only works one at a time, but can eventually operate as flag.
+ *
+ * \param mval: Mouse coords.
+ * (When NULL, ray-casting is handled without any projection matrix correction.)
+ * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
+ * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
+ * \param ray_direction: Unit length direction of the ray.
+ * \param depth_range: distances of clipe plane min and clip plane max;
*/
-static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px)
-{
- const RegionView3D *rv3d = ar->regiondata;
- if (ar->winx >= ar->winy)
- return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0];
- else
- return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1];
-}
-
-static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index)
+static void snap_data_set(
+ SnapData *snapdata,
+ const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
+ const float mval[2], const float ray_origin[3], const float ray_start[3],
+ const float ray_direction[3], const float depth_range[2])
{
- switch (meshdata->type) {
- case SNAP_MESH:
- {
- BVHTreeFromMesh *data = meshdata->userdata;
- const MVert *vert = data->vert;
- return vert[index].co;
- }
- case SNAP_EDIT_MESH:
- {
- BVHTreeFromEditMesh *data = meshdata->userdata;
- BMVert *eve = BM_vert_at_index(data->em->bm, index);
- return eve->co;
- }
- }
- return NULL;
+ if (ar) {
+ copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
+ snapdata->win_half[0] = ar->winx / 2;
+ snapdata->win_half[1] = ar->winy / 2;
+ }
+ if (mval) {
+ copy_v2_v2(snapdata->mval, mval);
+ }
+ snapdata->snap_to = snap_to;
+ copy_v3_v3(snapdata->ray_origin, ray_origin);
+ copy_v3_v3(snapdata->ray_start, ray_start);
+ copy_v3_v3(snapdata->ray_dir, ray_direction);
+ snapdata->view_proj = view_proj;
+ copy_v2_v2(snapdata->depth_range, depth_range);
}
static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3])
@@ -336,87 +334,13 @@ static void get_edge_verts(
}
}
-#define V3_MUL_ELEM(a, b) \
- (a)[0] * (b)[0], \
- (a)[1] * (b)[1], \
- (a)[2] * (b)[2]
-
-static bool test_vert_dist(
- const float vco[3], const float ray_co[3], const float ray_dir[3],
- const float ray_depth_range[2], const float scale[3],
- /* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
- /* return args */
- float r_co[3])
-{
- const float vco_sc[3] = {V3_MUL_ELEM(vco, scale)};
- const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
- const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
-
- float depth, dist_sq;
- dist_sq = dist_squared_to_ray_v3(origin_sc, dir_sc, vco_sc, &depth);
-
- if (depth < ray_depth_range[0]) {
- return false;
- }
-
- if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
- *dist_to_ray_sq = dist_sq;
-
- copy_v3_v3(r_co, vco);
-
- *ray_depth = depth;
- return true;
- }
- return false;
-}
-
-static bool test_edge_dist(
- const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3],
- const float ray_depth_range[2], const float scale[3],
- /* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
- /* return args */
- float r_co[3])
-{
- const float v1_sc[3] = {V3_MUL_ELEM(v1, scale)};
- const float v2_sc[3] = {V3_MUL_ELEM(v2, scale)};
- const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
- const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
-
- float tmp_co[3], depth, dist_sq;
- dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth);
-
- if (depth < ray_depth_range[0]) {
- return false;
- }
-
- if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
- *dist_to_ray_sq = dist_sq;
-
- tmp_co[0] /= scale[0];
- tmp_co[1] /= scale[1];
- tmp_co[2] /= scale[2];
-
- copy_v3_v3(r_co, tmp_co);
-
- *ray_depth = depth;
- return true;
- }
- return false;
-}
-
-#undef V3_MUL_ELEM
-
static bool test_projected_vert_dist(
- PreDefProject *projectdefs,
- const float co[3], const enum eViewProj view_proj,
- const float mval[2], const float depth_range[2],
- float r_co[3])
+ const float depth_range[2], const float mval[2], const float co[3],
+ float pmat[4][4], const float win_half[2], const bool is_persp,
+ float *dist_px_sq, float r_co[3])
{
float depth;
- float(*pmat)[4] = projectdefs->pmat;
- if (view_proj == VIEW_PROJ_PERSP) {
+ if (is_persp) {
depth = mul_project_m4_v3_zfac(pmat, co);
if (depth < depth_range[0] || depth > depth_range[1]) {
return false;
@@ -428,109 +352,103 @@ static bool test_projected_vert_dist(
(dot_m4_v3_row_y(pmat, co) + pmat[3][1]),
};
- if (view_proj == VIEW_PROJ_PERSP) {
+ if (is_persp) {
mul_v2_fl(co2d, 1 / depth);
}
co2d[0] += 1.0f;
co2d[1] += 1.0f;
- co2d[0] *= projectdefs->win_half[0];
- co2d[1] *= projectdefs->win_half[1];
+ co2d[0] *= win_half[0];
+ co2d[1] *= win_half[1];
const float dist_sq = len_squared_v2v2(mval, co2d);
- if (dist_sq < projectdefs->dist_px_sq) {
+ if (dist_sq < *dist_px_sq) {
copy_v3_v3(r_co, co);
- projectdefs->dist_px_sq = dist_sq;
+ *dist_px_sq = dist_sq;
return true;
}
return false;
}
static bool test_projected_edge_dist(
- PreDefProject *projectdefs,
- const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3],
- const enum eViewProj view_proj, const float mval[2], const float depth_range[2],
- float r_co[3])
+ const float depth_range[2], const float mval[2],
+ float pmat[4][4], const float win_half[2], const bool is_persp,
+ const float ray_start[3], const float ray_dir[3],
+ const float va[3], const float vb[3],
+ float *dist_px_sq, float r_co[3])
{
float tmp_co[3], depth;
- dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth);
- return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co);
+ dist_squared_ray_to_seg_v3(ray_start, ray_dir, va, vb, tmp_co, &depth);
+ return test_projected_vert_dist(depth_range, mval, tmp_co, pmat, win_half, is_persp, dist_px_sq, r_co);
}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
-/** \Walk DFS
- * \{ */
-typedef struct Object_Nearest2dPrecalc {
+typedef struct Nearest2dPrecalc {
float ray_origin_local[3];
float ray_direction_local[3];
float ray_inv_dir[3];
- PreDefProject projectdefs;
- float mval[2];
- bool sign[3];
- bool r_axis_closest[3];
float depth_range[2];
+ float pmat[4][4]; /* perspective matrix multiplied by object matrix */
+ float win_half[2];
- void *userdata;
- int index;
- float co[3];
- float no[3];
-} Object_Nearest2dPrecalc;
-
+ float mval[2];
+ bool sign[3];
+} Nearest2dPrecalc;
-static void nearest2d_precalc(
- Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar,
- const float dist_px, float obmat[4][4],
- const float ray_origin_local[3], const float ray_direction_local[3],
- const float mval[2], const float depth_range[2])
+/**
+ * \param lpmat: Perspective matrix multiplied by object matrix
+ */
+static void dist_squared_to_projected_aabb_precalc(
+ struct Nearest2dPrecalc *neasrest_precalc,
+ float lpmat[4][4], const float win_half[2],
+ const float depth_range[2], const float mval[2],
+ const float ray_origin_local[3], const float ray_direction_local[3])
{
- precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat);
+ copy_m4_m4(neasrest_precalc->pmat, lpmat);
+ copy_v2_v2(neasrest_precalc->win_half, win_half);
+ copy_v2_v2(neasrest_precalc->depth_range, depth_range);
+
copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local);
copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local);
copy_v2_v2(neasrest_precalc->mval, mval);
- copy_v2_v2(neasrest_precalc->depth_range, depth_range);
for (int i = 0; i < 3; i++) {
- neasrest_precalc->ray_inv_dir[i] =
+ neasrest_precalc->ray_inv_dir[i] =
(neasrest_precalc->ray_direction_local[i] != 0.0f) ?
(1.0f / neasrest_precalc->ray_direction_local[i]) : FLT_MAX;
neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f);
- neasrest_precalc->r_axis_closest[i] = true;
}
}
-static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
+static float dist_squared_to_projected_aabb(
+ struct Nearest2dPrecalc *data,
+ const float bbmin[3], const float bbmax[3],
+ bool r_axis_closest[3])
{
- Object_Nearest2dPrecalc *data = user_data;
float local_bvmin[3], local_bvmax[3];
if (data->sign[0]) {
- local_bvmin[0] = bounds[0].max;
- local_bvmax[0] = bounds[0].min;
+ local_bvmin[0] = bbmax[0];
+ local_bvmax[0] = bbmin[0];
}
else {
- local_bvmin[0] = bounds[0].min;
- local_bvmax[0] = bounds[0].max;
+ local_bvmin[0] = bbmin[0];
+ local_bvmax[0] = bbmax[0];
}
if (data->sign[1]) {
- local_bvmin[1] = bounds[1].max;
- local_bvmax[1] = bounds[1].min;
+ local_bvmin[1] = bbmax[1];
+ local_bvmax[1] = bbmin[1];
}
else {
- local_bvmin[1] = bounds[1].min;
- local_bvmax[1] = bounds[1].max;
+ local_bvmin[1] = bbmin[1];
+ local_bvmax[1] = bbmax[1];
}
if (data->sign[2]) {
- local_bvmin[2] = bounds[2].max;
- local_bvmax[2] = bounds[2].min;
+ local_bvmin[2] = bbmax[2];
+ local_bvmax[2] = bbmin[2];
}
else {
- local_bvmin[2] = bounds[2].min;
- local_bvmax[2] = bounds[2].max;
+ local_bvmin[2] = bbmin[2];
+ local_bvmax[2] = bbmax[2];
}
const float tmin[3] = {
@@ -543,7 +461,9 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
(local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1],
(local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2],
};
+ /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */
float va[3], vb[3];
+ /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */
float rtmin, rtmax;
int main_axis;
@@ -551,38 +471,38 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
rtmax = tmax[0];
va[0] = vb[0] = local_bvmax[0];
main_axis = 3;
- data->r_axis_closest[0] = data->sign[0];
+ r_axis_closest[0] = data->sign[0];
}
else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
rtmax = tmax[1];
va[1] = vb[1] = local_bvmax[1];
main_axis = 2;
- data->r_axis_closest[1] = data->sign[1];
+ r_axis_closest[1] = data->sign[1];
}
else {
rtmax = tmax[2];
va[2] = vb[2] = local_bvmax[2];
main_axis = 1;
- data->r_axis_closest[2] = data->sign[2];
+ r_axis_closest[2] = data->sign[2];
}
if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
rtmin = tmin[0];
va[0] = vb[0] = local_bvmin[0];
main_axis -= 3;
- data->r_axis_closest[0] = !data->sign[0];
+ r_axis_closest[0] = !data->sign[0];
}
else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
rtmin = tmin[1];
va[1] = vb[1] = local_bvmin[1];
main_axis -= 1;
- data->r_axis_closest[1] = !data->sign[1];
+ r_axis_closest[1] = !data->sign[1];
}
else {
rtmin = tmin[2];
va[2] = vb[2] = local_bvmin[2];
main_axis -= 2;
- data->r_axis_closest[2] = !data->sign[2];
+ r_axis_closest[2] = !data->sign[2];
}
if (main_axis < 0) {
main_axis += 3;
@@ -590,22 +510,34 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
/* if rtmin < rtmax, ray intersect `AABB` */
if (rtmin <= rtmax) {
+#define IGNORE_BEHIND_RAY
#ifdef IGNORE_BEHIND_RAY
- /* `if rtmax < depth_min`, the whole `AABB` is behind us */
- if (rtmax < min_depth) {
- return fallback;
+ /* `if rtmax < depth_min`, the hit is behind us */
+ if (rtmax < data->depth_range[0]) {
+ /* Test if the entire AABB is behind us */
+ float depth = depth_get(
+ local_bvmax, data->ray_origin_local, data->ray_direction_local);
+ if (depth < (data->depth_range[0])) {
+ return FLT_MAX;
+ }
}
#endif
const float proj = rtmin * data->ray_direction_local[main_axis];
- data->r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj);
- return true;
+ r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj);
+ return 0.0f;
}
#ifdef IGNORE_BEHIND_RAY
- /* `if rtmin < depth_min`, the whole `AABB` is behing us */
- else if (rtmin < min_depth) {
- return fallback;
+ /* `if rtmin < depth_min`, the hit is behing us */
+ else if (rtmin < data->depth_range[0]) {
+ /* Test if the entire AABB is behind us */
+ float depth = depth_get(
+ local_bvmax, data->ray_origin_local, data->ray_direction_local);
+ if (depth < (data->depth_range[0])) {
+ return FLT_MAX;
+ }
}
#endif
+#undef IGNORE_BEHIND_RAY
if (data->sign[main_axis]) {
va[main_axis] = local_bvmax[main_axis];
vb[main_axis] = local_bvmin[main_axis];
@@ -616,7 +548,7 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
}
float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]);
- float (*pmat)[4] = data->projectdefs.pmat;
+ float (*pmat)[4] = data->pmat;
float depth_a = mul_project_m4_v3_zfac(pmat, va);
float depth_b = depth_a + pmat[main_axis][3] * scale;
@@ -637,10 +569,10 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
vb2d[0] += 1.0f;
vb2d[1] += 1.0f;
- va2d[0] *= data->projectdefs.win_half[0];
- va2d[1] *= data->projectdefs.win_half[1];
- vb2d[0] *= data->projectdefs.win_half[0];
- vb2d[1] *= data->projectdefs.win_half[1];
+ va2d[0] *= data->win_half[0];
+ va2d[1] *= data->win_half[1];
+ vb2d[0] *= data->win_half[0];
+ vb2d[1] *= data->win_half[1];
//float dvec[2], edge[2], rdist;
//sub_v2_v2v2(dvec, data->mval, va2d);
@@ -653,73 +585,138 @@ static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *us
lambda /= edge[0] * edge[0] + edge[1] * edge[1];
if (lambda <= 0.0f) {
rdist = len_squared_v2v2(data->mval, va2d);
- data->r_axis_closest[main_axis] = true;
+ r_axis_closest[main_axis] = true;
}
else if (lambda >= 1.0f) {
rdist = len_squared_v2v2(data->mval, vb2d);
- data->r_axis_closest[main_axis] = false;
+ r_axis_closest[main_axis] = false;
}
else {
va2d[0] += edge[0] * lambda;
va2d[1] += edge[1] * lambda;
rdist = len_squared_v2v2(data->mval, va2d);
- data->r_axis_closest[main_axis] = lambda < 0.5f;
+ r_axis_closest[main_axis] = lambda < 0.5f;
}
}
else {
rdist = len_squared_v2v2(data->mval, va2d);
}
- return rdist < data->projectdefs.dist_px_sq;
+ return rdist;
+}
+
+static float dist_squared_to_projected_aabb_simple(
+ float lpmat[4][4], const float win_half[2],
+ const float depth_range[2], const float mval[2],
+ const float ray_origin_local[3], const float ray_direction_local[3],
+ const float bbmin[3], const float bbmax[3])
+{
+ struct Nearest2dPrecalc data;
+ dist_squared_to_projected_aabb_precalc(
+ &data, lpmat, win_half, depth_range,
+ mval, ray_origin_local, ray_direction_local);
+
+ bool dummy[3] = {true, true, true};
+ return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy);
+}
+
+static float dist_aabb_to_plane(
+ const float bbmin[3], const float bbmax[3],
+ const float plane_co[3], const float plane_no[3])
+{
+ const float local_bvmin[3] = {
+ (plane_no[0] < 0) ? bbmax[0] : bbmin[0],
+ (plane_no[1] < 0) ? bbmax[1] : bbmin[1],
+ (plane_no[2] < 0) ? bbmax[2] : bbmin[2],
+ };
+ return depth_get(local_bvmin, plane_co, plane_no);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \Walk DFS
+ * \{ */
+typedef struct Nearest2dUserData {
+ struct Nearest2dPrecalc data_precalc;
+
+ bool is_persp;
+ float dist_px_sq;
+
+ bool r_axis_closest[3];
+
+ void *userdata;
+ int index;
+ float co[3];
+ float no[3];
+} Nearest2dUserData;
+
+
+static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
+{
+ Nearest2dUserData *data = user_data;
+ const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min};
+ const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max};
+ const float rdist = dist_squared_to_projected_aabb(
+ &data->data_precalc, bbmin, bbmax, data->r_axis_closest);
+ return rdist < data->dist_px_sq;
}
static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata)
{
- struct Object_Nearest2dPrecalc *neasrest_precalc = userdata;
+ struct Nearest2dUserData *data = userdata;
+ struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc;
const float co[3] = {
(bounds[0].min + bounds[0].max) / 2,
(bounds[1].min + bounds[1].max) / 2,
(bounds[2].min + bounds[2].max) / 2,
};
- /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP)
- * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO),
- * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/
if (test_projected_vert_dist(
- &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP,
- neasrest_precalc->mval, neasrest_precalc->depth_range,
- neasrest_precalc->co))
+ neasrest_precalc->depth_range,
+ neasrest_precalc->mval, co,
+ neasrest_precalc->pmat,
+ neasrest_precalc->win_half,
+ data->is_persp,
+ &data->dist_px_sq,
+ data->co))
{
- copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no);
- neasrest_precalc->index = index;
+ copy_vert_no(data->userdata, index, data->no);
+ data->index = index;
}
return true;
}
static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
{
- struct Object_Nearest2dPrecalc *neasrest_precalc = userdata;
+ struct Nearest2dUserData *data = userdata;
+ struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc;
const float *v_pair[2];
- get_edge_verts(neasrest_precalc->userdata, index, v_pair);
+ get_edge_verts(data->userdata, index, v_pair);
- /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP)
- * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO),
- * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/
if (test_projected_edge_dist(
- &neasrest_precalc->projectdefs, v_pair[0], v_pair[1],
- neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local,
- VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range,
- neasrest_precalc->co))
+ neasrest_precalc->depth_range,
+ neasrest_precalc->mval,
+ neasrest_precalc->pmat,
+ neasrest_precalc->win_half,
+ data->is_persp,
+ neasrest_precalc->ray_origin_local,
+ neasrest_precalc->ray_direction_local,
+ v_pair[0], v_pair[1],
+ &data->dist_px_sq,
+ data->co))
{
- sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]);
- neasrest_precalc->index = index;
+ sub_v3_v3v3(data->no, v_pair[0], v_pair[1]);
+ data->index = index;
}
return true;
}
static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata)
{
- const bool *r_axis_closest = ((struct Object_Nearest2dPrecalc *)userdata)->r_axis_closest;
+ const bool *r_axis_closest = ((struct Nearest2dUserData *)userdata)->r_axis_closest;
return r_axis_closest[axis];
}
@@ -731,46 +728,56 @@ static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char a
* \{ */
static bool snapArmature(
- const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
- const short snap_to, const float origin[3], const float dir[3],
- const float mval[2], const enum eViewProj view_proj, const float depth_range[2],
+ SnapData *snapdata,
+ Object *ob, bArmature *arm, float obmat[4][4],
/* read/write args */
- float *dist_px,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
bool retval = false;
- float ray_start_local[3], ray_normal_local[3];
- if (snap_to != SCE_SNAP_MODE_VERTEX) {
+ float ray_start_local[3], ray_normal_local[3]; /* Used only in the snap to edges */
+ if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
float imat[4][4];
invert_m4_m4(imat, obmat);
- copy_v3_v3(ray_start_local, origin);
- copy_v3_v3(ray_normal_local, dir);
+ copy_v3_v3(ray_start_local, snapdata->ray_origin);
+ copy_v3_v3(ray_normal_local, snapdata->ray_dir);
mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
}
+ else if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { /* Currently only edge and vert */
+ return retval;
+ }
- PreDefProject projectdefs;
- precalc_project(&projectdefs, ar, *dist_px, obmat);
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float lpmat[4][4], dist_px_sq;
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ dist_px_sq = SQUARE(*dist_px);
if (arm->edbo) {
for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
if (eBone->layer & arm->layer) {
/* skip hidden or moving (selected) bones */
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
- &projectdefs, eBone->head, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, eBone->head,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
retval |= test_projected_vert_dist(
- &projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, eBone->tail,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
- &projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local,
- view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, lpmat,
+ snapdata->win_half, is_persp, ray_start_local, ray_normal_local,
+ eBone->head, eBone->tail,
+ &dist_px_sq, r_loc);
break;
}
}
@@ -785,52 +792,60 @@ static bool snapArmature(
const float *head_vec = pchan->pose_head;
const float *tail_vec = pchan->pose_tail;
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
- &projectdefs, head_vec, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, head_vec,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
retval |= test_projected_vert_dist(
- &projectdefs, tail_vec, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, tail_vec,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
- &projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local,
- view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, lpmat,
+ snapdata->win_half, is_persp, ray_start_local, ray_normal_local,
+ head_vec, tail_vec,
+ &dist_px_sq, r_loc);
break;
}
}
}
}
if (retval) {
- *dist_px = sqrtf(projectdefs.dist_px_sq);
+ *dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
return true;
}
return false;
}
static bool snapCurve(
- const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4],
- const short snap_to, const float mval[2], const enum eViewProj view_proj,
- const float depth_range[2],
+ SnapData *snapdata,
+ Object *ob, Curve *cu, float obmat[4][4],
/* read/write args */
- float *dist_px,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
bool retval = false;
/* only vertex snapping mode (eg control points and handles) supported for now) */
- if (snap_to != SCE_SNAP_MODE_VERTEX) {
+ if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) {
return retval;
}
- PreDefProject projectdefs;
- precalc_project(&projectdefs, ar, *dist_px, obmat);
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float lpmat[4][4], dist_px_sq;
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ dist_px_sq = SQUARE(*dist_px);
for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
for (int u = 0; u < nu->pntsu; u++) {
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
if (ob->mode == OB_MODE_EDIT) {
@@ -840,19 +855,25 @@ static bool snapCurve(
break;
}
retval |= test_projected_vert_dist(
- &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1],
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
/* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
if (!(nu->bezt[u].f1 & SELECT) &&
!(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
{
retval |= test_projected_vert_dist(
- &projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[0],
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
if (!(nu->bezt[u].f3 & SELECT) &&
!(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
{
retval |= test_projected_vert_dist(
- &projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[2],
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
}
else {
@@ -861,7 +882,9 @@ static bool snapCurve(
break;
}
retval |= test_projected_vert_dist(
- &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bp[u].vec,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
}
else {
@@ -869,11 +892,15 @@ static bool snapCurve(
if (nu->pntsu > 1) {
if (nu->bezt) {
retval |= test_projected_vert_dist(
- &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bezt[u].vec[1],
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
else {
retval |= test_projected_vert_dist(
- &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, nu->bp[u].vec,
+ lpmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
}
}
@@ -885,8 +912,9 @@ static bool snapCurve(
}
}
if (retval) {
- *dist_px = sqrtf(projectdefs.dist_px_sq);
+ *dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
return true;
}
return false;
@@ -894,11 +922,10 @@ static bool snapCurve(
/* may extend later (for now just snaps to empty center) */
static bool snapEmpty(
- const ARegion *ar, Object *ob, float obmat[4][4],
- const short snap_to, const float mval[2], const enum eViewProj view_proj,
- const float depth_range[2],
+ SnapData *snapdata,
+ Object *ob, float obmat[4][4],
/* read/write args */
- float *dist_px,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
@@ -909,15 +936,19 @@ static bool snapEmpty(
}
/* for now only vertex supported */
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
- PreDefProject projectdefs;
- precalc_project(&projectdefs, ar, *dist_px, NULL);
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
float tmp_co[3];
copy_v3_v3(tmp_co, obmat[3]);
- if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) {
- *dist_px = sqrtf(projectdefs.dist_px_sq);
+ if (test_projected_vert_dist(
+ snapdata->depth_range, snapdata->mval, tmp_co,
+ snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc)) {
+ *dist_px = sqrtf(dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;
}
break;
@@ -930,18 +961,17 @@ static bool snapEmpty(
}
static bool snapCamera(
- const SnapObjectContext *sctx, Object *object, float obmat[4][4],
- const short snap_to, const float mval[2], const enum eViewProj view_proj,
- const float depth_range[2],
+ const SnapObjectContext *sctx, SnapData *snapdata,
+ Object *object, float obmat[4][4],
/* read/write args */
- float *dist_px,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
Scene *scene = sctx->scene;
- PreDefProject projectdefs;
- precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL);
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
bool retval = false;
@@ -962,7 +992,7 @@ static bool snapCamera(
invert_m4_m4(orig_camera_imat, orig_camera_mat);
invert_m4_m4(imat, obmat);
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
MovieTrackingObject *tracking_object;
@@ -1002,7 +1032,9 @@ static bool snapCamera(
mul_m4_v3(vertex_obmat, bundle_pos);
retval |= test_projected_vert_dist(
- &projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc);
+ snapdata->depth_range, snapdata->mval, bundle_pos,
+ snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc);
}
}
@@ -1013,7 +1045,8 @@ static bool snapCamera(
}
if (retval) {
- *dist_px = sqrtf(projectdefs.dist_px_sq);
+ *dist_px = sqrtf(dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
return true;
}
return false;
@@ -1025,57 +1058,10 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
}
-struct NearestDM_Data {
- void *bvhdata;
- const float *depth_range;
- float *ray_depth;
-};
-
-static void test_vert_ray_dist_cb(
- void *userdata, const float origin[3], const float dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct NearestDM_Data *ndata = userdata;
- const struct BVHTreeFromMeshType *data = ndata->bvhdata;
-
- const float *co = get_vert_co(data, index);
-
- if (test_vert_dist(
- co, origin, dir, ndata->depth_range,
- scale, ndata->ray_depth, &nearest->dist_sq,
- nearest->co))
- {
- copy_vert_no(data, index, nearest->no);
- nearest->index = index;
- }
-}
-
-static void test_edge_ray_dist_cb(
- void *userdata, const float origin[3], const float dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct NearestDM_Data *ndata = userdata;
- BVHTreeFromMeshType *data = ndata->bvhdata;
-
- const float *v_pair[2];
- get_edge_verts(data, index, v_pair);
-
- if (test_edge_dist(
- v_pair[0], v_pair[1], origin, dir, ndata->depth_range,
- scale, ndata->ray_depth, &nearest->dist_sq,
- nearest->co))
- {
- sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
- nearest->index = index;
- }
-}
-
static bool snapDerivedMesh(
- SnapObjectContext *sctx,
+ SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
- const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
- const float depth_range[2],
+ bool do_bb,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1084,12 +1070,12 @@ static bool snapDerivedMesh(
{
bool retval = false;
- if (snap_to == SCE_SNAP_MODE_FACE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
if (dm->getNumPolys(dm) == 0) {
return retval;
}
}
- else if (snap_to == SCE_SNAP_MODE_EDGE) {
+ else if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (dm->getNumEdges(dm) == 0) {
return retval;
}
@@ -1101,7 +1087,9 @@ static bool snapDerivedMesh(
}
{
- bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO);
+ bool need_ray_start_correction_init =
+ (snapdata->snap_to == SCE_SNAP_MODE_FACE) &&
+ (snapdata->view_proj == VIEW_PROJ_ORTHO);
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
@@ -1111,8 +1099,8 @@ static bool snapDerivedMesh(
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_normal);
+ copy_v3_v3(ray_start_local, snapdata->ray_start);
+ copy_v3_v3(ray_normal_local, snapdata->ray_dir);
mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
@@ -1124,6 +1112,17 @@ static bool snapDerivedMesh(
local_depth *= local_scale;
}
+ float lpmat[4][4];
+ float ray_org_local[3];
+ float depth_range_local[2];
+ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
+ depth_range_local[0] = snapdata->depth_range[0] * local_scale;
+ depth_range_local[1] = local_depth + depth_range_local[0];
+ }
+
if (do_bb) {
BoundBox *bb = BKE_object_boundbox_get(ob);
@@ -1134,19 +1133,27 @@ static bool snapDerivedMesh(
* Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
- /* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'dist_px'),
- * scale up so we can snap against verts & edges on the boundbox, see T46816. */
- if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f);
- bb = &bb_temp;
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */
+ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
+ float dist_px_sq = dist_squared_to_projected_aabb_simple(
+ lpmat, snapdata->win_half, snapdata->depth_range, snapdata->mval,
+ ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
+ if (dist_px_sq > SQUARE(*dist_px))
+ {
+ return retval;
+ }
}
-
- /* was local_depth, see: T47838 */
- len_diff = BVH_RAYCAST_DIST_MAX;
-
- if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
- return retval;
+ else {
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
+ {
+ return retval;
+ }
}
+ /* was local_depth, see: T47838 */
+ len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local);
+ if (len_diff < 0) len_diff = 0.0f;
need_ray_start_correction_init = false;
}
}
@@ -1165,7 +1172,7 @@ static bool snapDerivedMesh(
}
int tree_index = -1;
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_FACE:
tree_index = 2;
break;
@@ -1196,7 +1203,7 @@ static bool snapDerivedMesh(
}
if (treedata && treedata->tree == NULL) {
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_FACE:
bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
break;
@@ -1213,12 +1220,12 @@ static bool snapDerivedMesh(
return retval;
}
- if (snap_to == SCE_SNAP_MODE_FACE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
/* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
* been *inside* boundbox, leading to snap failures (see T38409).
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
*/
- if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
+ if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
if (need_ray_start_correction_init) {
/* We *need* a reasonably valid len_diff in this case.
* Use BHVTree to find the closest face from ray_start_local.
@@ -1235,18 +1242,25 @@ static bool snapDerivedMesh(
len_diff = dot_v3v3(dvec, ray_normal_local);
}
}
- float ray_org_local[3];
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ float ray_org_local[3];
- copy_v3_v3(ray_org_local, ray_origin);
- mul_m4_v3(imat, ray_org_local);
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
- /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far
- * away ray_start values (as returned in case of ortho view3d), see T38358.
- */
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3v3fl(
- ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale);
- local_depth -= len_diff;
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T38358.
+ */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3v3fl(
+ ray_start_local, ray_org_local, ray_normal_local,
+ len_diff + snapdata->depth_range[0] * local_scale);
+ local_depth -= len_diff;
+ }
+ else len_diff = 0.0f;
}
else {
len_diff = 0.0f;
@@ -1304,78 +1318,39 @@ static bool snapDerivedMesh(
}
/* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */
else {
- const ARegion *ar = sctx->v3d_data.ar;
-
- float ray_org_local[3];
- copy_v3_v3(ray_org_local, ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH};
- if (view_proj == VIEW_PROJ_PERSP) {
- Object_Nearest2dPrecalc neasrest_precalc;
- neasrest_precalc.userdata = &treedata_type;
- neasrest_precalc.index = -1;
-
- nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
- ray_org_local, ray_normal_local, mval, depth_range);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc);
-
- if (neasrest_precalc.index != -1) {
- copy_v3_v3(r_loc, neasrest_precalc.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, neasrest_precalc.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
-
- retval = true;
+ Nearest2dUserData neasrest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .userdata = &treedata_type,
+ .index = -1};
+
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat, snapdata->win_half,
+ depth_range_local, snapdata->mval, ray_org_local, ray_normal_local);
+
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
+
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
+
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
- }
- else {
- BVHTreeNearest nearest;
-
- nearest.index = -1;
- float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px);
- nearest.dist_sq = SQUARE(dist_3d);
-
-
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
-
- struct NearestDM_Data userdata;
- userdata.bvhdata = &treedata_type;
- userdata.depth_range = depth_range;
- userdata.ray_depth = ray_depth;
-
- BVHTree_NearestToRayCallback cb_test_ray_dist =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- test_vert_ray_dist_cb : test_edge_ray_dist_cb;
-
- if (BLI_bvhtree_find_nearest_to_ray(
- treedata->tree, ray_org_local, ray_normal_local,
- true, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1)
- {
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px *= sqrtf(nearest.dist_sq) / dist_3d;
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
- retval = true;
- }
+ retval = true;
}
}
@@ -1390,11 +1365,8 @@ static bool snapDerivedMesh(
}
static bool snapEditMesh(
- SnapObjectContext *sctx,
+ SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
- const short snap_to, const float mval[2], const enum eViewProj view_proj,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
- const float depth_range[2],
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1403,12 +1375,12 @@ static bool snapEditMesh(
{
bool retval = false;
- if (snap_to == SCE_SNAP_MODE_FACE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
if (em->bm->totface == 0) {
return retval;
}
}
- if (snap_to == SCE_SNAP_MODE_EDGE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) {
if (em->bm->totedge == 0) {
return retval;
}
@@ -1427,10 +1399,17 @@ static bool snapEditMesh(
invert_m4_m4(imat, obmat);
transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_normal_local, ray_normal);
+ copy_v3_v3(ray_normal_local, snapdata->ray_dir);
mul_mat3_m4_v3(imat, ray_normal_local);
+ /* local scale in normal direction */
+ float local_scale = normalize_v3(ray_normal_local);
+ float local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
SnapObjectData_EditMesh *sod = NULL;
BVHTreeFromEditMesh *treedata = NULL, treedata_stack;
@@ -1446,7 +1425,7 @@ static bool snapEditMesh(
}
int tree_index = -1;
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_FACE:
tree_index = 2;
break;
@@ -1470,7 +1449,7 @@ static bool snapEditMesh(
}
if (treedata && treedata->tree == NULL) {
- switch (snap_to) {
+ switch (snapdata->snap_to) {
case SCE_SNAP_MODE_FACE:
{
BLI_bitmap *looptri_mask = NULL;
@@ -1528,24 +1507,17 @@ static bool snapEditMesh(
return retval;
}
- if (snap_to == SCE_SNAP_MODE_FACE) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
float ray_start_local[3];
- copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_start_local, snapdata->ray_start);
mul_m4_v3(imat, ray_start_local);
- /* local scale in normal direction */
- float local_scale = normalize_v3(ray_normal_local);
- float local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
-
- /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
- * been *inside* boundbox, leading to snap failures (see T38409).
+ /* Only use closer ray_start in case of ortho view! In perspective one, ray_start
+ * may already been *inside* boundbox, leading to snap failures (see T38409).
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
*/
float len_diff = 0.0f;
- if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
+ if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
/* We *need* a reasonably valid len_diff in this case.
* Use BHVTree to find the closest face from ray_start_local.
*/
@@ -1559,19 +1531,26 @@ static bool snapEditMesh(
float dvec[3];
sub_v3_v3v3(dvec, nearest.co, ray_start_local);
len_diff = dot_v3v3(dvec, ray_normal_local);
- float ray_org_local[3];
-
- copy_v3_v3(ray_org_local, ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
- /* We pass a temp ray_start, set from object's boundbox,
- * to avoid precision issues with very far away ray_start values
- * (as returned in case of ortho view3d), see T38358.
- */
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3v3fl(
- ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale);
- local_depth -= len_diff;
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ float ray_org_local[3];
+
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
+
+ /* We pass a temp ray_start, set from object's boundbox,
+ * to avoid precision issues with very far away ray_start values
+ * (as returned in case of ortho view3d), see T38358.
+ */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3v3fl(
+ ray_start_local, ray_org_local, ray_normal_local,
+ len_diff + snapdata->depth_range[0] * local_scale);
+ local_depth -= len_diff;
+ }
+ else len_diff = 0.0f;
}
}
if (r_hit_list) {
@@ -1626,78 +1605,47 @@ static bool snapEditMesh(
}
}
else {
- const ARegion *ar = sctx->v3d_data.ar;
-
float ray_org_local[3];
- copy_v3_v3(ray_org_local, ray_origin);
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH};
- if (view_proj == VIEW_PROJ_PERSP) {
- Object_Nearest2dPrecalc neasrest_precalc;
- neasrest_precalc.userdata = &treedata_type;
- neasrest_precalc.index = -1;
-
- nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
- ray_org_local, ray_normal_local, mval, depth_range);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc);
-
- if (neasrest_precalc.index != -1) {
- copy_v3_v3(r_loc, neasrest_precalc.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, neasrest_precalc.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
-
- retval = true;
+ Nearest2dUserData neasrest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .userdata = &treedata_type,
+ .index = -1};
+
+ float lpmat[4][4], depth_range_local[2];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ depth_range_local[0] = snapdata->depth_range[0] * local_scale;
+ depth_range_local[1] = local_depth + depth_range_local[0];
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat, snapdata->win_half,
+ snapdata->depth_range, snapdata->mval, ray_org_local, ray_normal_local);
+
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
+
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
+
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
- }
- else {
- BVHTreeNearest nearest;
-
- nearest.index = -1;
- float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px);
- nearest.dist_sq = SQUARE(dist_3d);
-
-
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
-
- struct NearestDM_Data userdata;
- userdata.bvhdata = &treedata_type;
- userdata.depth_range = depth_range;
- userdata.ray_depth = ray_depth;
-
- BVHTree_NearestToRayCallback cb_test_ray_dist =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- test_vert_ray_dist_cb : test_edge_ray_dist_cb;
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
- if (BLI_bvhtree_find_nearest_to_ray(
- treedata->tree, ray_org_local, ray_normal_local,
- false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1)
- {
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px *= sqrtf(nearest.dist_sq) / dist_3d;
-
- retval = true;
- }
+ retval = true;
}
}
@@ -1717,11 +1665,9 @@ static bool snapEditMesh(
* \note Duplicate args here are documented at #snapObjectsRay
*/
static bool snapObject(
- SnapObjectContext *sctx,
+ SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, float obmat[4][4], const unsigned int ob_index,
- bool use_obedit, const short snap_to, const float mval[2],
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
- const float depth_range[2],
+ bool use_obedit,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1729,12 +1675,6 @@ static bool snapObject(
Object **r_ob, float r_obmat[4][4],
ListBase *r_hit_list)
{
- const enum eViewProj view_proj =
- ((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE :
- (((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO);
-
- const ARegion *ar = sctx->v3d_data.ar;
-
bool retval = false;
if (ob->type == OB_MESH) {
@@ -1743,9 +1683,7 @@ static bool snapObject(
if (use_obedit) {
em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
- sctx, ob, em, obmat, ob_index,
- snap_to, mval, view_proj,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, ob, em, obmat, ob_index,
ray_depth, dist_px,
r_loc, r_no, r_index,
r_hit_list);
@@ -1762,9 +1700,8 @@ static bool snapObject(
dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
}
retval = snapDerivedMesh(
- sctx, ob, dm, obmat, ob_index,
- snap_to, mval, view_proj, true,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, ob, dm, obmat, ob_index,
+ true,
ray_depth, dist_px,
r_loc, r_no,
r_index, r_hit_list);
@@ -1772,32 +1709,32 @@ static bool snapObject(
dm->release(dm);
}
}
- else if (snap_to != SCE_SNAP_MODE_FACE) {
+ else if (snapdata->snap_to != SCE_SNAP_MODE_FACE) {
if (ob->type == OB_ARMATURE) {
retval = snapArmature(
- ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal,
- mval, view_proj, depth_range, dist_px,
+ snapdata,
+ ob, ob->data, obmat,
+ ray_depth, dist_px,
r_loc, r_no);
}
else if (ob->type == OB_CURVE) {
retval = snapCurve(
- ar, ob, ob->data, obmat, snap_to, mval, view_proj,
- depth_range,
- dist_px,
+ snapdata,
+ ob, ob->data, obmat,
+ ray_depth, dist_px,
r_loc, r_no);
}
else if (ob->type == OB_EMPTY) {
retval = snapEmpty(
- ar, ob, obmat, snap_to, mval, view_proj,
- depth_range,
- dist_px,
+ snapdata,
+ ob, obmat,
+ ray_depth, dist_px,
r_loc, r_no);
}
else if (ob->type == OB_CAMERA) {
retval = snapCamera(
- sctx, ob, obmat, snap_to, mval, view_proj,
- depth_range,
- dist_px,
+ sctx, snapdata, ob, obmat,
+ ray_depth, dist_px,
r_loc, r_no);
}
}
@@ -1819,18 +1756,9 @@ static bool snapObject(
* Walks through all objects in the scene to find the closest snap element ray.
*
* \param sctx: Snap context to store data.
- * \param snap_to: Element to snap, Vertice, Edge or Face.
- * Currently only works one at a time, but can eventually operate as flag.
- *
+ * \param snapdata: struct generated in `get_snapdata`.
* \param snap_select: from enum SnapSelect.
- *
* \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping.
- * \param mval: Mouse coords.
- * When NULL, ray-casting is handled without any projection matrix correction.
- * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
- * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
- * \param ray_normal: Unit length direction of the ray.
- * \param depth_range: distances of clipe plane min and clip plane max;
*
* Read/Write Args
* ---------------
@@ -1851,11 +1779,9 @@ static bool snapObject(
*
*/
static bool snapObjectsRay(
- SnapObjectContext *sctx,
- const unsigned short snap_to, const SnapSelect snap_select,
- const bool use_object_edit_cage, const float mval[2],
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
- const float depth_range[2],
+ SnapObjectContext *sctx, SnapData *snapdata,
+ const SnapSelect snap_select,
+ const bool use_object_edit_cage,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1878,9 +1804,7 @@ static bool snapObjectsRay(
Object *ob = base_act->object;
retval |= snapObject(
- sctx, ob, ob->obmat, ob_index++,
- false, snap_to, mval,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, ob, ob->obmat, ob_index++, false,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1914,9 +1838,8 @@ static bool snapObjectsRay(
Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
retval |= snapObject(
- sctx, dupli_snap, dupli_ob->mat, ob_index++,
- use_obedit_dupli, snap_to, mval,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, dupli_snap, dupli_ob->mat,
+ ob_index++, use_obedit_dupli,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1928,9 +1851,7 @@ static bool snapObjectsRay(
Object *ob_snap = use_obedit ? obedit : ob;
retval |= snapObject(
- sctx, ob_snap, ob->obmat, ob_index++,
- use_obedit, snap_to, mval,
- ray_origin, ray_start, ray_normal, depth_range,
+ sctx, snapdata, ob_snap, ob->obmat, ob_index++, use_obedit,
ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -2033,16 +1954,19 @@ bool ED_transform_snap_object_project_ray_ex(
SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3],
+ const float UNUSED(ray_start[3]), const float UNUSED(ray_normal[3]),
float *ray_depth,
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
const float depth_range[2] = {0.0f, FLT_MAX};
+
+ SnapData snapdata;
+ snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, r_loc, r_loc, r_no, depth_range);
+
return snapObjectsRay(
- sctx,
- snap_to, params->snap_select, params->use_object_edit_cage, NULL,
- ray_start, ray_start, ray_normal, depth_range,
+ sctx, &snapdata,
+ params->snap_select, params->use_object_edit_cage,
ray_depth, NULL,
r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
@@ -2071,10 +1995,13 @@ bool ED_transform_snap_object_project_ray_all(
float ray_depth_prev = ray_depth;
#endif
+ SnapData snapdata;
+ snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL,
+ ray_start, ray_start, ray_normal, depth_range);
+
bool retval = snapObjectsRay(
- sctx,
- snap_to, params->snap_select, params->use_object_edit_cage, NULL,
- ray_start, ray_start, ray_normal, depth_range,
+ sctx, &snapdata,
+ params->snap_select, params->use_object_edit_cage,
&ray_depth, NULL,
NULL, NULL, NULL, NULL, NULL,
r_hit_list);
@@ -2155,9 +2082,6 @@ static bool transform_snap_context_project_view3d_mixed_impl(
for (int i = 0; i < 3; i++) {
if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
- if (use_depth == false) {
- ray_depth = BVH_RAYCAST_DIST_MAX;
- }
if (ED_transform_snap_object_project_view3d(
sctx,
@@ -2166,6 +2090,14 @@ static bool transform_snap_context_project_view3d_mixed_impl(
r_co, r_no))
{
is_hit = true;
+ if (use_depth == false) {
+ ray_depth = BVH_RAYCAST_DIST_MAX;
+ }
+ else {
+ /* 0.01 is a random but small value to prioritizing
+ * the first elements of the loop */
+ ray_depth -= 0.01f;
+ }
}
}
}
@@ -2234,10 +2166,14 @@ bool ED_transform_snap_object_project_view3d_ex(
ray_depth = &ray_depth_fallback;
}
+ SnapData snapdata;
+ const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
+ snap_data_set(&snapdata, ar, snap_to, view_proj, mval,
+ ray_origin, ray_start, ray_normal, depth_range);
+
return snapObjectsRay(
- sctx,
- snap_to, params->snap_select, params->use_object_edit_cage,
- mval, ray_origin, ray_start, ray_normal, depth_range,
+ sctx, &snapdata,
+ params->snap_select, params->use_object_edit_cage,
ray_depth, dist_px,
r_loc, r_no, r_index, NULL, NULL, NULL);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index aa583c5ecf8..0f3ffa8244b 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -3536,6 +3536,8 @@ void node_light_path(
out float is_transmission_ray,
out float ray_length,
out float ray_depth,
+ out float diffuse_depth,
+ out float glossy_depth,
out float transparent_depth,
out float transmission_depth)
{
@@ -3548,6 +3550,8 @@ void node_light_path(
is_transmission_ray = 0.0;
ray_length = 1.0;
ray_depth = 1.0;
+ diffuse_depth = 1.0;
+ glossy_depth = 1.0;
transparent_depth = 1.0;
transmission_depth = 1.0;
}
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 8efa4d63675..8aee7b66916 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -96,7 +96,7 @@ static void foreachObjectLink(
{
ArmatureModifierData *amd = (ArmatureModifierData *) md;
- walk(userData, ob, &amd->object, IDWALK_NOP);
+ walk(userData, ob, &amd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 6017f964c26..61ac4d5692f 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -95,10 +95,10 @@ static void foreachObjectLink(
{
ArrayModifierData *amd = (ArrayModifierData *) md;
- walk(userData, ob, &amd->start_cap, IDWALK_NOP);
- walk(userData, ob, &amd->end_cap, IDWALK_NOP);
- walk(userData, ob, &amd->curve_ob, IDWALK_NOP);
- walk(userData, ob, &amd->offset_ob, IDWALK_NOP);
+ walk(userData, ob, &amd->start_cap, IDWALK_CB_NOP);
+ walk(userData, ob, &amd->end_cap, IDWALK_CB_NOP);
+ walk(userData, ob, &amd->curve_ob, IDWALK_CB_NOP);
+ walk(userData, ob, &amd->offset_ob, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index d2f19b78b50..51020566de6 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -101,7 +101,7 @@ static void foreachObjectLink(
{
BooleanModifierData *bmd = (BooleanModifierData *) md;
- walk(userData, ob, &bmd->object, IDWALK_NOP);
+ walk(userData, ob, &bmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 16c5de45c49..9e718eab639 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -102,7 +102,7 @@ static void foreachObjectLink(
{
CastModifierData *cmd = (CastModifierData *) md;
- walk(userData, ob, &cmd->object, IDWALK_NOP);
+ walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index b6a7b5b57ec..59eb00207df 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -214,11 +214,11 @@ static void foreachIDLink(ModifierData *md, Object *ob,
ClothModifierData *clmd = (ClothModifierData *) md;
if (clmd->coll_parms) {
- walk(userData, ob, (ID **)&clmd->coll_parms->group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&clmd->coll_parms->group, IDWALK_CB_NOP);
}
if (clmd->sim_parms && clmd->sim_parms->effector_weights) {
- walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group, IDWALK_CB_NOP);
}
}
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 3e9b46ad8ea..6f3dbe841aa 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -89,7 +89,7 @@ static void foreachObjectLink(
{
CurveModifierData *cmd = (CurveModifierData *) md;
- walk(userData, ob, &cmd->object, IDWALK_NOP);
+ walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index 26952e1e0d5..3bddbc7ee2b 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -124,7 +124,7 @@ static void foreachObjectLink(
ObjectWalkFunc walk, void *userData)
{
DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
- walk(userData, ob, &dtmd->ob_source, IDWALK_NOP);
+ walk(userData, ob, &dtmd->ob_source, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
@@ -163,7 +163,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
/* Only used to check wehther we are operating on org data or not... */
Mesh *me = ob->data;
- MVert *mvert;
const bool invert_vgroup = (dtmd->flags & MOD_DATATRANSFER_INVERT_VGROUP) != 0;
@@ -176,8 +175,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
BLI_SPACE_TRANSFORM_SETUP(space_transform, ob, dtmd->ob_source);
}
- mvert = dm->getVertArray(dm);
- if ((me->mvert == mvert) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) {
+ MVert *mvert = dm->getVertArray(dm);
+ MEdge *medge = dm->getEdgeArray(dm);
+ if (((me->mvert == mvert) || (me->medge == medge)) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) {
/* We need to duplicate data here, otherwise setting custom normals, edges' shaprness, etc., could
* modify org mesh, see T43671. */
dm = CDDM_copy(dm);
@@ -195,6 +195,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
if (BKE_reports_contain(&reports, RPT_ERROR)) {
modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR));
}
+ else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) {
+ modifier_setError((ModifierData *)dtmd, "Enable 'Auto Smooth' option in mesh settings");
+ }
else if (dm->getNumVerts(dm) > HIGH_POLY_WARNING || ((Mesh *)(dtmd->ob_source->data))->totvert > HIGH_POLY_WARNING) {
modifier_setError(md, "You are using a rather high poly as source or destination, computation might be slow");
}
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 4b5181e9c61..c7e539200f6 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -132,7 +132,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
{
DisplaceModifierData *dmd = (DisplaceModifierData *) md;
- walk(userData, ob, &dmd->map_object, IDWALK_NOP);
+ walk(userData, ob, &dmd->map_object, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -140,7 +140,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
DisplaceModifierData *dmd = (DisplaceModifierData *) md;
- walk(userData, ob, (ID **)&dmd->texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&dmd->texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index ee6df153905..794d8bf6951 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -153,15 +153,15 @@ static void foreachIDLink(ModifierData *md, Object *ob,
DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
for (; surface; surface = surface->next) {
- walk(userData, ob, (ID **)&surface->brush_group, IDWALK_NOP);
- walk(userData, ob, (ID **)&surface->init_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&surface->brush_group, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&surface->init_texture, IDWALK_CB_USER);
if (surface->effector_weights) {
- walk(userData, ob, (ID **)&surface->effector_weights->group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&surface->effector_weights->group, IDWALK_CB_NOP);
}
}
}
if (pmd->brush) {
- walk(userData, ob, (ID **)&pmd->brush->mat, IDWALK_USER);
+ walk(userData, ob, (ID **)&pmd->brush->mat, IDWALK_CB_USER);
}
}
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 13d94abc92d..210e91d159a 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -115,7 +115,7 @@ static void foreachObjectLink(
{
HookModifierData *hmd = (HookModifierData *) md;
- walk(userData, ob, &hmd->object, IDWALK_NOP);
+ walk(userData, ob, &hmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 292c2db61f8..2e02ab29d5f 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -88,7 +88,7 @@ static void foreachObjectLink(
{
LatticeModifierData *lmd = (LatticeModifierData *) md;
- walk(userData, ob, &lmd->object, IDWALK_NOP);
+ walk(userData, ob, &lmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 7cb2f2c25d5..1c4406e1a4f 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -74,7 +74,7 @@ static void foreachObjectLink(
ObjectWalkFunc walk, void *userData)
{
MaskModifierData *mmd = (MaskModifierData *)md;
- walk(userData, ob, &mmd->ob_arm, IDWALK_NOP);
+ walk(userData, ob, &mmd->ob_arm, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 27782b05cd2..ed1f5e8938b 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -119,7 +119,7 @@ static void foreachObjectLink(
{
MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
- walk(userData, ob, &mmd->object, IDWALK_NOP);
+ walk(userData, ob, &mmd->object, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 985c365bb69..0b9298a26a6 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -151,7 +151,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md;
- walk(userData, ob, (ID **)&mcmd->cache_file, IDWALK_USER);
+ walk(userData, ob, (ID **)&mcmd->cache_file, IDWALK_CB_USER);
}
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 9fdd75aeb68..8c01c560e75 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -72,7 +72,7 @@ static void foreachObjectLink(
{
MirrorModifierData *mmd = (MirrorModifierData *) md;
- walk(userData, ob, &mmd->mirror_ob, IDWALK_NOP);
+ walk(userData, ob, &mmd->mirror_ob, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index eefca658305..b73f1074bc1 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -501,7 +501,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
NormalEditModifierData *enmd = (NormalEditModifierData *) md;
- walk(userData, ob, &enmd->target, IDWALK_NOP);
+ walk(userData, ob, &enmd->target, IDWALK_CB_NOP);
}
static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index a468cc6600d..9d8e1e181a4 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -127,7 +127,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
- walk(userData, ob, &pimd->ob, IDWALK_NOP);
+ walk(userData, ob, &pimd->ob, IDWALK_CB_NOP);
}
static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index a834d1b5cae..1273a3a6e09 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -1075,7 +1075,7 @@ static void foreachObjectLink(
{
ScrewModifierData *ltmd = (ScrewModifierData *) md;
- walk(userData, ob, &ltmd->ob_axis, IDWALK_NOP);
+ walk(userData, ob, &ltmd->ob_axis, IDWALK_CB_NOP);
}
ModifierTypeInfo modifierType_Screw = {
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 29bce2ef3a4..d6d8c931c35 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -101,8 +101,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *) md;
- walk(userData, ob, &smd->target, IDWALK_NOP);
- walk(userData, ob, &smd->auxTarget, IDWALK_NOP);
+ walk(userData, ob, &smd->target, IDWALK_CB_NOP);
+ walk(userData, ob, &smd->auxTarget, IDWALK_CB_NOP);
}
static void deformVerts(ModifierData *md, Object *ob,
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 118d0117361..7c12de9059e 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -290,7 +290,7 @@ static void foreachObjectLink(
ObjectWalkFunc walk, void *userData)
{
SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
- walk(userData, ob, &smd->origin, IDWALK_NOP);
+ walk(userData, ob, &smd->origin, IDWALK_CB_NOP);
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index 637ed3ee390..8ba39819b5e 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -152,17 +152,17 @@ static void foreachIDLink(ModifierData *md, Object *ob,
SmokeModifierData *smd = (SmokeModifierData *) md;
if (smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain) {
- walk(userData, ob, (ID **)&smd->domain->coll_group, IDWALK_NOP);
- walk(userData, ob, (ID **)&smd->domain->fluid_group, IDWALK_NOP);
- walk(userData, ob, (ID **)&smd->domain->eff_group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&smd->domain->coll_group, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&smd->domain->fluid_group, IDWALK_CB_NOP);
+ walk(userData, ob, (ID **)&smd->domain->eff_group, IDWALK_CB_NOP);
if (smd->domain->effector_weights) {
- walk(userData, ob, (ID **)&smd->domain->effector_weights->group, IDWALK_NOP);
+ walk(userData, ob, (ID **)&smd->domain->effector_weights->group, IDWALK_CB_NOP);
}
}
if (smd->type == MOD_SMOKE_TYPE_FLOW && smd->flow) {
- walk(userData, ob, (ID **)&smd->flow->noise_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&smd->flow->noise_texture, IDWALK_CB_USER);
}
}
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 54c25b687e1..fdbf4f47ce8 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -92,7 +92,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
int i;
for (i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
- walk(userData, ob, &umd->projectors[i], IDWALK_NOP);
+ walk(userData, ob, &umd->projectors[i], IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -100,7 +100,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
UVProjectModifierData *umd = (UVProjectModifierData *) md;
- walk(userData, ob, (ID **)&umd->image, IDWALK_USER);
+ walk(userData, ob, (ID **)&umd->image, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 2ac6892b7b8..072267fc505 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -221,8 +221,8 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
UVWarpModifierData *umd = (UVWarpModifierData *) md;
- walk(userData, ob, &umd->object_dst, IDWALK_NOP);
- walk(userData, ob, &umd->object_src, IDWALK_NOP);
+ walk(userData, ob, &umd->object_dst, IDWALK_CB_NOP);
+ walk(userData, ob, &umd->object_src, IDWALK_CB_NOP);
}
static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index 13ce72ee2f5..8c6b94e5c79 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -116,16 +116,16 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
{
WarpModifierData *wmd = (WarpModifierData *) md;
- walk(userData, ob, &wmd->object_from, IDWALK_NOP);
- walk(userData, ob, &wmd->object_to, IDWALK_NOP);
- walk(userData, ob, &wmd->map_object, IDWALK_NOP);
+ walk(userData, ob, &wmd->object_from, IDWALK_CB_NOP);
+ walk(userData, ob, &wmd->object_to, IDWALK_CB_NOP);
+ walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WarpModifierData *wmd = (WarpModifierData *) md;
- walk(userData, ob, (ID **)&wmd->texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 291913675c3..a60607cf372 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -111,8 +111,8 @@ static void foreachObjectLink(
{
WaveModifierData *wmd = (WaveModifierData *) md;
- walk(userData, ob, &wmd->objectcenter, IDWALK_NOP);
- walk(userData, ob, &wmd->map_object, IDWALK_NOP);
+ walk(userData, ob, &wmd->objectcenter, IDWALK_CB_NOP);
+ walk(userData, ob, &wmd->map_object, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob,
@@ -120,7 +120,7 @@ static void foreachIDLink(ModifierData *md, Object *ob,
{
WaveModifierData *wmd = (WaveModifierData *) md;
- walk(userData, ob, (ID **)&wmd->texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 585b223d436..57a10a24411 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -126,14 +126,14 @@ static bool dependsOnTime(ModifierData *md)
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
- walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index a6adf72e4eb..9ab8fb4e0ff 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -175,14 +175,14 @@ static bool dependsOnTime(ModifierData *md)
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index b26cbc3a7d3..126a1f951ca 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -325,15 +325,15 @@ static bool dependsOnTime(ModifierData *md)
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- walk(userData, ob, &wmd->proximity_ob_target, IDWALK_NOP);
- walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_NOP);
+ walk(userData, ob, &wmd->proximity_ob_target, IDWALK_CB_NOP);
+ walk(userData, ob, &wmd->mask_tex_map_obj, IDWALK_CB_NOP);
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
{
WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_USER);
+ walk(userData, ob, (ID **)&wmd->mask_texture, IDWALK_CB_USER);
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
diff --git a/source/blender/python/intern/bpy_rna_id_collection.c b/source/blender/python/intern/bpy_rna_id_collection.c
index 1037c83815c..72705ffb3fb 100644
--- a/source/blender/python/intern/bpy_rna_id_collection.c
+++ b/source/blender/python/intern/bpy_rna_id_collection.c
@@ -263,7 +263,7 @@ static PyObject *bpy_user_map(PyObject *UNUSED(self), PyObject *args, PyObject *
}
data_cb.id_curr = id;
- BKE_library_foreach_ID_link(id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_NOP);
+ BKE_library_foreach_ID_link(NULL, id, foreach_libblock_id_user_map_callback, &data_cb, IDWALK_CB_NOP);
if (data_cb.py_id_curr) {
Py_DECREF(data_cb.py_id_curr);
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index a8abc3bb54f..6591005b5f3 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3950,8 +3950,12 @@ static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
}
}
-static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int UNUSED(cd_flag))
+static int previews_id_ensure_callback(void *userdata, ID *UNUSED(self_id), ID **idptr, int cb_flag)
{
+ if (cb_flag & IDWALK_CB_PRIVATE) {
+ return IDWALK_RET_NOP;
+ }
+
PreviewsIDEnsureData *data = userdata;
ID *id = *idptr;
@@ -3984,7 +3988,7 @@ static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op))
preview_id_data.scene = scene;
id = (ID *)scene;
- BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
+ BKE_library_foreach_ID_link(NULL, id, previews_id_ensure_callback, &preview_id_data, IDWALK_RECURSE);
}
/* Check a last time for ID not used (fake users only, in theory), and