diff options
author | Tianwei Shen <shentianweipku@gmail.com> | 2017-02-14 11:41:09 +0300 |
---|---|---|
committer | Tianwei Shen <shentianweipku@gmail.com> | 2017-02-14 11:41:09 +0300 |
commit | 459d429fec1c007b6a80e792a43cd99c5db2656e (patch) | |
tree | 9377c449f5b94b2a99195c362667af81af14e7db /source | |
parent | ea7c4f61daf2373e51af3ab8afae08d4b217562c (diff) | |
parent | 54102ab36eba24977c3a7fa373b95df51e50c123 (diff) |
Merge branch 'master' into soc-2016-multiview
Diffstat (limited to 'source')
115 files changed, 2680 insertions, 2028 deletions
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc index 4ecb9d944f2..282777f3af0 100644 --- a/source/blender/alembic/intern/abc_curves.cc +++ b/source/blender/alembic/intern/abc_curves.cc @@ -102,7 +102,7 @@ void AbcCurveWriter::do_write() const BPoint *point = nurbs->bp; for (int i = 0; i < totpoint; ++i, ++point) { - copy_zup_yup(temp_vert.getValue(), point->vec); + copy_yup_from_zup(temp_vert.getValue(), point->vec); verts.push_back(temp_vert); weights.push_back(point->vec[3]); widths.push_back(point->radius); @@ -118,7 +118,7 @@ void AbcCurveWriter::do_write() /* TODO(kevin): store info about handles, Alembic doesn't have this. */ for (int i = 0; i < totpoint; ++i, ++bezier) { - copy_zup_yup(temp_vert.getValue(), bezier->vec[1]); + copy_yup_from_zup(temp_vert.getValue(), bezier->vec[1]); verts.push_back(temp_vert); widths.push_back(bezier->radius); } @@ -322,7 +322,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) weight = (*weights)[idx]; } - copy_yup_zup(bp->vec, pos.getValue()); + copy_zup_from_yup(bp->vec, pos.getValue()); bp->vec[3] = weight; bp->f1 = SELECT; bp->radius = radius; @@ -389,7 +389,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float t for (int i = 0; i < totpoint; ++i, ++point, ++vertex_idx) { const Imath::V3f &pos = (*positions)[vertex_idx]; - copy_yup_zup(point->vec, pos.getValue()); + copy_zup_from_yup(point->vec, pos.getValue()); } } else if (nurbs->bezt) { @@ -397,7 +397,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float t for (int i = 0; i < totpoint; ++i, ++bezier, ++vertex_idx) { const Imath::V3f &pos = (*positions)[vertex_idx]; - copy_yup_zup(bezier->vec[1], pos.getValue()); + copy_zup_from_yup(bezier->vec[1], pos.getValue()); } } } diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index ff8b0442ab6..d17506ff8b0 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -382,7 +382,10 @@ void AbcExporter::createTransformWritersFlat() void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent) { - createTransformWriter(ob, parent, dupliObParent); + + if (export_object(&m_settings, ob) && object_is_shape(ob)) { + createTransformWriter(ob, parent, dupliObParent); + } ListBase *lb = object_duplilist(eval_ctx, m_scene, ob); @@ -410,8 +413,12 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl { const std::string name = get_object_dag_path_name(ob, dupliObParent); + /* An object should not be its own parent, or we'll get infinite loops. */ + BLI_assert(ob != parent); + BLI_assert(ob != dupliObParent); + /* check if we have already created a transform writer for this object */ - if (m_xforms.find(name) != m_xforms.end()){ + if (getXForm(name) != NULL){ std::cerr << "xform " << name << " already exists\n"; return; } @@ -426,6 +433,14 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl if (parent->parent) { createTransformWriter(parent, parent->parent, dupliObParent); } + else if (parent == dupliObParent) { + if (dupliObParent->parent == NULL) { + createTransformWriter(parent, NULL, NULL); + } + else { + createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent); + } + } else { createTransformWriter(parent, dupliObParent, dupliObParent); } diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc index 14bcf6731ea..e328df24e53 100644 --- a/source/blender/alembic/intern/abc_hair.cc +++ b/source/blender/alembic/intern/abc_hair.cc @@ -77,7 +77,6 @@ void AbcHairWriter::do_write() DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH); DM_ensure_tessface(dm); - DM_update_tessface_data(dm); std::vector<Imath::V3f> verts; std::vector<int32_t> hvertices; @@ -164,7 +163,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm, psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, normal, NULL, NULL, NULL, NULL); - copy_zup_yup(tmp_nor.getValue(), normal); + copy_yup_from_zup(tmp_nor.getValue(), normal); norm_values.push_back(tmp_nor); } } @@ -198,7 +197,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm, MVert *mv = mverts + vtx[o]; normal_short_to_float_v3(normal, mv->no); - copy_zup_yup(tmp_nor.getValue(), normal); + copy_yup_from_zup(tmp_nor.getValue(), normal); norm_values.push_back(tmp_nor); found = true; break; diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index bdd75f93189..8bc9c335054 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -112,7 +112,7 @@ static void get_vertices(DerivedMesh *dm, std::vector<Imath::V3f> &points) MVert *verts = dm->getVertArray(dm); for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) { - copy_zup_yup(points[i].getValue(), verts[i].co); + copy_yup_from_zup(points[i].getValue(), verts[i].co); } } @@ -182,7 +182,7 @@ static void get_vertex_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) { normal_short_to_float_v3(no, verts[i].no); - copy_zup_yup(normals[i].getValue(), no); + copy_yup_from_zup(normals[i].getValue(), no); } } @@ -211,7 +211,7 @@ static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals) for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { const int index = ml->v; - copy_zup_yup(normals[loop_index].getValue(), lnors[index]); + copy_yup_from_zup(normals[loop_index].getValue(), lnors[index]); } } } @@ -226,14 +226,14 @@ static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals) BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no); for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { - copy_zup_yup(normals[loop_index].getValue(), no); + copy_yup_from_zup(normals[loop_index].getValue(), no); } } else { /* Smooth shaded, use individual vert normals. */ for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { normal_short_to_float_v3(no, verts[ml->v].no); - copy_zup_yup(normals[loop_index].getValue(), no); + copy_yup_from_zup(normals[loop_index].getValue(), no); } } } @@ -590,7 +590,7 @@ void AbcMeshWriter::getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities); for (int i = 0; i < totverts; ++i) { - copy_zup_yup(vels[i].getValue(), mesh_vels); + copy_yup_from_zup(vels[i].getValue(), mesh_vels); mesh_vels += 3; } } @@ -726,7 +726,7 @@ static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions const Imath::V3f &ceil_pos = (*ceil_positions)[i]; interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight); - copy_yup_zup(mvert.co, tmp); + copy_zup_from_yup(mvert.co, tmp); mvert.bweight = 0; } @@ -755,7 +755,7 @@ void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArr MVert &mvert = mverts[i]; Imath::V3f pos_in = (*positions)[i]; - copy_yup_zup(mvert.co, pos_in.getValue()); + copy_zup_from_yup(mvert.co, pos_in.getValue()); mvert.bweight = 0; @@ -765,7 +765,7 @@ void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArr short no[3]; normal_float_to_short_v3(no, nor_in.getValue()); - copy_yup_zup(mvert.no, no); + copy_zup_from_yup(mvert.no, no); } } } diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc index 4f57dfdae9e..d0b9561f679 100644 --- a/source/blender/alembic/intern/abc_nurbs.cc +++ b/source/blender/alembic/intern/abc_nurbs.cc @@ -153,7 +153,7 @@ void AbcNurbsWriter::do_write() const BPoint *bp = nu->bp; for (int i = 0; i < size; ++i, ++bp) { - copy_zup_yup(positions[i].getValue(), bp->vec); + copy_yup_from_zup(positions[i].getValue(), bp->vec); weights[i] = bp->vec[3]; } @@ -281,7 +281,7 @@ void AbcNurbsReader::readObjectData(Main *bmain, float time) posw_in = (*weights)[i]; } - copy_yup_zup(bp->vec, pos_in.getValue()); + copy_zup_from_yup(bp->vec, pos_in.getValue()); bp->vec[3] = posw_in; bp->f1 = SELECT; bp->radius = 1.0f; diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index 9dfccdb8c7f..a5b8af542fc 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -97,14 +97,14 @@ Imath::Box3d AbcObjectWriter::bounds() return Imath::Box3d(); } - /* Convert Z-up to Y-up. */ + /* Convert Z-up to Y-up. This also changes which vector goes into which min/max property. */ this->m_bounds.min.x = bb->vec[0][0]; this->m_bounds.min.y = bb->vec[0][2]; - this->m_bounds.min.z = -bb->vec[0][1]; + this->m_bounds.min.z = -bb->vec[6][1]; this->m_bounds.max.x = bb->vec[6][0]; this->m_bounds.max.y = bb->vec[6][2]; - this->m_bounds.max.z = -bb->vec[6][1]; + this->m_bounds.max.z = -bb->vec[0][1]; return this->m_bounds; } diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index e2fc7674c4e..368a811bb2a 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -146,6 +146,6 @@ bool AbcEmptyReader::valid() const void AbcEmptyReader::readObjectData(Main *bmain, float /*time*/) { - m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str()); + m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_data_name.c_str()); m_object->data = NULL; } diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc index f8ce72d845d..08c94f437e6 100644 --- a/source/blender/alembic/intern/abc_util.cc +++ b/source/blender/alembic/intern/abc_util.cc @@ -197,7 +197,7 @@ void create_transform_matrix(float r_mat[4][4]) copy_m4_m3(transform_mat, rot_mat); /* Add translation to transformation matrix. */ - copy_yup_zup(transform_mat[3], loc); + copy_zup_from_yup(transform_mat[3], loc); /* Create scale matrix. */ scale_mat[0][0] = scale[0]; @@ -417,7 +417,7 @@ void create_transform_matrix(Object *obj, float transform_mat[4][4]) copy_m4_m3(transform_mat, rot_mat); /* Add translation to transformation matrix. */ - copy_zup_yup(transform_mat[3], loc); + copy_yup_from_zup(transform_mat[3], loc); /* Create scale matrix. */ scale_mat[0][0] = scale[0]; diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h index 60a96855d14..a7ac9df91c7 100644 --- a/source/blender/alembic/intern/abc_util.h +++ b/source/blender/alembic/intern/abc_util.h @@ -116,14 +116,14 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe /* Copy from Y-up to Z-up. */ -ABC_INLINE void copy_yup_zup(float zup[3], const float yup[3]) +ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3]) { zup[0] = yup[0]; zup[1] = -yup[2]; zup[2] = yup[1]; } -ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3]) +ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3]) { zup[0] = yup[0]; zup[1] = -yup[2]; @@ -132,14 +132,14 @@ ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3]) /* Copy from Z-up to Y-up. */ -ABC_INLINE void copy_zup_yup(float yup[3], const float zup[3]) +ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3]) { yup[0] = zup[0]; yup[1] = zup[2]; yup[2] = -zup[1]; } -ABC_INLINE void copy_zup_yup(short yup[3], const short zup[3]) +ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3]) { yup[0] = zup[0]; yup[1] = zup[2]; diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 07db2217bac..bf45a27e51c 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -133,6 +133,12 @@ BVHTree *bvhtree_from_editmesh_edges_ex( BVHTree *bvhtree_from_mesh_edges( struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); +BVHTree *bvhtree_from_mesh_edges_ex( + struct BVHTreeFromMesh *data, + struct MVert *vert, const bool vert_allocated, + struct MEdge *edge, const int edges_num, const bool edge_allocated, + const BLI_bitmap *edges_mask, int edges_num_active, + float epsilon, int tree_type, int axis); BVHTree *bvhtree_from_mesh_faces( struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 9948f21ba90..4876461bfe0 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -79,6 +79,7 @@ DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispba */ struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm); struct DerivedMesh *CDDM_copy_from_tessface(struct DerivedMesh *dm); +struct DerivedMesh *CDDM_copy_with_tessface(struct DerivedMesh *dm); /* creates a CDDerivedMesh with the same layer stack configuration as the * given DerivedMesh and containing the requested numbers of elements. 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 531be9e6e33..b241b5ca5b7 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 cf07a178fe8..d812ab832a1 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/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 1c5ea946f59..9a60eb29957 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -42,6 +42,7 @@ struct Brush; struct ColorBand; struct EnvMap; struct FreestyleLineStyle; +struct ImagePool; struct Lamp; struct Main; struct Material; @@ -133,6 +134,12 @@ struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot); bool BKE_texture_dependsOnTime(const struct Tex *texture); bool BKE_texture_is_image_user(const struct Tex *tex); +void BKE_texture_get_value_ex( + const struct Scene *scene, struct Tex *texture, + float *tex_co, struct TexResult *texres, + struct ImagePool *pool, + bool use_color_management); + void BKE_texture_get_value( const struct Scene *scene, struct Tex *texture, float *tex_co, struct TexResult *texres, bool use_color_management); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 0287d6ae9ca..02cc31e5977 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1037,6 +1037,17 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float if (use_dverts) { defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone"); defnrToPCIndex = MEM_callocN(sizeof(*defnrToPCIndex) * defbase_tot, "defnrToIndex"); + /* TODO(sergey): Some considerations here: + * + * - Make it more generic function, maybe even keep together with chanhash. + * - Check whether keeping this consistent across frames gives speedup. + * - Don't use hash for small armatures. + */ + GHash *idx_hash = BLI_ghash_ptr_new("pose channel index by name"); + int pchan_index = 0; + for (pchan = armOb->pose->chanbase.first; pchan != NULL; pchan = pchan->next, ++pchan_index) { + BLI_ghash_insert(idx_hash, pchan, SET_INT_IN_POINTER(pchan_index)); + } for (i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) { defnrToPC[i] = BKE_pose_channel_find_name(armOb->pose, dg->name); /* exclude non-deforming bones */ @@ -1045,10 +1056,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float defnrToPC[i] = NULL; } else { - defnrToPCIndex[i] = BLI_findindex(&armOb->pose->chanbase, defnrToPC[i]); + defnrToPCIndex[i] = GET_INT_FROM_POINTER(BLI_ghash_lookup(idx_hash, defnrToPC[i])); } } } + BLI_ghash_free(idx_hash, NULL, NULL); } } } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index a8670395fc4..afd60102453 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -234,7 +234,7 @@ int BKE_blender_test_break(void) * \note Don't use MEM_mallocN so functions can be registered at any time. * \{ */ -struct AtExitData { +static struct AtExitData { struct AtExitData *next; void (*func)(void *user_data); 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/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 264d87b86f3..d0e0c82e3be 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -376,6 +376,45 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r } } +#define V3_MUL_ELEM(a, b) \ + (a)[0] * (b)[0], \ + (a)[1] * (b)[1], \ + (a)[2] * (b)[2] + +/* Callback to bvh tree nearest edge to ray. + * The tree must have been built using bvhtree_from_mesh_edges. + * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */ +static void mesh_edges_nearest_to_ray( + void *userdata, const float ray_co[3], const float ray_dir[3], + const float scale[3], int index, BVHTreeNearest *nearest) +{ + struct BVHTreeFromMesh *data = userdata; + const MVert *vert = data->vert; + const MEdge *e = &data->edge[index]; + + const float t0[3] = {V3_MUL_ELEM(vert[e->v1].co, scale)}; + const float t1[3] = {V3_MUL_ELEM(vert[e->v2].co, 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, point[3]; + const float dist_sq = dist_squared_ray_to_seg_v3(origin_sc, dir_sc, t0, t1, point, &depth); + + if (dist_sq < nearest->dist_sq) { + nearest->dist_sq = dist_sq; + nearest->index = index; + + point[0] /= scale[0]; + point[1] /= scale[1]; + point[2] /= scale[2]; + + copy_v3_v3(nearest->co, point); + sub_v3_v3v3(nearest->no, t0, t1); + } +} + +#undef V3_MUL_ELEM + /** \} */ /* @@ -393,8 +432,6 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree( BMEditMesh *em, const int verts_num, const BLI_bitmap *verts_mask, int verts_num_active) { - BVHTree *tree = NULL; - int i; BM_mesh_elem_table_ensure(em->bm, BM_VERT); if (verts_mask) { BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); @@ -403,15 +440,14 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree( verts_num_active = verts_num; } - tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis); + BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis); if (tree) { - BMIter iter; - BMVert *eve; - BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + for (int i = 0; i < verts_num; i++) { if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) { continue; } + BMVert *eve = BM_vert_at_index(em->bm, i); BLI_bvhtree_insert(tree, i, eve->co, 1); } BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active); @@ -426,28 +462,25 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree( MVert *vert, const int verts_num, const BLI_bitmap *verts_mask, int verts_num_active) { - BVHTree *tree = NULL; - int i; - if (vert) { - if (verts_mask) { - BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); - } - else { - verts_num_active = verts_num; - } + BLI_assert(vert != NULL); + if (verts_mask) { + BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num)); + } + else { + verts_num_active = verts_num; + } - tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis); + BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis); - if (tree) { - for (i = 0; i < verts_num; i++) { - if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) { - continue; - } - BLI_bvhtree_insert(tree, i, vert[i].co, 1); + if (tree) { + for (int i = 0; i < verts_num; i++) { + if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) { + continue; } - BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active); - BLI_bvhtree_balance(tree); + BLI_bvhtree_insert(tree, i, vert[i].co, 1); } + BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active); + BLI_bvhtree_balance(tree); } return tree; @@ -488,11 +521,9 @@ BVHTree *bvhtree_from_editmesh_verts_ex( const BLI_bitmap *verts_mask, int verts_num_active, float epsilon, int tree_type, int axis) { - int vert_num = em->bm->totvert; - BVHTree *tree = bvhtree_from_editmesh_verts_create_tree( epsilon, tree_type, axis, - em, vert_num, verts_mask, verts_num_active); + em, em->bm->totvert, verts_mask, verts_num_active); if (tree) { memset(data, 0, sizeof(*data)); @@ -505,6 +536,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex( return tree; } + BVHTree *bvhtree_from_editmesh_verts( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) @@ -515,8 +547,8 @@ BVHTree *bvhtree_from_editmesh_verts( epsilon, tree_type, axis); } - -/* Builds a bvh tree where nodes are the vertices of the given dm */ +/* Builds a bvh tree where nodes are the vertices of the given dm + * and stores the BVHTree in dm->bvhCache */ BVHTree *bvhtree_from_mesh_verts( BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis) @@ -557,7 +589,8 @@ BVHTree *bvhtree_from_mesh_verts( } /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated); + bvhtree_from_mesh_verts_setup_data( + data, tree, true, epsilon, vert, vert_allocated); return data->tree; } @@ -577,7 +610,8 @@ BVHTree *bvhtree_from_mesh_verts_ex( epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active); /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_verts_setup_data(data, tree, false, epsilon, vert, vert_allocated); + bvhtree_from_mesh_verts_setup_data( + data, tree, false, epsilon, vert, vert_allocated); return data->tree; } @@ -595,8 +629,6 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree( BMEditMesh *em, const int edges_num, const BLI_bitmap *edges_mask, int edges_num_active) { - BVHTree *tree = NULL; - int i; BM_mesh_elem_table_ensure(em->bm, BM_EDGE); if (edges_mask) { BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edges_num)); @@ -605,9 +637,10 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree( edges_num_active = edges_num; } - tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis); + BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis); if (tree) { + int i; BMIter iter; BMEdge *eed; BM_ITER_MESH_INDEX (eed, &iter, em->bm, BM_EDGES_OF_MESH, i) { @@ -627,6 +660,70 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree( return tree; } +static BVHTree *bvhtree_from_mesh_edges_create_tree( + MVert *vert, MEdge *edge, const int edge_num, + const BLI_bitmap *edges_mask, int edges_num_active, + float epsilon, int tree_type, int axis) +{ + if (edges_mask) { + BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edge_num)); + } + else { + edges_num_active = edge_num; + } + BLI_assert(vert != NULL); + BLI_assert(edge != NULL); + + /* Create a bvh-tree of the given target */ + BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis); + if (tree) { + for (int i = 0; i < edge_num; i++) { + if (edges_mask && !BLI_BITMAP_TEST_BOOL(edges_mask, i)) { + continue; + } + float co[2][3]; + copy_v3_v3(co[0], vert[edge[i].v1].co); + copy_v3_v3(co[1], vert[edge[i].v2].co); + + BLI_bvhtree_insert(tree, i, co[0], 2); + } + BLI_bvhtree_balance(tree); + } + + return tree; +} + +static void bvhtree_from_mesh_edges_setup_data( + BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon, + MVert *vert, const bool vert_allocated, MEdge *edge, const bool edge_allocated) +{ + memset(data, 0, sizeof(*data)); + data->tree = tree; + + if (data->tree) { + data->cached = is_cached; + + data->nearest_callback = mesh_edges_nearest_point; + data->raycast_callback = mesh_edges_spherecast; + data->nearest_to_ray_callback = mesh_edges_nearest_to_ray; + + data->vert = vert; + data->vert_allocated = vert_allocated; + data->edge = edge; + data->edge_allocated = edge_allocated; + + data->sphere_radius = epsilon; + } + else { + if (vert_allocated) { + MEM_freeN(vert); + } + if (edge_allocated) { + MEM_freeN(edge); + } + } +} + /* Builds a bvh tree where nodes are the edges of the given em */ BVHTree *bvhtree_from_editmesh_edges_ex( BVHTreeFromEditMesh *data, BMEditMesh *em, @@ -651,6 +748,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex( return tree; } + BVHTree *bvhtree_from_editmesh_edges( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) @@ -683,27 +781,13 @@ BVHTree *bvhtree_from_mesh_edges( BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); tree = bvhcache_find(dm->bvhCache, BVHTREE_FROM_EDGES); if (tree == NULL) { - int i; - int numEdges = dm->getNumEdges(dm); - - if (vert != NULL && edge != NULL) { - /* Create a bvh-tree of the given target */ - tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis); - if (tree != NULL) { - for (i = 0; i < numEdges; i++) { - float co[2][3]; - copy_v3_v3(co[0], vert[edge[i].v1].co); - copy_v3_v3(co[1], vert[edge[i].v2].co); - - BLI_bvhtree_insert(tree, i, co[0], 2); - } - BLI_bvhtree_balance(tree); + tree = bvhtree_from_mesh_edges_create_tree( + vert, edge, dm->getNumEdges(dm), + NULL, -1, epsilon, tree_type, axis); - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES); - } - } + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES); } BLI_rw_mutex_unlock(&cache_rwlock); } @@ -711,33 +795,34 @@ BVHTree *bvhtree_from_mesh_edges( /* printf("BVHTree is already build, using cached tree\n"); */ } - /* Setup BVHTreeFromMesh */ - memset(data, 0, sizeof(*data)); - data->tree = tree; + bvhtree_from_mesh_edges_setup_data( + data, tree, true, epsilon, vert, vert_allocated, edge, edge_allocated); - if (data->tree) { - data->cached = true; + return data->tree; +} - data->nearest_callback = mesh_edges_nearest_point; - data->raycast_callback = mesh_edges_spherecast; - data->nearest_to_ray_callback = NULL; +/** + * Builds a bvh tree where nodes are the given edges . + * \param vert/edge_allocated if true, elem freeing will be done when freeing data. + * \param edges_mask if not null, true elements give which vert to add to BVH tree. + * \param edges_num_active if >= 0, number of active edges to add to BVH tree (else will be computed from mask). + */ +BVHTree *bvhtree_from_mesh_edges_ex( + BVHTreeFromMesh *data, + MVert *vert, const bool vert_allocated, + MEdge *edge, const int edges_num, const bool edge_allocated, + const BLI_bitmap *edges_mask, int edges_num_active, + float epsilon, int tree_type, int axis) +{ + BVHTree *tree = bvhtree_from_mesh_edges_create_tree( + vert, edge, edges_num, edges_mask, edges_num_active, + epsilon, tree_type, axis); - data->vert = vert; - data->vert_allocated = vert_allocated; - data->edge = edge; - data->edge_allocated = edge_allocated; + /* Setup BVHTreeFromMesh */ + bvhtree_from_mesh_edges_setup_data( + data, tree, false, epsilon, vert, vert_allocated, edge, edge_allocated); - data->sphere_radius = epsilon; - } - else { - if (vert_allocated) { - MEM_freeN(vert); - } - if (edge_allocated) { - MEM_freeN(edge); - } - } return data->tree; } 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/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index f2dd2a3fcf6..483fa977aff 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2398,21 +2398,28 @@ DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps, const bo use_tessface, em->tottri, (const BMLoop *(*)[3])em->looptris); } -static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) +static DerivedMesh *cddm_copy_ex(DerivedMesh *source, + const bool need_tessface_data, + const bool faces_from_tessfaces) { + const bool copy_tessface_data = (faces_from_tessfaces || need_tessface_data); CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); DerivedMesh *dm = &cddm->dm; int numVerts = source->numVertData; int numEdges = source->numEdgeData; - int numTessFaces = source->numTessFaceData; + int numTessFaces = copy_tessface_data ? source->numTessFaceData : 0; int numLoops = source->numLoopData; int numPolys = source->numPolyData; + /* NOTE: Don't copy tessellation faces if not requested explicitly. */ + /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getTessFaceDataArray(source, CD_ORIGINDEX); source->getPolyDataArray(source, CD_ORIGINDEX); + if (copy_tessface_data) { + source->getTessFaceDataArray(source, CD_ORIGINDEX); + } /* this initializes dm, and copies all non mvert/medge/mface layers */ DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, @@ -2421,23 +2428,33 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) dm->cd_flag = source->cd_flag; dm->dirty = source->dirty; + /* Tessellation data is never copied, so tag it here. */ + dm->dirty |= DM_DIRTY_TESS_CDLAYERS; + CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges); - CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces); + if (copy_tessface_data) { + CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces); + } /* now add mvert/medge/mface layers */ cddm->mvert = source->dupVertArray(source); cddm->medge = source->dupEdgeArray(source); - cddm->mface = source->dupTessFaceArray(source); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges); - CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces); - - if (!faces_from_tessfaces) + + if (faces_from_tessfaces || copy_tessface_data) { + cddm->mface = source->dupTessFaceArray(source); + CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces); + } + + if (!faces_from_tessfaces) { DM_DupPolys(source, dm); - else + } + else { CDDM_tessfaces_to_faces(dm); + } cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); @@ -2447,12 +2464,17 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) DerivedMesh *CDDM_copy(DerivedMesh *source) { - return cddm_copy_ex(source, 0); + return cddm_copy_ex(source, false, false); } DerivedMesh *CDDM_copy_from_tessface(DerivedMesh *source) { - return cddm_copy_ex(source, 1); + return cddm_copy_ex(source, false, true); +} + +DerivedMesh *CDDM_copy_with_tessface(DerivedMesh *source) +{ + return cddm_copy_ex(source, true, false); } /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 98d37fb07bf..c9f0b8ec9ca 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -2595,7 +2595,7 @@ bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, Custom if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT)) return false; -#undef TEST_RET +#undef LAYER_CMP /* if no layers are on either CustomData's, * then there was nothing to do... */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index a8341939692..294a4ce76b7 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2563,7 +2563,7 @@ void DAG_on_visible_update(Main *bmain, const bool do_time) } static void dag_id_flush_update__isDependentTexture( - void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag)) + void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cb_flag)) { struct { ID *id; bool is_dependent; } *data = userData; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index a2d94ccc478..318f6480aaf 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -3159,7 +3159,7 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons struct ImBuf *ibuf; char name[FILE_MAX]; int flag; - ImageUser iuser_t; + ImageUser iuser_t = {0}; /* XXX temp stuff? */ if (ima->lastframe != frame) @@ -3167,8 +3167,12 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons ima->lastframe = frame; - if (iuser) + if (iuser) { iuser_t = *iuser; + } + else { + /* TODO(sergey): Do we need to initialize something here? */ + } iuser_t.view = view_id; BKE_image_user_file_path(&iuser_t, ima, name); diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index d098366aef4..69a2067f4e6 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -174,15 +174,10 @@ void BKE_lamp_make_local(Main *bmain, Lamp *la, const bool lib_local) void BKE_lamp_free(Lamp *la) { - MTex *mtex; int a; for (a = 0; a < MAX_MTEX; a++) { - mtex = la->mtex[a]; - if (mtex && mtex->tex) - id_us_min(&mtex->tex->id); - if (mtex) - MEM_freeN(mtex); + MEM_SAFE_FREE(la->mtex[a]); } BKE_animdata_free((ID *)la, false); @@ -193,6 +188,7 @@ void BKE_lamp_free(Lamp *la) if (la->nodetree) { ntreeFreeTree(la->nodetree); MEM_freeN(la->nodetree); + la->nodetree = NULL; } BKE_previewimg_free(&la->preview); diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 77013a55d18..6b4b492b212 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 fa75c906fb1..9685f1f5af6 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -84,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); \ } \ @@ -129,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; @@ -140,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; } @@ -161,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; } @@ -207,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); @@ -230,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) { @@ -250,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. */ @@ -276,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; } /** @@ -285,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; @@ -313,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) { @@ -326,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: @@ -336,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); } } } @@ -377,39 +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_NOP); - CALLBACK_INVOKE(toolsett->particle.object, IDWALK_NOP); - CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_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); 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); @@ -419,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); @@ -430,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; } @@ -441,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); } } @@ -521,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); } } @@ -537,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 @@ -552,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); } } } @@ -562,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); } } } @@ -573,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; } @@ -591,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; } @@ -606,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; } @@ -617,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; } @@ -650,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; } @@ -658,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; } @@ -669,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; } @@ -690,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; } @@ -698,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; } @@ -707,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; } @@ -716,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; } @@ -726,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; @@ -737,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]) { @@ -749,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) { @@ -769,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); } } } @@ -789,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; } @@ -816,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); } } } @@ -834,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); } } } @@ -849,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); } } } @@ -857,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); } } } @@ -868,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; } @@ -891,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) { @@ -909,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); } } @@ -1049,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 { @@ -1080,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; } @@ -1109,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); } @@ -1160,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); } @@ -1237,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); } } } @@ -1264,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.c b/source/blender/blenkernel/intern/particle.c index 1ea27558545..228ae6afaba 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -633,8 +633,9 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa data->childcachebufs.last = psys->childcachebufs.last; data->totchildcache = psys->totchildcache; - if (psmd->dm_final) - data->dm = CDDM_copy(psmd->dm_final); + if (psmd->dm_final) { + data->dm = CDDM_copy_with_tessface(psmd->dm_final); + } data->totdmvert = psmd->totdmvert; data->totdmedge = psmd->totdmedge; data->totdmface = psmd->totdmface; 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 b5f34a29ebb..5353cc26295 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/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 1d2f5aee440..6a491ba5ec4 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -480,55 +480,74 @@ void BKE_sequencer_editing_free(Scene *scene) static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) { - if (ibuf->rect_float) { + if (ibuf->rect != NULL) { + IMB_colormanagement_assign_rect_colorspace(ibuf, scene->sequencer_colorspace_settings.name); + } + if (ibuf->rect_float != NULL) { IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name); } } void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make_float) { - const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + /* Early output check: if both buffers are NULL we have nothing to convert. */ + if (ibuf->rect_float == NULL && ibuf->rect == NULL) { + return; + } + /* Get common conversion settings. */ const char *to_colorspace = scene->sequencer_colorspace_settings.name; - const char *float_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); - - if (!ibuf->rect_float) { - if (ibuf->rect) { - const char *byte_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf); - if (make_float || !STREQ(to_colorspace, byte_colorspace)) { - /* If byte space is not in sequencer's working space, we deliver float color space, - * this is to to prevent data loss. - */ - - /* when converting byte buffer to float in sequencer we need to make float - * buffer be in sequencer's working space, which is currently only doable - * from linear space. - */ - - /* - * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's - */ - - IMB_float_from_rect(ibuf); - } - else { - return; - } + /* Perform actual conversion logic. */ + if (ibuf->rect_float == NULL) { + /* We are not requested to give float buffer and byte buffer is already + * in thee required colorspace. Can skip doing anything here. + */ + const char *from_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf); + if (!make_float && STREQ(from_colorspace, to_colorspace)) { + return; + } + if (false) { + /* The idea here is to provide as fast playback as possible and + * enforcing float buffer here (a) uses more cache memory (b) might + * make some other effects slower to apply. + * + * However, this might also have negative effect by adding weird + * artifacts which will then not happen in final render. + */ + IMB_colormanagement_transform_byte_threaded( + (unsigned char*)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace); } else { - return; + /* We perform conversion to a float buffer so we don't worry about + * precision loss. + */ + imb_addrectfloatImBuf(ibuf); + IMB_colormanagement_transform_from_byte_threaded( + ibuf->rect_float, (unsigned char*)ibuf->rect, + ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace); + /* We don't need byte buffer anymore. */ + imb_freerectImBuf(ibuf); } } - - if (from_colorspace && from_colorspace[0] != '\0') { - if (ibuf->rect) + else { + const char *from_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); + /* Unknown input color space, can't perform conversion. */ + if (from_colorspace == NULL || from_colorspace[0] == '\0') { + return; + } + /* We don't want both byte and float buffers around: they'll either run + * out of sync or conversion of byte buffer will loose precision in there. + */ + if (ibuf->rect != NULL) { imb_freerectImBuf(ibuf); - - if (!STREQ(float_colorspace, to_colorspace)) { - IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, true); - sequencer_imbuf_assign_spaces(scene, ibuf); } + IMB_colormanagement_transform_threaded(ibuf->rect_float, + ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, + true); } + sequencer_imbuf_assign_spaces(scene, ibuf); } void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 22288127119..8469351c54a 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -147,12 +147,12 @@ void BKE_sound_free(bSound *sound) BKE_sound_free_waveform(sound); +#endif /* WITH_AUDASPACE */ if (sound->spinlock) { BLI_spin_end(sound->spinlock); MEM_freeN(sound->spinlock); sound->spinlock = NULL; - } -#endif /* WITH_AUDASPACE */ + } } void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 88575c7d3be..298790a9e9b 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -1935,7 +1935,7 @@ void txt_do_undo(Text *text) int op = text->undo_buf[text->undo_pos]; int prev_flags; unsigned int linep; - unsigned int uchar; + unsigned int uni_char; unsigned int curln, selln; unsigned short curc, selc; unsigned short charp; @@ -1971,14 +1971,14 @@ void txt_do_undo(Text *text) case UNDO_BS_3: case UNDO_BS_4: charp = op - UNDO_BS_1 + 1; - uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); /* get and restore the cursors */ txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); txt_move_to(text, curln, curc, 0); txt_move_to(text, curln, curc, 1); - txt_add_char(text, uchar); + txt_add_char(text, uni_char); text->undo_pos--; break; @@ -1988,14 +1988,14 @@ void txt_do_undo(Text *text) case UNDO_DEL_3: case UNDO_DEL_4: charp = op - UNDO_DEL_1 + 1; - uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); /* get and restore the cursors */ txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); txt_move_to(text, curln, curc, 0); txt_move_to(text, curln, curc, 1); - txt_add_char(text, uchar); + txt_add_char(text, uni_char); txt_move_left(text, 0); @@ -2163,7 +2163,7 @@ void txt_do_redo(Text *text) char *buf; unsigned int linep; unsigned short charp; - unsigned int uchar; + unsigned int uni_uchar; unsigned int curln, selln; unsigned short curc, selc; @@ -2190,9 +2190,9 @@ void txt_do_redo(Text *text) txt_move_to(text, curln, curc, 1); charp = op - UNDO_INSERT_1 + 1; - uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp); + uni_uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp); - txt_add_char(text, uchar); + txt_add_char(text, uni_uchar); break; case UNDO_BS_1: diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 2d3ecad19ad..60990c03b0e 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -1485,9 +1485,11 @@ bool BKE_texture_dependsOnTime(const struct Tex *texture) /* ------------------------------------------------------------------------- */ -void BKE_texture_get_value( +void BKE_texture_get_value_ex( const Scene *scene, Tex *texture, - float *tex_co, TexResult *texres, bool use_color_management) + float *tex_co, TexResult *texres, + struct ImagePool *pool, + bool use_color_management) { int result_type; bool do_color_manage = false; @@ -1497,7 +1499,7 @@ void BKE_texture_get_value( } /* no node textures for now */ - result_type = multitex_ext_safe(texture, tex_co, texres, NULL, do_color_manage, false); + result_type = multitex_ext_safe(texture, tex_co, texres, pool, do_color_manage, false); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, since this is in the context of modifiers don't use perceptual color conversion. @@ -1510,3 +1512,10 @@ void BKE_texture_get_value( copy_v3_fl(&texres->tr, texres->tin); } } + +void BKE_texture_get_value( + const Scene *scene, Tex *texture, + float *tex_co, TexResult *texres, bool use_color_management) +{ + BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management); +} diff --git a/source/blender/blenlib/BLI_dynlib.h b/source/blender/blenlib/BLI_dynlib.h index 7d5eb888021..310db9ea051 100644 --- a/source/blender/blenlib/BLI_dynlib.h +++ b/source/blender/blenlib/BLI_dynlib.h @@ -34,7 +34,7 @@ typedef struct DynamicLibrary DynamicLibrary; -DynamicLibrary *BLI_dynlib_open(char *name); +DynamicLibrary *BLI_dynlib_open(const char *name); void *BLI_dynlib_find_symbol(DynamicLibrary *lib, const char *symname); char *BLI_dynlib_get_error_as_string(DynamicLibrary *lib); void BLI_dynlib_close(DynamicLibrary *lib); 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/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h index 7929e1d6551..9d8222c575d 100644 --- a/source/blender/blenlib/BLI_sys_types.h +++ b/source/blender/blenlib/BLI_sys_types.h @@ -80,6 +80,11 @@ typedef uint64_t u_int64_t; #include <stddef.h> /* size_t define */ #include <stdbool.h> +typedef unsigned int uint; +typedef unsigned short ushort; +typedef unsigned long ulong; +typedef unsigned char uchar; + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/PIL_time_utildefines.h b/source/blender/blenlib/PIL_time_utildefines.h index 9157e04a7bf..412cfb3a090 100644 --- a/source/blender/blenlib/PIL_time_utildefines.h +++ b/source/blender/blenlib/PIL_time_utildefines.h @@ -80,9 +80,10 @@ } \ const float _delta_##var = TIMEIT_VALUE(var); \ _sum_##var += _delta_##var; \ + _num_##var++; \ printf("time end (" #var "): %.6f" " " AT "\n", _delta_##var); \ - printf("time averaged (" #var "): %.6f" " " AT "\n", \ - (_sum_##var / ++_num_##var)); \ + printf("time averaged (" #var "): %.6f (total: %.6f, in %d runs)\n", \ + (_sum_##var / _num_##var), _sum_##var, (int)_num_##var); \ fflush(stdout); \ } (void)0 diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c index b47c2ee60a6..51b91fb360f 100644 --- a/source/blender/blenlib/intern/dynlib.c +++ b/source/blender/blenlib/intern/dynlib.c @@ -50,7 +50,7 @@ struct DynamicLibrary { #include "utf_winfunc.h" #include "utfconv.h" -DynamicLibrary *BLI_dynlib_open(char *name) +DynamicLibrary *BLI_dynlib_open(const char *name) { DynamicLibrary *lib; void *handle; @@ -106,7 +106,7 @@ void BLI_dynlib_close(DynamicLibrary *lib) #include <dlfcn.h> -DynamicLibrary *BLI_dynlib_open(char *name) +DynamicLibrary *BLI_dynlib_open(const char *name) { DynamicLibrary *lib; void *handle = dlopen(name, RTLD_LAZY); 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 17651c2e83a..971f5d54b10 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4708,12 +4708,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); } } @@ -9324,7 +9324,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; @@ -10416,6 +10416,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) else { mainptr->curlib->filedata = NULL; mainptr->curlib->id.tag |= LIB_TAG_MISSING; + /* Set lib version to current main one... Makes assert later happy. */ + mainptr->versionfile = mainptr->curlib->versionfile = mainl->versionfile; + mainptr->subversionfile = mainptr->curlib->subversionfile = mainl->subversionfile; } if (fd == NULL) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index b4cdd180945..106943d15dc 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -799,22 +799,18 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) static void write_actions(WriteData *wd, ListBase *idbase) { - bAction *act; - bActionGroup *grp; - TimeMarker *marker; - - for (act = idbase->first; act; act = act->id.next) { + for (bAction *act = idbase->first; act; act = act->id.next) { if (act->id.us > 0 || wd->current) { writestruct(wd, ID_AC, bAction, 1, act); write_iddata(wd, &act->id); write_fcurves(wd, &act->curves); - for (grp = act->groups.first; grp; grp = grp->next) { + for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) { writestruct(wd, DATA, bActionGroup, 1, grp); } - for (marker = act->markers.first; marker; marker = marker->next) { + for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { writestruct(wd, DATA, TimeMarker, 1, marker); } } @@ -1280,13 +1276,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches) } static void write_particlesettings(WriteData *wd, ListBase *idbase) { - ParticleSettings *part; - ParticleDupliWeight *dw; - GroupObject *go; - int a; - - part = idbase->first; - while (part) { + for (ParticleSettings *part = idbase->first; part; part = part->id.next) { if (part->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_PA, ParticleSettings, 1, part); @@ -1306,24 +1296,23 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) write_curvemapping(wd, part->roughcurve); } - dw = part->dupliweights.first; - for (; dw; dw = dw->next) { + for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) { /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ if (dw->ob != NULL) { dw->index = 0; if (part->dup_group) { /* can be NULL if lining fails or set to None */ - for (go = part->dup_group->gobject.first; go && go->ob != dw->ob; go = go->next, dw->index++); + for (GroupObject *go = part->dup_group->gobject.first; + go && go->ob != dw->ob; + go = go->next, dw->index++); } } writestruct(wd, DATA, ParticleDupliWeight, 1, dw); } if (part->boids && part->phystype == PART_PHYS_BOIDS) { - BoidState *state = part->boids->states.first; - writestruct(wd, DATA, BoidSettings, 1, part->boids); - for (; state; state = state->next) { + for (BoidState *state = part->boids->states.first; state; state = state->next) { write_boid_state(wd, state); } } @@ -1331,13 +1320,12 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid); } - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (part->mtex[a]) { writestruct(wd, DATA, MTex, 1, part->mtex[a]); } } } - part = part->id.next; } } static void write_particlesystems(WriteData *wd, ListBase *particles) @@ -1835,10 +1823,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) static void write_objects(WriteData *wd, ListBase *idbase) { - Object *ob; - - ob = idbase->first; - while (ob) { + for (Object *ob = idbase->first; ob; ob = ob->id.next) { if (ob->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_OB, Object, 1, ob); @@ -1894,11 +1879,9 @@ static void write_objects(WriteData *wd, ListBase *idbase) writelist(wd, DATA, LinkData, &ob->pc_ids); writelist(wd, DATA, LodLevel, &ob->lodlevels); - } - write_previews(wd, ob->preview); - - ob = ob->id.next; + write_previews(wd, ob->preview); + } } mywrite_flush(wd); @@ -1907,26 +1890,19 @@ static void write_objects(WriteData *wd, ListBase *idbase) static void write_vfonts(WriteData *wd, ListBase *idbase) { - VFont *vf; - PackedFile *pf; - - vf = idbase->first; - while (vf) { + for (VFont *vf = idbase->first; vf; vf = vf->id.next) { if (vf->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_VF, VFont, 1, vf); write_iddata(wd, &vf->id); /* direct data */ - if (vf->packedfile) { - pf = vf->packedfile; + PackedFile *pf = vf->packedfile; writestruct(wd, DATA, PackedFile, 1, pf); writedata(wd, DATA, pf->size, pf->data); } } - - vf = vf->id.next; } mywrite_flush(wd); @@ -1935,11 +1911,7 @@ static void write_vfonts(WriteData *wd, ListBase *idbase) static void write_keys(WriteData *wd, ListBase *idbase) { - Key *key; - KeyBlock *kb; - - key = idbase->first; - while (key) { + for (Key *key = idbase->first; key; key = key->id.next) { if (key->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_KE, Key, 1, key); @@ -1950,17 +1922,13 @@ static void write_keys(WriteData *wd, ListBase *idbase) } /* direct data */ - kb = key->block.first; - while (kb) { + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { writestruct(wd, DATA, KeyBlock, 1, kb); if (kb->data) { writedata(wd, DATA, kb->totelem * key->elemsize, kb->data); } - kb = kb->next; } } - - key = key->id.next; } mywrite_flush(wd); @@ -1968,10 +1936,7 @@ static void write_keys(WriteData *wd, ListBase *idbase) static void write_cameras(WriteData *wd, ListBase *idbase) { - Camera *cam; - - cam = idbase->first; - while (cam) { + for (Camera *cam = idbase->first; cam; cam = cam->id.next) { if (cam->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_CA, Camera, 1, cam); @@ -1981,18 +1946,12 @@ static void write_cameras(WriteData *wd, ListBase *idbase) write_animdata(wd, cam->adt); } } - - cam = cam->id.next; } } static void write_mballs(WriteData *wd, ListBase *idbase) { - MetaBall *mb; - MetaElem *ml; - - mb = idbase->first; - while (mb) { + for (MetaBall *mb = idbase->first; mb; mb = mb->id.next) { if (mb->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_MB, MetaBall, 1, mb); @@ -2004,23 +1963,16 @@ static void write_mballs(WriteData *wd, ListBase *idbase) write_animdata(wd, mb->adt); } - ml = mb->elems.first; - while (ml) { + for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) { writestruct(wd, DATA, MetaElem, 1, ml); - ml = ml->next; } } - mb = mb->id.next; } } static void write_curves(WriteData *wd, ListBase *idbase) { - Curve *cu; - Nurb *nu; - - cu = idbase->first; - while (cu) { + for (Curve *cu = idbase->first; cu; cu = cu->id.next) { if (cu->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_CU, Curve, 1, cu); @@ -2039,13 +1991,10 @@ static void write_curves(WriteData *wd, ListBase *idbase) } else { /* is also the order of reading */ - nu = cu->nurb.first; - while (nu) { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { writestruct(wd, DATA, Nurb, 1, nu); - nu = nu->next; } - nu = cu->nurb.first; - while (nu) { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt); } @@ -2058,11 +2007,9 @@ static void write_curves(WriteData *wd, ListBase *idbase) writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv); } } - nu = nu->next; } } } - cu = cu->id.next; } mywrite_flush(wd); @@ -2184,15 +2131,13 @@ static void write_customdata( static void write_meshes(WriteData *wd, ListBase *idbase) { - Mesh *mesh; - bool save_for_old_blender = false; - #ifdef USE_BMESH_SAVE_AS_COMPAT - save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */ + const bool save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */ +#else + const bool save_for_old_blender = false; #endif - mesh = idbase->first; - while (mesh) { + for (Mesh *mesh = idbase->first; mesh; mesh = mesh->id.next) { CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE]; CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE]; CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE]; @@ -2336,8 +2281,6 @@ static void write_meshes(WriteData *wd, ListBase *idbase) if (players && players != players_buff) { MEM_freeN(players); } - - mesh = mesh->id.next; } mywrite_flush(wd); @@ -2345,10 +2288,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase) static void write_lattices(WriteData *wd, ListBase *idbase) { - Lattice *lt; - - lt = idbase->first; - while (lt) { + for (Lattice *lt = idbase->first; lt; lt = lt->id.next) { if (lt->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_LT, Lattice, 1, lt); @@ -2363,9 +2303,7 @@ static void write_lattices(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def); write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert); - } - lt = lt->id.next; } mywrite_flush(wd); @@ -2373,14 +2311,10 @@ static void write_lattices(WriteData *wd, ListBase *idbase) static void write_images(WriteData *wd, ListBase *idbase) { - Image *ima; - PackedFile *pf; - ImageView *iv; - ImagePackedFile *imapf; - - ima = idbase->first; - while (ima) { + for (Image *ima = idbase->first; ima; ima = ima->id.next) { if (ima->id.us > 0 || wd->current) { + ImagePackedFile *imapf; + /* Some trickery to keep forward compatibility of packed images. */ BLI_assert(ima->packedfile == NULL); if (ima->packedfiles.first != NULL) { @@ -2395,7 +2329,7 @@ static void write_images(WriteData *wd, ListBase *idbase) for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { writestruct(wd, DATA, ImagePackedFile, 1, imapf); if (imapf->packedfile) { - pf = imapf->packedfile; + PackedFile *pf = imapf->packedfile; writestruct(wd, DATA, PackedFile, 1, pf); writedata(wd, DATA, pf->size, pf->data); } @@ -2403,14 +2337,13 @@ static void write_images(WriteData *wd, ListBase *idbase) write_previews(wd, ima->preview); - for (iv = ima->views.first; iv; iv = iv->next) { + for (ImageView *iv = ima->views.first; iv; iv = iv->next) { writestruct(wd, DATA, ImageView, 1, iv); } writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format); ima->packedfile = NULL; } - ima = ima->id.next; } mywrite_flush(wd); @@ -2418,10 +2351,7 @@ static void write_images(WriteData *wd, ListBase *idbase) static void write_textures(WriteData *wd, ListBase *idbase) { - Tex *tex; - - tex = idbase->first; - while (tex) { + for (Tex *tex = idbase->first; tex; tex = tex->id.next) { if (tex->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_TE, Tex, 1, tex); @@ -2462,7 +2392,6 @@ static void write_textures(WriteData *wd, ListBase *idbase) write_previews(wd, tex->preview); } - tex = tex->id.next; } mywrite_flush(wd); @@ -2470,11 +2399,7 @@ static void write_textures(WriteData *wd, ListBase *idbase) static void write_materials(WriteData *wd, ListBase *idbase) { - Material *ma; - int a; - - ma = idbase->first; - while (ma) { + for (Material *ma = idbase->first; ma; ma = ma->id.next) { if (ma->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_MA, Material, 1, ma); @@ -2484,7 +2409,7 @@ static void write_materials(WriteData *wd, ListBase *idbase) write_animdata(wd, ma->adt); } - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (ma->mtex[a]) { writestruct(wd, DATA, MTex, 1, ma->mtex[a]); } @@ -2505,17 +2430,12 @@ static void write_materials(WriteData *wd, ListBase *idbase) write_previews(wd, ma->preview); } - ma = ma->id.next; } } static void write_worlds(WriteData *wd, ListBase *idbase) { - World *wrld; - int a; - - wrld = idbase->first; - while (wrld) { + for (World *wrld = idbase->first; wrld; wrld = wrld->id.next) { if (wrld->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_WO, World, 1, wrld); @@ -2525,7 +2445,7 @@ static void write_worlds(WriteData *wd, ListBase *idbase) write_animdata(wd, wrld->adt); } - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (wrld->mtex[a]) { writestruct(wd, DATA, MTex, 1, wrld->mtex[a]); } @@ -2539,17 +2459,12 @@ static void write_worlds(WriteData *wd, ListBase *idbase) write_previews(wd, wrld->preview); } - wrld = wrld->id.next; } } static void write_lamps(WriteData *wd, ListBase *idbase) { - Lamp *la; - int a; - - la = idbase->first; - while (la) { + for (Lamp *la = idbase->first; la; la = la->id.next) { if (la->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_LA, Lamp, 1, la); @@ -2560,7 +2475,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase) } /* direct data */ - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (la->mtex[a]) { writestruct(wd, DATA, MTex, 1, la->mtex[a]); } @@ -2577,9 +2492,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase) } write_previews(wd, la->preview); - } - la = la->id.next; } mywrite_flush(wd); @@ -2628,22 +2541,7 @@ static void write_paint(WriteData *wd, Paint *p) static void write_scenes(WriteData *wd, ListBase *scebase) { - Scene *sce; - Base *base; - Editing *ed; - Sequence *seq; - MetaStack *ms; - Strip *strip; - TimeMarker *marker; - TransformOrientation *ts; - SceneRenderLayer *srl; - SceneRenderView *srv; - ToolSettings *tos; - FreestyleModuleConfig *fmc; - FreestyleLineSet *fls; - - sce = scebase->first; - while (sce) { + for (Scene *sce = scebase->first; sce; sce = sce->id.next) { /* write LibData */ writestruct(wd, ID_SCE, Scene, 1, sce); write_iddata(wd, &sce->id); @@ -2654,13 +2552,11 @@ static void write_scenes(WriteData *wd, ListBase *scebase) write_keyingsets(wd, &sce->keyingsets); /* direct data */ - base = sce->base.first; - while (base) { + for (Base *base = sce->base.first; base; base = base->next) { writestruct(wd, DATA, Base, 1, base); - base = base->next; } - tos = sce->toolsettings; + ToolSettings *tos = sce->toolsettings; writestruct(wd, DATA, ToolSettings, 1, tos); if (tos->vpaint) { writestruct(wd, DATA, VPaint, 1, tos->vpaint); @@ -2699,8 +2595,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase) write_paint(wd, &tos->imapaint.paint); - ed = sce->ed; + Editing *ed = sce->ed; if (ed) { + Sequence *seq; + writestruct(wd, DATA, Editing, 1, ed); /* reset write flags too */ @@ -2747,7 +2645,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format); - strip = seq->strip; + Strip *strip = seq->strip; writestruct(wd, DATA, Strip, 1, strip); if (seq->flag & SEQ_USE_CROP && strip->crop) { writestruct(wd, DATA, StripCrop, 1, strip->crop); @@ -2779,7 +2677,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) SEQ_END /* new; meta stack too, even when its nasty restore code */ - for (ms = ed->metastack.first; ms; ms = ms->next) { + for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) { writestruct(wd, DATA, MetaStack, 1, ms); } } @@ -2805,27 +2703,27 @@ static void write_scenes(WriteData *wd, ListBase *scebase) } /* writing dynamic list of TimeMarkers to the blend file */ - for (marker = sce->markers.first; marker; marker = marker->next) { + for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) { writestruct(wd, DATA, TimeMarker, 1, marker); } /* writing dynamic list of TransformOrientations to the blend file */ - for (ts = sce->transform_spaces.first; ts; ts = ts->next) { + for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) { writestruct(wd, DATA, TransformOrientation, 1, ts); } - for (srl = sce->r.layers.first; srl; srl = srl->next) { + for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) { writestruct(wd, DATA, SceneRenderLayer, 1, srl); - for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { + for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc); } - for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { + for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { writestruct(wd, DATA, FreestyleLineSet, 1, fls); } } /* writing MultiView to the blend file */ - for (srv = sce->r.views.first; srv; srv = srv->next) { + for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) { writestruct(wd, DATA, SceneRenderView, 1, srv); } @@ -2845,8 +2743,6 @@ static void write_scenes(WriteData *wd, ListBase *scebase) write_previews(wd, sce->preview); write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve); - - sce = sce->id.next; } mywrite_flush(wd); @@ -2854,13 +2750,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) static void write_gpencils(WriteData *wd, ListBase *lb) { - bGPdata *gpd; - bGPDlayer *gpl; - bGPDframe *gpf; - bGPDstroke *gps; - bGPDpalette *palette; - - for (gpd = lb->first; gpd; gpd = gpd->id.next) { + for (bGPdata *gpd = lb->first; gpd; gpd = gpd->id.next) { if (gpd->id.us > 0 || wd->current) { /* write gpd data block to file */ writestruct(wd, ID_GD, bGPdata, 1, gpd); @@ -2872,22 +2762,21 @@ static void write_gpencils(WriteData *wd, ListBase *lb) /* write grease-pencil layers to file */ writelist(wd, DATA, bGPDlayer, &gpd->layers); - for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { - + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* write this layer's frames to file */ writelist(wd, DATA, bGPDframe, &gpl->frames); - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { /* write strokes */ writelist(wd, DATA, bGPDstroke, &gpf->strokes); - for (gps = gpf->strokes.first; gps; gps = gps->next) { + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points); } } } + /* write grease-pencil palettes */ writelist(wd, DATA, bGPDpalette, &gpd->palettes); - for (palette = gpd->palettes.first; palette; palette = palette->next) { + for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) { writelist(wd, DATA, bGPDpalettecolor, &palette->colors); } } @@ -2898,14 +2787,11 @@ static void write_gpencils(WriteData *wd, ListBase *lb) static void write_windowmanagers(WriteData *wd, ListBase *lb) { - wmWindowManager *wm; - wmWindow *win; - - for (wm = lb->first; wm; wm = wm->id.next) { + for (wmWindowManager *wm = lb->first; wm; wm = wm->id.next) { writestruct(wd, ID_WM, wmWindowManager, 1, wm); write_iddata(wd, &wm->id); - for (win = wm->windows.first; win; win = win->next) { + for (wmWindow *win = wm->windows.first; win; win = win->next) { writestruct(wd, DATA, wmWindow, 1, win); writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format); } @@ -3004,29 +2890,22 @@ static void write_soops(WriteData *wd, SpaceOops *so) static void write_screens(WriteData *wd, ListBase *scrbase) { - bScreen *sc; - ScrArea *sa; - ScrVert *sv; - ScrEdge *se; - - sc = scrbase->first; - while (sc) { - + for (bScreen *sc = scrbase->first; sc; sc = sc->id.next) { /* write LibData */ /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ writestruct(wd, ID_SCRN, bScreen, 1, sc); write_iddata(wd, &sc->id); /* direct data */ - for (sv = sc->vertbase.first; sv; sv = sv->next) { + for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) { writestruct(wd, DATA, ScrVert, 1, sv); } - for (se = sc->edgebase.first; se; se = se->next) { + for (ScrEdge *se = sc->edgebase.first; se; se = se->next) { writestruct(wd, DATA, ScrEdge, 1, se); } - for (sa = sc->areabase.first; sa; sa = sa->next) { + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { SpaceLink *sl; Panel *pa; uiList *ui_list; @@ -3056,8 +2935,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase) } } - sl = sa->spacedata.first; - while (sl) { + for (sl = sa->spacedata.first; sl; sl = sl->next) { for (ar = sl->regionbase.first; ar; ar = ar->next) { write_region(wd, ar, sl->spacetype); } @@ -3171,12 +3049,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase) else if (sl->spacetype == SPACE_INFO) { writestruct(wd, DATA, SpaceInfo, 1, sl); } - - sl = sl->next; } } - - sc = sc->id.next; } mywrite_flush(wd); @@ -3204,11 +3078,7 @@ static void write_bone(WriteData *wd, Bone *bone) static void write_armatures(WriteData *wd, ListBase *idbase) { - bArmature *arm; - Bone *bone; - - arm = idbase->first; - while (arm) { + for (bArmature *arm = idbase->first; arm; arm = arm->id.next) { if (arm->id.us > 0 || wd->current) { writestruct(wd, ID_AR, bArmature, 1, arm); write_iddata(wd, &arm->id); @@ -3218,13 +3088,10 @@ static void write_armatures(WriteData *wd, ListBase *idbase) } /* Direct data */ - bone = arm->bonebase.first; - while (bone) { + for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) { write_bone(wd, bone); - bone = bone->next; } } - arm = arm->id.next; } mywrite_flush(wd); @@ -3232,12 +3099,8 @@ static void write_armatures(WriteData *wd, ListBase *idbase) static void write_texts(WriteData *wd, ListBase *idbase) { - Text *text; - TextLine *tmp; - - text = idbase->first; - while (text) { - if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) { + for (Text *text = idbase->first; text; text = text->id.next) { + if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) { text->flags &= ~TXT_ISEXT; } @@ -3251,21 +3114,14 @@ static void write_texts(WriteData *wd, ListBase *idbase) if (!(text->flags & TXT_ISEXT)) { /* now write the text data, in two steps for optimization in the readfunction */ - tmp = text->lines.first; - while (tmp) { + for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) { writestruct(wd, DATA, TextLine, 1, tmp); - tmp = tmp->next; } - tmp = text->lines.first; - while (tmp) { + for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) { writedata(wd, DATA, tmp->len + 1, tmp->line); - tmp = tmp->next; } } - - - text = text->id.next; } mywrite_flush(wd); @@ -3273,10 +3129,7 @@ static void write_texts(WriteData *wd, ListBase *idbase) static void write_speakers(WriteData *wd, ListBase *idbase) { - Speaker *spk; - - spk = idbase->first; - while (spk) { + for (Speaker *spk = idbase->first; spk; spk = spk->id.next) { if (spk->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_SPK, Speaker, 1, spk); @@ -3286,30 +3139,23 @@ static void write_speakers(WriteData *wd, ListBase *idbase) write_animdata(wd, spk->adt); } } - spk = spk->id.next; } } static void write_sounds(WriteData *wd, ListBase *idbase) { - bSound *sound; - - PackedFile *pf; - - sound = idbase->first; - while (sound) { + for (bSound *sound = idbase->first; sound; sound = sound->id.next) { if (sound->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_SO, bSound, 1, sound); write_iddata(wd, &sound->id); if (sound->packedfile) { - pf = sound->packedfile; + PackedFile *pf = sound->packedfile; writestruct(wd, DATA, PackedFile, 1, pf); writedata(wd, DATA, pf->size, pf->data); } } - sound = sound->id.next; } mywrite_flush(wd); @@ -3317,10 +3163,7 @@ static void write_sounds(WriteData *wd, ListBase *idbase) static void write_groups(WriteData *wd, ListBase *idbase) { - Group *group; - GroupObject *go; - - for (group = idbase->first; group; group = group->id.next) { + for (Group *group = idbase->first; group; group = group->id.next) { if (group->id.us > 0 || wd->current) { /* write LibData */ writestruct(wd, ID_GR, Group, 1, group); @@ -3328,10 +3171,8 @@ static void write_groups(WriteData *wd, ListBase *idbase) write_previews(wd, group->preview); - go = group->gobject.first; - while (go) { + for (GroupObject *go = group->gobject.first; go; go = go->next) { writestruct(wd, DATA, GroupObject, 1, go); - go = go->next; } } } @@ -3341,9 +3182,7 @@ static void write_groups(WriteData *wd, ListBase *idbase) static void write_nodetrees(WriteData *wd, ListBase *idbase) { - bNodeTree *ntree; - - for (ntree = idbase->first; ntree; ntree = ntree->id.next) { + for (bNodeTree *ntree = idbase->first; ntree; ntree = ntree->id.next) { if (ntree->id.us > 0 || wd->current) { writestruct(wd, ID_NT, bNodeTree, 1, ntree); /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot @@ -3427,9 +3266,7 @@ static void customnodes_free_deprecated_data(Main *mainvar) static void write_brushes(WriteData *wd, ListBase *idbase) { - Brush *brush; - - for (brush = idbase->first; brush; brush = brush->id.next) { + for (Brush *brush = idbase->first; brush; brush = brush->id.next) { if (brush->id.us > 0 || wd->current) { writestruct(wd, ID_BR, Brush, 1, brush); write_iddata(wd, &brush->id); @@ -3446,9 +3283,7 @@ static void write_brushes(WriteData *wd, ListBase *idbase) static void write_palettes(WriteData *wd, ListBase *idbase) { - Palette *palette; - - for (palette = idbase->first; palette; palette = palette->id.next) { + for (Palette *palette = idbase->first; palette; palette = palette->id.next) { if (palette->id.us > 0 || wd->current) { PaletteColor *color; writestruct(wd, ID_PAL, Palette, 1, palette); @@ -3463,9 +3298,7 @@ static void write_palettes(WriteData *wd, ListBase *idbase) static void write_paintcurves(WriteData *wd, ListBase *idbase) { - PaintCurve *pc; - - for (pc = idbase->first; pc; pc = pc->id.next) { + for (PaintCurve *pc = idbase->first; pc; pc = pc->id.next) { if (pc->id.us > 0 || wd->current) { writestruct(wd, ID_PC, PaintCurve, 1, pc); write_iddata(wd, &pc->id); @@ -3523,10 +3356,7 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction static void write_movieclips(WriteData *wd, ListBase *idbase) { - MovieClip *clip; - - clip = idbase->first; - while (clip) { + for (MovieClip *clip = idbase->first; clip; clip = clip->id.next) { if (clip->id.us > 0 || wd->current) { MovieTracking *tracking = &clip->tracking; MovieTrackingObject *object; @@ -3554,8 +3384,6 @@ static void write_movieclips(WriteData *wd, ListBase *idbase) object = object->next; } } - - clip = clip->id.next; } mywrite_flush(wd); @@ -3563,10 +3391,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase) static void write_masks(WriteData *wd, ListBase *idbase) { - Mask *mask; - - mask = idbase->first; - while (mask) { + for (Mask *mask = idbase->first; mask; mask = mask->id.next) { if (mask->id.us > 0 || wd->current) { MaskLayer *masklay; @@ -3614,8 +3439,6 @@ static void write_masks(WriteData *wd, ListBase *idbase) } } } - - mask = mask->id.next; } mywrite_flush(wd); @@ -3877,10 +3700,7 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier static void write_linestyles(WriteData *wd, ListBase *idbase) { - FreestyleLineStyle *linestyle; - int a; - - for (linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) { + for (FreestyleLineStyle *linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) { if (linestyle->id.us > 0 || wd->current) { writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle); write_iddata(wd, &linestyle->id); @@ -3893,7 +3713,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase) write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers); write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers); write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers); - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (linestyle->mtex[a]) { writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]); } @@ -3908,9 +3728,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase) static void write_cachefiles(WriteData *wd, ListBase *idbase) { - CacheFile *cache_file; - - for (cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) { + for (CacheFile *cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) { if (cache_file->id.us > 0 || wd->current) { writestruct(wd, ID_CF, CacheFile, 1, cache_file); @@ -3930,7 +3748,6 @@ static void write_libraries(WriteData *wd, Main *main) bool found_one; for (; main; main = main->next) { - a = tot = set_listbasepointers(main, lbarray); /* test: is lib being used */ @@ -3939,16 +3756,13 @@ static void write_libraries(WriteData *wd, Main *main) } else { found_one = false; - while (tot--) { + while (!found_one && tot--) { for (id = lbarray[tot]->first; id; id = id->next) { if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) { found_one = true; break; } } - if (found_one) { - break; - } } } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index bb61f66e267..59ce91a3e70 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -945,6 +945,10 @@ void BM_mesh_bm_to_me( /* propagate edited basis offsets to other shapes */ if (apply_offset) { add_v3_v3(fp, *ofs_pt++); + /* Apply back new coordinates of offsetted shapekeys into BMesh. + * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous + * call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */ + copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp); } fp += 3; diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp index b8971fffe3e..36bc176b1a6 100644 --- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp +++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp @@ -43,8 +43,6 @@ void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const NodeInput *valueSocket = this->getInputSocket(3); NodeInput *facSocket = this->getInputSocket(4); NodeOutput *outputSocket = this->getOutputSocket(0); - bNode *editorsnode = getbNode(); - NodeHueSat *storage = (NodeHueSat *)editorsnode->storage; ConvertRGBToHSVOperation *rgbToHSV = new ConvertRGBToHSVOperation(); converter.addOperation(rgbToHSV); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 9d78b99341b..6b7fb5246ca 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/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index ba7818c21ad..94cff521edc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -129,8 +129,8 @@ static bool python_driver_depends_on_time(ChannelDriver *driver) /* Function calls are considered dependent on a time. */ return true; } - if (strstr(driver->expression, "time") != NULL) { - /* Variable `time` depends on time. */ + if (strstr(driver->expression, "frame") != NULL) { + /* Variable `frame` depends on time. */ /* TODO(sergey): This is a bit weak, but not sure about better way of * handling this. */ diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 065f65659e6..3a042535d26 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -53,6 +53,7 @@ extern "C" { #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" #include "intern/depsgraph.h" +#include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" /* Unfinished and unused, and takes quite some pre-processing time. */ @@ -362,6 +363,11 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx, return; } + DEG_DEBUG_PRINTF("%s: layers:%u, graph->layers:%u\n", + __func__, + layers, + graph->layers); + /* Set time for the current graph evaluation context. */ TimeSourceDepsNode *time_src = graph->find_time_source(); eval_ctx->ctime = time_src->cfra; diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 33e44d73894..a4ba95420c1 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -46,6 +46,8 @@ #include "BLI_dlrbTree.h" #include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_nla.h" #include "BKE_mask.h" @@ -308,7 +310,8 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo fcu->prev_norm_factor = 1.0f; if (fcu->bezt) { - BezTriple *bezt; + const bool use_preview_only = PRVRANGEON; + const BezTriple *bezt; int i; float max_coord = -FLT_MAX; float min_coord = FLT_MAX; @@ -318,28 +321,77 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo return 1.0f; } - if (PRVRANGEON) { - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) { - max_coord = max_ff(max_coord, bezt->vec[0][1]); - max_coord = max_ff(max_coord, bezt->vec[1][1]); - max_coord = max_ff(max_coord, bezt->vec[2][1]); - - min_coord = min_ff(min_coord, bezt->vec[0][1]); - min_coord = min_ff(min_coord, bezt->vec[1][1]); - min_coord = min_ff(min_coord, bezt->vec[2][1]); - } + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0], + scene->r.psfra, + scene->r.pefra)) + { + continue; } - } - else { - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - max_coord = max_ff(max_coord, bezt->vec[0][1]); + + if (i == 0) { + /* We ignore extrapolation flags and handle here, and use the + * control point position only. so we normalize "interesting" + * part of the curve. + * + * Here we handle left extrapolation. + */ max_coord = max_ff(max_coord, bezt->vec[1][1]); - max_coord = max_ff(max_coord, bezt->vec[2][1]); - min_coord = min_ff(min_coord, bezt->vec[0][1]); min_coord = min_ff(min_coord, bezt->vec[1][1]); - min_coord = min_ff(min_coord, bezt->vec[2][1]); + } + else { + const BezTriple *prev_bezt = bezt - 1; + if (prev_bezt->ipo == BEZT_IPO_CONST) { + /* Constant interpolation: previous CV value is used up + * to the current keyframe. + */ + max_coord = max_ff(max_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + } + else if (prev_bezt->ipo == BEZT_IPO_LIN) { + /* Linear interpolation: min/max using both previous and + * and current CV. + */ + max_coord = max_ff(max_coord, bezt->vec[1][1]); + min_coord = min_ff(min_coord, bezt->vec[1][1]); + max_coord = max_ff(max_coord, prev_bezt->vec[1][1]); + min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); + } + else if (prev_bezt->ipo == BEZT_IPO_BEZ) { + const int resol = fcu->driver + ? 32 + : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), 32); + if (resol < 2) { + max_coord = max_ff(max_coord, prev_bezt->vec[1][1]); + min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); + } + else { + float data[120]; + float v1[2], v2[2], v3[2], v4[2]; + + v1[0] = prev_bezt->vec[1][0]; + v1[1] = prev_bezt->vec[1][1]; + v2[0] = prev_bezt->vec[2][0]; + v2[1] = prev_bezt->vec[2][1]; + + v3[0] = bezt->vec[0][0]; + v3[1] = bezt->vec[0][1]; + v4[0] = bezt->vec[1][0]; + v4[1] = bezt->vec[1][1]; + + correct_bezpart(v1, v2, v3, v4); + + BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3); + BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3); + + for (int j = 0; j <= resol; ++j) { + const float *fp = &data[j * 3]; + max_coord = max_ff(max_coord, fp[1]); + min_coord = min_ff(min_coord, fp[1]); + } + } + } } } 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/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index cc4c1809fbc..f6c04e9570a 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -970,6 +970,9 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S ToolSettings *ts = CTX_data_tool_settings(C); int point_added = 0; + /* TODO: Since the function `ED_transform_snap_object_context_create_view3d` creates a cache, + * the ideal would be to call this function only at the beginning of the snap operation, + * or at the beginning of the operator itself */ struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( CTX_data_main(C), CTX_data_scene(C), 0, CTX_wm_region(C), CTX_wm_view3d(C)); @@ -1038,6 +1041,8 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S } } + /* TODO: The ideal would be to call this function only once. + * At the end of the operator */ ED_transform_snap_object_context_destroy(snap_context); return point_added; } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 5b011b679a6..e118e490f25 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -953,6 +953,9 @@ static int gp_dissolve_selected_points(bContext *C) /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(gpl, gps) == false) + continue; if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; @@ -1165,6 +1168,9 @@ static int gp_delete_selected_points(bContext *C) /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; + /* check if the color is editable */ + if (ED_gpencil_stroke_color_use(gpl, gps) == false) + continue; if (gps->flag & GP_STROKE_SELECT) { @@ -1204,7 +1210,7 @@ static int gp_delete_exec(bContext *C, wmOperator *op) case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */ result = gp_delete_selected_points(C); break; - + case GP_DELETEOP_FRAME: /* active frame */ result = gp_actframe_delete_exec(C, op); break; diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 7944b434057..6eaae49912c 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -65,10 +65,6 @@ struct SnapObjectParams { unsigned int use_object_edit_cage : 1; }; -enum { - SNAP_OBJECT_USE_CACHE = (1 << 0), -}; - typedef struct SnapObjectContext SnapObjectContext; SnapObjectContext *ED_transform_snap_object_context_create( struct Main *bmain, struct Scene *scene, int flag); diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 8a2111fa6b2..b6d565e4e79 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -653,9 +653,9 @@ DEF_ICON(IPO_BACK) DEF_ICON(IPO_EASE_IN) DEF_ICON(IPO_EASE_OUT) DEF_ICON(IPO_EASE_IN_OUT) +DEF_ICON(NORMALIZE_FCURVES) #ifndef DEF_ICON_BLANK_SKIP /* available */ - DEF_ICON(BLANK203) DEF_ICON(BLANK204) DEF_ICON(BLANK205) DEF_ICON(BLANK206) diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 7262b453e02..ca2538022b0 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2078,15 +2078,7 @@ static void ui_litem_estimate_row(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); - if (item->type == ITEM_BUTTON) { - const uiBut *but = ((uiButtonItem *)item)->but; - const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0'); - - min_size_flag = min_size_flag && icon_only; - } - else { - min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); - } + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); litem->w += itemw; litem->h = MAX2(itemh, litem->h); @@ -2232,15 +2224,7 @@ static void ui_litem_estimate_column(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); - if (item->type == ITEM_BUTTON) { - const uiBut *but = ((uiButtonItem *)item)->but; - const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0'); - - min_size_flag = min_size_flag && icon_only; - } - else { - min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); - } + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); litem->w = MAX2(litem->w, itemw); litem->h += itemh; @@ -3336,6 +3320,14 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but) bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem"); bitem->item.type = ITEM_BUTTON; bitem->but = but; + + int w, h; + ui_item_size((uiItem *)bitem, &w, &h); + /* XXX uiBut hasn't scaled yet + * we can flag the button as not expandable, depending on its size */ + if (w <= 2 * UI_UNIT_X) + bitem->item.flag |= UI_ITEM_MIN; + BLI_addtail(&layout->items, bitem); if (layout->context) { diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index d43a94c5514..b3736a71e74 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1584,7 +1584,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) { - widget_draw_icon(but, ICON_X, alpha, &temp, false); + widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, false); } else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false); diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index d2b2f12c1a5..fa2c1f25cfc 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -447,7 +447,8 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltax", 0); RNA_int_set(op->ptr, "deltay", -40); - if (RNA_boolean_get(op->ptr, "page")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { ARegion *ar = CTX_wm_region(C); RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymin - ar->v2d.mask.ymax); } @@ -497,7 +498,8 @@ static int view_scrollup_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltax", 0); RNA_int_set(op->ptr, "deltay", 40); - if (RNA_boolean_get(op->ptr, "page")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { ARegion *ar = CTX_wm_region(C); RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask)); } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 8f004bcf72b..65ee097e8e1 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -306,7 +306,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) ED_view3d_init_mats_rv3d(obedit, ar->regiondata); struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), CTX_data_scene(C), 0, ar, CTX_wm_view3d(C)); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index b26989113d4..743efb246ab 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -75,26 +75,213 @@ /* join selected meshes into the active mesh, context sensitive * return 0 if no join is made (error) and 1 if the join is done */ +static void join_mesh_single( + Main *bmain, Scene *scene, + Object *ob_dst, Base *base_src, float imat[4][4], + MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp, + CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata, + int totvert, int totedge, int totloop, int totpoly, + Key *key, Key *nkey, + Material **matar, int *matmap, int totcol, + int *vertofs, int *edgeofs, int *loopofs, int *polyofs) +{ + int a, b; + + Mesh *me = base_src->object->data; + MVert *mvert = *mvert_pp; + MEdge *medge = *medge_pp; + MLoop *mloop = *mloop_pp; + MPoly *mpoly = *mpoly_pp; + + if (me->totvert) { + /* merge customdata flag */ + ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag; + + /* standard data */ + CustomData_merge(&me->vdata, vdata, CD_MASK_MESH, CD_DEFAULT, totvert); + CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert); + + /* vertex groups */ + MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT); + + /* NB: vertex groups here are new version */ + if (dvert) { + for (a = 0; a < me->totvert; a++) { + for (b = 0; b < dvert[a].totweight; b++) { + /* Find the old vertex group */ + bDeformGroup *dg, *odg = BLI_findlink(&base_src->object->defbase, dvert[a].dw[b].def_nr); + int index; + if (odg) { + /* Search for a match in the new object, and set new index */ + for (dg = ob_dst->defbase.first, index = 0; dg; dg = dg->next, index++) { + if (STREQ(dg->name, odg->name)) { + dvert[a].dw[b].def_nr = index; + break; + } + } + } + } + } + } + + /* if this is the object we're merging into, no need to do anything */ + if (base_src->object != ob_dst) { + float cmat[4][4]; + + /* watch this: switch matmul order really goes wrong */ + mul_m4_m4m4(cmat, imat, base_src->object->obmat); + + /* transform vertex coordinates into new space */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) { + mul_m4_v3(cmat, mvert->co); + } + + /* for each shapekey in destination mesh: + * - if there's a matching one, copy it across (will need to transform vertices into new space...) + * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) + */ + if (key) { + /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs; + + /* check if this mesh has such a shapekey */ + KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; + if (okb) { + /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ + float (*ocos)[3] = okb->data; + for (a = 0; a < me->totvert; a++, cos++, ocos++) { + copy_v3_v3(*cos, *ocos); + mul_m4_v3(cmat, *cos); + } + } + else { + /* copy this mesh's vertex coordinates to the destination shapekey */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { + copy_v3_v3(*cos, mvert->co); + } + } + } + } + } + else { + /* for each shapekey in destination mesh: + * - if it was an 'original', copy the appropriate data from nkey + * - otherwise, copy across plain coordinates (no need to transform coordinates) + */ + if (key) { + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs; + + /* check if this was one of the original shapekeys */ + KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; + if (okb) { + /* copy this mesh's shapekey to the destination shapekey */ + float (*ocos)[3] = okb->data; + for (a = 0; a < me->totvert; a++, cos++, ocos++) { + copy_v3_v3(*cos, *ocos); + } + } + else { + /* copy base-coordinates to the destination shapekey */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { + copy_v3_v3(*cos, mvert->co); + } + } + } + } + } + } + + if (me->totedge) { + CustomData_merge(&me->edata, edata, CD_MASK_MESH, CD_DEFAULT, totedge); + CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge); + + for (a = 0; a < me->totedge; a++, medge++) { + medge->v1 += *vertofs; + medge->v2 += *vertofs; + } + } + + if (me->totloop) { + if (base_src->object != ob_dst) { + MultiresModifierData *mmd; + + multiresModifier_prepare_join(scene, base_src->object, ob_dst); + + if ((mmd = get_multires_modifier(scene, base_src->object, true))) { + ED_object_iter_other(bmain, base_src->object, true, + ED_object_multires_update_totlevels_cb, + &mmd->totlvl); + } + } + + CustomData_merge(&me->ldata, ldata, CD_MASK_MESH, CD_DEFAULT, totloop); + CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop); + + for (a = 0; a < me->totloop; a++, mloop++) { + mloop->v += *vertofs; + mloop->e += *edgeofs; + } + } + + if (me->totpoly) { + if (matmap) { + /* make mapping for materials */ + for (a = 1; a <= base_src->object->totcol; a++) { + Material *ma = give_current_material(base_src->object, a); + + for (b = 0; b < totcol; b++) { + if (ma == matar[b]) { + matmap[a - 1] = b; + break; + } + } + } + } + + CustomData_merge(&me->pdata, pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); + CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly); + + for (a = 0; a < me->totpoly; a++, mpoly++) { + mpoly->loopstart += *loopofs; + mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0; + } + } + + /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */ + *vertofs += me->totvert; + *mvert_pp += me->totvert; + *edgeofs += me->totedge; + *medge_pp += me->totedge; + *loopofs += me->totloop; + *mloop_pp += me->totloop; + *polyofs += me->totpoly; + *mpoly_pp += me->totpoly; +} + int join_mesh_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); - Material **matar, *ma; + Base *ob_base = CTX_data_active_base(C); + Object *ob = ob_base->object; + Material **matar = NULL, *ma; Mesh *me; - MVert *mvert, *mv; + MVert *mvert = NULL; MEdge *medge = NULL; MPoly *mpoly = NULL; MLoop *mloop = NULL; Key *key, *nkey = NULL; - KeyBlock *kb, *okb, *kbn; - float imat[4][4], cmat[4][4], *fp1, *fp2; + KeyBlock *kb, *kbn; + float imat[4][4]; int a, b, totcol, totmat = 0, totedge = 0, totvert = 0; int totloop = 0, totpoly = 0, vertofs, *matmap = NULL; - int i, j, index, haskey = 0, edgeofs, loopofs, polyofs; + int i, haskey = 0, edgeofs, loopofs, polyofs; bool ok = false; bDeformGroup *dg, *odg; - MDeformVert *dvert; CustomData vdata, edata, fdata, ldata, pdata; if (scene->obedit) { @@ -154,8 +341,10 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_mesh_tessface_clear(me); /* new material indices and material array */ - matar = MEM_callocN(sizeof(void *) * totmat, "join_mesh matar"); - if (totmat) matmap = MEM_callocN(sizeof(int) * totmat, "join_mesh matmap"); + if (totmat) { + matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar"); + matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap"); + } totcol = ob->totcol; /* obact materials in new main array, is nicer start! */ @@ -214,7 +403,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) ma = give_current_material(base->object, a); for (b = 0; b < totcol; b++) { - if (ma == matar[b]) break; + if (ma == matar[b]) { + break; + } } if (b == totcol) { matar[b] = ma; @@ -223,8 +414,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) } totcol++; } - if (totcol >= MAXMAT) + if (totcol >= MAXMAT) { break; + } } } @@ -301,187 +493,41 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* inverse transform for all selected meshes in this object */ invert_m4_m4(imat, ob->obmat); - + + /* Add back active mesh first. This allows to keep things similar as they were, as much as possible (i.e. data from + * active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084. + */ + join_mesh_single( + bmain, scene, + ob, ob_base, imat, + &mvert, &medge, &mloop, &mpoly, + &vdata, &edata, &ldata, &pdata, + totvert, totedge, totloop, totpoly, + key, nkey, + matar, matmap, totcol, + &vertofs, &edgeofs, &loopofs, &polyofs); + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { + if (base->object == ob) { + continue; + } /* only join if this is a mesh */ if (base->object->type == OB_MESH) { - me = base->object->data; - - if (me->totvert) { - - /* merge customdata flag */ - ((Mesh *)ob->data)->cd_flag |= me->cd_flag; - - /* standard data */ - CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); - CustomData_copy_data_named(&me->vdata, &vdata, 0, vertofs, me->totvert); - - /* vertex groups */ - dvert = CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); - - /* NB: vertex groups here are new version */ - if (dvert) { - for (i = 0; i < me->totvert; i++) { - for (j = 0; j < dvert[i].totweight; j++) { - /* Find the old vertex group */ - odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr); - if (odg) { - /* Search for a match in the new object, and set new index */ - for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) { - if (STREQ(dg->name, odg->name)) { - dvert[i].dw[j].def_nr = index; - break; - } - } - } - } - } - } - - /* if this is the object we're merging into, no need to do anything */ - if (base->object != ob) { - /* watch this: switch matmul order really goes wrong */ - mul_m4_m4m4(cmat, imat, base->object->obmat); - - /* transform vertex coordinates into new space */ - for (a = 0, mv = mvert; a < me->totvert; a++, mv++) { - mul_m4_v3(cmat, mv->co); - } - - /* for each shapekey in destination mesh: - * - if there's a matching one, copy it across (will need to transform vertices into new space...) - * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) - */ - if (key) { - /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ - for (kb = key->block.first; kb; kb = kb->next) { - /* get pointer to where to write data for this mesh in shapekey's data array */ - fp1 = ((float *)kb->data) + (vertofs * 3); - - /* check if this mesh has such a shapekey */ - okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; - - if (okb) { - /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ - fp2 = ((float *)(okb->data)); - for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { - copy_v3_v3(fp1, fp2); - mul_m4_v3(cmat, fp1); - } - } - else { - /* copy this mesh's vertex coordinates to the destination shapekey */ - mv = mvert; - for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { - copy_v3_v3(fp1, mv->co); - } - } - } - } - } - else { - /* for each shapekey in destination mesh: - * - if it was an 'original', copy the appropriate data from nkey - * - otherwise, copy across plain coordinates (no need to transform coordinates) - */ - if (key) { - for (kb = key->block.first; kb; kb = kb->next) { - /* get pointer to where to write data for this mesh in shapekey's data array */ - fp1 = ((float *)kb->data) + (vertofs * 3); - - /* check if this was one of the original shapekeys */ - okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; - if (okb) { - /* copy this mesh's shapekey to the destination shapekey */ - fp2 = ((float *)(okb->data)); - for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { - copy_v3_v3(fp1, fp2); - } - } - else { - /* copy base-coordinates to the destination shapekey */ - mv = mvert; - for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { - copy_v3_v3(fp1, mv->co); - } - } - } - } - } - - /* advance mvert pointer to end of base mesh's data */ - mvert += me->totvert; - } - - if (me->totedge) { - CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); - CustomData_copy_data_named(&me->edata, &edata, 0, edgeofs, me->totedge); - - for (a = 0; a < me->totedge; a++, medge++) { - medge->v1 += vertofs; - medge->v2 += vertofs; - } - } - - if (me->totloop) { - if (base->object != ob) { - MultiresModifierData *mmd; - - multiresModifier_prepare_join(scene, base->object, ob); + join_mesh_single( + bmain, scene, + ob, base, imat, + &mvert, &medge, &mloop, &mpoly, + &vdata, &edata, &ldata, &pdata, + totvert, totedge, totloop, totpoly, + key, nkey, + matar, matmap, totcol, + &vertofs, &edgeofs, &loopofs, &polyofs); - if ((mmd = get_multires_modifier(scene, base->object, true))) { - ED_object_iter_other(bmain, base->object, true, - ED_object_multires_update_totlevels_cb, - &mmd->totlvl); - } - } - - CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop); - CustomData_copy_data_named(&me->ldata, &ldata, 0, loopofs, me->totloop); - - for (a = 0; a < me->totloop; a++, mloop++) { - mloop->v += vertofs; - mloop->e += edgeofs; - } - } - - if (me->totpoly) { - if (totmat) { - /* make mapping for materials */ - for (a = 1; a <= base->object->totcol; a++) { - ma = give_current_material(base->object, a); - - for (b = 0; b < totcol; b++) { - if (ma == matar[b]) { - matmap[a - 1] = b; - break; - } - } - } - } - - CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); - CustomData_copy_data_named(&me->pdata, &pdata, 0, polyofs, me->totpoly); - - for (a = 0; a < me->totpoly; a++, mpoly++) { - mpoly->loopstart += loopofs; - mpoly->mat_nr = matmap ? matmap[(int)mpoly->mat_nr] : 0; - } - - polyofs += me->totpoly; - } - - /* these are used for relinking (cannot be set earlier, - * or else reattaching goes wrong) - */ - vertofs += me->totvert; - edgeofs += me->totedge; - loopofs += me->totloop; - /* free base, now that data is merged */ - if (base->object != ob) + if (base->object != ob) { ED_base_object_free_and_unlink(bmain, scene, base); + } } } CTX_DATA_END; @@ -529,34 +575,20 @@ int join_mesh_exec(bContext *C, wmOperator *op) if (totcol) { me->mat = matar; - ob->mat = MEM_callocN(sizeof(void *) * totcol, "join obmatar"); - ob->matbits = MEM_callocN(sizeof(char) * totcol, "join obmatbits"); + ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar"); + ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits"); + MEM_freeN(matmap); } - else - MEM_freeN(matar); - + ob->totcol = me->totcol = totcol; - if (matmap) MEM_freeN(matmap); - /* other mesh users */ test_all_objects_materials(bmain, (ID *)me); /* free temp copy of destination shapekeys (if applicable) */ if (nkey) { - /* XXX 2.5 Animato */ -#if 0 - /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */ - if (nkey->ipo) { - BKE_ipo_free(nkey->ipo); - BLI_remlink(&bmain->ipo, nkey->ipo); - MEM_freeN(nkey->ipo); - } -#endif - - BKE_key_free(nkey); - BLI_remlink(&bmain->key, nkey); - MEM_freeN(nkey); + /* We can assume nobody is using that ID currently. */ + BKE_libblock_free_ex(bmain, nkey, false, false); } /* ensure newly inserted keys are time sorted */ @@ -564,7 +596,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_key_sort(key); } - DAG_relations_tag_update(bmain); // removed objects, need to rebuild dag + DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); 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/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 56f59dca9a1..3c406764157 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -363,8 +363,8 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot /* matching index only */ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) { - MDeformVert **dvert_array_from, **dvf; - MDeformVert **dvert_array, **dv; + MDeformVert **dvert_array_from = NULL, **dvf; + MDeformVert **dvert_array = NULL, **dv; int dvert_tot_from; int dvert_tot; int i; @@ -375,26 +375,30 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) if (ob == ob_from) return true; - ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false); - ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); - - if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) { + /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */ + if (ob->data != ob_from->data) { + ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false); ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); - new_vgroup = true; - } - if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) { + if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) { + ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); + new_vgroup = true; + } - if (dvert_array) MEM_freeN(dvert_array); - if (dvert_array_from) MEM_freeN(dvert_array_from); + if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) { + if (dvert_array) + MEM_freeN(dvert_array); + if (dvert_array_from) + MEM_freeN(dvert_array_from); - if (new_vgroup == true) { - /* free the newly added vgroup since it wasn't compatible */ - BKE_object_defgroup_remove_all(ob); - } + if (new_vgroup == true) { + /* free the newly added vgroup since it wasn't compatible */ + BKE_object_defgroup_remove_all(ob); + } - /* if true: both are 0 and nothing needs changing, consider this a success */ - return (dvert_tot == dvert_tot_from); + /* if true: both are 0 and nothing needs changing, consider this a success */ + return (dvert_tot == dvert_tot_from); + } } /* do the copy */ @@ -412,22 +416,23 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from) MEM_freeN(remap); } - dvf = dvert_array_from; - dv = dvert_array; + if (dvert_array_from != NULL && dvert_array != NULL) { + dvf = dvert_array_from; + dv = dvert_array; - for (i = 0; i < dvert_tot; i++, dvf++, dv++) { - if ((*dv)->dw) - MEM_freeN((*dv)->dw); + for (i = 0; i < dvert_tot; i++, dvf++, dv++) { + MEM_SAFE_FREE((*dv)->dw); + *(*dv) = *(*dvf); - *(*dv) = *(*dvf); + if ((*dv)->dw) { + (*dv)->dw = MEM_dupallocN((*dv)->dw); + } + } - if ((*dv)->dw) - (*dv)->dw = MEM_dupallocN((*dv)->dw); + MEM_freeN(dvert_array); + MEM_freeN(dvert_array_from); } - MEM_freeN(dvert_array); - MEM_freeN(dvert_array_from); - return true; } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 075b1faf502..964f4bcdd9c 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1256,21 +1256,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot } break; } - - /* removed since BKE_image_user_frame_calc is now called in view3d_draw_bgpic because screen_ops doesnt call the notifier. */ -#if 0 - if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) { - View3D *v3d = area->spacedata.first; - BGpic *bgpic = v3d->bgpicbase.first; - - for (; bgpic; bgpic = bgpic->next) { - if (bgpic->ima) { - Scene *scene = wmn->reference; - BKE_image_user_frame_calc(&bgpic->iuser, scene->r.cfra, 0); - } - } - } -#endif } const char *view3d_context_dir[] = { diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index 688f459108b..aefe30bbe32 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -280,7 +280,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) } else if (state == RULER_STATE_DRAG) { ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), CTX_data_scene(C), 0, ruler_info->ar, CTX_wm_view3d(C)); } else { diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 17c08ed4205..542dc410bc3 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -588,7 +588,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->rv3d->rflag |= RV3D_NAVIGATING; walk->snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), walk->scene, SNAP_OBJECT_USE_CACHE, + CTX_data_main(C), walk->scene, 0, walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 31ffa019e4e..1916f9b4dab 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -3722,6 +3722,12 @@ static void initRotation(TransInfo *t) copy_v3_v3(t->axis_orig, t->axis); } +/** + * Applies values of rotation to `td->loc` and `td->ext->quat` + * based on a rotation matrix (mat) and a pivot (center). + * + * Protected axis and other transform settings are taken into account. + */ static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], const float *center) { float vec[3], totmat[3][3], smat[3][3]; @@ -4339,9 +4345,22 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) { TransData *td = t->data; float tvec[3]; - int i; - for (i = 0; i < t->total; i++, td++) { + /* The ideal would be "apply_snap_align_rotation" only when a snap point is found + * so, maybe inside this function is not the best place to apply this rotation. + * but you need "handle snapping rotation before doing the translation" (really?) */ + const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT); + float pivot[3]; + if (apply_snap_align_rotation) { + copy_v3_v3(pivot, t->tsnap.snapTarget); + /* The pivot has to be in local-space (see T49494) */ + if (t->flag & (T_EDIT | T_POSE)) { + Object *ob = t->obedit ? t->obedit : t->poseobj; + mul_m4_v3(ob->imat, pivot); + } + } + + for (int i = 0; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) break; @@ -4352,7 +4371,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) bool use_rotate_offset = false; /* handle snapping rotation before doing the translation */ - if (usingSnappingNormal(t)) { + if (apply_snap_align_rotation) { float mat[3][3]; if (validSnappingNormal(t)) { @@ -4370,7 +4389,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) unit_m3(mat); } - ElementRotation_ex(t, td, mat, t->tsnap.snapTarget); + ElementRotation_ex(t, td, mat, pivot); if (td->loc) { use_rotate_offset = true; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 7ea4448a44e..d60eb2f0778 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -84,8 +84,8 @@ typedef struct TransSnap { bool peel; bool snap_spatial_grid; short status; - float snapPoint[3]; /* snapping from this point */ - float snapTarget[3]; /* to this point */ + float snapPoint[3]; /* snapping from this point (in global-space)*/ + float snapTarget[3]; /* to this point (in global-space)*/ float snapNormal[3]; char snapNodeBorder; ListBase points; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index ce3d903b8f6..091a5773cf0 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2393,7 +2393,12 @@ static void createTransEditVerts(TransInfo *t) editmesh_set_connectivity_distance(em->bm, mtx, dists); } - if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + /* Only in case of rotation and resize, we want the elements of the edited + * object to behave as groups whose pivot are the individual origins + * + * TODO: use island_info to detect the closest point when the "Snap Target" + * in Blender UI is "Closest" */ + if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) { island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map); } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index f8bb124e943..318d2718969 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 */ @@ -599,7 +601,7 @@ static void initSnappingMode(TransInfo *t) if (t->spacetype == SPACE_VIEW3D) { if (t->tsnap.object_context == NULL) { t->tsnap.object_context = ED_transform_snap_object_context_create_view3d( - G.main, t->scene, SNAP_OBJECT_USE_CACHE, + G.main, t->scene, 0, t->ar, t->view); ED_transform_snap_object_context_set_editmesh_callbacks( @@ -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 fba965f69a7..7c9dc43dbe4 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,113 +235,87 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH /** \Common utilities * \{ */ - /** - * Struct that kepts basic information about a BVHTree build from a editmesh. + * Generates a struct with the immutable parameters that will be used on all objects. + * + * \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; */ -typedef struct BVHTreeFromMeshType { - void *userdata; - 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 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]) +{ + 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 precalc_project( - PreDefProject *projectdefs, const ARegion *ar, - const float dist_px, float obmat[4][4]) +MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) { - 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); + float dvec[3]; + sub_v3_v3v3(dvec, co, ray_start); + return dot_v3v3(dvec, ray_dir); } -static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index) +static void copy_dm_vert_no(const int index, float r_no[3], const BVHTreeFromMesh *data) { - 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; + const MVert *vert = data->vert + index; + + normal_short_to_float_v3(r_no, vert->no); } -static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3]) +static void copy_bvert_no(const int index, float r_no[3], const BVHTreeFromEditMesh *data) { - switch (meshdata->type) { - case SNAP_MESH: - { - BVHTreeFromMesh *data = meshdata->userdata; - const MVert *vert = data->vert + index; - normal_short_to_float_v3(r_no, vert->no); - break; - } - case SNAP_EDIT_MESH: - { - BVHTreeFromEditMesh *data = meshdata->userdata; - BMVert *eve = BM_vert_at_index(data->em->bm, index); - copy_v3_v3(r_no, eve->no); - break; - } - } + BMVert *eve = BM_vert_at_index(data->em->bm, index); + + copy_v3_v3(r_no, eve->no); } -static void get_edge_verts( - const BVHTreeFromMeshType *meshdata, const int index, - const float *v_pair[2]) +static void get_dm_edge_verts(const int index, const float *v_pair[2], const BVHTreeFromMesh *data) { - switch (meshdata->type) { - case SNAP_MESH: - { - BVHTreeFromMesh *data = meshdata->userdata; + const MVert *vert = data->vert; + const MEdge *edge = data->edge + index; - const MVert *vert = data->vert; - const MEdge *edge = data->edge + index; + v_pair[0] = vert[edge->v1].co; + v_pair[1] = vert[edge->v2].co; +} - v_pair[0] = vert[edge->v1].co; - v_pair[1] = vert[edge->v2].co; - break; - } - case SNAP_EDIT_MESH: - { - BVHTreeFromEditMesh *data = meshdata->userdata; - BMEdge *eed = BM_edge_at_index(data->em->bm, index); +static void get_bedge_verts(const int index, const float *v_pair[2], const BVHTreeFromEditMesh *data) +{ + BMEdge *eed = BM_edge_at_index(data->em->bm, index); - v_pair[0] = eed->v1->co; - v_pair[1] = eed->v2->co; - break; - } - } + v_pair[0] = eed->v1->co; + v_pair[1] = eed->v2->co; } 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; @@ -341,109 +327,106 @@ 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 ray_min_dist; + float pmat[4][4]; /* perspective matrix multiplied by object matrix */ + bool is_persp; + float win_half[2]; + float mval[2]; bool sign[3]; - bool r_axis_closest[3]; - float depth_range[2]; - - void *userdata; - int index; - float co[3]; - float no[3]; -} Object_Nearest2dPrecalc; +} 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], bool is_persp, const float win_half[2], + const float ray_min_dist, 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); + neasrest_precalc->is_persp = is_persp; + copy_v2_v2(neasrest_precalc->win_half, win_half); + neasrest_precalc->ray_min_dist = ray_min_dist; + 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) +/* Returns the distance from a 2d coordinate to a BoundBox (Projected) */ +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] = { @@ -456,9 +439,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[3] and vb[3] are the coordinates of the AABB edge closest to the ray */ + /* `va` and `vb` are the coordinates of the AABB edge closest to the ray */ float va[3], vb[3]; - /* rtmin and rtmax are the distances of the minimum and maximum ray hits on the AABB */ + /* `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB */ float rtmin, rtmax; int main_axis; @@ -466,38 +449,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; @@ -505,25 +488,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 hit is behind us - * TODO: Check if the entire AABB is behind ray - * this will prevent unnecessary leaf testing*/ - if (rtmax < depth_range[0]) { - return false; + /* `if rtmax < depth_min`, the hit is behind us */ + if (rtmax < data->ray_min_dist) { + /* 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->ray_min_dist)) { + 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 hit is behing us - * TODO: Check if the entire AABB is behind ray */ - else if (rtmin < depth_range[0]) { - return false; + /* `if rtmin < depth_min`, the hit is behing us */ + else if (rtmin < data->ray_min_dist) { + /* 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->ray_min_dist)) { + 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]; @@ -534,31 +526,35 @@ 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 depth_a = mul_project_m4_v3_zfac(pmat, va); - float depth_b = depth_a + pmat[main_axis][3] * scale; + float (*pmat)[4] = data->pmat; float va2d[2] = { (dot_m4_v3_row_x(pmat, va) + pmat[3][0]), (dot_m4_v3_row_y(pmat, va) + pmat[3][1]), }; float vb2d[2] = { - (va2d[0] + pmat[main_axis][0] * scale) / depth_b, - (va2d[1] + pmat[main_axis][1] * scale) / depth_b, + (va2d[0] + pmat[main_axis][0] * scale), + (va2d[1] + pmat[main_axis][1] * scale), }; - va2d[0] /= depth_a; - va2d[1] /= depth_a; + if (data->is_persp) { + float depth_a = mul_project_m4_v3_zfac(pmat, va); + float depth_b = depth_a + pmat[main_axis][3] * scale; + va2d[0] /= depth_a; + va2d[1] /= depth_a; + vb2d[0] /= depth_b; + vb2d[1] /= depth_b; + } va2d[0] += 1.0f; va2d[1] += 1.0f; 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); @@ -571,73 +567,146 @@ 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 ray_min_dist, 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, true, win_half, ray_min_dist, + 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 void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data); +typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data); + +typedef struct Nearest2dUserData { + struct Nearest2dPrecalc data_precalc; + + float dist_px_sq; + + bool r_axis_closest[3]; + + float depth_range[2]; + + void *userdata; + Nearest2DGetEdgeVertsCallback get_edge_verts; + Nearest2DCopyVertNoCallback copy_vert_no; + + 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, }; - /* Although this function is also used in the Othogonal view (VIEW_PROJ_ORTHO), - * we put `eViewProj view_proj` as` VIEW_PROJ_PERSP` because it works in both cases - * (with the disadvantage of executing unnecessary calculations) */ if (test_projected_vert_dist( - &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP, - neasrest_precalc->mval, neasrest_precalc->depth_range, - neasrest_precalc->co)) + data->depth_range, + neasrest_precalc->mval, co, + neasrest_precalc->pmat, + neasrest_precalc->win_half, + neasrest_precalc->is_persp, + &data->dist_px_sq, + data->co)) { - copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no); - neasrest_precalc->index = index; + data->copy_vert_no(index, data->no, data->userdata); + 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); + data->get_edge_verts(index, v_pair, data->userdata); - /* Although this function is also used in the Othogonal view (VIEW_PROJ_ORTHO), - * we put `eViewProj view_proj` as` VIEW_PROJ_PERSP` because it works in both cases - * (with the disadvantage of executing unnecessary calculations) */ 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)) + data->depth_range, + neasrest_precalc->mval, + neasrest_precalc->pmat, + neasrest_precalc->win_half, + neasrest_precalc->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]; } @@ -649,46 +718,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; } } @@ -703,52 +782,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) { @@ -758,19 +845,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 { @@ -779,7 +872,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 { @@ -787,11 +882,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); } } } @@ -803,8 +902,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; @@ -812,11 +912,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)) { @@ -827,15 +926,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; @@ -848,18 +951,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; @@ -880,7 +982,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; @@ -920,7 +1022,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); } } @@ -931,7 +1035,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; @@ -943,18 +1048,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 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 */ @@ -963,12 +1060,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; } @@ -979,251 +1076,259 @@ 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 */ - float ray_start_local[3], ray_normal_local[3]; - float local_scale, local_depth, len_diff; + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_start_local[3], ray_normal_local[3]; + float local_scale, local_depth, len_diff; - invert_m4_m4(imat, obmat); - transpose_m3_m4(timat, imat); + 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); + mul_m4_v3(imat, ray_start_local); + mul_mat3_m4_v3(imat, ray_normal_local); - /* local scale in normal direction */ - local_scale = normalize_v3(ray_normal_local); - local_depth = *ray_depth; - if (local_depth != BVH_RAYCAST_DIST_MAX) { - local_depth *= local_scale; - } + /* local scale in normal direction */ + local_scale = normalize_v3(ray_normal_local); + local_depth = *ray_depth; + if (local_depth != BVH_RAYCAST_DIST_MAX) { + local_depth *= local_scale; + } - if (do_bb) { - BoundBox *bb = BKE_object_boundbox_get(ob); + float lpmat[4][4]; + float ray_org_local[3]; + float ray_min_dist; + if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + ray_min_dist = snapdata->depth_range[0] * local_scale; + } - if (bb) { - BoundBox bb_temp; + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); - /* We cannot afford a bounding box with some null dimension, which may happen in some cases... - * 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); + if (do_bb) { + BoundBox *bb = BKE_object_boundbox_get(ob); - /* 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; - } + if (bb) { + BoundBox bb_temp; - /* was local_depth, see: T47838 */ - len_diff = BVH_RAYCAST_DIST_MAX; + /* We cannot afford a bounding box with some null dimension, which may happen in some cases... + * 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); - if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) { + /* 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, ray_min_dist, snapdata->mval, + ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); + if (dist_px_sq > SQUARE(*dist_px)) + { return retval; } - need_ray_start_correction_init = false; - } - } - - SnapObjectData_Mesh *sod = NULL; - BVHTreeFromMesh *treedata = NULL, treedata_stack; - - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { - sod = *sod_p; } else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_MESH; - } - - int tree_index = -1; - switch (snap_to) { - case SCE_SNAP_MODE_FACE: - tree_index = 2; - break; - case SCE_SNAP_MODE_EDGE: - tree_index = 1; - break; - case SCE_SNAP_MODE_VERTEX: - tree_index = 0; - break; - } - if (tree_index != -1) { - if (sod->bvh_trees[tree_index] == NULL) { - sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); - } - treedata = sod->bvh_trees[tree_index]; - - /* the tree is owned by the DM and may have been freed since we last used! */ - if (treedata && treedata->tree) { - if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) { - free_bvhtree_from_mesh(treedata); - } + /* 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; } - else { - treedata = &treedata_stack; - memset(treedata, 0, sizeof(*treedata)); + } + + SnapObjectData_Mesh *sod = NULL; + BVHTreeFromMesh *treedata = NULL; + + void **sod_p; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + sod = *sod_p; + } + else { + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_MESH; + } + + int tree_index = -1; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + tree_index = 2; + break; + case SCE_SNAP_MODE_EDGE: + tree_index = 1; + break; + case SCE_SNAP_MODE_VERTEX: + tree_index = 0; + break; + } + if (tree_index != -1) { + if (sod->bvh_trees[tree_index] == NULL) { + sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); } + treedata = sod->bvh_trees[tree_index]; - if (treedata && treedata->tree == NULL) { - switch (snap_to) { - case SCE_SNAP_MODE_FACE: - bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); - break; - case SCE_SNAP_MODE_EDGE: - bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6); - break; - case SCE_SNAP_MODE_VERTEX: - bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6); - break; + /* the tree is owned by the DM and may have been freed since we last used! */ + if (treedata && treedata->tree) { + if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) { + free_bvhtree_from_mesh(treedata); } } + } - if (!treedata || !treedata->tree) { - return retval; + if (treedata && treedata->tree == NULL) { + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); + break; + case SCE_SNAP_MODE_EDGE: + bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6); + break; + case SCE_SNAP_MODE_VERTEX: + bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6); + break; } + } + if (!treedata || !treedata->tree) { + return retval; + } - if (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 (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. - */ - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); - if (nearest.index != -1) { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - } + 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 (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. + */ + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); + if (nearest.index != -1) { + 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. + } + /* 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) { + /* 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. */ + 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); + 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) { - struct RayCastAll_Data data; - - data.bvhdata = treedata; - data.raycast_callback = treedata->raycast_callback; - data.obmat = obmat; - data.timat = timat; - data.len_diff = len_diff; - data.local_scale = local_scale; - data.ob = ob; - data.ob_uuid = ob_index; - data.hit_list = r_hit_list; - data.retval = retval; - - BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); - - retval = data.retval; - } - else { - BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - - if (BLI_bvhtree_ray_cast( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - &hit, treedata->raycast_callback, treedata) != -1) - { - hit.dist += len_diff; - hit.dist /= local_scale; - if (hit.dist <= *ray_depth) { - *ray_depth = hit.dist; - copy_v3_v3(r_loc, hit.co); - - /* back to worldspace */ - mul_m4_v3(obmat, r_loc); - - if (r_no) { - copy_v3_v3(r_no, hit.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } - - retval = true; - - if (r_index) { - *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]); - } - } - } - } + else len_diff = 0.0f; } - /* 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}; - - 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); + len_diff = 0.0f; + } + if (r_hit_list) { + struct RayCastAll_Data data; + + data.bvhdata = treedata; + data.raycast_callback = treedata->raycast_callback; + data.obmat = obmat; + data.timat = timat; + data.len_diff = len_diff; + data.local_scale = local_scale; + data.ob = ob; + data.ob_uuid = ob_index; + data.hit_list = r_hit_list; + data.retval = retval; + + BLI_bvhtree_ray_cast_all( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); + + retval = data.retval; + } + else { + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - BVHTree_WalkLeafCallback cb_walk_leaf = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; + if (BLI_bvhtree_ray_cast( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + &hit, treedata->raycast_callback, treedata) != -1) + { + hit.dist += len_diff; + hit.dist /= local_scale; + if (hit.dist <= *ray_depth) { + *ray_depth = hit.dist; + copy_v3_v3(r_loc, hit.co); + + /* back to worldspace */ + mul_m4_v3(obmat, r_loc); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } - BLI_bvhtree_walk_dfs( - treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); + retval = true; - 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); + if (r_index) { + *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]); + } } - *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); - - retval = true; } } - - if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) { - if (treedata) { - free_bvhtree_from_mesh(treedata); + } + /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ + else { + Nearest2dUserData neasrest2d = { + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .userdata = treedata, + .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts, + .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no, + .index = -1}; + + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, + ray_min_dist, 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); } + *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + + retval = true; } } @@ -1231,11 +1336,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 */ @@ -1244,12 +1346,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; } @@ -1260,254 +1362,246 @@ static bool snapEditMesh( } } - { - float imat[4][4]; - float timat[3][3]; /* transpose inverse matrix for normals */ - float ray_normal_local[3]; + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_normal_local[3]; - invert_m4_m4(imat, obmat); - transpose_m3_m4(timat, imat); + 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); + mul_mat3_m4_v3(imat, ray_normal_local); - SnapObjectData_EditMesh *sod = NULL; + /* 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; + } - BVHTreeFromEditMesh *treedata = NULL, treedata_stack; + SnapObjectData_EditMesh *sod = NULL; - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - void **sod_p; - if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { - sod = *sod_p; - } - else { - sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); - sod->sd.type = SNAP_EDIT_MESH; - } + BVHTreeFromEditMesh *treedata = NULL; - int tree_index = -1; - switch (snap_to) { - case SCE_SNAP_MODE_FACE: - tree_index = 2; - break; - case SCE_SNAP_MODE_EDGE: - tree_index = 1; - break; - case SCE_SNAP_MODE_VERTEX: - tree_index = 0; - break; - } - if (tree_index != -1) { - if (sod->bvh_trees[tree_index] == NULL) { - sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); - } - treedata = sod->bvh_trees[tree_index]; - } - } - else { - treedata = &treedata_stack; - memset(treedata, 0, sizeof(*treedata)); + void **sod_p; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + sod = *sod_p; + } + else { + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_EDIT_MESH; + } + + int tree_index = -1; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + tree_index = 2; + break; + case SCE_SNAP_MODE_EDGE: + tree_index = 1; + break; + case SCE_SNAP_MODE_VERTEX: + tree_index = 0; + break; + } + if (tree_index != -1) { + if (sod->bvh_trees[tree_index] == NULL) { + sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); } + treedata = sod->bvh_trees[tree_index]; + } - if (treedata && treedata->tree == NULL) { - switch (snap_to) { - case SCE_SNAP_MODE_FACE: - { - BLI_bitmap *looptri_mask = NULL; - int looptri_num_active = -1; - if (sctx->callbacks.edit_mesh.test_face_fn) { - looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__); - looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( - em->bm, looptri_mask, - sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_looptri_ex(treedata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6, NULL); - if (looptri_mask) { - MEM_freeN(looptri_mask); - } - break; + if (treedata && treedata->tree == NULL) { + BLI_bitmap *elem_mask = NULL; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_FACE: + { + int looptri_num_active = -1; + if (sctx->callbacks.edit_mesh.test_face_fn) { + elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); + looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( + em->bm, elem_mask, + sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); } - case SCE_SNAP_MODE_EDGE: - { - BLI_bitmap *edges_mask = NULL; - int edges_num_active = -1; - if (sctx->callbacks.edit_mesh.test_edge_fn) { - edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); - edges_num_active = BM_iter_mesh_bitmap_from_filter( - BM_EDGES_OF_MESH, em->bm, edges_mask, - (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, - sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_edges_ex(treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6); - if (edges_mask) { - MEM_freeN(edges_mask); - } - break; + bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL); + break; + } + case SCE_SNAP_MODE_EDGE: + { + int edges_num_active = -1; + if (sctx->callbacks.edit_mesh.test_edge_fn) { + elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); + edges_num_active = BM_iter_mesh_bitmap_from_filter( + BM_EDGES_OF_MESH, em->bm, elem_mask, + (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, + sctx->callbacks.edit_mesh.user_data); } - case SCE_SNAP_MODE_VERTEX: - { - BLI_bitmap *verts_mask = NULL; - int verts_num_active = -1; - if (sctx->callbacks.edit_mesh.test_vert_fn) { - verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); - verts_num_active = BM_iter_mesh_bitmap_from_filter( - BM_VERTS_OF_MESH, em->bm, verts_mask, - (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, - sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_verts_ex(treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6); - if (verts_mask) { - MEM_freeN(verts_mask); - } - break; + bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6); + break; + } + case SCE_SNAP_MODE_VERTEX: + { + int verts_num_active = -1; + if (sctx->callbacks.edit_mesh.test_vert_fn) { + elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + verts_num_active = BM_iter_mesh_bitmap_from_filter( + BM_VERTS_OF_MESH, em->bm, elem_mask, + (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, + sctx->callbacks.edit_mesh.user_data); } + bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6); + break; } } - - if (!treedata || !treedata->tree) { - return retval; + if (elem_mask) { + MEM_freeN(elem_mask); } + } - if (snap_to == SCE_SNAP_MODE_FACE) { - float ray_start_local[3]; - copy_v3_v3(ray_start_local, ray_start); - mul_m4_v3(imat, ray_start_local); + if (!treedata || !treedata->tree) { + return retval; + } - /* 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; - } + if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { + float ray_start_local[3]; + copy_v3_v3(ray_start_local, snapdata->ray_start); + mul_m4_v3(imat, ray_start_local); - /* 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! + /* 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 (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. */ - float len_diff = 0.0f; - if (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. - */ - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - if (BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) - { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + if (BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) + { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); + /* 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); + 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. */ + 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); + 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) { - struct RayCastAll_Data data; - - data.bvhdata = treedata; - data.raycast_callback = treedata->raycast_callback; - data.obmat = obmat; - data.timat = timat; - data.len_diff = len_diff; - data.local_scale = local_scale; - data.ob = ob; - data.ob_uuid = ob_index; - data.hit_list = r_hit_list; - data.retval = retval; - - BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); - - retval = data.retval; - } - else { - BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - - if (BLI_bvhtree_ray_cast( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - &hit, treedata->raycast_callback, treedata) != -1) - { - hit.dist += len_diff; - hit.dist /= local_scale; - if (hit.dist <= *ray_depth) { - *ray_depth = hit.dist; - copy_v3_v3(r_loc, hit.co); - - /* back to worldspace */ - mul_m4_v3(obmat, r_loc); - - if (r_no) { - copy_v3_v3(r_no, hit.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } - - retval = true; - - if (r_index) { - *r_index = hit.index; - } - } - } - } + } + if (r_hit_list) { + struct RayCastAll_Data data; + + data.bvhdata = treedata; + data.raycast_callback = treedata->raycast_callback; + data.obmat = obmat; + data.timat = timat; + data.len_diff = len_diff; + data.local_scale = local_scale; + data.ob = ob; + data.ob_uuid = ob_index; + data.hit_list = r_hit_list; + data.retval = retval; + + BLI_bvhtree_ray_cast_all( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); + + retval = data.retval; } 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_EDIT_MESH}; - - Object_Nearest2dPrecalc neasrest_precalc; - neasrest_precalc.userdata = &treedata_type; - neasrest_precalc.index = -1; + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - 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; + if (BLI_bvhtree_ray_cast( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + &hit, treedata->raycast_callback, treedata) != -1) + { + hit.dist += len_diff; + hit.dist /= local_scale; + if (hit.dist <= *ray_depth) { + *ray_depth = hit.dist; + copy_v3_v3(r_loc, hit.co); + + /* back to worldspace */ + mul_m4_v3(obmat, r_loc); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } - BLI_bvhtree_walk_dfs( - treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); + retval = true; - 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); + if (r_index) { + *r_index = hit.index; + } } - *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); - - retval = true; } } - - if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) { - if (treedata) { - free_bvhtree_from_editmesh(treedata); + } + else { + float ray_org_local[3]; + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); + + Nearest2dUserData neasrest2d = { + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .userdata = treedata, + .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts, + .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no, + .index = -1}; + + float lpmat[4][4]; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, + (snapdata->depth_range[0] * local_scale), 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); } + *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + + retval = true; } } @@ -1520,11 +1614,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 */ @@ -1532,12 +1624,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) { @@ -1546,9 +1632,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); @@ -1565,9 +1649,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); @@ -1575,32 +1658,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); } } @@ -1622,18 +1705,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 * --------------- @@ -1654,11 +1728,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 */ @@ -1681,9 +1753,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); } @@ -1717,9 +1787,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); } @@ -1731,9 +1800,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); } @@ -1760,6 +1827,9 @@ SnapObjectContext *ED_transform_snap_object_context_create( sctx->bmain = bmain; sctx->scene = scene; + sctx->cache.object_map = BLI_ghash_ptr_new(__func__); + sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + return sctx; } @@ -1774,11 +1844,6 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d( sctx->v3d_data.ar = ar; sctx->v3d_data.v3d = v3d; - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - sctx->cache.object_map = BLI_ghash_ptr_new(__func__); - sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - } - return sctx; } @@ -1810,10 +1875,8 @@ static void snap_object_data_free(void *sod_v) void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) { - if (sctx->flag & SNAP_OBJECT_USE_CACHE) { - BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); - BLI_memarena_free(sctx->cache.mem_arena); - } + BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); + BLI_memarena_free(sctx->cache.mem_arena); MEM_freeN(sctx); } @@ -1842,10 +1905,15 @@ bool ED_transform_snap_object_project_ray_ex( 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, ray_start, ray_start, ray_normal, 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); } @@ -1874,10 +1942,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); @@ -1956,19 +2027,40 @@ static bool transform_snap_context_project_view3d_mixed_impl( BLI_assert(snap_to_flag != 0); BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0); - 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 (use_depth) { + const float dist_px_orig = dist_px ? *dist_px : 0; + for (int i = 2; i >= 0; i--) { + if (snap_to_flag & (1 << i)) { + if (i == 0) { + BLI_assert(dist_px != NULL); + *dist_px = dist_px_orig; + } + if (ED_transform_snap_object_project_view3d( + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) + { + /* 0.01 is a random but small value to prioritizing + * the first elements of the loop */ + ray_depth += 0.01f; + is_hit = true; + } } - - if (ED_transform_snap_object_project_view3d( - sctx, - elem_type[i], params, - mval, dist_px, &ray_depth, - r_co, r_no)) - { - is_hit = true; + } + } + else { + for (int i = 0; i < 3; i++) { + if (snap_to_flag & (1 << i)) { + if (ED_transform_snap_object_project_view3d( + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) + { + is_hit = true; + break; + } } } } @@ -2037,10 +2129,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/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index b857aea29ad..4e2043471b6 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -609,7 +609,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode GPU_link(mat, "lamp_visibility_spot", GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), - GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), + GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTBLEND, lamp->ob), inpr, visifac, &visifac); } 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/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 52febe642a0..4164f5fa75d 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -77,6 +77,16 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha const char *from_colorspace, const char *to_colorspace, bool predivide); void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide); +void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); +void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace); void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace); void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace); @@ -185,6 +195,8 @@ void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_proc void IMB_colormanagement_processor_apply_pixel(struct ColormanageProcessor *cm_processor, float *pixel, int channels); void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height, int channels, bool predivide); +void IMB_colormanagement_processor_apply_byte(struct ColormanageProcessor *cm_processor, + unsigned char *buffer, int width, int height, int channels); void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor); /* ** OpenGL drawing routines using GLSL for color space transform ** */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index a45346279d9..48cba3e0800 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1555,21 +1555,25 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ typedef struct ProcessorTransformThread { ColormanageProcessor *cm_processor; - float *buffer; + unsigned char *byte_buffer; + float *float_buffer; int width; int start_line; int tot_line; int channels; bool predivide; + bool float_from_byte; } ProcessorTransformThread; typedef struct ProcessorTransformInit { ColormanageProcessor *cm_processor; - float *buffer; + unsigned char *byte_buffer; + float *float_buffer; int width; int height; int channels; bool predivide; + bool float_from_byte; } ProcessorTransformInitData; static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) @@ -1577,17 +1581,24 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; ProcessorTransformInitData *init_data = (ProcessorTransformInitData *) init_data_v; - int channels = init_data->channels; - int width = init_data->width; - bool predivide = init_data->predivide; + const int channels = init_data->channels; + const int width = init_data->width; + const bool predivide = init_data->predivide; + const bool float_from_byte = init_data->float_from_byte; - size_t offset = ((size_t)channels) * start_line * width; + const size_t offset = ((size_t)channels) * start_line * width; memset(handle, 0, sizeof(ProcessorTransformThread)); handle->cm_processor = init_data->cm_processor; - handle->buffer = init_data->buffer + offset; + if (init_data->byte_buffer != NULL) { + /* TODO(serge): Offset might be different for byte and float buffers. */ + handle->byte_buffer = init_data->byte_buffer + offset; + } + if (init_data->float_buffer != NULL) { + handle->float_buffer = init_data->float_buffer + offset; + } handle->width = width; @@ -1596,33 +1607,62 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int handle->channels = channels; handle->predivide = predivide; + handle->float_from_byte = float_from_byte; } static void *do_processor_transform_thread(void *handle_v) { ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; - float *buffer = handle->buffer; - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - bool predivide = handle->predivide; - - IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide); + unsigned char *byte_buffer = handle->byte_buffer; + float *float_buffer = handle->float_buffer; + const int channels = handle->channels; + const int width = handle->width; + const int height = handle->tot_line; + const bool predivide = handle->predivide; + const bool float_from_byte = handle->float_from_byte; + + if (float_from_byte) { + IMB_buffer_float_from_byte(float_buffer, byte_buffer, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, + true, + width, height, width, width); + IMB_colormanagement_processor_apply(handle->cm_processor, + float_buffer, + width, height, channels, + predivide); + } + else { + if (byte_buffer != NULL) { + IMB_colormanagement_processor_apply_byte(handle->cm_processor, + byte_buffer, + width, height, channels); + } + if (float_buffer != NULL) { + IMB_colormanagement_processor_apply(handle->cm_processor, + float_buffer, + width, height, channels, + predivide); + } + } return NULL; } -static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels, - ColormanageProcessor *cm_processor, bool predivide) +static void processor_transform_apply_threaded(unsigned char *byte_buffer, float *float_buffer, + const int width, const int height, const int channels, + ColormanageProcessor *cm_processor, + const bool predivide, const bool float_from_byte) { ProcessorTransformInitData init_data; init_data.cm_processor = cm_processor; - init_data.buffer = buffer; + init_data.byte_buffer = byte_buffer; + init_data.float_buffer = float_buffer; init_data.width = width; init_data.height = height; init_data.channels = channels; init_data.predivide = predivide; + init_data.float_from_byte = float_from_byte; IMB_processor_apply_threaded(height, sizeof(ProcessorTransformThread), &init_data, processor_transform_init_handle, do_processor_transform_thread); @@ -1631,8 +1671,10 @@ static void processor_transform_apply_threaded(float *buffer, int width, int hei /*********************** Color space transformation functions *************************/ /* convert the whole buffer from specified by name color space to another - internal implementation */ -static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace, - const char *to_colorspace, bool predivide, bool do_threaded) +static void colormanagement_transform_ex(unsigned char *byte_buffer, float *float_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace, + bool predivide, bool do_threaded) { ColormanageProcessor *cm_processor; @@ -1649,10 +1691,19 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); - if (do_threaded) - processor_transform_apply_threaded(buffer, width, height, channels, cm_processor, predivide); - else - IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide); + if (do_threaded) { + processor_transform_apply_threaded(byte_buffer, float_buffer, + width, height, channels, + cm_processor, predivide, false); + } + else { + if (byte_buffer != NULL) { + IMB_colormanagement_processor_apply_byte(cm_processor, byte_buffer, width, height, channels); + } + if (float_buffer != NULL) { + IMB_colormanagement_processor_apply(cm_processor, float_buffer, width, height, channels, predivide); + } + } IMB_colormanagement_processor_free(cm_processor); } @@ -1661,7 +1712,7 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide) { - colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); + colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); } /* convert the whole buffer from specified by name color space to another @@ -1670,7 +1721,54 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide) { - colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); + colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); +} + +/* Similar to functions above, but operates on byte buffer. */ +void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, false); +} +void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, true); +} + +/* Similar to above, but gets float buffer from display one. */ +void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + IMB_buffer_float_from_byte(float_buffer, byte_buffer, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, + true, + width, height, width, width); + IMB_colormanagement_transform(float_buffer, + width, height, channels, + from_colorspace, to_colorspace, + true); +} +void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + ColormanageProcessor *cm_processor; + if (from_colorspace == NULL || from_colorspace[0] == '\0') { + return; + } + if (STREQ(from_colorspace, to_colorspace)) { + /* If source and destination color spaces are identical, skip + * threading overhead and simply do nothing + */ + return; + } + cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); + processor_transform_apply_threaded(byte_buffer, float_buffer, + width, height, channels, + cm_processor, true, true); + IMB_colormanagement_processor_free(cm_processor); } void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace) @@ -1974,12 +2072,14 @@ void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float); float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space"); + /* TODO(sergey): Convert float directly to byte buffer. */ + memcpy(display_buffer_float, buffer, float_buffer_size); cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - processor_transform_apply_threaded(display_buffer_float, width, height, channels, - cm_processor, true); + processor_transform_apply_threaded(NULL, display_buffer_float, width, height, channels, + cm_processor, true, false); IMB_buffer_byte_from_float(display_buffer, display_buffer_float, channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, @@ -3100,6 +3200,25 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo } } +void IMB_colormanagement_processor_apply_byte(ColormanageProcessor *cm_processor, + unsigned char *buffer, + int width, int height, int channels) +{ + /* TODO(sergey): Would be nice to support arbitrary channels configurations, + * but for now it's not so important. + */ + BLI_assert(channels == 4); + float pixel[4]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + size_t offset = channels * (((size_t)y) * width + x); + rgba_uchar_to_float(pixel, buffer + offset); + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + rgba_float_to_uchar(buffer + offset, pixel); + } + } +} + void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) { if (cm_processor->curve_mapping) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 4eb5a4a5de4..a75e3c13fce 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3949,7 +3949,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dpi"); - RNA_def_property_range(prop, 16, 256); + RNA_def_property_range(prop, 48, 144); RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 567505ea45d..2400dbcb898 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index b049457e640..2b739dc0093 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index da0f5aa3923..f828bc68857 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 2fe27730370..ddcf1852dc6 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index ac75b4dbee9..e8c39770a14 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -234,11 +234,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 9bc96e593fd..09444476bfe 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 1e69ba87f9c..a2210893602 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 059e096ddb4..f6acbef96e9 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -38,10 +38,12 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BLI_task.h" #include "BKE_cdderivedmesh.h" #include "BKE_library.h" #include "BKE_library_query.h" +#include "BKE_image.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_texture.h" @@ -132,7 +134,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 +142,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); } @@ -200,21 +202,130 @@ static void updateDepsgraph(ModifierData *md, } } +typedef struct DisplaceUserdata { + /*const*/ DisplaceModifierData *dmd; + struct ImagePool *pool; + MDeformVert *dvert; + float weight; + int defgrp_index; + int direction; + bool use_global_direction; + float (*tex_co)[3]; + float (*vertexCos)[3]; + float local_mat[4][4]; + MVert *mvert; + float (*vert_clnors)[3]; +} DisplaceUserdata; + +static void displaceModifier_do_task(void *userdata, const int iter) +{ + DisplaceUserdata *data = (DisplaceUserdata *)userdata; + DisplaceModifierData *dmd = data->dmd; + MDeformVert *dvert = data->dvert; + float weight = data->weight; + int defgrp_index = data->defgrp_index; + int direction = data->direction; + bool use_global_direction = data->use_global_direction; + float (*tex_co)[3] = data->tex_co; + float (*vertexCos)[3] = data->vertexCos; + MVert *mvert = data->mvert; + float (*vert_clnors)[3] = data->vert_clnors; + + const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */ + + TexResult texres; + float strength = dmd->strength; + float delta; + float local_vec[3]; + + if (dvert) { + weight = defvert_find_weight(dvert + iter, defgrp_index); + if (weight == 0.0f) { + return; + } + } + + if (dmd->texture) { + texres.nor = NULL; + BKE_texture_get_value_ex(dmd->modifier.scene, dmd->texture, tex_co[iter], &texres, data->pool, false); + delta = texres.tin - dmd->midlevel; + } + else { + delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */ + } + + if (dvert) { + strength *= weight; + } + + delta *= strength; + CLAMP(delta, -10000, 10000); + + switch (direction) { + case MOD_DISP_DIR_X: + if (use_global_direction) { + vertexCos[iter][0] += delta * data->local_mat[0][0]; + vertexCos[iter][1] += delta * data->local_mat[1][0]; + vertexCos[iter][2] += delta * data->local_mat[2][0]; + } + else { + vertexCos[iter][0] += delta; + } + break; + case MOD_DISP_DIR_Y: + if (use_global_direction) { + vertexCos[iter][0] += delta * data->local_mat[0][1]; + vertexCos[iter][1] += delta * data->local_mat[1][1]; + vertexCos[iter][2] += delta * data->local_mat[2][1]; + } + else { + vertexCos[iter][1] += delta; + } + break; + case MOD_DISP_DIR_Z: + if (use_global_direction) { + vertexCos[iter][0] += delta * data->local_mat[0][2]; + vertexCos[iter][1] += delta * data->local_mat[1][2]; + vertexCos[iter][2] += delta * data->local_mat[2][2]; + } + else { + vertexCos[iter][2] += delta; + } + break; + case MOD_DISP_DIR_RGB_XYZ: + local_vec[0] = texres.tr - dmd->midlevel; + local_vec[1] = texres.tg - dmd->midlevel; + local_vec[2] = texres.tb - dmd->midlevel; + if (use_global_direction) { + mul_transposed_mat3_m4_v3(data->local_mat, local_vec); + } + mul_v3_fl(local_vec, strength); + add_v3_v3(vertexCos[iter], local_vec); + break; + case MOD_DISP_DIR_NOR: + vertexCos[iter][0] += delta * (mvert[iter].no[0] / 32767.0f); + vertexCos[iter][1] += delta * (mvert[iter].no[1] / 32767.0f); + vertexCos[iter][2] += delta * (mvert[iter].no[2] / 32767.0f); + break; + case MOD_DISP_DIR_CLNOR: + madd_v3_v3fl(vertexCos[iter], vert_clnors[iter], delta); + break; + } +} + /* dm must be a CDDerivedMesh */ static void displaceModifier_do( DisplaceModifierData *dmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { - int i; MVert *mvert; MDeformVert *dvert; int direction = dmd->direction; int defgrp_index; float (*tex_co)[3]; float weight = 1.0f; /* init value unused but some compilers may complain */ - const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */ float (*vert_clnors)[3] = NULL; - float local_mat[4][4]; + float local_mat[4][4] = {0}; const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL; if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return; @@ -259,81 +370,25 @@ static void displaceModifier_do( copy_m4_m4(local_mat, ob->obmat); } - for (i = 0; i < numVerts; i++) { - TexResult texres; - float strength = dmd->strength; - float delta; - float local_vec[3]; - - if (dvert) { - weight = defvert_find_weight(dvert + i, defgrp_index); - if (weight == 0.0f) continue; - } - - if (dmd->texture) { - texres.nor = NULL; - BKE_texture_get_value(dmd->modifier.scene, dmd->texture, tex_co[i], &texres, false); - delta = texres.tin - dmd->midlevel; - } - else { - delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */ - } + DisplaceUserdata data = {NULL}; + data.dmd = dmd; + data.dvert = dvert; + data.weight = weight; + data.defgrp_index = defgrp_index; + data.direction = direction; + data.use_global_direction = use_global_direction; + data.tex_co = tex_co; + data.vertexCos = vertexCos; + copy_m4_m4(data.local_mat, local_mat); + data.mvert = mvert; + data.vert_clnors = vert_clnors; + if (dmd->texture != NULL) { + data.pool = BKE_image_pool_new(); + } + BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512); - if (dvert) strength *= weight; - - delta *= strength; - CLAMP(delta, -10000, 10000); - - switch (direction) { - case MOD_DISP_DIR_X: - if (use_global_direction) { - vertexCos[i][0] += delta * local_mat[0][0]; - vertexCos[i][1] += delta * local_mat[1][0]; - vertexCos[i][2] += delta * local_mat[2][0]; - } - else { - vertexCos[i][0] += delta; - } - break; - case MOD_DISP_DIR_Y: - if (use_global_direction) { - vertexCos[i][0] += delta * local_mat[0][1]; - vertexCos[i][1] += delta * local_mat[1][1]; - vertexCos[i][2] += delta * local_mat[2][1]; - } - else { - vertexCos[i][1] += delta; - } - break; - case MOD_DISP_DIR_Z: - if (use_global_direction) { - vertexCos[i][0] += delta * local_mat[0][2]; - vertexCos[i][1] += delta * local_mat[1][2]; - vertexCos[i][2] += delta * local_mat[2][2]; - } - else { - vertexCos[i][2] += delta; - } - break; - case MOD_DISP_DIR_RGB_XYZ: - local_vec[0] = texres.tr - dmd->midlevel; - local_vec[1] = texres.tg - dmd->midlevel; - local_vec[2] = texres.tb - dmd->midlevel; - if (use_global_direction) { - mul_transposed_mat3_m4_v3(local_mat, local_vec); - } - mul_v3_fl(local_vec, strength); - add_v3_v3(vertexCos[i], local_vec); - break; - case MOD_DISP_DIR_NOR: - vertexCos[i][0] += delta * (mvert[i].no[0] / 32767.0f); - vertexCos[i][1] += delta * (mvert[i].no[1] / 32767.0f); - vertexCos[i][2] += delta * (mvert[i].no[2] / 32767.0f); - break; - case MOD_DISP_DIR_CLNOR: - madd_v3_v3fl(vertexCos[i], vert_clnors[i], delta); - break; - } + if (data.pool != NULL) { + BKE_image_pool_free(data.pool); } if (tex_co) { diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index b49a407da78..05068b9b597 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -181,15 +181,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_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 38ffdaa709b..ca7b3ce8039 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -1001,8 +1001,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, ExplodeModifierData *emd = (ExplodeModifierData *) md; ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ob, md); - DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ - if (psmd) { ParticleSystem *psys = psmd->psys; @@ -1010,6 +1008,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (psys->part == NULL || psys->particles == NULL) return derivedData; if (psmd->dm_final == NULL) return derivedData; + DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ + /* 1. find faces to be exploded if needed */ if (emd->facepa == NULL || psmd->flag & eParticleSystemFlag_Pars || diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 9186b10d8ca..56c494ff3c0 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 7d4701e3ef2..dc246084dca 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c index 5e01a20d93b..dcc7fe4d4f1 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 3f34319d25f..406ce398ee0 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 2f00a7c71b0..d956763fc1f 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 88facb22e0e..dd127cc255c 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 454c97451a8..20eae751ca4 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 4e78e758dc3..fbf5a958254 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -145,7 +145,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 290e19736bb..87859cd240a 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -1093,7 +1093,7 @@ static void foreachObjectLink( { ScrewModifierData *ltmd = (ScrewModifierData *) md; - walk(userData, ob, <md->ob_axis, IDWALK_NOP); + walk(userData, ob, <md->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 633311c2b87..a14747bc153 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 c68f2651191..379eaea5b0c 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 updateDepgraph(ModifierData *md, DagForest *forest, diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index a7b23ae2403..c105a3ab3a7 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -174,17 +174,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 fb7668d16e0..78dc1ea8bcb 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 89994c3ae22..b3fc3842635 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 b38de140a91..92d44257d03 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 683649ed1c0..f0c4940816e 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 93567aed2c4..2a822ac07b5 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 170fbbed7f1..9bff7bf11f1 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 af59f11ba15..2c87838aeab 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/python/intern/gpu.c b/source/blender/python/intern/gpu.c index 50dd4618166..48230a723d2 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -138,6 +138,7 @@ static PyObject *PyInit_gpu(void) PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_MIR); /* -------------------------------------------------------------------- */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index ef69ed31ef6..cef5e7e4a8e 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3910,8 +3910,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; @@ -3944,7 +3948,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 diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 28a5f0a3588..77a0266c85b 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -235,13 +235,13 @@ struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) void RE_texture_rng_init() RET_NONE void RE_texture_rng_exit() RET_NONE -bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;} +bool RE_layers_have_name(struct RenderResult *result) RET_ZERO const char *RE_engine_active_view_get(struct RenderEngine *engine) RET_NULL -void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);} -void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo, float *r_modelmat) {STUB_ASSERT(0);} +void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) RET_NONE +void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo, float *r_modelmat) RET_NONE float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo) RET_ZERO int RE_engine_get_spherical_stereo(struct RenderEngine *engine, struct Object *camera) RET_ZERO -void RE_SetActiveRenderView(struct Render *re, const char *viewname) {STUB_ASSERT(0);} +void RE_SetActiveRenderView(struct Render *re, const char *viewname) RET_NONE struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL bool RE_HasFakeLayer(RenderResult *res) RET_ZERO @@ -463,17 +463,17 @@ void ED_node_texture_default(const struct bContext *C, struct Tex *tex) RET_NONE void ED_node_tag_update_id(struct ID *id) RET_NONE void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node) RET_NONE void ED_node_tree_update(const struct bContext *C) RET_NONE -void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo){} -void ED_init_custom_node_type(struct bNodeType *ntype){} -void ED_init_custom_node_socket_type(struct bNodeSocketType *stype){} +void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo) RET_NONE +void ED_init_custom_node_type(struct bNodeType *ntype) RET_NONE +void ED_init_custom_node_socket_type(struct bNodeSocketType *stype) RET_NONE void ED_init_standard_node_socket_type(struct bNodeSocketType *stype) RET_NONE void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype) RET_NONE -int ED_node_tree_path_length(struct SpaceNode *snode){return 0;} -void ED_node_tree_path_get(struct SpaceNode *snode, char *value){} -void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length){} -void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from){} -void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode){} -void ED_node_tree_pop(struct SpaceNode *snode){} +int ED_node_tree_path_length(struct SpaceNode *snode) RET_ZERO +void ED_node_tree_path_get(struct SpaceNode *snode, char *value) RET_NONE +void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length) RET_NONE +void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from) RET_NONE +void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode) RET_NONE +void ED_node_tree_pop(struct SpaceNode *snode) RET_NONE int ED_view3d_scene_layer_set(int lay, const int *values, int *active) RET_ZERO void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip) RET_NONE void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) RET_NONE @@ -671,9 +671,9 @@ struct RenderEngine *RE_engine_create(struct RenderEngineType *type) RET_NULL void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe) RET_NONE void RE_FreePersistentData(void) RET_NONE void RE_point_density_cache(struct Scene *scene, struct PointDensity *pd, const bool use_render_params) RET_NONE -void RE_point_density_minmax(struct Scene *scene, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE; -void RE_point_density_sample(struct Scene *scene, struct PointDensity *pd, int resolution, const bool use_render_params, float *values) RET_NONE; -void RE_point_density_free(struct PointDensity *pd) RET_NONE; +void RE_point_density_minmax(struct Scene *scene, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE +void RE_point_density_sample(struct Scene *scene, struct PointDensity *pd, int resolution, const bool use_render_params, float *values) RET_NONE +void RE_point_density_free(struct PointDensity *pd) RET_NONE void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE void RE_FreeAllPersistentData(void) RET_NONE float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO @@ -755,7 +755,7 @@ void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb * void macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) RET_ZERO struct PyObject *pyrna_id_CreatePyObject(struct ID *id) RET_NULL -void BPY_context_update(struct bContext *C) RET_NONE; +void BPY_context_update(struct bContext *C) RET_NONE const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) RET_ARG(msgid) /* intern/dualcon */ diff --git a/source/tools b/source/tools -Subproject 6bbb68073bfa11e94bb0b3623db38f847037add +Subproject b11375e89061303401376f7aeae42ac2fd64692 |