diff options
Diffstat (limited to 'source/blender')
188 files changed, 2717 insertions, 2188 deletions
diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc index 20ca659d32f..63887d36381 100644 --- a/source/blender/alembic/intern/abc_customdata.cc +++ b/source/blender/alembic/intern/abc_customdata.cc @@ -353,7 +353,7 @@ static void read_custom_data_mcols(const std::string &iobject_full_name, /* Read the vertex colors */ void *cd_data = config.add_customdata_cb( - config.user_data, prop_header.getName().c_str(), CD_MLOOPCOL); + config.mesh, prop_header.getName().c_str(), CD_MLOOPCOL); MCol *cfaces = static_cast<MCol *>(cd_data); MPoly *mpolys = config.mpoly; MLoop *mloops = config.mloop; @@ -437,8 +437,7 @@ static void read_custom_data_uvs(const ICompoundProperty &prop, return; } - void *cd_data = config.add_customdata_cb( - config.user_data, prop_header.getName().c_str(), CD_MLOOPUV); + void *cd_data = config.add_customdata_cb(config.mesh, prop_header.getName().c_str(), CD_MLOOPUV); read_uvs(config, cd_data, sample.getVals(), sample.getIndices()); } diff --git a/source/blender/alembic/intern/abc_customdata.h b/source/blender/alembic/intern/abc_customdata.h index c36029d5116..0ffafa8848e 100644 --- a/source/blender/alembic/intern/abc_customdata.h +++ b/source/blender/alembic/intern/abc_customdata.h @@ -28,6 +28,7 @@ #include <Alembic/AbcGeom/All.h> struct CustomData; +struct Mesh; struct MLoop; struct MLoopUV; struct MPoly; @@ -60,8 +61,8 @@ struct CDStreamConfig { /* TODO(kevin): might need a better way to handle adding and/or updating * custom datas such that it updates the custom data holder and its pointers * properly. */ - void *user_data; - void *(*add_customdata_cb)(void *user_data, const char *name, int data_type); + Mesh *mesh; + void *(*add_customdata_cb)(Mesh *mesh, const char *name, int data_type); float weight; float time; @@ -75,7 +76,7 @@ struct CDStreamConfig { totpoly(0), totvert(0), pack_uvs(false), - user_data(NULL), + mesh(NULL), add_customdata_cb(NULL), weight(0.0f), time(0.0f), diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index b0129a358ec..9e6f2dd6b52 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -46,6 +46,8 @@ extern "C" { #include "BKE_modifier.h" #include "BKE_object.h" +#include "MEM_guardedalloc.h" + #include "WM_api.h" #include "WM_types.h" @@ -122,7 +124,7 @@ static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points) static void get_topology(struct Mesh *mesh, std::vector<int32_t> &poly_verts, std::vector<int32_t> &loop_counts, - bool &smooth_normal) + bool &r_export_loop_normals) { const int num_poly = mesh->totpoly; const int num_loops = mesh->totloop; @@ -139,7 +141,7 @@ static void get_topology(struct Mesh *mesh, MPoly &poly = mpoly[i]; loop_counts.push_back(poly.totloop); - smooth_normal |= ((poly.flag & ME_SMOOTH) != 0); + r_export_loop_normals |= (poly.flag & ME_SMOOTH) != 0; MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1); @@ -203,17 +205,14 @@ static void get_loop_normals(struct Mesh *mesh, std::vector<Imath::V3f> &normals normals.clear(); normals.resize(mesh->totloop); - unsigned loop_index = 0; - /* NOTE: data needs to be written in the reverse order. */ + int abc_index = 0; if (lnors) { for (int i = 0, e = mesh->totpoly; i < e; ++i, ++mp) { - ml = mloop + mp->loopstart + (mp->totloop - 1); - - for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { - const int index = ml->v; - copy_yup_from_zup(normals[loop_index].getValue(), lnors[index]); + for (int j = mp->totloop - 1; j >= 0; --j, ++abc_index) { + int blender_index = mp->loopstart + j; + copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]); } } } @@ -227,15 +226,15 @@ static void get_loop_normals(struct Mesh *mesh, std::vector<Imath::V3f> &normals if ((mp->flag & ME_SMOOTH) == 0) { BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no); - for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { - copy_yup_from_zup(normals[loop_index].getValue(), no); + for (int j = 0; j < mp->totloop; --ml, ++j, ++abc_index) { + copy_yup_from_zup(normals[abc_index].getValue(), no); } } else { /* Smooth shaded, use individual vert normals. */ - for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) { + for (int j = 0; j < mp->totloop; --ml, ++j, ++abc_index) { normal_short_to_float_v3(no, verts[ml->v].no); - copy_yup_from_zup(normals[loop_index].getValue(), no); + copy_yup_from_zup(normals[abc_index].getValue(), no); } } } @@ -411,10 +410,10 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh) std::vector<int32_t> poly_verts, loop_counts; std::vector<Imath::V3f> velocities; - bool smooth_normal = false; + bool export_loop_normals = (mesh->flag & ME_AUTOSMOOTH) != 0; get_vertices(mesh, points); - get_topology(mesh, poly_verts, loop_counts, smooth_normal); + get_topology(mesh, poly_verts, loop_counts, export_loop_normals); if (m_first_frame && m_settings.export_face_sets) { writeFaceSets(mesh, m_mesh_schema); @@ -442,7 +441,7 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh) } if (m_settings.export_normals) { - if (smooth_normal) { + if (export_loop_normals) { get_loop_normals(mesh, normals); } else { @@ -451,7 +450,7 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh) ON3fGeomParam::Sample normals_sample; if (!normals.empty()) { - normals_sample.setScope((smooth_normal) ? kFacevaryingScope : kVertexScope); + normals_sample.setScope(export_loop_normals ? kFacevaryingScope : kVertexScope); normals_sample.setVals(V3fArraySample(normals)); } @@ -477,10 +476,10 @@ void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh) std::vector<int32_t> poly_verts, loop_counts; std::vector<int32_t> crease_indices, crease_lengths; - bool smooth_normal = false; + bool export_loop_normals = false; get_vertices(mesh, points); - get_topology(mesh, poly_verts, loop_counts, smooth_normal); + get_topology(mesh, poly_verts, loop_counts, export_loop_normals); get_creases(mesh, crease_indices, crease_lengths, crease_sharpness); if (m_first_frame && m_settings.export_face_sets) { @@ -758,7 +757,8 @@ struct AbcMeshData { P3fArraySamplePtr ceil_positions; N3fArraySamplePtr vertex_normals; - N3fArraySamplePtr face_normals; + N3fArraySamplePtr loop_normals; + bool poly_flag_smooth; V2fArraySamplePtr uvs; UInt32ArraySamplePtr uvs_indices; @@ -832,7 +832,6 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) const size_t uvs_size = uvs == nullptr ? 0 : uvs->size(); const UInt32ArraySamplePtr &uvs_indices = mesh_data.uvs_indices; - const N3fArraySamplePtr &normals = mesh_data.face_normals; const bool do_uvs = (mloopuvs && uvs && uvs_indices) && (uvs_indices->size() == face_indices->size()); @@ -847,9 +846,12 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) poly.loopstart = loop_index; poly.totloop = face_size; - if (normals != NULL) { + if (mesh_data.poly_flag_smooth) { poly.flag |= ME_SMOOTH; } + else { + poly.flag &= ~ME_SMOOTH; + } /* NOTE: Alembic data is stored in the reverse order. */ rev_loop_index = loop_index + (face_size - 1); @@ -873,6 +875,40 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) } } } + + BKE_mesh_calc_edges(config.mesh, false, false); +} + +static void process_normals(CDStreamConfig &config, const AbcMeshData &mesh_data) +{ + Mesh *mesh = config.mesh; + + if (!mesh_data.loop_normals) { + BKE_mesh_calc_normals(config.mesh); + config.mesh->flag &= ~ME_AUTOSMOOTH; + return; + } + + config.mesh->flag |= ME_AUTOSMOOTH; + + const Alembic::AbcGeom::N3fArraySample &loop_normals = *mesh_data.loop_normals; + long int loop_count = loop_normals.size(); + + float(*lnors)[3] = static_cast<float(*)[3]>( + MEM_malloc_arrayN(loop_count, sizeof(float[3]), "ABC::FaceNormals")); + + MPoly *mpoly = mesh->mpoly; + int abc_index = 0; + for (int i = 0, e = mesh->totpoly; i < e; ++i, ++mpoly) { + /* As usual, ABC orders the loops in reverse. */ + for (int j = mpoly->totloop - 1; j >= 0; --j, ++abc_index) { + int blender_index = mpoly->loopstart + j; + copy_zup_from_yup(lnors[blender_index], loop_normals[abc_index].getValue()); + } + } + BKE_mesh_set_custom_normals(config.mesh, lnors); + + MEM_freeN(lnors); } ABC_INLINE void read_uvs_params(CDStreamConfig &config, @@ -900,15 +936,11 @@ ABC_INLINE void read_uvs_params(CDStreamConfig &config, name = uv.getName(); } - void *cd_ptr = config.add_customdata_cb(config.user_data, name.c_str(), CD_MLOOPUV); + void *cd_ptr = config.add_customdata_cb(config.mesh, name.c_str(), CD_MLOOPUV); config.mloopuv = static_cast<MLoopUV *>(cd_ptr); } } -/* TODO(kevin): normals from Alembic files are not read in anymore, this is due - * to the fact that there are many issues that are not so easy to solve, mainly - * regarding the way normals are handled in Blender (MPoly.flag vs loop normals). - */ ABC_INLINE void read_normals_params(AbcMeshData &abc_data, const IN3fGeomParam &normals, const ISampleSelector &selector) @@ -919,42 +951,26 @@ ABC_INLINE void read_normals_params(AbcMeshData &abc_data, IN3fGeomParam::Sample normsamp = normals.getExpandedValue(selector); - if (normals.getScope() == kFacevaryingScope) { - abc_data.face_normals = normsamp.getVals(); - } - else if ((normals.getScope() == kVertexScope) || (normals.getScope() == kVaryingScope)) { - abc_data.vertex_normals = N3fArraySamplePtr(); - } -} - -static bool check_smooth_poly_flag(Mesh *mesh) -{ - MPoly *mpolys = mesh->mpoly; - - for (int i = 0, e = mesh->totpoly; i < e; ++i) { - MPoly &poly = mpolys[i]; - - if ((poly.flag & ME_SMOOTH) != 0) { - return true; - } - } - - return false; -} - -static void set_smooth_poly_flag(Mesh *mesh) -{ - MPoly *mpolys = mesh->mpoly; - - for (int i = 0, e = mesh->totpoly; i < e; ++i) { - MPoly &poly = mpolys[i]; - poly.flag |= ME_SMOOTH; + Alembic::AbcGeom::GeometryScope scope = normals.getScope(); + switch (scope) { + case Alembic::AbcGeom::kFacevaryingScope: + abc_data.loop_normals = normsamp.getVals(); + break; + case Alembic::AbcGeom::kVertexScope: + case Alembic::AbcGeom::kVaryingScope: + /* Vertex normals from ABC aren't handled for now. */ + abc_data.poly_flag_smooth = true; + abc_data.vertex_normals = N3fArraySamplePtr(); + break; + case Alembic::AbcGeom::kConstantScope: + case Alembic::AbcGeom::kUniformScope: + case Alembic::AbcGeom::kUnknownScope: + break; } } -static void *add_customdata_cb(void *user_data, const char *name, int data_type) +static void *add_customdata_cb(Mesh *mesh, const char *name, int data_type) { - Mesh *mesh = static_cast<Mesh *>(user_data); CustomDataType cd_data_type = static_cast<CustomDataType>(data_type); void *cd_ptr; CustomData *loopdata; @@ -994,8 +1010,7 @@ static void read_mesh_sample(const std::string &iobject_full_name, ImportSettings *settings, const IPolyMeshSchema &schema, const ISampleSelector &selector, - CDStreamConfig &config, - bool &do_normals) + CDStreamConfig &config) { const IPolyMeshSchema::Sample sample = schema.getValue(selector); @@ -1003,11 +1018,10 @@ static void read_mesh_sample(const std::string &iobject_full_name, abc_mesh_data.face_counts = sample.getFaceCounts(); abc_mesh_data.face_indices = sample.getFaceIndices(); abc_mesh_data.positions = sample.getPositions(); + abc_mesh_data.poly_flag_smooth = false; read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector); - do_normals = (abc_mesh_data.face_normals != NULL); - get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); if (config.weight != 0.0f) { @@ -1026,6 +1040,7 @@ static void read_mesh_sample(const std::string &iobject_full_name, if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { read_mpolys(config, abc_mesh_data); + process_normals(config, abc_mesh_data); } if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { @@ -1039,7 +1054,7 @@ CDStreamConfig get_config(Mesh *mesh) BLI_assert(mesh->mvert || mesh->totvert == 0); - config.user_data = mesh; + config.mesh = mesh; config.mvert = mesh->mvert; config.mloop = mesh->mloop; config.mpoly = mesh->mpoly; @@ -1079,13 +1094,16 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, NULL); if (read_mesh != mesh) { BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true); + + /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_nomain_to_mesh() */ + mesh->flag |= (read_mesh->flag & ME_AUTOSMOOTH); } if (m_settings->validate_meshes) { BKE_mesh_validate(mesh, false, false); } - readFaceSetsSample(bmain, mesh, 0, sample_sel); + readFaceSetsSample(bmain, mesh, sample_sel); if (has_animations(m_schema, m_settings)) { addCacheModifier(); @@ -1151,6 +1169,8 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, existing_mesh, positions->size(), 0, 0, face_indices->size(), face_counts->size()); settings.read_flag |= MOD_MESHSEQ_READ_ALL; + /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_new_nomain_from_template() */ + new_mesh->flag |= (existing_mesh->flag & ME_AUTOSMOOTH); } else { /* If the face count changed (e.g. by triangulation), only read points. @@ -1171,39 +1191,25 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, CDStreamConfig config = get_config(new_mesh ? new_mesh : existing_mesh); config.time = sample_sel.getRequestedTime(); - bool do_normals = false; - read_mesh_sample(m_iobject.getFullName(), &settings, m_schema, sample_sel, config, do_normals); + read_mesh_sample(m_iobject.getFullName(), &settings, m_schema, sample_sel, config); if (new_mesh) { - /* Check if we had ME_SMOOTH flag set to restore it. */ - if (!do_normals && check_smooth_poly_flag(existing_mesh)) { - set_smooth_poly_flag(new_mesh); - } - - BKE_mesh_calc_normals(new_mesh); - BKE_mesh_calc_edges(new_mesh, false, false); - /* Here we assume that the number of materials doesn't change, i.e. that * the material slots that were created when the object was loaded from * Alembic are still valid now. */ size_t num_polys = new_mesh->totpoly; if (num_polys > 0) { std::map<std::string, int> mat_map; - assign_facesets_to_mpoly(sample_sel, 0, new_mesh->mpoly, num_polys, mat_map); + assign_facesets_to_mpoly(sample_sel, new_mesh->mpoly, num_polys, mat_map); } return new_mesh; } - if (do_normals) { - BKE_mesh_calc_normals(existing_mesh); - } - return existing_mesh; } void AbcMeshReader::assign_facesets_to_mpoly(const ISampleSelector &sample_sel, - size_t poly_start, MPoly *mpoly, int totpoly, std::map<std::string, int> &r_mat_map) @@ -1239,7 +1245,7 @@ void AbcMeshReader::assign_facesets_to_mpoly(const ISampleSelector &sample_sel, const size_t num_group_faces = group_faces->size(); for (size_t l = 0; l < num_group_faces; l++) { - size_t pos = (*group_faces)[l] + poly_start; + size_t pos = (*group_faces)[l]; if (pos >= totpoly) { std::cerr << "Faceset overflow on " << faceset.getName() << '\n'; @@ -1252,13 +1258,10 @@ void AbcMeshReader::assign_facesets_to_mpoly(const ISampleSelector &sample_sel, } } -void AbcMeshReader::readFaceSetsSample(Main *bmain, - Mesh *mesh, - size_t poly_start, - const ISampleSelector &sample_sel) +void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const ISampleSelector &sample_sel) { std::map<std::string, int> mat_map; - assign_facesets_to_mpoly(sample_sel, poly_start, mesh->mpoly, mesh->totpoly, mat_map); + assign_facesets_to_mpoly(sample_sel, mesh->mpoly, mesh->totpoly, mat_map); utils::assign_materials(bmain, m_object, mat_map); } @@ -1289,7 +1292,7 @@ static void read_subd_sample(const std::string &iobject_full_name, abc_mesh_data.face_counts = sample.getFaceCounts(); abc_mesh_data.face_indices = sample.getFaceIndices(); abc_mesh_data.vertex_normals = N3fArraySamplePtr(); - abc_mesh_data.face_normals = N3fArraySamplePtr(); + abc_mesh_data.loop_normals = N3fArraySamplePtr(); abc_mesh_data.positions = sample.getPositions(); get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); @@ -1309,7 +1312,14 @@ static void read_subd_sample(const std::string &iobject_full_name, } if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) { + /* Alembic's 'SubD' scheme is used to store subdivision surfaces, i.e. the pre-subdivision + * mesh. Currently we don't add a subdivison modifier when we load such data. This code is + * assuming that the subdivided surface should be smooth, and sets a flag that will eventually + * mark all polygons as such. */ + abc_mesh_data.poly_flag_smooth = true; + read_mpolys(config, abc_mesh_data); + process_normals(config, abc_mesh_data); } if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { @@ -1397,9 +1407,6 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; } - BKE_mesh_calc_normals(mesh); - BKE_mesh_calc_edges(mesh, false, false); - if (m_settings->validate_meshes) { BKE_mesh_validate(mesh, false, false); } @@ -1466,17 +1473,5 @@ Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh, config.time = sample_sel.getRequestedTime(); read_subd_sample(m_iobject.getFullName(), &settings, m_schema, sample_sel, config); - if (new_mesh) { - /* Check if we had ME_SMOOTH flag set to restore it. */ - if (check_smooth_poly_flag(existing_mesh)) { - set_smooth_poly_flag(new_mesh); - } - - BKE_mesh_calc_normals(new_mesh); - BKE_mesh_calc_edges(new_mesh, false, false); - - return new_mesh; - } - - return existing_mesh; + return config.mesh; } diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h index 6cbaeea6536..859ab121eb6 100644 --- a/source/blender/alembic/intern/abc_mesh.h +++ b/source/blender/alembic/intern/abc_mesh.h @@ -114,11 +114,9 @@ class AbcMeshReader : public AbcObjectReader { private: void readFaceSetsSample(Main *bmain, Mesh *mesh, - size_t poly_start, const Alembic::AbcGeom::ISampleSelector &sample_sel); void assign_facesets_to_mpoly(const Alembic::Abc::ISampleSelector &sample_sel, - size_t poly_start, MPoly *mpoly, int totpoly, std::map<std::string, int> &r_mat_map); diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index 54450ce1cb2..7b0d94a2305 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -343,8 +343,7 @@ void AbcObjectReader::read_matrix(float r_mat[4][4], /* Only apply scaling to root objects, parenting will propagate it. */ float scale_mat[4][4]; scale_m4_fl(scale_mat, scale); - scale_mat[3][3] = scale; /* scale translations too */ - mul_m4_m4m4(r_mat, r_mat, scale_mat); + mul_m4_m4m4(r_mat, scale_mat, r_mat); } is_constant = schema.isConstant(); diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 448bb0d621a..bf0aa96df84 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -223,6 +223,7 @@ void BLF_dir_free(char **dirs, int count) ATTR_NONNULL(); /* blf_thumbs.c */ void BLF_thumb_preview(const char *filename, const char **draw_str, + const char **i18n_draw_str, const unsigned char draw_str_lines, const float font_color[4], const int font_size, diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 049af7678d5..66be94aaa06 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -96,7 +96,7 @@ KerningCacheBLF *blf_kerning_cache_new(FontBLF *font) .x = 0, .y = 0, }; - if (g_prev && FT_Get_Kerning(font->face, g_prev->idx, g->idx, kc->mode, &delta) == 0) { + if (g && g_prev && FT_Get_Kerning(font->face, g_prev->idx, g->idx, kc->mode, &delta) == 0) { kc->table[i][j] = (int)delta.x >> 6; } else { diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index 802f97fc5f5..d6710b91539 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -50,6 +50,7 @@ */ void BLF_thumb_preview(const char *filename, const char **draw_str, + const char **i18n_draw_str, const unsigned char draw_str_lines, const float font_color[4], const int font_size, @@ -90,7 +91,7 @@ void BLF_thumb_preview(const char *filename, blf_draw_buffer__start(font); for (i = 0; i < draw_str_lines; i++) { - const char *draw_str_i18n = BLT_translate_do(BLT_I18NCONTEXT_DEFAULT, draw_str[i]); + const char *draw_str_i18n = i18n_draw_str[i] != NULL ? i18n_draw_str[i] : draw_str[i]; const size_t draw_str_i18n_len = strlen(draw_str_i18n); int draw_str_i18n_nbr = 0; diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 73e62f6a7b3..99c6bb405b5 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -75,6 +75,9 @@ void BKE_armature_copy_data(struct Main *bmain, const int flag); struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature *arm); +void BKE_armature_copy_bone_transforms(struct bArmature *armature_dst, + const struct bArmature *armature_src); + /* Bounding box. */ struct BoundBox *BKE_armature_boundbox_get(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index a400e4411cf..062e185eb23 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -26,8 +26,8 @@ * * \note Use #STRINGIFY() rather than defining with quotes. */ -#define BLENDER_VERSION 280 -#define BLENDER_SUBVERSION 75 +#define BLENDER_VERSION 281 +#define BLENDER_SUBVERSION 0 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 @@ -36,7 +36,7 @@ /** Can be left blank, otherwise a,b,c... etc with no quotes. */ #define BLENDER_VERSION_CHAR /** alpha/beta/rc/release, docs use this. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /** Defined in from blender.c */ extern char versionstr[]; diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index 76c05b0411a..7fc27321fc7 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -32,12 +32,6 @@ struct ReportList; struct UserDef; struct bContext; -enum { - BKE_BLENDFILE_READ_FAIL = 0, /* no load */ - BKE_BLENDFILE_READ_OK = 1, /* OK */ - BKE_BLENDFILE_READ_OK_USERPREFS = 2, /* OK, and with new user settings */ -}; - int BKE_blendfile_read(struct bContext *C, const char *filepath, const struct BlendFileReadParams *params, diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 54fbda1fa31..d6b4fa72281 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -123,6 +123,8 @@ struct Mesh *BKE_mesh_new_nomain_from_template(const struct Mesh *me_src, int loops_len, int polys_len); +void BKE_mesh_eval_delete(struct Mesh *me_eval); + /* Performs copy for use during evaluation, * optional referencing original arrays to reduce memory. */ struct Mesh *BKE_mesh_copy_for_eval(struct Mesh *source, bool reference); diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 9425f396bc5..14d7784f93e 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -118,7 +118,9 @@ bool BKE_movieclip_put_frame_if_possible(struct MovieClip *clip, /* Dependency graph evaluation. */ -void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, struct MovieClip *clip); +void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, + struct Main *bmain, + struct MovieClip *clip); void BKE_movieclip_eval_selection_update(struct Depsgraph *depsgraph, struct MovieClip *clip); /* caching flags */ diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 6b6eb24d5fa..bf417403d43 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -355,6 +355,12 @@ void BKE_tracking_reconstruction_solve(struct MovieReconstructContext *context, bool BKE_tracking_reconstruction_finish(struct MovieReconstructContext *context, struct MovieTracking *tracking); +void BKE_tracking_reconstruction_report_error_message(struct MovieReconstructContext *context, + const char *error_message); + +const char *BKE_tracking_reconstruction_error_message_get( + const struct MovieReconstructContext *context); + void BKE_tracking_reconstruction_scale(struct MovieTracking *tracking, float scale[3]); /* **** Feature detection **** */ diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h index 50c29c456d1..6d8e04336ac 100644 --- a/source/blender/blenkernel/BKE_undo_system.h +++ b/source/blender/blenkernel/BKE_undo_system.h @@ -48,6 +48,7 @@ UNDO_REF_ID_TYPE(Mesh); UNDO_REF_ID_TYPE(Object); UNDO_REF_ID_TYPE(Scene); UNDO_REF_ID_TYPE(Text); +UNDO_REF_ID_TYPE(Image); typedef struct UndoStack { ListBase steps; @@ -194,24 +195,6 @@ void BKE_undosys_foreach_ID_ref(UndoStack *ustack, void *user_data); #endif -/* Use when the undo step stores many arbitrary pointers. */ -struct UndoIDPtrMap; -struct UndoIDPtrMap *BKE_undosys_ID_map_create(void); -void BKE_undosys_ID_map_destroy(struct UndoIDPtrMap *map); -void BKE_undosys_ID_map_add(struct UndoIDPtrMap *map, ID *id); -struct ID *BKE_undosys_ID_map_lookup(const struct UndoIDPtrMap *map, const struct ID *id_src); - -void BKE_undosys_ID_map_add_with_prev(struct UndoIDPtrMap *map, - struct ID *id, - struct ID **id_prev); -struct ID *BKE_undosys_ID_map_lookup_with_prev(const struct UndoIDPtrMap *map, - struct ID *id_src, - struct ID *id_prev_match[2]); - -void BKE_undosys_ID_map_foreach_ID_ref(struct UndoIDPtrMap *map, - UndoTypeForEachIDRefFn foreach_ID_ref_fn, - void *user_data); - void BKE_undosys_print(UndoStack *ustack); #endif /* __BKE_UNDO_SYSTEM_H__ */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_legacy.c b/source/blender/blenkernel/intern/CCGSubSurf_legacy.c index 720c828664a..d8b30c9d4ef 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_legacy.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_legacy.c @@ -135,7 +135,7 @@ typedef struct CCGSubSurfCalcSubdivData { } CCGSubSurfCalcSubdivData; static void ccgSubSurf__calcVertNormals_faces_accumulate_cb( - void *__restrict userdata, const int ptrIdx, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict UNUSED(tls)) { CCGSubSurfCalcSubdivData *data = userdata; @@ -234,7 +234,7 @@ static void ccgSubSurf__calcVertNormals_faces_accumulate_cb( } static void ccgSubSurf__calcVertNormals_faces_finalize_cb( - void *__restrict userdata, const int ptrIdx, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict UNUSED(tls)) { CCGSubSurfCalcSubdivData *data = userdata; @@ -273,7 +273,7 @@ static void ccgSubSurf__calcVertNormals_faces_finalize_cb( } static void ccgSubSurf__calcVertNormals_edges_accumulate_cb( - void *__restrict userdata, const int ptrIdx, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict UNUSED(tls)) { CCGSubSurfCalcSubdivData *data = userdata; @@ -347,7 +347,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, }; { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = CCG_TASK_LIMIT; BLI_task_parallel_range( @@ -379,7 +379,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, } { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = CCG_TASK_LIMIT; BLI_task_parallel_range( @@ -387,7 +387,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, } { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = CCG_TASK_LIMIT; BLI_task_parallel_range( @@ -425,7 +425,7 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, } static void ccgSubSurf__calcSubdivLevel_interior_faces_edges_midpoints_cb( - void *__restrict userdata, const int ptrIdx, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict UNUSED(tls)) { CCGSubSurfCalcSubdivData *data = userdata; @@ -513,7 +513,7 @@ static void ccgSubSurf__calcSubdivLevel_interior_faces_edges_midpoints_cb( } static void ccgSubSurf__calcSubdivLevel_interior_faces_edges_centerpoints_shift_cb( - void *__restrict userdata, const int ptrIdx, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict UNUSED(tls)) { CCGSubSurfCalcSubdivData *data = userdata; @@ -619,7 +619,7 @@ static void ccgSubSurf__calcSubdivLevel_interior_faces_edges_centerpoints_shift_ } static void ccgSubSurf__calcSubdivLevel_verts_copydata_cb( - void *__restrict userdata, const int ptrIdx, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int ptrIdx, const TaskParallelTLS *__restrict UNUSED(tls)) { CCGSubSurfCalcSubdivData *data = userdata; @@ -691,7 +691,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, }; { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = CCG_TASK_LIMIT; BLI_task_parallel_range(0, @@ -991,7 +991,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, } { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = CCG_TASK_LIMIT; BLI_task_parallel_range(0, @@ -1012,7 +1012,7 @@ static void ccgSubSurf__calcSubdivLevel(CCGSubSurf *ss, } { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = CCG_TASK_LIMIT; BLI_task_parallel_range( diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index c36acd1eae1..742e3634bf1 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -239,6 +239,35 @@ bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm) return arm_copy; } +static void copy_bone_transform(Bone *bone_dst, const Bone *bone_src) +{ + bone_dst->roll = bone_src->roll; + + copy_v3_v3(bone_dst->head, bone_src->head); + copy_v3_v3(bone_dst->tail, bone_src->tail); + + copy_m3_m3(bone_dst->bone_mat, bone_src->bone_mat); + + copy_v3_v3(bone_dst->arm_head, bone_src->arm_head); + copy_v3_v3(bone_dst->arm_tail, bone_src->arm_tail); + + copy_m4_m4(bone_dst->arm_mat, bone_src->arm_mat); + + bone_dst->arm_roll = bone_src->arm_roll; +} + +void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature *armature_src) +{ + Bone *bone_dst = armature_dst->bonebase.first; + const Bone *bone_src = armature_src->bonebase.first; + while (bone_dst != NULL) { + BLI_assert(bone_src != NULL); + copy_bone_transform(bone_dst, bone_src); + bone_dst = bone_dst->next; + bone_src = bone_src->next; + } +} + static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name) { Bone *curBone, *rbone; @@ -1350,7 +1379,7 @@ typedef struct ArmatureUserdata { static void armature_vert_task(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const ArmatureUserdata *data = userdata; float(*const vertexCos)[3] = data->vertexCos; @@ -1648,7 +1677,7 @@ void armature_deform_verts(Object *armOb, mul_m4_m4m4(data.postmat, obinv, armOb->obmat); invert_m4_m4(data.premat, data.postmat); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 32; BLI_task_parallel_range(0, numVerts, &data, armature_vert_task, &settings); @@ -2374,6 +2403,9 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected pchanw.mpath = pchan->mpath; pchan->mpath = NULL; + /* Reset runtime data, we don't want to share that with the proxy. */ + BKE_pose_channel_runtime_reset(&pchanw.runtime); + /* this is freed so copy a copy, else undo crashes */ if (pchanw.prop) { pchanw.prop = IDP_CopyProperty(pchanw.prop); diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 9fd3c24092c..805c098d238 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -306,6 +306,7 @@ void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *use LIST_SWAP(themes); LIST_SWAP(addons); LIST_SWAP(user_keymaps); + LIST_SWAP(user_keyconfig_prefs); DATA_SWAP(font_path_ui); DATA_SWAP(font_path_ui_mono); diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c index 6c077ac75ba..7c12747283c 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -73,7 +73,7 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C) G.fileflags |= G_FILE_NO_UI; if (UNDO_DISK) { - success = (BKE_blendfile_read(C, mfu->filename, NULL, 0) != BKE_BLENDFILE_READ_FAIL); + success = BKE_blendfile_read(C, mfu->filename, NULL, 0); } else { success = BKE_blendfile_read_from_memfile( diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index afbd2627a2a..e31494ecb4e 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -405,35 +405,31 @@ int BKE_blendfile_read(bContext *C, ReportList *reports) { BlendFileData *bfd; - int retval = BKE_BLENDFILE_READ_OK; + bool success = false; - /* don't print user-pref loading */ - if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) { + /* Don't print startup file loading. */ + if (params->is_startup == false) { printf("Read blend: %s\n", filepath); } bfd = BLO_read_from_file(filepath, params->skip_flags, reports); if (bfd) { - if (bfd->user) { - retval = BKE_BLENDFILE_READ_OK_USERPREFS; - } - if (0 == handle_subversion_warning(bfd->main, reports)) { BKE_main_free(bfd->main); MEM_freeN(bfd); bfd = NULL; - retval = BKE_BLENDFILE_READ_FAIL; } else { setup_app_blend_file_data(C, bfd, filepath, params, reports); BLO_blendfiledata_free(bfd); + success = true; } } else { BKE_reports_prependf(reports, "Loading '%s' failed: ", filepath); } - return (bfd ? retval : BKE_BLENDFILE_READ_FAIL); + return success; } bool BKE_blendfile_read_from_memory(bContext *C, diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 965f6e4bc51..25f2797915a 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -1100,7 +1100,7 @@ void BKE_collection_parent_relations_rebuild(Collection *collection) static void collection_parents_rebuild_recursive(Collection *collection) { BKE_collection_parent_relations_rebuild(collection); - collection->id.tag &= ~LIB_TAG_DOIT; + collection->tag &= ~COLLECTION_TAG_RELATION_REBUILD; for (CollectionChild *child = collection->children.first; child != NULL; child = child->next) { collection_parents_rebuild_recursive(child->collection); @@ -1109,8 +1109,6 @@ static void collection_parents_rebuild_recursive(Collection *collection) /** * Rebuild parent relationships from child ones, for all collections in given \a bmain. - * - * \note Uses LIB_TAG_DOIT internally... */ void BKE_main_collections_parent_relations_rebuild(Main *bmain) { @@ -1119,7 +1117,7 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain) collection = collection->id.next) { BLI_freelistN(&collection->parents); - collection->id.tag |= LIB_TAG_DOIT; + collection->tag |= COLLECTION_TAG_RELATION_REBUILD; } /* Scene's master collections will be 'root' parent of most of our collections, so start with @@ -1132,7 +1130,7 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain) * lib_link_collection_data() seems to assume that, so do the same here. */ for (Collection *collection = bmain->collections.first; collection != NULL; collection = collection->id.next) { - if (collection->id.tag & LIB_TAG_DOIT) { + if (collection->tag & COLLECTION_TAG_RELATION_REBUILD) { /* Note: we do not have easy access to 'which collections is root' info in that case, which * means test for cycles in collection relationships may fail here. I don't think that is an * issue in practice here, but worth keeping in mind... */ diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index ff6258ac339..69afda9997a 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -851,7 +851,7 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd, static void cloth_collision(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { ColDetectData *data = (ColDetectData *)userdata; @@ -908,7 +908,7 @@ static void cloth_collision(void *__restrict userdata, static void cloth_selfcollision(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SelfColDetectData *data = (SelfColDetectData *)userdata; @@ -1154,7 +1154,7 @@ static bool cloth_bvh_objcollisions_nearcheck(ClothModifierData *clmd, .collided = false, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = true; BLI_task_parallel_range(0, numresult, &data, cloth_collision, &settings); @@ -1174,7 +1174,7 @@ static bool cloth_bvh_selfcollisions_nearcheck(ClothModifierData *clmd, .collided = false, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = true; BLI_task_parallel_range(0, numresult, &data, cloth_selfcollision, &settings); diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 863d6351738..aa5f74c6297 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1385,7 +1385,7 @@ typedef struct ScopesUpdateDataChunk { static void scopes_update_cb(void *__restrict userdata, const int y, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { const ScopesUpdateData *data = userdata; @@ -1634,7 +1634,7 @@ void scopes_update(Scopes *scopes, ScopesUpdateDataChunk data_chunk = {{0}}; INIT_MINMAX(data_chunk.min, data_chunk.max); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y > 256); settings.userdata_chunk = &data_chunk; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 7e916feac24..936fe3b3bea 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -645,7 +645,7 @@ static void freeGrid(PaintSurfaceData *data) static void grid_bound_insert_cb_ex(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { PaintBakeData *bData = userdata; @@ -667,7 +667,7 @@ static void grid_bound_insert_finalize(void *__restrict userdata, void *__restri static void grid_cell_points_cb_ex(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { PaintBakeData *bData = userdata; VolumeGrid *grid = bData->grid; @@ -702,7 +702,7 @@ static void grid_cell_points_finalize(void *__restrict userdata, void *__restric static void grid_cell_bounds_cb(void *__restrict userdata, const int x, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { PaintBakeData *bData = userdata; VolumeGrid *grid = bData->grid; @@ -749,7 +749,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) /* Important to init correctly our ref grid_bound... */ boundInsert(&grid->grid_bounds, bData->realCoord[bData->s_pos[0]].v); { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); settings.userdata_chunk = &grid->grid_bounds; @@ -810,7 +810,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) if (!error) { /* calculate number of points within each cell */ { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); settings.userdata_chunk = grid->s_num; @@ -834,7 +834,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) /* calculate cell bounds */ { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (grid_cells > 1000); BLI_task_parallel_range(0, grid->dim[0], bData, grid_cell_bounds_cb, &settings); @@ -1508,7 +1508,7 @@ typedef struct DynamicPaintSetInitColorData { } DynamicPaintSetInitColorData; static void dynamic_paint_set_init_color_tex_to_vcol_cb( - void *__restrict userdata, const int i, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintSetInitColorData *data = userdata; @@ -1543,7 +1543,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb( } static void dynamic_paint_set_init_color_tex_to_imseq_cb( - void *__restrict userdata, const int i, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintSetInitColorData *data = userdata; @@ -1582,7 +1582,7 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb( } static void dynamic_paint_set_init_color_vcol_to_imseq_cb( - void *__restrict userdata, const int i, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintSetInitColorData *data = userdata; @@ -1667,7 +1667,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface .pool = pool, .scene_color_manage = scene_color_manage, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (tottri > 1000); BLI_task_parallel_range( @@ -1681,7 +1681,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface .mloopuv = mloopuv, .scene_color_manage = scene_color_manage, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -1718,7 +1718,7 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface .mlooptri = mlooptri, .mloopcol = col, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -1820,7 +1820,7 @@ typedef struct DynamicPaintModifierApplyData { static void dynamic_paint_apply_surface_displace_cb(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintModifierApplyData *data = userdata; @@ -1854,7 +1854,7 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Mesh .surface = surface, .mvert = mvert, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 10000); BLI_task_parallel_range( @@ -1863,7 +1863,7 @@ static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Mesh } static void dynamic_paint_apply_surface_vpaint_blend_cb( - void *__restrict userdata, const int i, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintModifierApplyData *data = userdata; @@ -1877,7 +1877,7 @@ static void dynamic_paint_apply_surface_vpaint_blend_cb( static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata, const int p_index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintModifierApplyData *data = userdata; @@ -1913,7 +1913,7 @@ static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata, static void dynamic_paint_apply_surface_wave_cb(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintModifierApplyData *data = userdata; @@ -1966,7 +1966,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * .fcolor = fcolor, }; { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range(0, @@ -2001,7 +2001,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * data.mloopcol_wet = mloopcol_wet; { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (totpoly > 1000); BLI_task_parallel_range( @@ -2053,7 +2053,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * .surface = surface, .mvert = mvert, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -2236,7 +2236,7 @@ typedef struct DynamicPaintCreateUVSurfaceData { } DynamicPaintCreateUVSurfaceData; static void dynamic_paint_create_uv_surface_direct_cb( - void *__restrict userdata, const int ty, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int ty, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintCreateUVSurfaceData *data = userdata; @@ -2330,7 +2330,7 @@ static void dynamic_paint_create_uv_surface_direct_cb( } static void dynamic_paint_create_uv_surface_neighbor_cb( - void *__restrict userdata, const int ty, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int ty, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintCreateUVSurfaceData *data = userdata; @@ -2948,7 +2948,7 @@ int dynamicPaint_createUVSurface(Scene *scene, .faceBB = faceBB, }; { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (h > 64 || tottri > 1000); BLI_task_parallel_range(0, h, &data, dynamic_paint_create_uv_surface_direct_cb, &settings); @@ -2965,7 +2965,7 @@ int dynamicPaint_createUVSurface(Scene *scene, */ data.active_points = &active_points; { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (h > 64); BLI_task_parallel_range(0, h, &data, dynamic_paint_create_uv_surface_neighbor_cb, &settings); @@ -3216,7 +3216,7 @@ typedef struct DynamicPaintOutputSurfaceImageData { } DynamicPaintOutputSurfaceImageData; static void dynamic_paint_output_surface_image_paint_cb( - void *__restrict userdata, const int index, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintOutputSurfaceImageData *data = userdata; @@ -3238,7 +3238,7 @@ static void dynamic_paint_output_surface_image_paint_cb( } static void dynamic_paint_output_surface_image_displace_cb( - void *__restrict userdata, const int index, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintOutputSurfaceImageData *data = userdata; @@ -3264,7 +3264,7 @@ static void dynamic_paint_output_surface_image_displace_cb( } static void dynamic_paint_output_surface_image_wave_cb( - void *__restrict userdata, const int index, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintOutputSurfaceImageData *data = userdata; @@ -3288,7 +3288,7 @@ static void dynamic_paint_output_surface_image_wave_cb( } static void dynamic_paint_output_surface_image_wetmap_cb( - void *__restrict userdata, const int index, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintOutputSurfaceImageData *data = userdata; @@ -3346,7 +3346,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, case MOD_DPAINT_SURFACE_T_PAINT: switch (output_layer) { case 0: { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 10000); BLI_task_parallel_range(0, @@ -3357,7 +3357,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, break; } case 1: { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 10000); BLI_task_parallel_range(0, @@ -3375,7 +3375,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, case MOD_DPAINT_SURFACE_T_DISPLACE: switch (output_layer) { case 0: { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 10000); BLI_task_parallel_range(0, @@ -3395,7 +3395,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, case MOD_DPAINT_SURFACE_T_WAVE: switch (output_layer) { case 0: { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 10000); BLI_task_parallel_range(0, @@ -3758,7 +3758,7 @@ typedef struct DynamicPaintBrushVelocityData { static void dynamic_paint_brush_velocity_compute_cb(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintBrushVelocityData *data = userdata; @@ -3857,7 +3857,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph, .prev_obmat = prev_obmat, .timescale = timescale, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (numOfVerts_c > 10000); BLI_task_parallel_range( @@ -3942,7 +3942,7 @@ typedef struct DynamicPaintPaintData { * Paint a brush object mesh to the surface */ static void dynamic_paint_paint_mesh_cell_point_cb_ex( - void *__restrict userdata, const int id, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int id, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintPaintData *data = userdata; @@ -4365,7 +4365,7 @@ static int dynamicPaint_paintMesh(Depsgraph *depsgraph, .brushVelocity = brushVelocity, .treeData = &treeData, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (grid->s_num[c_index] > 250); BLI_task_parallel_range(0, @@ -4393,7 +4393,7 @@ static int dynamicPaint_paintMesh(Depsgraph *depsgraph, * Paint a particle system to the surface */ static void dynamic_paint_paint_particle_cell_point_cb_ex( - void *__restrict userdata, const int id, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int id, const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintPaintData *data = userdata; @@ -4666,7 +4666,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, .c_index = c_index, .treeData = tree, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (grid->s_num[c_index] > 250); BLI_task_parallel_range(0, @@ -4685,7 +4685,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, /* paint a single point of defined proximity radius to the surface */ static void dynamic_paint_paint_single_point_cb_ex(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintPaintData *data = userdata; @@ -4808,7 +4808,7 @@ static int dynamicPaint_paintSinglePoint(Depsgraph *depsgraph, .brushVelocity = &brushVel, .pointCoord = pointCoord, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -4825,7 +4825,7 @@ static int dynamicPaint_paintSinglePoint(Depsgraph *depsgraph, static void dynamic_paint_prepare_adjacency_cb(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { PaintSurfaceData *sData = userdata; PaintBakeData *bData = sData->bData; @@ -4870,7 +4870,7 @@ static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, cons return; } - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -5085,7 +5085,7 @@ typedef struct DynamicPaintEffectData { */ static void dynamic_paint_prepare_effect_cb(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintEffectData *data = userdata; @@ -5167,7 +5167,7 @@ static int dynamicPaint_prepareEffectStep(struct Depsgraph *depsgraph, .force = *force, .effectors = effectors, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -5207,7 +5207,7 @@ static int dynamicPaint_prepareEffectStep(struct Depsgraph *depsgraph, */ static void dynamic_paint_effect_spread_cb(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintEffectData *data = userdata; @@ -5266,7 +5266,7 @@ static void dynamic_paint_effect_spread_cb(void *__restrict userdata, static void dynamic_paint_effect_shrink_cb(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintEffectData *data = userdata; @@ -5327,7 +5327,7 @@ static void dynamic_paint_effect_shrink_cb(void *__restrict userdata, static void dynamic_paint_effect_drip_cb(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintEffectData *data = userdata; @@ -5481,7 +5481,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, .prevPoint = prevPoint, .eff_scale = eff_scale, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -5503,7 +5503,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, .prevPoint = prevPoint, .eff_scale = eff_scale, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -5530,7 +5530,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, .force = force, .point_locks = point_locks, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -5542,7 +5542,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, static void dynamic_paint_border_cb(void *__restrict userdata, const int b_index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintEffectData *data = userdata; @@ -5613,7 +5613,7 @@ static void dynamicPaint_doBorderStep(DynamicPaintSurface *surface) .surface = surface, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->adj_data->total_border > 1000); BLI_task_parallel_range( @@ -5622,7 +5622,7 @@ static void dynamicPaint_doBorderStep(DynamicPaintSurface *surface) static void dynamic_paint_wave_step_cb(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintEffectData *data = userdata; @@ -5777,7 +5777,7 @@ static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescal .damp_factor = damp_factor, .reset_wave = (ss == steps - 1), }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range(0, sData->total_points, &data, dynamic_paint_wave_step_cb, &settings); @@ -5802,7 +5802,7 @@ typedef struct DynamicPaintDissolveDryData { static void dynamic_paint_surface_pre_step_cb(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintDissolveDryData *data = userdata; @@ -5938,7 +5938,7 @@ typedef struct DynamicPaintGenerateBakeData { static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const DynamicPaintGenerateBakeData *data = userdata; @@ -6170,7 +6170,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, .do_velocity_data = do_velocity_data, .new_bdata = new_bdata, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( @@ -6217,7 +6217,7 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph, .surface = surface, .timescale = timescale, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index b8178bec52f..83b354ffb4a 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -889,7 +889,7 @@ typedef struct LatticeDeformUserdata { static void lattice_deform_vert_task(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const LatticeDeformUserdata *data = userdata; @@ -948,7 +948,7 @@ void lattice_deform_verts(Object *laOb, .defgrp_index = defgrp_index, .fac = fac}; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 32; BLI_task_parallel_range(0, numVerts, &data, lattice_deform_vert_task, &settings); diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 2ab5b69a022..e03903c05e4 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -1462,7 +1462,7 @@ typedef struct MaskRasterizeBufferData { static void maskrasterize_buffer_cb(void *__restrict userdata, const int y, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { MaskRasterizeBufferData *data = userdata; @@ -1503,7 +1503,7 @@ void BKE_maskrasterize_buffer(MaskRasterHandle *mr_handle, .width = width, .buffer = buffer, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((size_t)height * width > 10000); BLI_task_parallel_range(0, (int)height, &data, maskrasterize_buffer_cb, &settings); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index f5e93dcf9b7..9e01bfe62d6 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -697,6 +697,15 @@ Mesh *BKE_mesh_new_nomain_from_template(const Mesh *me_src, me_src, verts_len, edges_len, tessface_len, loops_len, polys_len, CD_MASK_EVERYTHING); } +void BKE_mesh_eval_delete(struct Mesh *mesh_eval) +{ + /* Evaluated mesh may point to edit mesh, but never owns it. */ + mesh_eval->edit_mesh = NULL; + BKE_mesh_free(mesh_eval); + BKE_libblock_free_data(&mesh_eval->id, false); + MEM_freeN(mesh_eval); +} + Mesh *BKE_mesh_copy_for_eval(struct Mesh *source, bool reference) { int flags = LIB_ID_COPY_LOCALIZE; diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 17b22a6d095..e28d50cbde4 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -220,7 +220,7 @@ typedef struct MeshCalcNormalsData { static void mesh_calc_normals_poly_cb(void *__restrict userdata, const int pidx, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { MeshCalcNormalsData *data = userdata; const MPoly *mp = &data->mpolys[pidx]; @@ -230,7 +230,7 @@ static void mesh_calc_normals_poly_cb(void *__restrict userdata, static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata, const int pidx, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { MeshCalcNormalsData *data = userdata; const MPoly *mp = &data->mpolys[pidx]; @@ -294,7 +294,7 @@ static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata, static void mesh_calc_normals_poly_finalize_cb(void *__restrict userdata, const int vidx, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { MeshCalcNormalsData *data = userdata; @@ -321,7 +321,7 @@ void BKE_mesh_calc_normals_poly(MVert *mverts, { float(*pnors)[3] = r_polynors; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 1024; diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index dac12233539..c8e75532075 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -1200,7 +1200,7 @@ void BKE_mesh_strip_loose_polysloops(Mesh *me) int i = p->loopstart; int stop = i + p->totloop; - if (stop > me->totloop || stop < i) { + if (stop > me->totloop || stop < i || p->loopstart < 0) { invalid = true; } else { diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 6bc83f8dd09..f67bc419210 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -53,6 +53,7 @@ #include "BKE_animsys.h" #include "BKE_colortools.h" +#include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_movieclip.h" @@ -1772,9 +1773,17 @@ static void movieclip_selection_synchronize(MovieClip *clip_dst, const MovieClip } } -void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, MovieClip *clip) +static void movieclip_eval_update_reload(struct Depsgraph *depsgraph, Main *bmain, MovieClip *clip) +{ + BKE_movieclip_reload(bmain, clip); + if (DEG_is_active(depsgraph)) { + MovieClip *clip_orig = (MovieClip *)DEG_get_original_id(&clip->id); + BKE_movieclip_reload(bmain, clip_orig); + } +} + +static void movieclip_eval_update_generic(struct Depsgraph *depsgraph, MovieClip *clip) { - DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip); BKE_tracking_dopesheet_tag_update(&clip->tracking); if (DEG_is_active(depsgraph)) { MovieClip *clip_orig = (MovieClip *)DEG_get_original_id(&clip->id); @@ -1782,6 +1791,17 @@ void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, MovieClip *clip) } } +void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, Main *bmain, MovieClip *clip) +{ + DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip); + if (clip->id.recalc & ID_RECALC_SOURCE) { + movieclip_eval_update_reload(depsgraph, bmain, clip); + } + else { + movieclip_eval_update_generic(depsgraph, clip); + } +} + void BKE_movieclip_eval_selection_update(struct Depsgraph *depsgraph, MovieClip *clip) { DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 29337ca9985..bbae1f4d3bc 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1078,7 +1078,7 @@ typedef struct MultiresThreadedData { static void multires_disp_run_cb(void *__restrict userdata, const int pidx, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { MultiresThreadedData *tdata = userdata; @@ -1230,7 +1230,7 @@ static void multiresModifier_disp_run( } } - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = CCG_TASK_LIMIT; diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index 749cedb5388..d939267ac5a 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -955,7 +955,7 @@ typedef struct ReshapeFromCCGTaskData { static void reshape_from_ccg_task(void *__restrict userdata, const int coarse_poly_index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { ReshapeFromCCGTaskData *data = userdata; const CCGKey *key = data->key; @@ -1045,7 +1045,7 @@ bool multiresModifier_reshapeFromCCG(const int tot_level, Mesh *coarse_mesh, Sub MultiresPropagateData propagate_data; multires_reshape_propagate_prepare(&propagate_data, coarse_mesh, key.level, top_level); /* Threaded grids iteration. */ - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); BLI_task_parallel_range( 0, coarse_mesh->totpoly, &data, reshape_from_ccg_task, ¶llel_range_settings); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d7256cc9604..69ba7ccab8e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -442,19 +442,13 @@ void BKE_object_free_derived_caches(Object *ob) if (ob->runtime.mesh_eval != NULL) { if (ob->runtime.is_mesh_eval_owned) { Mesh *mesh_eval = ob->runtime.mesh_eval; - /* Evaluated mesh points to edit mesh, but does not own it. */ - mesh_eval->edit_mesh = NULL; - BKE_mesh_free(mesh_eval); - BKE_libblock_free_data(&mesh_eval->id, false); - MEM_freeN(mesh_eval); + BKE_mesh_eval_delete(mesh_eval); } ob->runtime.mesh_eval = NULL; } if (ob->runtime.mesh_deform_eval != NULL) { Mesh *mesh_deform_eval = ob->runtime.mesh_deform_eval; - BKE_mesh_free(mesh_deform_eval); - BKE_libblock_free_data(&mesh_deform_eval->id, false); - MEM_freeN(mesh_deform_eval); + BKE_mesh_eval_delete(mesh_deform_eval); ob->runtime.mesh_deform_eval = NULL; } diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index b5df7d5fe9b..39fb668c873 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -510,7 +510,7 @@ typedef struct OceanSimulateData { static void ocean_compute_htilda(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { OceanSimulateData *osd = userdata; const Ocean *o = osd->o; @@ -779,7 +779,7 @@ void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount * but remains reasonably simple and should be OK most of the time. */ /* compute a new htilda */ - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (o->_M > 16); BLI_task_parallel_range(0, o->_M, &osd, ocean_compute_htilda, &settings); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 079a348745c..b80f64e3472 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3112,7 +3112,7 @@ typedef struct CacheEditrPathsIterData { static void psys_cache_edit_paths_iter(void *__restrict iter_data_v, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { CacheEditrPathsIterData *iter_data = (CacheEditrPathsIterData *)iter_data_v; PTCacheEdit *edit = iter_data->edit; @@ -3334,7 +3334,7 @@ void psys_cache_edit_paths(Depsgraph *depsgraph, iter_data.nosel_col[2] = (float)edit->nosel_col[2] / 255.0f; } - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, psys_cache_edit_paths_iter, &settings); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 27722aab2d9..e12537784f3 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3685,7 +3685,7 @@ typedef struct DynamicStepSolverTaskData { static void dynamics_step_sph_ddr_task_cb_ex(void *__restrict userdata, const int p, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { DynamicStepSolverTaskData *data = userdata; ParticleSimulationData *sim = data->sim; @@ -3720,7 +3720,7 @@ static void dynamics_step_sph_ddr_task_cb_ex(void *__restrict userdata, } static void dynamics_step_sph_classical_basic_integrate_task_cb_ex( - void *__restrict userdata, const int p, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int p, const TaskParallelTLS *__restrict UNUSED(tls)) { DynamicStepSolverTaskData *data = userdata; ParticleSimulationData *sim = data->sim; @@ -3736,7 +3736,7 @@ static void dynamics_step_sph_classical_basic_integrate_task_cb_ex( } static void dynamics_step_sph_classical_calc_density_task_cb_ex( - void *__restrict userdata, const int p, const ParallelRangeTLS *__restrict tls) + void *__restrict userdata, const int p, const TaskParallelTLS *__restrict tls) { DynamicStepSolverTaskData *data = userdata; ParticleSimulationData *sim = data->sim; @@ -3754,7 +3754,7 @@ static void dynamics_step_sph_classical_calc_density_task_cb_ex( } static void dynamics_step_sph_classical_integrate_task_cb_ex( - void *__restrict userdata, const int p, const ParallelRangeTLS *__restrict tls) + void *__restrict userdata, const int p, const TaskParallelTLS *__restrict tls) { DynamicStepSolverTaskData *data = userdata; ParticleSimulationData *sim = data->sim; @@ -3963,7 +3963,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) /* Apply SPH forces using double-density relaxation algorithm * (Clavat et. al.) */ - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; @@ -3980,7 +3980,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) * this algorithm is separated into distinct loops. */ { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (psys->totpart > 100); BLI_task_parallel_range(0, @@ -3994,7 +3994,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) /* Note that we could avoid copying sphdata for each thread here (it's only read here), * but doubt this would gain us anything except confusion... */ { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; @@ -4008,7 +4008,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) /* do global forces & effectors */ { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index ffc4ec65d4d..860e2bdaa93 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -995,7 +995,7 @@ typedef struct PBVHUpdateData { static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { PBVHUpdateData *data = userdata; @@ -1045,7 +1045,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, static void pbvh_update_normals_store_task_cb(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { PBVHUpdateData *data = userdata; PBVH *bvh = data->bvh; @@ -1094,7 +1094,7 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode) .vnors = vnors, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (totnode > PBVH_THREADED_LIMIT); @@ -1107,7 +1107,7 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode) static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { PBVHUpdateData *data = userdata; PBVH *bvh = data->bvh; @@ -1138,7 +1138,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) .flag = flag, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (totnode > PBVH_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings); diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 6a72b46a8f2..9b9fd33f52d 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -344,7 +344,7 @@ void BKE_shrinkwrap_compute_boundary_data(struct Mesh *mesh) */ static void shrinkwrap_calc_nearest_vertex_cb_ex(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { ShrinkwrapCalcCBData *data = userdata; @@ -416,7 +416,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) .calc = calc, .tree = calc->tree, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (calc->numVerts > BKE_MESH_OMP_LIMIT); settings.userdata_chunk = &nearest; @@ -510,7 +510,7 @@ bool BKE_shrinkwrap_project_normal(char options, static void shrinkwrap_calc_normal_projection_cb_ex(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { ShrinkwrapCalcCBData *data = userdata; @@ -703,7 +703,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) .proj_axis = proj_axis, .local2aux = &local2aux, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (calc->numVerts > BKE_MESH_OMP_LIMIT); settings.userdata_chunk = &hit; @@ -1115,7 +1115,7 @@ void BKE_shrinkwrap_find_nearest_surface(struct ShrinkwrapTreeData *tree, */ static void shrinkwrap_calc_nearest_surface_point_cb_ex(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { ShrinkwrapCalcCBData *data = userdata; @@ -1363,7 +1363,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) .calc = calc, .tree = calc->tree, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (calc->numVerts > BKE_MESH_OMP_LIMIT); settings.userdata_chunk = &nearest; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index bb8fd18ea58..1dcbf7615f7 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -819,7 +819,7 @@ typedef struct ObstaclesFromDMData { static void obstacles_from_mesh_task_cb(void *__restrict userdata, const int z, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { ObstaclesFromDMData *data = userdata; SmokeDomainSettings *sds = data->sds; @@ -974,7 +974,7 @@ static void obstacles_from_mesh(Object *coll_ob, .velocityZ = velocityZ, .num_obstacles = num_obstacles, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range( @@ -1328,7 +1328,7 @@ typedef struct EmitFromParticlesData { static void emit_from_particles_task_cb(void *__restrict userdata, const int z, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { EmitFromParticlesData *data = userdata; SmokeFlowSettings *sfs = data->sfs; @@ -1567,7 +1567,7 @@ static void emit_from_particles(Object *flow_ob, .hr_smooth = hr_smooth, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(min[2], max[2], &data, emit_from_particles_task_cb, &settings); @@ -1770,7 +1770,7 @@ typedef struct EmitFromDMData { static void emit_from_mesh_task_cb(void *__restrict userdata, const int z, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { EmitFromDMData *data = userdata; EmissionMap *em = data->em; @@ -1975,7 +1975,7 @@ static void emit_from_mesh( .res = res, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(min[2], max[2], &data, emit_from_mesh_task_cb, &settings); @@ -2893,7 +2893,7 @@ typedef struct UpdateEffectorsData { static void update_effectors_task_cb(void *__restrict userdata, const int x, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { UpdateEffectorsData *data = userdata; SmokeDomainSettings *sds = data->sds; @@ -2967,7 +2967,7 @@ static void update_effectors( data.velocity_z = smoke_get_velocity_z(sds->fluid); data.obstacle = smoke_get_obstacle(sds->fluid); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, sds->res[0], &data, update_effectors_task_cb, &settings); diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index fac1e1dbe75..472fbd9ad18 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -267,7 +267,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_ static void subdiv_ccg_eval_grids_task(void *__restrict userdata_v, const int face_index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { CCGEvalGridsData *data = userdata_v; SubdivCCG *subdiv_ccg = data->subdiv_ccg; @@ -295,7 +295,7 @@ static bool subdiv_ccg_evaluate_grids(SubdivCCG *subdiv_ccg, data.mask_evaluator = mask_evaluator; data.material_flags_evaluator = material_flags_evaluator; /* Threaded grids evaluation. */ - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); BLI_task_parallel_range( 0, num_faces, &data, subdiv_ccg_eval_grids_task, ¶llel_range_settings); @@ -747,7 +747,7 @@ static void subdiv_ccg_average_inner_face_normals(SubdivCCG *subdiv_ccg, static void subdiv_ccg_recalc_inner_normal_task(void *__restrict userdata_v, const int grid_index, - const ParallelRangeTLS *__restrict tls_v) + const TaskParallelTLS *__restrict tls_v) { RecalcInnerNormalsData *data = userdata_v; RecalcInnerNormalsTLSData *tls = tls_v->userdata_chunk; @@ -772,7 +772,7 @@ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG *subdiv_ccg) .key = &key, }; RecalcInnerNormalsTLSData tls_data = {NULL}; - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); @@ -802,7 +802,7 @@ typedef struct RecalcModifiedInnerNormalsData { static void subdiv_ccg_recalc_modified_inner_normal_task(void *__restrict userdata_v, const int face_index, - const ParallelRangeTLS *__restrict tls_v) + const TaskParallelTLS *__restrict tls_v) { RecalcModifiedInnerNormalsData *data = userdata_v; SubdivCCG *subdiv_ccg = data->subdiv_ccg; @@ -838,7 +838,7 @@ static void subdiv_ccg_recalc_modified_inner_grid_normals(SubdivCCG *subdiv_ccg, .effected_ccg_faces = (SubdivCCGFace **)effected_faces, }; RecalcInnerNormalsTLSData tls_data = {NULL}; - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); @@ -991,7 +991,7 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG *subdiv_ccg, static void subdiv_ccg_average_inner_grids_task(void *__restrict userdata_v, const int face_index, - const ParallelRangeTLS *__restrict UNUSED(tls_v)) + const TaskParallelTLS *__restrict UNUSED(tls_v)) { AverageInnerGridsData *data = userdata_v; SubdivCCG *subdiv_ccg = data->subdiv_ccg; @@ -1050,7 +1050,7 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG *subdiv_ccg, static void subdiv_ccg_average_grids_boundaries_task(void *__restrict userdata_v, const int adjacent_edge_index, - const ParallelRangeTLS *__restrict tls_v) + const TaskParallelTLS *__restrict tls_v) { AverageGridsBoundariesData *data = userdata_v; AverageGridsBoundariesTLSData *tls = tls_v->userdata_chunk; @@ -1097,7 +1097,7 @@ static void subdiv_ccg_average_grids_corners(SubdivCCG *subdiv_ccg, static void subdiv_ccg_average_grids_corners_task(void *__restrict userdata_v, const int adjacent_vertex_index, - const ParallelRangeTLS *__restrict UNUSED(tls_v)) + const TaskParallelTLS *__restrict UNUSED(tls_v)) { AverageGridsCornerData *data = userdata_v; SubdivCCG *subdiv_ccg = data->subdiv_ccg; @@ -1108,7 +1108,7 @@ static void subdiv_ccg_average_grids_corners_task(void *__restrict userdata_v, static void subdiv_ccg_average_all_boundaries(SubdivCCG *subdiv_ccg, CCGKey *key) { - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); AverageGridsBoundariesData boundaries_data = { .subdiv_ccg = subdiv_ccg, @@ -1127,7 +1127,7 @@ static void subdiv_ccg_average_all_boundaries(SubdivCCG *subdiv_ccg, CCGKey *key static void subdiv_ccg_average_all_corners(SubdivCCG *subdiv_ccg, CCGKey *key) { - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); AverageGridsCornerData corner_data = { .subdiv_ccg = subdiv_ccg, @@ -1150,7 +1150,7 @@ void BKE_subdiv_ccg_average_grids(SubdivCCG *subdiv_ccg) { CCGKey key; BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); /* Average inner boundaries of grids (within one face), across faces * from different face-corners. */ @@ -1175,7 +1175,7 @@ typedef struct StitchFacesInnerGridsData { static void subdiv_ccg_stitch_face_inner_grids_task( void *__restrict userdata_v, const int face_index, - const ParallelRangeTLS *__restrict UNUSED(tls_v)) + const TaskParallelTLS *__restrict UNUSED(tls_v)) { StitchFacesInnerGridsData *data = userdata_v; SubdivCCG *subdiv_ccg = data->subdiv_ccg; @@ -1197,7 +1197,7 @@ void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG *subdiv_ccg, .key = &key, .effected_ccg_faces = effected_faces, }; - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); BLI_task_parallel_range(0, num_effected_faces, diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c index 98afbef6c0a..c3f9bc3400c 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.c +++ b/source/blender/blenkernel/intern/subdiv_foreach.c @@ -1681,7 +1681,7 @@ static void subdiv_foreach_polys(SubdivForeachTaskContext *ctx, void *tls, int p static void subdiv_foreach_loose_vertices_task(void *__restrict userdata, const int coarse_vertex_index, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SubdivForeachTaskContext *ctx = userdata; if (BLI_BITMAP_TEST_BOOL(ctx->coarse_vertices_used_map, coarse_vertex_index)) { @@ -1695,7 +1695,7 @@ static void subdiv_foreach_loose_vertices_task(void *__restrict userdata, static void subdiv_foreach_vertices_of_loose_edges_task(void *__restrict userdata, const int coarse_edge_index, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SubdivForeachTaskContext *ctx = userdata; if (BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, coarse_edge_index)) { @@ -1767,7 +1767,7 @@ static void subdiv_foreach_single_thread_tasks(SubdivForeachTaskContext *ctx) static void subdiv_foreach_task(void *__restrict userdata, const int poly_index, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SubdivForeachTaskContext *ctx = userdata; /* Traverse hi-poly vertex coordinates and normals. */ @@ -1786,7 +1786,7 @@ static void subdiv_foreach_task(void *__restrict userdata, static void subdiv_foreach_boundary_edges_task(void *__restrict userdata, const int edge_index, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SubdivForeachTaskContext *ctx = userdata; subdiv_foreach_boundary_edges(ctx, tls->userdata_chunk, edge_index); @@ -1821,7 +1821,7 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv, /* Run all the code which is not supposed to be run from threads. */ subdiv_foreach_single_thread_tasks(&ctx); /* Threaded traversal of the rest of topology. */ - ParallelRangeSettings parallel_range_settings; + TaskParallelSettings parallel_range_settings; BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = context->user_data_tls; parallel_range_settings.userdata_chunk_size = context->user_data_tls_size; diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index 75e05f8ffab..1ff9140681f 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -1086,20 +1086,27 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext * const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index]; Mesh *subdiv_mesh = ctx->subdiv_mesh; MVert *subdiv_mvert = subdiv_mesh->mvert; + const bool is_simple = ctx->subdiv->settings.is_simple; /* Find neighbors of the current loose edge. */ const MEdge *neighbors[2]; find_edge_neighbors(ctx, coarse_edge, neighbors); - /* Get points for b-spline interpolation. */ - float points[4][3]; - points_for_loose_edges_interpolation_get(ctx, coarse_edge, neighbors, points); - /* Perform interpolation. */ - float weights[4]; - key_curve_position_weights(u, weights, KEY_BSPLINE); /* Interpolate custom data. */ subdiv_mesh_vertex_of_loose_edge_interpolate(ctx, coarse_edge, u, subdiv_vertex_index); - /* Initialize */ + /* Interpolate coordinate. */ MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index]; - interp_v3_v3v3v3v3(subdiv_vertex->co, points[0], points[1], points[2], points[3], weights); + if (is_simple) { + const MVert *coarse_mvert = coarse_mesh->mvert; + const MVert *vert_1 = &coarse_mvert[coarse_edge->v1]; + const MVert *vert_2 = &coarse_mvert[coarse_edge->v2]; + interp_v3_v3v3(subdiv_vertex->co, vert_1->co, vert_2->co, u); + } + else { + float points[4][3]; + points_for_loose_edges_interpolation_get(ctx, coarse_edge, neighbors, points); + float weights[4]; + key_curve_position_weights(u, weights, KEY_BSPLINE); + interp_v3_v3v3v3v3(subdiv_vertex->co, points[0], points[1], points[2], points[3], weights); + } /* Reset flags and such. */ subdiv_vertex->flag = 0; /* TODO(sergey): This matches old behavior, but we can as well interpolate diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 4171c1aac4f..09a073e3ca6 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1459,7 +1459,7 @@ typedef struct CopyFinalLoopArrayData { static void copyFinalLoopArray_task_cb(void *__restrict userdata, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { CopyFinalLoopArrayData *data = userdata; CCGDerivedMesh *ccgdm = data->ccgdm; @@ -1536,7 +1536,7 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop) */ data.mloop_index = data.grid_size >= 5 ? 1 : 8; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 1; diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 8a474725b0c..84855cf4b82 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -377,7 +377,7 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, static void autotrack_context_step_cb(void *__restrict userdata, const int track, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { AutoTrackContext *context = userdata; const int frame_delta = context->backwards ? -1 : 1; @@ -446,7 +446,7 @@ bool BKE_autotrack_context_step(AutoTrackContext *context) const int frame_delta = context->backwards ? -1 : 1; context->step_ok = false; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (context->num_tracks > 1); BLI_task_parallel_range(0, context->num_tracks, context, autotrack_context_step_cb, &settings); diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c index cfa41cb7d92..7e7a839b645 100644 --- a/source/blender/blenkernel/intern/tracking_solver.c +++ b/source/blender/blenkernel/intern/tracking_solver.c @@ -65,6 +65,9 @@ typedef struct MovieReconstructContext { TracksMap *tracks_map; int sfra, efra; + + /* Details about reconstruction error, reported by Libmv. */ + char error_message[1024]; } MovieReconstructContext; typedef struct ReconstructProgressData { @@ -426,9 +429,26 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieClip *clip context->keyframe2 = keyframe2; context->refine_flags = reconstruct_refine_intrinsics_get_flags(tracking, object); + context->error_message[0] = '\0'; + return context; } +void BKE_tracking_reconstruction_report_error_message(MovieReconstructContext *context, + const char *error_message) +{ + if (context->error_message[0]) { + /* Only keep initial error message, the rest are inducted ones. */ + return; + } + BLI_strncpy(context->error_message, error_message, sizeof(context->error_message)); +} + +const char *BKE_tracking_reconstruction_error_message_get(const MovieReconstructContext *context) +{ + return context->error_message; +} + /* Free memory used by a reconstruction process. */ void BKE_tracking_reconstruction_context_free(MovieReconstructContext *context) { @@ -534,7 +554,8 @@ bool BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieT MovieTrackingObject *object; if (!libmv_reconstructionIsValid(context->reconstruction)) { - printf("Failed solve the motion: most likely there are no good keyframes\n"); + BKE_tracking_reconstruction_report_error_message( + context, "Failed to solve the motion: most likely there are no good keyframes"); return false; } diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index b852e8a12cd..03229c654fb 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -611,16 +611,19 @@ static bool average_track_contributions(StabContext *ctx, float rotation, scale, quality; quality = rotation_contribution( stabilization_base, marker, aspect, r_pivot, &rotation, &scale); - weight *= quality; - weight_sum += weight; - *r_angle += rotation * weight; + const float quality_weight = weight * quality; + weight_sum += quality_weight; + *r_angle += rotation * quality_weight; if (stab->flag & TRACKING_STABILIZE_SCALE) { - *r_scale_step += logf(scale) * weight; + *r_scale_step += logf(scale) * quality_weight; } else { *r_scale_step = 0; } - ok |= (weight_sum > EPSILON_WEIGHT); + /* NOTE: Use original marker weight and not the scaled one with the proximity here to allow + * simple stabilization setups when there is a single track in a close proximity of the + * center. */ + ok |= (weight > EPSILON_WEIGHT); } } } @@ -1338,7 +1341,7 @@ typedef struct TrackingStabilizeFrameInterpolationData { } TrackingStabilizeFrameInterpolationData; static void tracking_stabilize_frame_interpolation_cb( - void *__restrict userdata, const int j, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int j, const TaskParallelTLS *__restrict UNUSED(tls)) { TrackingStabilizeFrameInterpolationData *data = userdata; ImBuf *ibuf = data->ibuf; @@ -1443,7 +1446,7 @@ ImBuf *BKE_tracking_stabilize_frame( .interpolation = interpolation, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (tmpibuf->y > 128); BLI_task_parallel_range( diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index d312dc0190b..07cf5205cab 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -311,13 +311,20 @@ static void undosys_stack_clear_all_last(UndoStack *ustack, UndoStep *us) } } -static void undosys_stack_clear_all_first(UndoStack *ustack, UndoStep *us) +static void undosys_stack_clear_all_first(UndoStack *ustack, UndoStep *us, UndoStep *us_exclude) { + if (us && us == us_exclude) { + us = us->prev; + } + if (us) { bool is_not_empty = true; UndoStep *us_iter; do { us_iter = ustack->steps.first; + if (us_iter == us_exclude) { + us_iter = us_iter->next; + } BLI_assert(us_iter != ustack->step_active); undosys_step_free_and_unlink(ustack, us_iter); undosys_stack_validate(ustack, is_not_empty); @@ -395,9 +402,7 @@ void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size CLOG_INFO(&LOG, 1, "steps=%d, memory_limit=%zu", steps, memory_limit); UndoStep *us; -#ifdef WITH_GLOBAL_UNDO_KEEP_ONE UndoStep *us_exclude = NULL; -#endif /* keep at least two (original + other) */ size_t data_size_all = 0; size_t us_count = 0; @@ -427,23 +432,14 @@ void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size /* Hack, we need to keep at least one BKE_UNDOSYS_TYPE_MEMFILE. */ if (us->type != BKE_UNDOSYS_TYPE_MEMFILE) { us_exclude = us->prev; - while (us_exclude && us->type != BKE_UNDOSYS_TYPE_MEMFILE) { + while (us_exclude && us_exclude->type != BKE_UNDOSYS_TYPE_MEMFILE) { us_exclude = us_exclude->prev; } - if (us_exclude) { - BLI_remlink(&ustack->steps, us_exclude); - } } #endif /* Free from first to last, free functions may update de-duplication info * (see #MemFileUndoStep). */ - undosys_stack_clear_all_first(ustack, us->prev); - -#ifdef WITH_GLOBAL_UNDO_KEEP_ONE - if (us_exclude) { - BLI_addhead(&ustack->steps, us_exclude); - } -#endif + undosys_stack_clear_all_first(ustack, us->prev, us_exclude); } } @@ -564,12 +560,15 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, } if (use_memfile_step) { - const char *name_internal = "MemFile Internal (post)"; + /* Make this the user visible undo state, so redo always applies + * on top of the mem-file undo instead of skipping it. see: T67256. */ + UndoStep *us_prev = ustack->step_active; + const char *name_internal = us_prev->name; const bool ok = undosys_stack_push_main(ustack, name_internal, G_MAIN); if (ok) { UndoStep *us = ustack->steps.last; BLI_assert(STREQ(us->name, name_internal)); - us->skip = true; + us_prev->skip = true; #ifdef WITH_GLOBAL_UNDO_CORRECT_ORDER ustack->step_active_memfile = us; #endif @@ -849,10 +848,6 @@ void BKE_undosys_type_free_all(void) * Unfortunately we need this for a handful of places. */ -/* Disable for now since it accesses freed memory. - * The pointer can only be a key, we can't read it's contents. */ -#define USE_LIB_SKIP - static void UNUSED_FUNCTION(BKE_undosys_foreach_ID_ref(UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)) @@ -865,176 +860,6 @@ static void UNUSED_FUNCTION(BKE_undosys_foreach_ID_ref(UndoStack *ustack, } } -typedef struct UndoIDPtrMapItem { - /** Never changes (matches undo data). Use as sort key for binary search. */ - const void *ptr; - /** Write the new pointers here. */ - uint index; -} UndoIDPtrMapItem; - -typedef struct UndoIDPtrMap { - UndoRefID *refs; - /** - * Pointer map, update 'dst' members before use. - * This is always sorted (adds some overhead when adding, in practice it's acceptable since). - */ - UndoIDPtrMapItem *pmap; - - /** Length for both 'refs' & 'pmap' */ - uint len; - uint len_alloc; -} UndoIDPtrMap; - -#ifdef DEBUG -# define PMAP_DEFAULT_ALLOC 1 -#else -# define PMAP_DEFAULT_ALLOC 32 -#endif - -void BKE_undosys_ID_map_foreach_ID_ref(UndoIDPtrMap *map, - UndoTypeForEachIDRefFn foreach_ID_ref_fn, - void *user_data) -{ - for (uint i = 0; i < map->len; i++) { - foreach_ID_ref_fn(user_data, &map->refs[i]); - } -} - -/** - * Return true when found, otherwise index is set to the index we should insert. - */ -static bool undosys_ID_map_lookup_index(const UndoIDPtrMap *map, const void *key, uint *r_index) -{ - const UndoIDPtrMapItem *pmap = map->pmap; - const uint len = map->len; - if (len == 0) { - if (r_index) { - *r_index = 0; - } - return false; - } - int min = 0, max = len - 1; - while (min <= max) { - const uint mid = (min + max) / 2; - if (pmap[mid].ptr < key) { - min = mid + 1; - } - else if (pmap[mid].ptr == key) { - if (r_index) { - *r_index = mid; - } - return true; - } - else if (pmap[mid].ptr > key) { - max = mid - 1; - } - } - if (r_index) { - *r_index = min; - } - return false; -} - -/** - * A set of ID's use for efficient decoding, so we can map pointers back to the newly loaded data - * without performing full look ups each time. - * - * This can be used as an old_pointer -> new_pointer lookup. - */ -UndoIDPtrMap *BKE_undosys_ID_map_create(void) -{ - UndoIDPtrMap *map = MEM_mallocN(sizeof(*map), __func__); - map->len_alloc = PMAP_DEFAULT_ALLOC; - map->refs = MEM_mallocN(sizeof(*map->refs) * map->len_alloc, __func__); - map->pmap = MEM_mallocN(sizeof(*map->pmap) * map->len_alloc, __func__); - map->len = 0; - return map; -} -void BKE_undosys_ID_map_destroy(UndoIDPtrMap *idpmap) -{ - MEM_SAFE_FREE(idpmap->refs); - MEM_SAFE_FREE(idpmap->pmap); - MEM_freeN(idpmap); -} - -void BKE_undosys_ID_map_add(UndoIDPtrMap *map, ID *id) -{ - uint index; -#ifdef USE_LIB_SKIP - if (id->lib != NULL) { - return; - } -#endif - - if (undosys_ID_map_lookup_index(map, id, &index)) { - return; /* exists. */ - } - - const uint len_src = map->len; - const uint len_dst = map->len + 1; - if (len_dst > map->len_alloc) { - map->len_alloc *= 2; - BLI_assert(map->len_alloc >= len_dst); - map->pmap = MEM_reallocN(map->pmap, sizeof(*map->pmap) * map->len_alloc); - map->refs = MEM_reallocN(map->refs, sizeof(*map->refs) * map->len_alloc); - } - -#if 0 /* Will be done automatically in callback. */ - BLI_strncpy(map->refs[len_src].name, id->name, sizeof(id->name)); -#else - map->refs[len_src].name[0] = '\0'; -#endif - map->refs[len_src].ptr = id; - - if (len_src != 0 && index != len_src) { - memmove(&map->pmap[index + 1], &map->pmap[index], sizeof(*map->pmap) * (len_src - index)); - } - map->pmap[index].ptr = id; - map->pmap[index].index = len_src; - - map->len = len_dst; -} - -ID *BKE_undosys_ID_map_lookup(const UndoIDPtrMap *map, const ID *id_src) -{ - /* We should only ever lookup indices which exist! */ - uint index; - if (!undosys_ID_map_lookup_index(map, id_src, &index)) { - BLI_assert(0); - } - index = map->pmap[index].index; - ID *id_dst = map->refs[index].ptr; - BLI_assert(id_dst != NULL); - BLI_assert(STREQ(id_dst->name, map->refs[index].name)); - return id_dst; -} - -void BKE_undosys_ID_map_add_with_prev(UndoIDPtrMap *map, ID *id, ID **id_prev) -{ - if (id == *id_prev) { - return; - } - *id_prev = id; - BKE_undosys_ID_map_add(map, id); -} - -ID *BKE_undosys_ID_map_lookup_with_prev(const UndoIDPtrMap *map, ID *id_src, ID *id_prev_match[2]) -{ - if (id_src == id_prev_match[0]) { - return id_prev_match[1]; - } - else { -#ifdef USE_LIB_SKIP - ID *id_dst = BKE_undosys_ID_map_lookup(map, id_src); -#else - ID *id_dst = (id_src->lib == NULL) ? BKE_undosys_ID_map_lookup(map, id_src) : id_src; -#endif - id_prev_match[0] = id_src; - id_prev_match[1] = id_dst; - return id_dst; - } -} - /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 18689cca55a..c1618061b38 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -302,6 +302,13 @@ bool isect_line_line_strict_v3(const float v1[3], float vi[3], float *r_lambda); +bool isect_ray_ray_v3(const float ray_origin_a[3], + const float ray_direction_a[3], + const float ray_origin_b[3], + const float ray_direction_b[3], + float *r_lambda_a, + float *r_lambda_b); + bool isect_ray_plane_v3(const float ray_origin[3], const float ray_direction[3], const float plane[4], diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index d11ba15a7e0..568d6c9a84a 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -142,22 +142,23 @@ typedef enum eTaskSchedulingMode { } eTaskSchedulingMode; /* Per-thread specific data passed to the callback. */ -typedef struct ParallelRangeTLS { +typedef struct TaskParallelTLS { /* Identifier of the thread who this data belongs to. */ int thread_id; /* Copy of user-specifier chunk, which is copied from original chunk to all * worker threads. This is similar to OpenMP's firstprivate. */ void *userdata_chunk; -} ParallelRangeTLS; +} TaskParallelTLS; + +typedef void (*TaskParallelFinalizeFunc)(void *__restrict userdata, + void *__restrict userdata_chunk); typedef void (*TaskParallelRangeFunc)(void *__restrict userdata, const int iter, - const ParallelRangeTLS *__restrict tls); -typedef void (*TaskParallelRangeFuncFinalize)(void *__restrict userdata, - void *__restrict userdata_chunk); + const TaskParallelTLS *__restrict tls); -typedef struct ParallelRangeSettings { +typedef struct TaskParallelSettings { /* Whether caller allows to do threading of the particular range. * Usually set by some equation, which forces threading off when threading * overhead becomes higher than speed benefit. @@ -175,7 +176,7 @@ typedef struct ParallelRangeSettings { /* Function called from calling thread once whole range have been * processed. */ - TaskParallelRangeFuncFinalize func_finalize; + TaskParallelFinalizeFunc func_finalize; /* Minimum allowed number of range iterators to be handled by a single * thread. This allows to achieve following: * - Reduce amount of threading overhead. @@ -187,15 +188,15 @@ typedef struct ParallelRangeSettings { * having a global use_threading switch based on just range size. */ int min_iter_per_thread; -} ParallelRangeSettings; +} TaskParallelSettings; -BLI_INLINE void BLI_parallel_range_settings_defaults(ParallelRangeSettings *settings); +BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings); void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, - const ParallelRangeSettings *settings); + const TaskParallelSettings *settings); typedef void (*TaskParallelListbaseFunc)(void *userdata, struct Link *iter, int index); void BLI_task_parallel_listbase(struct ListBase *listbase, @@ -211,16 +212,13 @@ void BLI_task_parallel_mempool(struct BLI_mempool *mempool, const bool use_threading); /* TODO(sergey): Think of a better place for this. */ -BLI_INLINE void BLI_parallel_range_settings_defaults(ParallelRangeSettings *settings) +BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings) { memset(settings, 0, sizeof(*settings)); settings->use_threading = true; settings->scheduling_mode = TASK_SCHEDULING_STATIC; - /* NOTE: Current value mimics old behavior, but it's not ideal by any - * means. Would be cool to find a common value which will work good enough - * for both static and dynamic scheduling. - */ - settings->min_iter_per_thread = 1; + /* Use default heuristic to define actual chunk size. */ + settings->min_iter_per_thread = 0; } #ifdef __cplusplus diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index f43f55a352b..f1811ff6e4f 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -700,7 +700,7 @@ typedef struct BVHDivNodesData { static void non_recursive_bvh_div_nodes_task_cb(void *__restrict userdata, const int j, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { BVHDivNodesData *data = userdata; @@ -841,14 +841,14 @@ static void non_recursive_bvh_div_nodes(const BVHTree *tree, cb_data.depth = depth; if (true) { - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD); BLI_task_parallel_range(i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb, &settings); } else { /* Less hassle for debugging. */ - ParallelRangeTLS tls = {0}; + TaskParallelTLS tls = {0}; for (int i_task = i; i_task < i_stop; i_task++) { non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task, &tls); } @@ -1195,7 +1195,7 @@ int BLI_bvhtree_overlap_thread_num(const BVHTree *tree) static void bvhtree_overlap_task_cb(void *__restrict userdata, const int j, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { BVHOverlapData_Thread *data = &((BVHOverlapData_Thread *)userdata)[j]; BVHOverlapData_Shared *data_shared = data->shared; @@ -1262,7 +1262,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap( data[j].thread = j; } - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (tree1->totleaf > KDOPBVH_THREAD_LEAF_THRESHOLD); BLI_task_parallel_range(0, thread_num, data, bvhtree_overlap_task_cb, &settings); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 367494537e3..c130c46a0fb 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2798,6 +2798,46 @@ bool isect_line_line_strict_v3(const float v1[3], } } +/** + * Check if two rays are not parallel and returns a factor that indicates + * the distance from \a ray_origin_b to the closest point on ray-a to ray-b. + * + * \note Neither directions need to be normalized. + */ +bool isect_ray_ray_v3(const float ray_origin_a[3], + const float ray_direction_a[3], + const float ray_origin_b[3], + const float ray_direction_b[3], + float *r_lambda_a, + float *r_lambda_b) +{ + BLI_assert(r_lambda_a || r_lambda_b); + float n[3]; + cross_v3_v3v3(n, ray_direction_b, ray_direction_a); + const float nlen = len_squared_v3(n); + + if (UNLIKELY(nlen == 0.0f)) { + /* The lines are parallel. */ + return false; + } + + float t[3], c[3], cray[3]; + sub_v3_v3v3(t, ray_origin_b, ray_origin_a); + sub_v3_v3v3(c, n, t); + + if (r_lambda_a != NULL) { + cross_v3_v3v3(cray, c, ray_direction_b); + *r_lambda_a = dot_v3v3(cray, n) / nlen; + } + + if (r_lambda_b != NULL) { + cross_v3_v3v3(cray, c, ray_direction_a); + *r_lambda_b = dot_v3v3(cray, n) / nlen; + } + + return true; +} + bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], diff --git a/source/blender/blenlib/intern/math_statistics.c b/source/blender/blenlib/intern/math_statistics.c index 7c461120520..d4fcb32ce37 100644 --- a/source/blender/blenlib/intern/math_statistics.c +++ b/source/blender/blenlib/intern/math_statistics.c @@ -42,7 +42,7 @@ typedef struct CovarianceData { static void covariance_m_vn_ex_task_cb(void *__restrict userdata, const int a, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { CovarianceData *data = userdata; const float *cos_vn = data->cos_vn; @@ -122,7 +122,7 @@ void BLI_covariance_m_vn_ex(const int n, .nbr_cos_vn = nbr_cos_vn, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((nbr_cos_vn * n * n) >= 10000); BLI_task_parallel_range(0, n * n, &data, covariance_m_vn_ex_task_cb, &settings); diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 39af73ac175..4ba198ac0b8 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -297,56 +297,72 @@ bool BLI_is_file(const char *path) return (mode && !S_ISDIR(mode)); } -void *BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size) +/** + * Use for both text and binary file reading. + */ +static void *file_read_data_as_mem_impl(FILE *fp, + bool read_size_exact, + size_t pad_bytes, + size_t *r_size) { - FILE *fp = BLI_fopen(filepath, "r"); - void *mem = NULL; + struct stat st; + if (fstat(fileno(fp), &st) == -1) { + return NULL; + } + if (S_ISDIR(st.st_mode)) { + return NULL; + } + if (fseek(fp, 0L, SEEK_END) == -1) { + return NULL; + } + /* Don't use the 'st_size' because it may be the symlink. */ + const long int filelen = ftell(fp); + if (filelen == -1) { + return NULL; + } + if (fseek(fp, 0L, SEEK_SET) == -1) { + return NULL; + } - if (fp) { - struct stat st; - if (fstat(fileno(fp), &st) == -1) { - goto finally; - } - if (S_ISDIR(st.st_mode)) { - goto finally; - } - if (fseek(fp, 0L, SEEK_END) == -1) { - goto finally; - } - /* Don't use the 'st_size' because it may be the symlink. */ - const long int filelen = ftell(fp); - if (filelen == -1) { - goto finally; - } - if (fseek(fp, 0L, SEEK_SET) == -1) { - goto finally; - } + void *mem = MEM_mallocN(filelen + pad_bytes, __func__); + if (mem == NULL) { + return NULL; + } - mem = MEM_mallocN(filelen + pad_bytes, __func__); - if (mem == NULL) { - goto finally; - } + const long int filelen_read = fread(mem, 1, filelen, fp); + if ((filelen_read < 0) || ferror(fp)) { + MEM_freeN(mem); + return NULL; + } - const long int filelen_read = fread(mem, 1, filelen, fp); - if ((filelen_read < 0) || ferror(fp)) { + if (read_size_exact) { + if (filelen_read != filelen) { MEM_freeN(mem); - mem = NULL; - goto finally; + return NULL; } - + } + else { if (filelen_read < filelen) { mem = MEM_reallocN(mem, filelen_read + pad_bytes); if (mem == NULL) { - goto finally; + return NULL; } } + } - *r_size = filelen_read; + *r_size = filelen_read; + + return mem; +} - finally: +void *BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size) +{ + FILE *fp = BLI_fopen(filepath, "r"); + void *mem = NULL; + if (fp) { + mem = file_read_data_as_mem_impl(fp, true, pad_bytes, r_size); fclose(fp); } - return mem; } @@ -354,45 +370,10 @@ void *BLI_file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t { FILE *fp = BLI_fopen(filepath, "rb"); void *mem = NULL; - if (fp) { - struct stat st; - if (fstat(fileno(fp), &st) == -1) { - goto finally; - } - if (S_ISDIR(st.st_mode)) { - goto finally; - } - if (fseek(fp, 0L, SEEK_END) == -1) { - goto finally; - } - /* Don't use the 'st_size' because it may be the symlink. */ - const long int filelen = ftell(fp); - if (filelen == -1) { - goto finally; - } - if (fseek(fp, 0L, SEEK_SET) == -1) { - goto finally; - } - - mem = MEM_mallocN(filelen + pad_bytes, __func__); - if (mem == NULL) { - goto finally; - } - - const long int filelen_read = fread(mem, 1, filelen, fp); - if ((filelen_read != filelen) || ferror(fp)) { - MEM_freeN(mem); - mem = NULL; - goto finally; - } - - *r_size = filelen_read; - - finally: + mem = file_read_data_as_mem_impl(fp, false, pad_bytes, r_size); fclose(fp); } - return mem; } diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index 85d39f2f98e..bea38a232cc 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -1054,6 +1054,49 @@ typedef struct ParallelRangeState { int chunk_size; } ParallelRangeState; +BLI_INLINE void task_parallel_range_calc_chunk_size(const TaskParallelSettings *settings, + const int num_tasks, + ParallelRangeState *state) +{ + const int tot_items = state->stop - state->start; + int chunk_size = 0; + + if (settings->min_iter_per_thread > 0) { + /* Already set by user, no need to do anything here. */ + chunk_size = settings->min_iter_per_thread; + } + else { + /* Basic heuristic to avoid threading on low amount of items. We could make that limit + * configurable in settings too... */ + if (tot_items > 0 && tot_items < 256) { + chunk_size = tot_items; + } + /* NOTE: The idea here is to compensate for rather measurable threading + * overhead caused by fetching tasks. With too many CPU threads we are starting + * to spend too much time in those overheads. */ + else if (num_tasks > 32) { + chunk_size = 128; + } + else if (num_tasks > 16) { + chunk_size = 64; + } + else { + chunk_size = 32; + } + } + + BLI_assert(chunk_size > 0); + + switch (settings->scheduling_mode) { + case TASK_SCHEDULING_STATIC: + state->chunk_size = max_ii(chunk_size, tot_items / (num_tasks)); + break; + case TASK_SCHEDULING_DYNAMIC: + state->chunk_size = chunk_size; + break; + } +} + BLI_INLINE bool parallel_range_next_iter_get(ParallelRangeState *__restrict state, int *__restrict iter, int *__restrict count) @@ -1069,7 +1112,7 @@ BLI_INLINE bool parallel_range_next_iter_get(ParallelRangeState *__restrict stat static void parallel_range_func(TaskPool *__restrict pool, void *userdata_chunk, int thread_id) { ParallelRangeState *__restrict state = BLI_task_pool_userdata(pool); - ParallelRangeTLS tls = { + TaskParallelTLS tls = { .thread_id = thread_id, .userdata_chunk = userdata_chunk, }; @@ -1085,7 +1128,7 @@ static void parallel_range_single_thread(const int start, int const stop, void *userdata, TaskParallelRangeFunc func, - const ParallelRangeSettings *settings) + const TaskParallelSettings *settings) { void *userdata_chunk = settings->userdata_chunk; const size_t userdata_chunk_size = settings->userdata_chunk_size; @@ -1095,7 +1138,7 @@ static void parallel_range_single_thread(const int start, userdata_chunk_local = MALLOCA(userdata_chunk_size); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); } - ParallelRangeTLS tls = { + TaskParallelTLS tls = { .thread_id = 0, .userdata_chunk = userdata_chunk_local, }; @@ -1118,7 +1161,7 @@ void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, - const ParallelRangeSettings *settings) + const TaskParallelSettings *settings) { TaskScheduler *task_scheduler; TaskPool *task_pool; @@ -1162,16 +1205,8 @@ void BLI_task_parallel_range(const int start, state.userdata = userdata; state.func = func; state.iter = start; - switch (settings->scheduling_mode) { - case TASK_SCHEDULING_STATIC: - state.chunk_size = max_ii(settings->min_iter_per_thread, (stop - start) / (num_tasks)); - break; - case TASK_SCHEDULING_DYNAMIC: - /* TODO(sergey): Make it configurable from min_iter_per_thread. */ - state.chunk_size = 32; - break; - } + task_parallel_range_calc_chunk_size(settings, num_tasks, &state); num_tasks = min_ii(num_tasks, max_ii(1, (stop - start) / state.chunk_size)); if (num_tasks == 1) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 19e9c5142dd..6fe5c4516b5 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6220,6 +6220,7 @@ static void direct_link_collection(FileData *fd, Collection *collection) collection->preview = direct_link_preview_image(fd, collection->preview); collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; + collection->tag = 0; BLI_listbase_clear(&collection->object_cache); BLI_listbase_clear(&collection->parents); @@ -7038,6 +7039,7 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd) /* init stroke buffer */ gpd->runtime.sbuffer = NULL; + gpd->runtime.sbuffer_used = 0; gpd->runtime.sbuffer_size = 0; gpd->runtime.tot_cp_points = 0; @@ -9138,7 +9140,18 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const int ta id->icon_id = 0; id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */ id->orig_id = NULL; - id->recalc = 0; + + /* NOTE: It is important to not clear the recalc flags for undo/redo. + * Preserving recalc flags on redo/undo is the only way to make dependency graph detect + * that animation is to be evaluated on undo/redo. If this is not enforced by the recalc + * flags dependency graph does not do animation update to avoid loss of unkeyed changes., + * which conflicts with undo/redo of changes to animation data itself. + * + * But for regular file load we clear the flag, since the flags might have been changed sinde + * the version the file has been saved with. */ + if (!fd->memfile) { + id->recalc = 0; + } /* this case cannot be direct_linked: it's just the ID part */ if (bhead->code == ID_LINK_PLACEHOLDER) { diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 57c674ae1b1..1cbafc7a707 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -36,6 +36,8 @@ #include "DNA_userdef_types.h" #include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "BKE_appdir.h" #include "BKE_brush.h" @@ -358,6 +360,20 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) CURVE_PRESET_BELL, CURVEMAP_SLOPE_POSITIVE); } + + /* Correct default startup UV's. */ + Mesh *me = BLI_findstring(&bmain->meshes, "Cube", offsetof(ID, name) + 2); + if (me && (me->totloop == 24) && (me->mloopuv != NULL)) { + const float uv_values[24][2] = { + {0.625, 0.50}, {0.875, 0.50}, {0.875, 0.75}, {0.625, 0.75}, {0.375, 0.75}, {0.625, 0.75}, + {0.625, 1.00}, {0.375, 1.00}, {0.375, 0.00}, {0.625, 0.00}, {0.625, 0.25}, {0.375, 0.25}, + {0.125, 0.50}, {0.375, 0.50}, {0.375, 0.75}, {0.125, 0.75}, {0.375, 0.50}, {0.625, 0.50}, + {0.625, 0.75}, {0.375, 0.75}, {0.375, 0.25}, {0.625, 0.25}, {0.625, 0.50}, {0.375, 0.50}, + }; + for (int i = 0; i < ARRAY_SIZE(uv_values); i++) { + copy_v2_v2(me->mloopuv[i].uv, uv_values[i]); + } + } } /** diff --git a/source/blender/blentranslation/CMakeLists.txt b/source/blender/blentranslation/CMakeLists.txt index 34952911dce..70e68ca06d7 100644 --- a/source/blender/blentranslation/CMakeLists.txt +++ b/source/blender/blentranslation/CMakeLists.txt @@ -22,6 +22,7 @@ set(INC . ../blenkernel ../blenlib + ../imbuf ../makesdna ../makesrna ../../../intern/guardedalloc diff --git a/source/blender/blentranslation/intern/blt_lang.c b/source/blender/blentranslation/intern/blt_lang.c index 75a4681deb2..82386a17776 100644 --- a/source/blender/blentranslation/intern/blt_lang.c +++ b/source/blender/blentranslation/intern/blt_lang.c @@ -42,6 +42,8 @@ #include "BKE_appdir.h" +#include "IMB_thumbs.h" + #include "DNA_userdef_types.h" #include "MEM_guardedalloc.h" @@ -288,6 +290,7 @@ void BLT_lang_set(const char *str) (void)str; #endif blt_lang_check_ime_supported(); + IMB_thumb_clear_translations(); } /* Get the current locale (short code, e.g. es_ES). */ diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index c58521297dd..5aa67ad8c78 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -461,7 +461,7 @@ typedef struct BMLoopInterpMultiresData { static void loop_interp_multires_cb(void *__restrict userdata, const int ix, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { BMLoopInterpMultiresData *data = userdata; @@ -561,7 +561,7 @@ void BM_loop_interp_multires_ex(BMesh *UNUSED(bm), .res = res, .d = 1.0f / (float)(res - 1), }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (res > 5); BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, &settings); diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 14b73693b03..64768474765 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -495,13 +495,16 @@ bool BM_face_split_edgenet(BMesh *bm, return false; } + /* These arrays used to be stack memory, however they can be + * large for singe faces with complex edgenets, see: T65980. */ + /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */ - edge_order = BLI_array_alloca(edge_order, edge_order_len); + edge_order = MEM_mallocN(sizeof(*edge_order) * edge_order_len, __func__); /* use later */ - face_verts = BLI_array_alloca(face_verts, edge_net_len + f->len); + face_verts = MEM_mallocN(sizeof(*face_verts) * (edge_net_len + f->len), __func__); - vert_queue = BLI_array_alloca(vert_queue, edge_net_len + f->len); + vert_queue = MEM_mallocN(sizeof(vert_queue) * (edge_net_len + f->len), __func__); STACK_INIT(vert_queue, f->len + edge_net_len); BLI_assert(BM_ELEM_API_FLAG_TEST(f, FACE_NET) == 0); @@ -687,6 +690,10 @@ bool BM_face_split_edgenet(BMesh *bm, } } + MEM_freeN(edge_order); + MEM_freeN(face_verts); + MEM_freeN(vert_queue); + return true; } @@ -1247,7 +1254,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm, */ const uint edge_arr_len = (uint)edge_net_init_len + (uint)f->len; - BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len); + BMEdge **edge_arr = BLI_memarena_alloc(mem_arena, sizeof(*edge_arr) * edge_arr_len); bool ok = false; uint edge_net_new_len = (uint)edge_net_init_len; @@ -1342,7 +1349,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm, BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK); unique_edges_in_group++; - BLI_linklist_prepend_alloca(&edge_links, e_iter); + BLI_linklist_prepend_arena(&edge_links, e_iter, mem_arena); BMVert *v_other = BM_edge_other_vert(e_iter, v_iter); if (BM_elem_flag_test(v_other, VERT_NOT_IN_STACK)) { @@ -1353,7 +1360,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm, } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_iter)) != v_iter->e); } - struct EdgeGroupIsland *g = alloca(sizeof(*g)); + struct EdgeGroupIsland *g = BLI_memarena_alloc(mem_arena, sizeof(*g)); g->vert_len = unique_verts_in_group; g->edge_len = unique_edges_in_group; edge_in_group_tot += unique_edges_in_group; diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index cf3d6b8bf56..2eedefe7980 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -807,6 +807,7 @@ void BM_mesh_calc_uvs_grid(BMesh *bm, const float dx = 1.0f / (float)(x_segments - 1); const float dy = 1.0f / (float)(y_segments - 1); + const float dx_wrap = 1.0 - (dx / 2.0f); float x = 0.0f; float y = dy; @@ -844,7 +845,7 @@ void BM_mesh_calc_uvs_grid(BMesh *bm, } x += dx; - if (x >= 1.0f) { + if (x >= dx_wrap) { x = 0.0f; y += dy; } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 90df3cd225e..c317d064086 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -3837,7 +3837,7 @@ static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp) /* Is this a good candidate for using tri_corner_adj_vmesh? */ static int tri_corner_test(BevelParams *bp, BevVert *bv) { - float ang, totang, angdiff; + float ang, absang, totang, angdiff; EdgeHalf *e; int i; int in_plane_e = 0; @@ -3852,10 +3852,11 @@ static int tri_corner_test(BevelParams *bp, BevVert *bv) for (i = 0; i < bv->edgecount; i++) { e = &bv->edges[i]; ang = BM_edge_calc_face_angle_signed_ex(e->e, 0.0f); - if (ang <= M_PI_4) { + absang = fabsf(ang); + if (absang <= M_PI_4) { in_plane_e++; } - else if (ang >= 3.0f * (float)M_PI_4) { + else if (absang >= 3.0f * (float)M_PI_4) { return -1; } totang += ang; @@ -3863,7 +3864,7 @@ static int tri_corner_test(BevelParams *bp, BevVert *bv) if (in_plane_e != bv->edgecount - 3) { return -1; } - angdiff = fabsf(totang - 3.0f * (float)M_PI_2); + angdiff = fabsf(fabsf(totang) - 3.0f * (float)M_PI_2); if ((bp->pro_super_r == PRO_SQUARE_R && angdiff > (float)M_PI / 16.0f) || (angdiff > (float)M_PI_4)) { return -1; diff --git a/source/blender/collada/Materials.cpp b/source/blender/collada/Materials.cpp index e1d5b2e9d5c..3b2c68ef95e 100644 --- a/source/blender/collada/Materials.cpp +++ b/source/blender/collada/Materials.cpp @@ -196,7 +196,7 @@ void MaterialNode::set_alpha(COLLADAFW::EffectCommon::OpaqueMode mode, } float alpha = transparent_alpha * transparency_alpha; - if (mode == COLLADASW::EffectProfile::RGB_ZERO) { + if (mode == COLLADAFW::EffectCommon::RGB_ZERO) { alpha = 1 - alpha; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index 36c6d246097..4cbdd169980 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -204,7 +204,7 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph) /* Re-tag IDs for update if it was tagged before the relations * update tag. */ for (IDNode *id_node : graph->id_nodes) { - ID *id = id_node->id_orig; + ID *id_orig = id_node->id_orig; id_node->finalize_build(graph); int flag = 0; /* Tag rebuild if special evaluation flags changed. */ @@ -219,10 +219,13 @@ void deg_graph_build_finalize(Main *bmain, Depsgraph *graph) flag |= ID_RECALC_COPY_ON_WRITE; /* This means ID is being added to the dependency graph first * time, which is similar to "ob-visible-change" */ - if (GS(id->name) == ID_OB) { + if (GS(id_orig->name) == ID_OB) { flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY; } } + /* Restore recalc flags from original ID, which could possibly contain recalc flags set by + * an operator and then were carried on by the undo system. */ + flag |= id_orig->recalc; if (flag != 0) { graph_id_tag_update(bmain, graph, id_node->id_orig, flag, DEG_UPDATE_SOURCE_RELATIONS); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index fa6d7bc6028..b06d6e73de0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1557,7 +1557,7 @@ void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip) add_operation_node(clip_id, NodeType::PARAMETERS, OperationCode::MOVIECLIP_EVAL, - function_bind(BKE_movieclip_eval_update, _1, clip_cow)); + function_bind(BKE_movieclip_eval_update, _1, bmain_, clip_cow)); add_operation_node(clip_id, NodeType::BATCH_CACHE, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 5bb3ebf40c4..be494104522 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -279,7 +279,8 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, } else if (RNA_struct_is_a(ptr->type, &RNA_Mesh) || RNA_struct_is_a(ptr->type, &RNA_Modifier) || RNA_struct_is_a(ptr->type, &RNA_GpencilModifier) || - RNA_struct_is_a(ptr->type, &RNA_Spline) || RNA_struct_is_a(ptr->type, &RNA_TextBox)) { + RNA_struct_is_a(ptr->type, &RNA_Spline) || RNA_struct_is_a(ptr->type, &RNA_TextBox) || + RNA_struct_is_a(ptr->type, &RNA_GPencilLayer)) { /* When modifier is used as FROM operation this is likely referencing to * the property (for example, modifier's influence). * But when it's used as TO operation, this is geometry component. */ diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index d8a9b41206b..6d3aed65a14 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -68,6 +68,7 @@ template<typename T> static void remove_from_vector(vector<T> *vector, const T & Depsgraph::Depsgraph(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode) : time_source(NULL), need_update(true), + need_update_time(false), scene(scene), view_layer(view_layer), mode(mode), diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index f194a44346b..507d2d9ec08 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -160,6 +160,10 @@ struct Depsgraph { /* Nodes which have been tagged as "directly modified". */ GSet *entry_tags; + /* Special entry tag for time source. Allows to tag invisible dependency graphs for update when + * scene frame changes, so then when dependency graph becomes visible it is on a proper state. */ + bool need_update_time; + /* Convenience Data ................... */ /* XXX: should be collected after building (if actually needed?) */ diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc index 6f3262174b4..f519fe76724 100644 --- a/source/blender/depsgraph/intern/depsgraph_eval.cc +++ b/source/blender/depsgraph/intern/depsgraph_eval.cc @@ -61,6 +61,7 @@ void DEG_evaluate_on_refresh(Depsgraph *graph) BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime); } DEG::deg_evaluate_on_refresh(deg_graph); + deg_graph->need_update_time = false; } /* Frame-change happened for root scene that graph belongs to. */ @@ -79,6 +80,7 @@ void DEG_evaluate_on_framechange(Main *bmain, Depsgraph *graph, float ctime) } /* Perform recalculation updates. */ DEG::deg_evaluate_on_refresh(deg_graph); + deg_graph->need_update_time = false; } bool DEG_needs_eval(Depsgraph *graph) diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 583191490d2..59f0c8c1933 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -229,6 +229,12 @@ void depsgraph_tag_to_component_opcode(const ID *id, case ID_RECALC_PARAMETERS: *component_type = NodeType::PARAMETERS; break; + case ID_RECALC_SOURCE: + *component_type = NodeType::PARAMETERS; + break; + case ID_RECALC_TIME: + BLI_assert(!"Should be handled outside of this function"); + break; case ID_RECALC_ALL: case ID_RECALC_PSYS_ALL: BLI_assert(!"Should not happen"); @@ -360,6 +366,12 @@ static void graph_id_tag_update_single_flag(Main *bmain, } return; } + else if (tag == ID_RECALC_TIME) { + if (graph != NULL) { + graph->need_update_time = true; + } + return; + } /* Get description of what is to be tagged. */ NodeType component_type; OperationCode operation_code; @@ -438,6 +450,24 @@ const char *update_source_as_string(eUpdateSource source) return "UNKNOWN"; } +int deg_recalc_flags_for_legacy_zero() +{ + return ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION | ID_RECALC_SOURCE); +} + +int deg_recalc_flags_effective(Depsgraph *graph, int flags) +{ + if (graph != NULL) { + if (!graph->is_active) { + return 0; + } + } + if (flags == 0) { + return deg_recalc_flags_for_legacy_zero(); + } + return flags; +} + /* Special tag function which tags all components which needs to be tagged * for update flag=0. * @@ -453,7 +483,7 @@ void deg_graph_node_tag_zero(Main *bmain, } ID *id = id_node->id_orig; /* TODO(sergey): Which recalc flags to set here? */ - id_node->id_cow->recalc |= ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION); + id_node->id_cow->recalc |= deg_recalc_flags_for_legacy_zero(); GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { if (comp_node->type == NodeType::ANIMATION) { continue; @@ -598,6 +628,16 @@ void graph_id_tag_update( if (id_node != NULL) { id_node->id_cow->recalc |= flag; } + /* When ID is tagged for update based on an user edits store the recalc flags in the original ID. + * This way IDs in the undo steps will have this flag preserved, making it possible to restore + * all needed tags when new dependency graph is created on redo. + * This is the only way to ensure modifications to animation data (such as keyframes i.e.) + * properly triggers animation update for the newely constructed dependency graph on redo (while + * usually newly created dependency graph skips animation update to avoid loss of unkeyed + * changes). */ + if (update_source == DEG_UPDATE_SOURCE_USER_EDIT) { + id->recalc |= deg_recalc_flags_effective(graph, flag); + } int current_flag = flag; while (current_flag != 0) { IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(¤t_flag)); @@ -664,6 +704,10 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag) return "AUDIO"; case ID_RECALC_PARAMETERS: return "PARAMETERS"; + case ID_RECALC_TIME: + return "TIME"; + case ID_RECALC_SOURCE: + return "SOURCE"; case ID_RECALC_ALL: return "ALL"; } @@ -768,9 +812,19 @@ void DEG_ids_check_recalc( DEG::deg_editors_scene_update(&update_ctx, updated); } +static void deg_graph_clear_id_recalc_flags(ID *id) +{ + id->recalc &= ~ID_RECALC_ALL; + bNodeTree *ntree = ntreeFromID(id); + /* Clear embedded node trees too. */ + if (ntree) { + ntree->id.recalc &= ~ID_RECALC_ALL; + } +} + static void deg_graph_clear_id_node_func(void *__restrict data_v, const int i, - const ParallelRangeTLS *__restrict /*tls*/) + const TaskParallelTLS *__restrict /*tls*/) { /* TODO: we clear original ID recalc flags here, but this may not work * correctly when there are multiple depsgraph with others still using @@ -779,12 +833,10 @@ static void deg_graph_clear_id_node_func(void *__restrict data_v, DEG::IDNode *id_node = deg_graph->id_nodes[i]; id_node->is_user_modified = false; - id_node->id_cow->recalc &= ~ID_RECALC_ALL; - /* Clear embedded node trees too. */ - bNodeTree *ntree_cow = ntreeFromID(id_node->id_cow); - if (ntree_cow) { - ntree_cow->id.recalc &= ~ID_RECALC_ALL; + deg_graph_clear_id_recalc_flags(id_node->id_cow); + if (deg_graph->is_active) { + deg_graph_clear_id_recalc_flags(id_node->id_orig); } } @@ -798,7 +850,7 @@ void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph) } /* Go over all ID nodes nodes, clearing tags. */ const int num_id_nodes = deg_graph->id_nodes.size(); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 1024; BLI_task_parallel_range(0, num_id_nodes, deg_graph, deg_graph_clear_id_node_func, &settings); diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 950deee2b07..b2415c9e89d 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -108,7 +108,7 @@ static bool check_operation_node_visible(OperationNode *op_node) static void calculate_pending_func(void *__restrict data_v, const int i, - const ParallelRangeTLS *__restrict /*tls*/) + const TaskParallelTLS *__restrict /*tls*/) { CalculatePendingData *data = (CalculatePendingData *)data_v; Depsgraph *graph = data->graph; @@ -148,7 +148,7 @@ static void calculate_pending_parents(Depsgraph *graph) const int num_operations = graph->operations.size(); CalculatePendingData data; data.graph = graph; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 1024; BLI_task_parallel_range(0, num_operations, &data, calculate_pending_func, &settings); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 83fcf4c6ea1..8079a3df879 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -39,6 +39,7 @@ extern "C" { #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "DRW_engine.h" } /* extern "C" */ @@ -53,6 +54,7 @@ extern "C" { #include "intern/node/deg_node_factory.h" #include "intern/node/deg_node_id.h" #include "intern/node/deg_node_operation.h" +#include "intern/node/deg_node_time.h" #include "intern/eval/deg_eval_copy_on_write.h" @@ -86,7 +88,7 @@ namespace { void flush_init_operation_node_func(void *__restrict data_v, const int i, - const ParallelRangeTLS *__restrict /*tls*/) + const TaskParallelTLS *__restrict /*tls*/) { Depsgraph *graph = (Depsgraph *)data_v; OperationNode *node = graph->operations[i]; @@ -95,7 +97,7 @@ void flush_init_operation_node_func(void *__restrict data_v, void flush_init_id_node_func(void *__restrict data_v, const int i, - const ParallelRangeTLS *__restrict /*tls*/) + const TaskParallelTLS *__restrict /*tls*/) { Depsgraph *graph = (Depsgraph *)data_v; IDNode *id_node = graph->id_nodes[i]; @@ -109,14 +111,14 @@ BLI_INLINE void flush_prepare(Depsgraph *graph) { { const int num_operations = graph->operations.size(); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 1024; BLI_task_parallel_range(0, num_operations, graph, flush_init_operation_node_func, &settings); } { const int num_id_nodes = graph->id_nodes.size(); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 1024; BLI_task_parallel_range(0, num_id_nodes, graph, flush_init_id_node_func, &settings); @@ -348,9 +350,16 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) BLI_assert(bmain != NULL); BLI_assert(graph != NULL); /* Nothing to update, early out. */ - if (BLI_gset_len(graph->entry_tags) == 0) { + if (BLI_gset_len(graph->entry_tags) == 0 && !graph->need_update_time) { return; } + if (graph->need_update_time) { + const Scene *scene_orig = graph->scene; + const float ctime = scene_orig->r.cfra + scene_orig->r.subframe; + DEG::TimeSourceNode *time_source = graph->find_time_source(); + graph->ctime = ctime; + time_source->tag_update(graph, DEG::DEG_UPDATE_SOURCE_TIME); + } /* Reset all flags, get ready for the flush. */ flush_prepare(graph); /* Starting from the tagged "entry" nodes, flush outwards. */ @@ -387,7 +396,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) static void graph_clear_operation_func(void *__restrict data_v, const int i, - const ParallelRangeTLS *__restrict /*tls*/) + const TaskParallelTLS *__restrict /*tls*/) { Depsgraph *graph = (Depsgraph *)data_v; OperationNode *node = graph->operations[i]; @@ -402,7 +411,7 @@ void deg_graph_clear_tags(Depsgraph *graph) /* Go over all operation nodes, clearing tags. */ { const int num_operations = graph->operations.size(); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 1024; BLI_task_parallel_range(0, num_operations, graph, graph_clear_operation_func, &settings); diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 8631a9f556b..664484d9a57 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -126,6 +126,7 @@ set(SRC engines/gpencil/gpencil_engine.h engines/gpencil/gpencil_render.c engines/gpencil/gpencil_shader_fx.c + engines/select/select_engine.c DRW_engine.h intern/DRW_render.h @@ -150,6 +151,7 @@ set(SRC engines/external/external_engine.h engines/workbench/workbench_engine.h engines/workbench/workbench_private.h + engines/select/select_engine.h ) set(LIB @@ -363,6 +365,9 @@ data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl SRC) data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC) +data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC) +data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC) + list(APPEND INC ) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index b4a7d3b84fc..a51c3a04239 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -26,6 +26,7 @@ #include "BLI_sys_types.h" /* for bool */ struct ARegion; +struct Base; struct DRWInstanceDataList; struct DRWPass; struct Depsgraph; @@ -128,7 +129,8 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, void DRW_draw_depth_loop(struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, - struct GPUViewport *viewport); + struct GPUViewport *viewport, + bool use_opengl_context); void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, struct ARegion *ar, struct View3D *v3d, @@ -136,19 +138,12 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, void DRW_draw_depth_object(struct ARegion *ar, struct GPUViewport *viewport, struct Object *object); -void DRW_draw_select_id_object(struct Scene *scene, - struct RegionView3D *rv3d, - struct Object *ob, - short select_mode, - bool draw_facedot, - uint initial_offset, - uint *r_vert_offset, - uint *r_edge_offset, - uint *r_face_offset); - -void DRW_framebuffer_select_id_setup(struct ARegion *ar, const bool clear); -void DRW_framebuffer_select_id_release(struct ARegion *ar); -void DRW_framebuffer_select_id_read(const struct rcti *rect, uint *r_buf); +void DRW_draw_select_id(struct Depsgraph *depsgraph, + struct ARegion *ar, + struct View3D *v3d, + struct Base **bases, + const uint bases_len, + short select_mode); /* grease pencil render */ bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph); @@ -186,4 +181,20 @@ void DRW_deferred_shader_remove(struct GPUMaterial *mat); struct DrawDataList *DRW_drawdatalist_from_id(struct ID *id); void DRW_drawdata_free(struct ID *id); +/* select_engine.c */ +void DRW_select_context_create(struct Depsgraph *depsgraph, + struct Base **bases, + const uint bases_len, + short select_mode); +bool DRW_select_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type); +uint DRW_select_context_offset_for_object_elem(const uint base_index, char elem_type); +uint DRW_select_context_elem_len(void); +void DRW_framebuffer_select_id_read(const struct rcti *rect, uint *r_buf); +void DRW_draw_select_id_object(struct Depsgraph *depsgraph, + struct ViewLayer *view_layer, + struct ARegion *ar, + struct View3D *v3d, + struct Object *ob, + short select_mode); + #endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 3977fd160fc..c82a112b343 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -266,7 +266,8 @@ static bool EEVEE_lightcache_validate(const LightCache *light_cache, (irr_size[2] == light_cache->grid_tx.tex_size[2]) && (grid_len == light_cache->grid_len)) { int mip_len = (int)(floorf(log2f(cube_res)) - MIN_CUBE_LOD_LEVEL); if ((cube_res == light_cache->cube_tx.tex_size[0]) && - (cube_len == light_cache->cube_tx.tex_size[2]) && (mip_len == light_cache->mips_len)) { + (cube_len == light_cache->cube_tx.tex_size[2]) && (cube_len == light_cache->cube_len) && + (mip_len == light_cache->mips_len)) { return true; } } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 18950f00823..d5f8d062593 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -375,7 +375,7 @@ GPUBatch *gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness) Object *ob = draw_ctx->obact; tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; + int totpoints = gpd->runtime.sbuffer_used; /* if cyclic needs more vertex */ int cyclic_add = (gpd->runtime.sbuffer_sflag & GP_STROKE_CYCLIC) ? 1 : 0; int totvertex = totpoints + cyclic_add + 2; @@ -477,7 +477,7 @@ GPUBatch *gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness) Object *ob = draw_ctx->obact; tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; + int totpoints = gpd->runtime.sbuffer_used; static GPUVertFormat format = {0}; static uint pos_id, color_id, thickness_id, uvdata_id, prev_pos_id; @@ -621,7 +621,7 @@ GPUBatch *gpencil_get_buffer_fill_geom(bGPdata *gpd) } const tGPspoint *points = gpd->runtime.sbuffer; - int totpoints = gpd->runtime.sbuffer_size; + int totpoints = gpd->runtime.sbuffer_used; if (totpoints < 3) { return NULL; } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 181d2efbabb..9b755217946 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -1493,7 +1493,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) */ - if (gpd->runtime.sbuffer_size > 0) { + if (gpd->runtime.sbuffer_used > 0) { if ((gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* It should also be noted that sbuffer contains temporary point types * i.e. tGPspoints NOT bGPDspoints @@ -1506,7 +1506,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, stl->storage->alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH; /* if only one point, don't need to draw buffer because the user has no time to see it */ - if (gpd->runtime.sbuffer_size > 1) { + if (gpd->runtime.sbuffer_used > 1) { if ((gp_style) && (gp_style->mode == GP_STYLE_MODE_LINE)) { stl->g_data->shgrps_drawing_stroke = gpencil_shgroup_stroke_create( vedata, @@ -1562,7 +1562,7 @@ void gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, DRW_shgroup_call( stl->g_data->shgrps_drawing_stroke, stl->g_data->batch_buffer_stroke, NULL); - if ((gpd->runtime.sbuffer_size >= 3) && + if ((gpd->runtime.sbuffer_used >= 3) && (gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) && ((gpd->runtime.sbuffer_sflag & GP_STROKE_NOFILL) == 0) && ((brush->gpencil_settings->flag & GP_BRUSH_DISSABLE_LASSO) == 0) && diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 5d7ec490fb6..16162645f3d 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -430,7 +430,7 @@ void GPENCIL_cache_init(void *vedata) /* need the original to avoid cow overhead while drawing */ bGPdata *gpd_orig = (bGPdata *)DEG_get_original_id(&obact_gpd->id); if (((gpd_orig->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) && - (gpd_orig->runtime.sbuffer_size > 0) && + (gpd_orig->runtime.sbuffer_used > 0) && ((gpd_orig->flag & GP_DATA_STROKE_POLYGON) == 0) && !DRW_state_is_depth() && (stl->storage->background_ready == true)) { stl->g_data->session_flag |= GP_DRW_PAINT_PAINTING; diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index 306444303e2..0f4043ce278 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -463,12 +463,11 @@ static void gpencil_fx_shadow(ShaderFxData *fx, DRW_shgroup_uniform_vec3(fx_shgrp, "loc", fxd->runtime.loc, 1); } - const int nowave = -1; if (fxd->flag & FX_SHADOW_USE_WAVE) { DRW_shgroup_uniform_int(fx_shgrp, "orientation", &fxd->orientation, 1); } else { - DRW_shgroup_uniform_int(fx_shgrp, "orientation", &nowave, 1); + DRW_shgroup_uniform_int_copy(fx_shgrp, "orientation", -1); } DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1); DRW_shgroup_uniform_float(fx_shgrp, "period", &fxd->period, 1); diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl index b226d4f93bc..01d4fe40195 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl @@ -42,7 +42,11 @@ void main() vec2 tc = uv - center; float dist = length(tc); - float pxradius = (ProjectionMatrix[3][3] == 0.0) ? (radius / (loc.z * defaultpixsize)) : + float locpixsize = abs((loc.z * defaultpixsize)); + if (locpixsize == 0) { + locpixsize = 1; + } + float pxradius = (ProjectionMatrix[3][3] == 0.0) ? (radius / locpixsize) : (radius / defaultpixsize); pxradius = max(pxradius, 1); diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c new file mode 100644 index 00000000000..260fe8793e6 --- /dev/null +++ b/source/blender/draw/engines/select/select_engine.c @@ -0,0 +1,641 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + * + * Engine for drawing a selection map where the pixels indicate the selection indices. + */ + +#include "BLI_rect.h" + +#include "BKE_editmesh.h" + +#include "DNA_mesh_types.h" +#include "DNA_screen_types.h" + +#include "ED_view3d.h" + +#include "GPU_shader.h" +#include "GPU_select.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "UI_resources.h" + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "draw_cache_impl.h" + +#include "select_engine.h" +/* Shaders */ + +#define SELECT_ENGINE "SELECT_ENGINE" + +/* *********** LISTS *********** */ + +/* GPUViewport.storage + * Is freed everytime the viewport engine changes */ +typedef struct SELECTID_StorageList { + struct SELECTID_PrivateData *g_data; +} SELECTID_StorageList; + +typedef struct SELECTID_PassList { + struct DRWPass *select_id_face_pass; + struct DRWPass *select_id_edge_pass; + struct DRWPass *select_id_vert_pass; +} SELECTID_PassList; + +typedef struct SELECTID_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + SELECTID_PassList *psl; + SELECTID_StorageList *stl; +} SELECTID_Data; + +typedef struct SELECTID_Shaders { + /* Depth Pre Pass */ + struct GPUShader *select_id_flat; + struct GPUShader *select_id_uniform; +} SELECTID_Shaders; + +/* *********** STATIC *********** */ + +static struct { + SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN]; + + struct GPUFrameBuffer *framebuffer_select_id; + struct GPUTexture *texture_u32; + + struct { + struct BaseOffset *base_array_index_offsets; + uint bases_len; + uint last_base_drawn; + /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */ + uint last_index_drawn; + + struct Depsgraph *depsgraph; + short select_mode; + } context; +} e_data = {{{NULL}}}; /* Engine data */ + +typedef struct SELECTID_PrivateData { + DRWShadingGroup *shgrp_face_unif; + DRWShadingGroup *shgrp_face_flat; + DRWShadingGroup *shgrp_edge; + DRWShadingGroup *shgrp_vert; + + DRWView *view_faces; + DRWView *view_edges; + DRWView *view_verts; +} SELECTID_PrivateData; /* Transient data */ + +struct BaseOffset { + /* For convenience only. */ + union { + uint offset; + uint face_start; + }; + union { + uint face; + uint edge_start; + }; + union { + uint edge; + uint vert_start; + }; + uint vert; +}; + +/* Shaders */ +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_selection_id_3D_vert_glsl[]; +extern char datatoc_selection_id_frag_glsl[]; + +/* -------------------------------------------------------------------- */ +/** \name Selection Utilities + * \{ */ + +static void draw_select_framebuffer_select_id_setup(void) +{ + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + int size[2]; + size[0] = GPU_texture_width(dtxl->depth); + size[1] = GPU_texture_height(dtxl->depth); + + if (e_data.framebuffer_select_id == NULL) { + e_data.framebuffer_select_id = GPU_framebuffer_create(); + } + + if ((e_data.texture_u32 != NULL) && ((GPU_texture_width(e_data.texture_u32) != size[0]) || + (GPU_texture_height(e_data.texture_u32) != size[1]))) { + + GPU_texture_free(e_data.texture_u32); + e_data.texture_u32 = NULL; + } + + if (e_data.texture_u32 == NULL) { + e_data.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL); + + GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0); + GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0); + GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL); + } +} + +static void draw_select_id_object(void *vedata, + Object *ob, + short select_mode, + bool draw_facedot, + uint initial_offset, + uint *r_vert_offset, + uint *r_edge_offset, + uint *r_face_offset) +{ + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; + + BLI_assert(initial_offset > 0); + + switch (ob->type) { + case OB_MESH: + if (ob->mode & OB_MODE_EDIT) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; + + DRW_mesh_batch_cache_validate(me); + + BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); + + struct GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; + geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + if (select_mode & SCE_SELECT_EDGE) { + geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); + } + if (select_mode & SCE_SELECT_VERTEX) { + geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + } + if (use_faceselect && draw_facedot) { + geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); + } + + DRWShadingGroup *face_shgrp; + if (use_faceselect) { + face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat); + DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset); + + if (draw_facedot) { + DRW_shgroup_call(face_shgrp, geom_facedots, ob); + } + *r_face_offset = initial_offset + em->bm->totface; + } + else { + face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif); + DRW_shgroup_uniform_int_copy(face_shgrp, "id", 0); + + *r_face_offset = initial_offset; + } + DRW_shgroup_call(face_shgrp, geom_faces, ob); + + /* Unlike faces, only draw edges if edge select mode. */ + if (select_mode & SCE_SELECT_EDGE) { + DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge); + DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset); + DRW_shgroup_call(edge_shgrp, geom_edges, ob); + *r_edge_offset = *r_face_offset + em->bm->totedge; + } + else { + /* Note that `r_vert_offset` is calculated from `r_edge_offset`. + * Otherwise the first vertex is never selected, see: T53512. */ + *r_edge_offset = *r_face_offset; + } + + /* Unlike faces, only verts if vert select mode. */ + if (select_mode & SCE_SELECT_VERTEX) { + DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert); + DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *(int *)r_edge_offset); + DRW_shgroup_call(vert_shgrp, geom_verts, ob); + *r_vert_offset = *r_edge_offset + em->bm->totvert; + } + else { + *r_vert_offset = *r_edge_offset; + } + } + else { + Mesh *me_orig = DEG_get_original_object(ob)->data; + Mesh *me_eval = ob->data; + + struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval); + if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) && + /* Currently vertex select supports weight paint and vertex paint. */ + ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { + + struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval); + + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif); + DRW_shgroup_uniform_int_copy(face_shgrp, "id", 0); + DRW_shgroup_call(face_shgrp, geom_faces, ob); + + DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert); + DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", 1); + DRW_shgroup_call(vert_shgrp, geom_verts, ob); + + *r_face_offset = *r_edge_offset = initial_offset; + *r_vert_offset = me_eval->totvert + 1; + } + else { + DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat); + DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset); + DRW_shgroup_call(face_shgrp, geom_faces, ob); + + *r_face_offset = initial_offset + me_eval->totpoly; + *r_edge_offset = *r_vert_offset = *r_face_offset; + } + } + break; + case OB_CURVE: + case OB_SURF: + break; + } +} + +static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt) +{ + if (select_mode & SCE_SELECT_FACE) { + if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) { + return true; + } + if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) { + return true; + } + if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) { + /* Since we can't deduce face selection when edges aren't visible - show dots. */ + return true; + } + } + return false; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Functions + * \{ */ + +static void select_engine_init(void *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + eGPUShaderConfig sh_cfg = draw_ctx->sh_cfg; + + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; + SELECTID_Shaders *sh_data = &e_data.sh_data[sh_cfg]; + + /* Prepass */ + if (!sh_data->select_id_flat) { + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; + sh_data->select_id_flat = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_selection_id_3D_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, NULL}, + }); + } + if (!sh_data->select_id_uniform) { + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg]; + sh_data->select_id_uniform = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, + datatoc_common_view_lib_glsl, + datatoc_selection_id_3D_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define UNIFORM_ID\n", NULL}, + }); + } + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + { + /* Create view with depth offset */ + stl->g_data->view_faces = (DRWView *)DRW_view_default_get(); + stl->g_data->view_edges = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f); + stl->g_data->view_verts = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.1f); + } +} + +static void select_cache_init(void *vedata) +{ + SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl; + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; + + const DRWContextState *draw_ctx = DRW_context_state_get(); + SELECTID_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + { + psl->select_id_face_pass = DRW_pass_create("Face Pass", DRW_STATE_DEFAULT); + stl->g_data->shgrp_face_unif = DRW_shgroup_create(sh_data->select_id_uniform, + psl->select_id_face_pass); + + stl->g_data->shgrp_face_flat = DRW_shgroup_create(sh_data->select_id_flat, + psl->select_id_face_pass); + + psl->select_id_edge_pass = DRW_pass_create( + "Edge Pass", DRW_STATE_DEFAULT | DRW_STATE_FIRST_VERTEX_CONVENTION); + + stl->g_data->shgrp_edge = DRW_shgroup_create(sh_data->select_id_flat, + psl->select_id_edge_pass); + + psl->select_id_vert_pass = DRW_pass_create("Vert Pass", DRW_STATE_DEFAULT); + stl->g_data->shgrp_vert = DRW_shgroup_create(sh_data->select_id_flat, + psl->select_id_vert_pass); + + DRW_shgroup_uniform_float_copy(stl->g_data->shgrp_vert, "sizeVertex", G_draw.block.sizeVertex); + + if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) { + DRW_shgroup_state_enable(stl->g_data->shgrp_face_unif, DRW_STATE_CLIP_PLANES); + DRW_shgroup_state_enable(stl->g_data->shgrp_face_flat, DRW_STATE_CLIP_PLANES); + DRW_shgroup_state_enable(stl->g_data->shgrp_edge, DRW_STATE_CLIP_PLANES); + DRW_shgroup_state_enable(stl->g_data->shgrp_vert, DRW_STATE_CLIP_PLANES); + } + } + + e_data.context.last_base_drawn = 0; + e_data.context.last_index_drawn = 1; +} + +static void select_cache_populate(void *vedata, Object *ob) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + short select_mode = e_data.context.select_mode; + + if (select_mode == -1) { + ToolSettings *ts = draw_ctx->scene->toolsettings; + select_mode = ts->selectmode; + } + + bool draw_facedot = check_ob_drawface_dot(select_mode, draw_ctx->v3d, ob->dt); + + struct BaseOffset *base_ofs = + &e_data.context.base_array_index_offsets[e_data.context.last_base_drawn++]; + + uint offset = e_data.context.last_index_drawn; + + draw_select_id_object(vedata, + ob, + select_mode, + draw_facedot, + offset, + &base_ofs->vert, + &base_ofs->edge, + &base_ofs->face); + + base_ofs->offset = offset; + e_data.context.last_index_drawn = base_ofs->vert; +} + +static void select_draw_scene(void *vedata) +{ + SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl; + SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl; + + /* Setup framebuffer */ + draw_select_framebuffer_select_id_setup(); + GPU_framebuffer_bind(e_data.framebuffer_select_id); + + /* dithering and AA break color coding, so disable */ + glDisable(GL_DITHER); + + GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, (const float[4]){0.0f}, 1.0f); + + DRW_view_set_active(stl->g_data->view_faces); + DRW_draw_pass(psl->select_id_face_pass); + + DRW_view_set_active(stl->g_data->view_edges); + DRW_draw_pass(psl->select_id_edge_pass); + + DRW_view_set_active(stl->g_data->view_verts); + DRW_draw_pass(psl->select_id_vert_pass); +} + +static void select_engine_free(void) +{ + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + SELECTID_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + DRW_SHADER_FREE_SAFE(sh_data->select_id_flat); + DRW_SHADER_FREE_SAFE(sh_data->select_id_uniform); + } + + DRW_TEXTURE_FREE_SAFE(e_data.texture_u32); + GPU_FRAMEBUFFER_FREE_SAFE(e_data.framebuffer_select_id); + MEM_SAFE_FREE(e_data.context.base_array_index_offsets); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Exposed `DRW_engine.h` functions + * \{ */ + +bool DRW_select_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type) +{ + char elem_type = 0; + uint elem_id; + uint base_index = 0; + + for (; base_index < e_data.context.bases_len; base_index++) { + struct BaseOffset *base_ofs = &e_data.context.base_array_index_offsets[base_index]; + + if (base_ofs->face > sel_id) { + elem_id = sel_id - base_ofs->face_start; + elem_type = SCE_SELECT_FACE; + break; + } + if (base_ofs->edge > sel_id) { + elem_id = sel_id - base_ofs->edge_start; + elem_type = SCE_SELECT_EDGE; + break; + } + if (base_ofs->vert > sel_id) { + elem_id = sel_id - base_ofs->vert_start; + elem_type = SCE_SELECT_VERTEX; + break; + } + } + + if (base_index == e_data.context.bases_len) { + return false; + } + + *r_elem = elem_id; + + if (r_base_index) { + *r_base_index = base_index; + } + + if (r_elem_type) { + *r_elem_type = elem_type; + } + + return true; +} + +uint DRW_select_context_offset_for_object_elem(const uint base_index, char elem_type) +{ + struct BaseOffset *base_ofs = &e_data.context.base_array_index_offsets[base_index]; + + if (elem_type == SCE_SELECT_VERTEX) { + return base_ofs->vert_start - 1; + } + if (elem_type == SCE_SELECT_EDGE) { + return base_ofs->edge_start - 1; + } + if (elem_type == SCE_SELECT_FACE) { + return base_ofs->face_start - 1; + } + BLI_assert(0); + return 0; +} + +uint DRW_select_context_elem_len(void) +{ + return e_data.context.last_index_drawn; +} + +/* Read a block of pixels from the select frame buffer. */ +void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf) +{ + /* clamp rect by texture */ + rcti r = { + .xmin = 0, + .xmax = GPU_texture_width(e_data.texture_u32), + .ymin = 0, + .ymax = GPU_texture_height(e_data.texture_u32), + }; + + rcti rect_clamp = *rect; + if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) { + DRW_opengl_context_enable(); + GPU_framebuffer_bind(e_data.framebuffer_select_id); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(rect_clamp.xmin, + rect_clamp.ymin, + BLI_rcti_size_x(&rect_clamp), + BLI_rcti_size_y(&rect_clamp), + GL_RED_INTEGER, + GL_UNSIGNED_INT, + r_buf); + + GPU_framebuffer_restore(); + DRW_opengl_context_disable(); + + if (!BLI_rcti_compare(rect, &rect_clamp)) { + GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); + } + } + else { + size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf); + + memset(r_buf, 0, buf_size); + } +} + +void DRW_select_context_create(Depsgraph *depsgraph, + Base **UNUSED(bases), + const uint bases_len, + short select_mode) +{ + e_data.context.depsgraph = depsgraph; + e_data.context.select_mode = select_mode; + e_data.context.bases_len = bases_len; + + MEM_SAFE_FREE(e_data.context.base_array_index_offsets); + e_data.context.base_array_index_offsets = MEM_mallocN( + sizeof(*e_data.context.base_array_index_offsets) * bases_len, __func__); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Legacy + * \{ */ + +void DRW_draw_select_id_object(Depsgraph *depsgraph, + ViewLayer *view_layer, + ARegion *ar, + View3D *v3d, + Object *ob, + short select_mode) +{ + Base *base = BKE_view_layer_base_find(view_layer, ob); + DRW_draw_select_id(depsgraph, ar, v3d, &base, 1, select_mode); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Type + * \{ */ + +static const DrawEngineDataSize select_data_size = DRW_VIEWPORT_DATA_SIZE(SELECTID_Data); + +DrawEngineType draw_engine_select_type = { + NULL, + NULL, + N_("Select ID"), + &select_data_size, + &select_engine_init, + &select_engine_free, + &select_cache_init, + &select_cache_populate, + NULL, + NULL, + &select_draw_scene, + NULL, + NULL, + NULL, +}; + +/* Note: currently unused, we may want to register so we can see this when debugging the view. */ + +RenderEngineType DRW_engine_viewport_select_type = { + NULL, + NULL, + SELECT_ENGINE, + N_("Select ID"), + RE_INTERNAL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &draw_engine_select_type, + {NULL, NULL, NULL}, +}; + +/** \} */ + +#undef SELECT_ENGINE diff --git a/source/blender/draw/engines/select/select_engine.h b/source/blender/draw/engines/select/select_engine.h new file mode 100644 index 00000000000..5b900ccaf27 --- /dev/null +++ b/source/blender/draw/engines/select/select_engine.h @@ -0,0 +1,29 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#ifndef __SELECT_ENGINE_H__ +#define __SELECT_ENGINE_H__ + +extern DrawEngineType draw_engine_select_type; +extern RenderEngineType DRW_engine_viewport_select_type; + +#endif /* __SELECT_ID_ENGINE_H__ */ diff --git a/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl b/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl new file mode 100644 index 00000000000..9b0107cffdb --- /dev/null +++ b/source/blender/draw/engines/select/shaders/selection_id_3D_vert.glsl @@ -0,0 +1,26 @@ + +uniform float sizeVertex; + +in vec3 pos; + +#ifndef UNIFORM_ID +uniform int offset; +in uint color; + +flat out uint id; +#endif + +void main() +{ +#ifndef UNIFORM_ID + id = floatBitsToUint(intBitsToFloat(offset)) + color; +#endif + + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); + gl_PointSize = sizeVertex; + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(world_pos); +#endif +} diff --git a/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl index 1f22b9cb0b4..ea86ddc7301 100644 --- a/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl +++ b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl @@ -1,6 +1,7 @@ #ifdef UNIFORM_ID -uniform uint id; +uniform int id; +# define id floatBitsToUint(intBitsToFloat(id)) #else flat in uint id; #endif diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 306031809d1..2376787a273 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -4830,7 +4830,7 @@ static void uvedit_fill_buffer_data(MeshRenderData *rdata, /* Tag hidden faces */ BM_elem_flag_set(efa, BM_ELEM_TAG, uvedit_face_visible_nolocal_ex(rdata->toolsettings, efa)); - if (vbo_area && BM_elem_flag_test(efa, BM_ELEM_TAG)) { + if (vbo_area) { edit_uv_preprocess_stretch_area( efa, cd_loop_uv_offset, fidx++, &totarea, &totuvarea, faces_areas); } diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 1abe68b622d..f8640f17419 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -89,6 +89,7 @@ #include "engines/workbench/workbench_engine.h" #include "engines/external/external_engine.h" #include "engines/gpencil/gpencil_engine.h" +#include "engines/select/select_engine.h" #include "GPU_context.h" @@ -2136,16 +2137,13 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, static struct DRWSelectBuffer { struct GPUFrameBuffer *framebuffer_depth_only; - struct GPUFrameBuffer *framebuffer_select_id; struct GPUTexture *texture_depth; - struct GPUTexture *texture_u32; } g_select_buffer = {NULL}; static void draw_select_framebuffer_depth_only_setup(const int size[2]) { if (g_select_buffer.framebuffer_depth_only == NULL) { g_select_buffer.framebuffer_depth_only = GPU_framebuffer_create(); - g_select_buffer.framebuffer_select_id = GPU_framebuffer_create(); } if ((g_select_buffer.texture_depth != NULL) && @@ -2162,32 +2160,7 @@ static void draw_select_framebuffer_depth_only_setup(const int size[2]) GPU_framebuffer_texture_attach( g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0); - GPU_framebuffer_texture_attach( - g_select_buffer.framebuffer_select_id, g_select_buffer.texture_depth, 0, 0); - GPU_framebuffer_check_valid(g_select_buffer.framebuffer_depth_only, NULL); - GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL); - } -} - -static void draw_select_framebuffer_select_id_setup(const int size[2]) -{ - draw_select_framebuffer_depth_only_setup(size); - - if ((g_select_buffer.texture_u32 != NULL) && - ((GPU_texture_width(g_select_buffer.texture_u32) != size[0]) || - (GPU_texture_height(g_select_buffer.texture_u32) != size[1]))) { - GPU_texture_free(g_select_buffer.texture_u32); - g_select_buffer.texture_u32 = NULL; - } - - if (g_select_buffer.texture_u32 == NULL) { - g_select_buffer.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL); - - GPU_framebuffer_texture_attach( - g_select_buffer.framebuffer_select_id, g_select_buffer.texture_u32, 0, 0); - - GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL); } } @@ -2479,14 +2452,17 @@ static void drw_draw_depth_loop_imp(void) void DRW_draw_depth_loop(struct Depsgraph *depsgraph, ARegion *ar, View3D *v3d, - GPUViewport *viewport) + GPUViewport *viewport, + bool use_opengl_context) { Scene *scene = DEG_get_evaluated_scene(depsgraph); RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); RegionView3D *rv3d = ar->regiondata; - DRW_opengl_context_enable(); + if (use_opengl_context) { + DRW_opengl_context_enable(); + } /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -2525,7 +2501,9 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, #endif /* Changin context */ - DRW_opengl_context_disable(); + if (use_opengl_context) { + DRW_opengl_context_disable(); + } } /** @@ -2575,6 +2553,78 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, DRW_opengl_context_disable(); } +void DRW_draw_select_id(Depsgraph *depsgraph, + ARegion *ar, + View3D *v3d, + Base **bases, + const uint bases_len, + short select_mode) +{ + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + + DRW_select_context_create(depsgraph, bases, bases_len, select_mode); + + DRW_opengl_context_enable(); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + DST.buffer_finish_called = true; + + /* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */ + DST.draw_ctx = (DRWContextState){ + .ar = ar, + .rv3d = ar->regiondata, + .v3d = v3d, + .scene = scene, + .view_layer = view_layer, + .obact = OBACT(view_layer), + .depsgraph = depsgraph, + }; + + use_drw_engine(&draw_engine_select_type); + drw_context_state_init(); + + /* Setup viewport */ + DST.viewport = WM_draw_region_get_viewport(ar, 0); + drw_viewport_var_init(); + + /* Update ubos */ + DRW_globals_update(); + + /* Init engines */ + drw_engines_init(); + + { + drw_engines_cache_init(); + + /* Keep `base_index` in sync with `e_data.context.last_base_drawn`. + * So don't skip objects. */ + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obj_eval = DEG_get_evaluated_object(depsgraph, bases[base_index]->object); + drw_engines_cache_populate(obj_eval); + } + + drw_engines_cache_finish(); + } + + /* Start Drawing */ + DRW_state_reset(); + drw_engines_draw_scene(); + DRW_state_reset(); + + drw_engines_disable(); + +#ifdef DEBUG + /* Avoid accidental reuse. */ + drw_state_ensure_not_reused(&DST); +#endif + + /* Changin context */ + GPU_framebuffer_restore(); + DRW_opengl_context_disable(); +} + /** See #DRW_shgroup_world_clip_planes_from_rv3d. */ static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4]) { @@ -2646,294 +2696,6 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) DRW_opengl_context_disable(); } -static void draw_mesh_verts(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) -{ - GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); - - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); -} - -static void draw_mesh_edges(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) -{ - GPU_line_width(1.0f); - glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - - glProvokingVertex(GL_LAST_VERTEX_CONVENTION); -} - -/* two options, facecolors or black */ -static void draw_mesh_face(GPUBatch *batch, - uint offset, - const bool use_select, - const float world_clip_planes[6][4]) -{ - if (use_select) { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } - else { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "id", 0); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } -} - -static void draw_mesh_face_dot(GPUBatch *batch, uint offset, const float world_clip_planes[6][4]) -{ - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); -} - -void DRW_draw_select_id_object(Scene *scene, - RegionView3D *rv3d, - Object *ob, - short select_mode, - bool draw_facedot, - uint initial_offset, - uint *r_vert_offset, - uint *r_edge_offset, - uint *r_face_offset) -{ - ToolSettings *ts = scene->toolsettings; - if (select_mode == -1) { - select_mode = ts->selectmode; - } - - /* Init the scene of the draw context. When using face dot selection on - * when the subsurf modifier is active on the cage, the scene needs to be - * valid. It is read from the context in the - * `DRW_mesh_batch_cache_create_requested` and used in the `isDisabled` - * method of the SubSurfModifier. */ - DRWContextState *draw_ctx = &DST.draw_ctx; - draw_ctx->scene = scene; - - GPU_matrix_mul(ob->obmat); - - const float(*world_clip_planes)[4] = NULL; - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_local(rv3d, ob->obmat); - world_clip_planes = rv3d->clip_local; - } - - BLI_assert(initial_offset > 0); - - switch (ob->type) { - case OB_MESH: - if (ob->mode & OB_MODE_EDIT) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; - const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; - - DRW_mesh_batch_cache_validate(me); - - BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); - - GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; - geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - if (select_mode & SCE_SELECT_EDGE) { - geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); - } - if (select_mode & SCE_SELECT_VERTEX) { - geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - } - if (use_faceselect && draw_facedot) { - geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); - } - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - - draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes); - - if (use_faceselect && draw_facedot) { - draw_mesh_face_dot(geom_facedots, initial_offset, world_clip_planes); - } - - if (select_mode & SCE_SELECT_FACE) { - *r_face_offset = initial_offset + em->bm->totface; - } - else { - *r_face_offset = initial_offset; - } - - ED_view3d_polygon_offset(rv3d, 1.0); - - /* Unlike faces, only draw edges if edge select mode. */ - if (select_mode & SCE_SELECT_EDGE) { - draw_mesh_edges(geom_edges, *r_face_offset, world_clip_planes); - *r_edge_offset = *r_face_offset + em->bm->totedge; - } - else { - /* Note that `r_vert_offset` is calculated from `r_edge_offset`. - * Otherwise the first vertex is never selected, see: T53512. */ - *r_edge_offset = *r_face_offset; - } - - ED_view3d_polygon_offset(rv3d, 1.1); - - /* Unlike faces, only verts if vert select mode. */ - if (select_mode & SCE_SELECT_VERTEX) { - draw_mesh_verts(geom_verts, *r_edge_offset, world_clip_planes); - *r_vert_offset = *r_edge_offset + em->bm->totvert; - } - else { - *r_vert_offset = *r_edge_offset; - } - - ED_view3d_polygon_offset(rv3d, 0.0); - } - else { - Mesh *me_orig = DEG_get_original_object(ob)->data; - Mesh *me_eval = ob->data; - - DRW_mesh_batch_cache_validate(me_eval); - GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval); - if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) && - /* Currently vertex select supports weight paint and vertex paint. */ - ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { - - GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval); - DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true); - - /* Only draw faces to mask out verts, we don't want their selection ID's. */ - draw_mesh_face(geom_faces, 0, false, world_clip_planes); - draw_mesh_verts(geom_verts, 1, world_clip_planes); - - *r_face_offset = *r_edge_offset = initial_offset; - *r_vert_offset = me_eval->totvert + 1; - } - else { - const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); - DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide); - - draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes); - - *r_face_offset = initial_offset + me_eval->totpoly; - *r_edge_offset = *r_vert_offset = *r_face_offset; - } - } - break; - case OB_CURVE: - case OB_SURF: - break; - } - - GPU_matrix_set(rv3d->viewmat); -} - -/* Set an opengl context to be used with shaders that draw on U32 colors. */ -void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear) -{ - RegionView3D *rv3d = ar->regiondata; - - DRW_opengl_context_enable(); - - /* Setup framebuffer */ - int viewport_size[2] = {ar->winx, ar->winy}; - draw_select_framebuffer_select_id_setup(viewport_size); - GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id); - - /* dithering and AA break color coding, so disable */ - glDisable(GL_DITHER); - - GPU_depth_test(true); - GPU_program_point_size(false); - - if (clear) { - GPU_framebuffer_clear_color_depth( - g_select_buffer.framebuffer_select_id, (const float[4]){0.0f}, 1.0f); - } - - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); - } -} - -/* Ends the context for selection and restoring the previous one. */ -void DRW_framebuffer_select_id_release(ARegion *ar) -{ - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_disable(); - } - - GPU_depth_test(false); - - GPU_framebuffer_restore(); - - DRW_opengl_context_disable(); -} - -/* Read a block of pixels from the select frame buffer. */ -void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf) -{ - /* clamp rect by texture */ - rcti r = { - .xmin = 0, - .xmax = GPU_texture_width(g_select_buffer.texture_u32), - .ymin = 0, - .ymax = GPU_texture_height(g_select_buffer.texture_u32), - }; - - rcti rect_clamp = *rect; - if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) { - DRW_opengl_context_enable(); - GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(rect_clamp.xmin, - rect_clamp.ymin, - BLI_rcti_size_x(&rect_clamp), - BLI_rcti_size_y(&rect_clamp), - GL_RED_INTEGER, - GL_UNSIGNED_INT, - r_buf); - - GPU_framebuffer_restore(); - DRW_opengl_context_disable(); - - if (!BLI_rcti_compare(rect, &rect_clamp)) { - GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf); - } - } - else { - size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf); - - memset(r_buf, 0, buf_size); - } -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -3089,6 +2851,7 @@ void DRW_engines_register(void) DRW_engine_register(&draw_engine_pose_type); DRW_engine_register(&draw_engine_sculpt_type); DRW_engine_register(&draw_engine_gpencil_type); + DRW_engine_register(&draw_engine_select_type); /* setup callbacks */ { @@ -3123,9 +2886,7 @@ void DRW_engines_free(void) DRW_opengl_context_enable(); - DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_u32); DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth); - GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_select_id); GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only); DRW_hair_free(); diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 9fc11e4f36f..8d4083f1723 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -1242,7 +1242,7 @@ static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data, unit_m4(win_m4_scale); unit_m4(win_m4_translate); unit_m4(scale_m4); - axis_angle_to_mat4_single(rot_m4, 'Z', bgpic->rotation); + axis_angle_to_mat4_single(rot_m4, 'Z', -bgpic->rotation); unit_m4(translate_m4); const float *size = DRW_viewport_size_get(); @@ -1256,7 +1256,7 @@ static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data, if (!DRW_state_is_image_render()) { rctf render_border; - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &render_border, true); + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &render_border, false); camera_width = render_border.xmax - render_border.xmin; camera_height = render_border.ymax - render_border.ymin; camera_aspect = camera_width / camera_height; @@ -1311,9 +1311,9 @@ static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data, scale_m4[0][0] = scale_x; scale_m4[1][1] = scale_y; - // translate - translate_m4[3][0] = bgpic->offset[0]; - translate_m4[3][1] = bgpic->offset[1]; + /* Translate, using coordinates that aren't squashed by the aspect. */ + translate_m4[3][0] = bgpic->offset[0] * 2.0f * max_ff(1.0f, 1.0f / camera_aspect); + translate_m4[3][1] = bgpic->offset[1] * 2.0f * max_ff(1.0f, camera_aspect); mul_m4_series(bg_data->transform_mat, win_m4_translate, diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index b93d52a1b2d..7e913014a87 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1705,7 +1705,7 @@ static void ANIM_OT_channels_ungroup(wmOperatorType *ot) /* ******************** Delete Channel Operator *********************** */ -static void update_dependencies_on_delete(bAnimListElem *ale) +static void tag_update_animation_element(bAnimListElem *ale) { ID *id = ale->id; AnimData *adt = BKE_animdata_from_id(id); @@ -1801,7 +1801,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) /* try to free F-Curve */ ANIM_fcurve_delete_from_animdata(&ac, adt, fcu); - update_dependencies_on_delete(ale); + tag_update_animation_element(ale); break; } case ANIMTYPE_NLACURVE: { @@ -1823,7 +1823,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op)) /* unlink and free the F-Curve */ BLI_remlink(&strip->fcurves, fcu); free_fcurve(fcu); - update_dependencies_on_delete(ale); + tag_update_animation_element(ale); break; } case ANIMTYPE_GPLAYER: { @@ -1967,6 +1967,7 @@ static void setflag_anim_channels(bAnimContext *ac, /* set the setting in the appropriate way */ ANIM_channel_setting_set(ac, ale, setting, mode); + tag_update_animation_element(ale); /* if flush status... */ if (flush) { diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 61bf7f95340..7ab50afe3a1 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -422,23 +422,16 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo } 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. + if (!ELEM(prev_bezt->ipo, BEZT_IPO_BEZ, BEZT_IPO_BACK, BEZT_IPO_ELASTIC)) { + /* The points on the curve will lie inside the start and end points. + * Calculate min/max using both previous 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) { + else { const int resol = fcu->driver ? 32 : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), @@ -448,30 +441,12 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo 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); - + float step_size = (bezt->vec[1][0] - prev_bezt->vec[1][0]) / resol; 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]); + float eval_time = prev_bezt->vec[1][0] + step_size * j; + float eval_value = evaluate_fcurve_only_curve(fcu, eval_time); + max_coord = max_ff(max_coord, eval_value); + min_coord = min_ff(min_coord, eval_value); } } } diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 6811e32cc2a..9debea7bf88 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -89,8 +89,6 @@ struct StrokeElem { }; struct CurveDrawData { - Depsgraph *depsgraph; - short init_event_type; short curve_type; @@ -578,8 +576,6 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke) struct CurveDrawData *cdd = MEM_callocN(sizeof(*cdd), __func__); - cdd->depsgraph = CTX_data_depsgraph(C); - if (is_invoke) { ED_view3d_viewcontext_init(C, &cdd->vc); if (ELEM(NULL, cdd->vc.ar, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) { diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index e8f97290173..dce6ed29c05 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -924,7 +924,7 @@ static void annotation_draw_data_layers( * i.e. tGPspoints NOT bGPDspoints */ annotation_draw_stroke_buffer(gpd->runtime.sbuffer, - gpd->runtime.sbuffer_size, + gpd->runtime.sbuffer_used, lthick, dflag, gpd->runtime.sbuffer_sflag, diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 5962d95c5af..5793b407bdc 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -281,7 +281,7 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2 int dy = (int)fabsf(mval[1] - pmval[1]); /* if buffer is empty, just let this go through (i.e. so that dots will work) */ - if (p->gpd->runtime.sbuffer_size == 0) { + if (p->gpd->runtime.sbuffer_used == 0) { return true; /* check if mouse moved at least certain distance on both axes (best case) @@ -382,7 +382,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) { bGPdata *gpd = p->gpd; - short num_points = gpd->runtime.sbuffer_size; + short num_points = gpd->runtime.sbuffer_used; /* Do nothing if not enough points to smooth out */ if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) { @@ -437,7 +437,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* check painting mode */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only - i.e. only store start and end point in buffer */ - if (gpd->runtime.sbuffer_size == 0) { + if (gpd->runtime.sbuffer_used == 0) { /* first point in buffer (start point) */ pt = (tGPspoint *)(gpd->runtime.sbuffer); @@ -449,7 +449,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure pt->time = (float)(curtime - p->inittime); /* increment buffer size */ - gpd->runtime.sbuffer_size++; + gpd->runtime.sbuffer_used++; } else { /* just reset the endpoint to the latest value @@ -465,20 +465,19 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure pt->time = (float)(curtime - p->inittime); /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */ - gpd->runtime.sbuffer_size = 2; + gpd->runtime.sbuffer_used = 2; } /* can keep carrying on this way :) */ return GP_STROKEADD_NORMAL; } else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */ - /* check if still room in buffer */ - if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX) { - return GP_STROKEADD_OVERFLOW; - } + /* check if still room in buffer or add more */ + gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure( + gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false); /* get pointer to destination point */ - pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size); + pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used); /* store settings */ copy_v2_v2(&pt->x, mval); @@ -490,19 +489,13 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure pt->time = (float)(curtime - p->inittime); /* increment counters */ - gpd->runtime.sbuffer_size++; + gpd->runtime.sbuffer_used++; /* smooth while drawing previous points with a reduction factor for previous */ for (int s = 0; s < 3; s++) { - gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_size - s); + gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s); } - /* check if another operation can still occur */ - if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX) { - return GP_STROKEADD_FULL; - } - else { - return GP_STROKEADD_NORMAL; - } + return GP_STROKEADD_NORMAL; } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { /* get pointer to destination point */ @@ -524,7 +517,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure bGPDspoint *pts; /* first time point is adding to temporary buffer -- need to allocate new point in stroke */ - if (gpd->runtime.sbuffer_size == 0) { + if (gpd->runtime.sbuffer_used == 0) { gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); gps->totpoints++; } @@ -557,8 +550,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure } /* increment counters */ - if (gpd->runtime.sbuffer_size == 0) { - gpd->runtime.sbuffer_size++; + if (gpd->runtime.sbuffer_used == 0) { + gpd->runtime.sbuffer_used++; } return GP_STROKEADD_NORMAL; @@ -576,7 +569,7 @@ static void gp_stroke_simplify(tGPsdata *p) { bGPdata *gpd = p->gpd; tGPspoint *old_points = (tGPspoint *)gpd->runtime.sbuffer; - short num_points = gpd->runtime.sbuffer_size; + short num_points = gpd->runtime.sbuffer_used; short flag = gpd->runtime.sbuffer_sflag; short i, j; @@ -668,17 +661,17 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) * - drawing straight-lines only requires the endpoints */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { - totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size; + totelem = (gpd->runtime.sbuffer_used >= 2) ? 2 : gpd->runtime.sbuffer_used; } else { - totelem = gpd->runtime.sbuffer_size; + totelem = gpd->runtime.sbuffer_used; } /* exit with error if no valid points from this stroke */ if (totelem == 0) { if (G.debug & G_DEBUG) { printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", - gpd->runtime.sbuffer_size); + gpd->runtime.sbuffer_used); } return; } @@ -736,7 +729,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) if (totelem == 2) { /* last point if applicable */ - ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1); + ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_used - 1); /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); @@ -769,9 +762,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) int interp_depth = 0; int found_depth = 0; - depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points"); + depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_used, "depth_points"); - for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) { + for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used; i++, ptc++, pt++) { round_v2i_v2fl(mval_i, &ptc->x); if ((ED_view3d_autodist_depth(p->ar, mval_i, depth_margin, depth_arr + i) == 0) && @@ -788,7 +781,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) if (found_depth == false) { /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */ - for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) { + for (i = gpd->runtime.sbuffer_used - 1; i >= 0; i--) { depth_arr[i] = 0.9999f; } } @@ -798,14 +791,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) int first_valid = 0; int last_valid = 0; - for (i = 0; i < gpd->runtime.sbuffer_size; i++) { + for (i = 0; i < gpd->runtime.sbuffer_used; i++) { if (depth_arr[i] != FLT_MAX) { break; } } first_valid = i; - for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) { + for (i = gpd->runtime.sbuffer_used - 1; i >= 0; i--) { if (depth_arr[i] != FLT_MAX) { break; } @@ -821,7 +814,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } if (interp_depth) { - interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX); + interp_sparse_array(depth_arr, gpd->runtime.sbuffer_used, FLT_MAX); } } } @@ -829,7 +822,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) pt = gps->points; /* convert all points (normal behavior) */ - for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc; + for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used && ptc; i++, ptc++, pt++) { /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); @@ -1049,19 +1042,8 @@ static void gp_session_validatebuffer(tGPsdata *p) { bGPdata *gpd = p->gpd; - /* clear memory of buffer (or allocate it if starting a new session) */ - if (gpd->runtime.sbuffer) { - /* printf("\t\tGP - reset sbuffer\n"); */ - memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX); - } - else { - /* printf("\t\tGP - allocate sbuffer\n"); */ - gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, - "gp_session_strokebuffer"); - } - - /* reset indices */ - gpd->runtime.sbuffer_size = 0; + gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure( + gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, true); /* reset flags */ gpd->runtime.sbuffer_sflag = 0; @@ -1295,6 +1277,7 @@ static void gp_session_cleanup(tGPsdata *p) } /* clear flags */ + gpd->runtime.sbuffer_used = 0; gpd->runtime.sbuffer_size = 0; gpd->runtime.sbuffer_sflag = 0; p->inittime = 0.0; diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index 4d62d169bf8..c4528518009 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -829,8 +829,7 @@ static const ColorTemplate gp_monkey_pct_pupils = { void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4]) { Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); bGPdata *gpd = (bGPdata *)ob->data; bGPDstroke *gps; @@ -852,8 +851,8 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4]) /* frames */ /* NOTE: No need to check for existing, as this will take care of it for us */ - bGPDframe *frameFills = BKE_gpencil_frame_addnew(Fills, cfra_eval); - bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, cfra_eval); + bGPDframe *frameFills = BKE_gpencil_frame_addnew(Fills, CFRA); + bGPDframe *frameLines = BKE_gpencil_frame_addnew(Lines, CFRA); /* generate strokes */ gps = BKE_gpencil_add_stroke(frameFills, color_Skin, 270, 75); diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index f6ff5ed4f13..80e239c9ae5 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -215,8 +215,7 @@ static const ColorTemplate gp_stroke_material_grey = { void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4]) { Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); bGPdata *gpd = (bGPdata *)ob->data; bGPDstroke *gps; @@ -236,8 +235,8 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4]) bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true); /* frames */ - bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, cfra_eval); - bGPDframe *frame_lines = BKE_gpencil_frame_addnew(lines, cfra_eval); + bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, CFRA); + bGPDframe *frame_lines = BKE_gpencil_frame_addnew(lines, CFRA); UNUSED_VARS(frame_color); /* generate stroke */ diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index 7d866aedd87..d97207baed8 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -87,7 +87,6 @@ typedef struct tGP_BrushEditData { /* Current editor/region/etc. */ /* NOTE: This stuff is mainly needed to handle 3D view projection stuff... */ - Depsgraph *depsgraph; struct Main *bmain; Scene *scene; Object *object; @@ -1051,11 +1050,8 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) tGPSB_CloneBrushData *data = gso->customdata; Object *ob = CTX_data_active_object(C); - bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); - - bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW); + bGPdata *gpd = (bGPdata *)ob->data; + Scene *scene = CTX_data_scene(C); bGPDstroke *gps; float delta[3]; @@ -1074,6 +1070,18 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) bGPDspoint *pt; int i; + bGPDlayer *gpl = NULL; + /* Try to use original layer. */ + if (gps->runtime.tmp_layerinfo != NULL) { + gpl = BLI_findstring(&gpd->layers, gps->runtime.tmp_layerinfo, offsetof(bGPDlayer, info)); + } + + /* if not available, use active layer. */ + if (gpl == NULL) { + gpl = CTX_data_active_gpencil_layer(C); + } + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW); + /* Make a new stroke */ new_stroke = MEM_dupallocN(gps); @@ -1088,10 +1096,10 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) BLI_addtail(&gpf->strokes, new_stroke); /* Fix color references */ - Material *ma = BLI_ghash_lookup(data->new_colors, &new_stroke->mat_nr); - gps->mat_nr = BKE_gpencil_object_material_get_index(ob, ma); - if (!ma || gps->mat_nr) { - gps->mat_nr = 0; + Material *ma = BLI_ghash_lookup(data->new_colors, POINTER_FROM_INT(new_stroke->mat_nr)); + new_stroke->mat_nr = BKE_gpencil_object_material_get_index(ob, ma); + if (!ma || new_stroke->mat_nr < 0) { + new_stroke->mat_nr = 0; } /* Adjust all the stroke's points, so that the strokes * get pasted relative to where the cursor is now @@ -1224,7 +1232,6 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) gso = MEM_callocN(sizeof(tGP_BrushEditData), "tGP_BrushEditData"); op->customdata = gso; - gso->depsgraph = CTX_data_depsgraph(C); gso->bmain = CTX_data_main(C); /* store state */ gso->settings = gpsculpt_get_settings(scene); @@ -1400,10 +1407,11 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso) bGPdata *gpd = gso->gpd; bGPDlayer *gpl; - int cfra_eval = (int)DEG_get_ctime(gso->depsgraph); + Scene *scene = gso->scene; + int cfra = CFRA; /* only try to add a new frame if this is the first stroke, or the frame has changed */ - if ((gpd == NULL) || (cfra_eval == gso->cfra)) { + if ((gpd == NULL) || (cfra == gso->cfra)) { return; } @@ -1419,14 +1427,14 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso) * spent too much time editing the wrong frame. */ // XXX: should this be allowed when framelock is enabled? - if (gpf->framenum != cfra_eval) { - BKE_gpencil_frame_addcopy(gpl, cfra_eval); + if (gpf->framenum != cfra) { + BKE_gpencil_frame_addcopy(gpl, cfra); } } } /* save off new current frame, so that next update works fine */ - gso->cfra = cfra_eval; + gso->cfra = cfra; } /* Apply ----------------------------------------------- */ @@ -1478,7 +1486,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, /* Skip if neither one is selected * (and we are only allowed to edit/consider selected points) */ - if (gso->settings->flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) { + if ((gso->settings->flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) && (!gso->is_weight_mode)) { if (!(pt1->flag & GP_SPOINT_SELECT) && !(pt2->flag & GP_SPOINT_SELECT)) { include_last = false; continue; diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 5afa379e04f..087d8540b03 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1274,10 +1274,9 @@ static void gp_layer_to_curve(bContext *C, struct Main *bmain = CTX_data_main(C); ViewLayer *view_layer = CTX_data_view_layer(C); Collection *collection = CTX_data_collection(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); - bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV); bGPDstroke *gps, *prev_gps = NULL; Object *ob; Curve *cu; @@ -1406,8 +1405,7 @@ static void gp_layer_to_curve(bContext *C, */ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); bGPDframe *gpf = NULL; bGPDstroke *gps = NULL; @@ -1416,7 +1414,7 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe int i; bool valid = true; - if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV)) || + if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV)) || !(gps = gpf->strokes.first)) { return false; } @@ -1468,8 +1466,7 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), static bool gp_convert_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); if ((ob == NULL) || (ob->type != OB_GPENCIL)) { return false; @@ -1484,7 +1481,7 @@ static bool gp_convert_poll(bContext *C) * and if we are not in edit mode! */ return ((sa && sa->spacetype == SPACE_VIEW3D) && (gpl = BKE_gpencil_layer_getactive(gpd)) && - (gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV)) && + (gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV)) && (gpf->strokes.first) && (!GPENCIL_ANY_EDIT_MODE(gpd))); } diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 90a2b2d613c..0ee4fd20f0f 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -594,8 +594,7 @@ static int gp_frame_duplicate_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); int mode = RNA_enum_get(op->ptr, "mode"); @@ -605,12 +604,12 @@ static int gp_frame_duplicate_exec(bContext *C, wmOperator *op) } if (mode == 0) { - BKE_gpencil_frame_addcopy(gpl, cfra_eval); + BKE_gpencil_frame_addcopy(gpl, CFRA); } else { for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { if ((gpl->flag & GP_LAYER_LOCKED) == 0) { - BKE_gpencil_frame_addcopy(gpl, cfra_eval); + BKE_gpencil_frame_addcopy(gpl, CFRA); } } } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 0c1c24a9432..0fc051e4756 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1237,8 +1237,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); /* only use active for copy merge */ - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); bGPDframe *gpf; eGP_PasteMode type = RNA_enum_get(op->ptr, "type"); @@ -1329,7 +1328,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) * we are obliged to add a new frame if one * doesn't exist already */ - gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW); + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW); if (gpf) { /* Create new stroke */ bGPDstroke *new_stroke = MEM_dupallocN(gps); @@ -1408,8 +1407,7 @@ static int gp_move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *U static int gp_move_to_layer_exec(bContext *C, wmOperator *op) { bGPdata *gpd = CTX_data_gpencil_data(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); bGPDlayer *target_layer = NULL; ListBase strokes = {NULL, NULL}; int layer_num = RNA_enum_get(op->ptr, "layer"); @@ -1482,7 +1480,7 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) /* Paste them all in one go */ if (strokes.first) { - bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, cfra_eval, GP_GETFRAME_ADD_NEW); + bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, CFRA, GP_GETFRAME_ADD_NEW); BLI_movelisttolist(&gpf->strokes, &strokes); BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL)); @@ -1545,8 +1543,8 @@ static bool UNUSED_FUNCTION(gp_blank_frame_add_poll)(bContext *C) static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); + int cfra = CFRA; bGPDlayer *active_gpl = BKE_gpencil_layer_getactive(gpd); @@ -1568,7 +1566,7 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) } /* 1) Check for an existing frame on the current frame */ - bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, cfra_eval); + bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, cfra); if (gpf) { /* Shunt all frames after (and including) the existing one later by 1-frame */ for (; gpf; gpf = gpf->next) { @@ -1577,7 +1575,7 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) } /* 2) Now add a new frame, with nothing in it */ - gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_NEW); + gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_ADD_NEW); } CTX_DATA_END; @@ -1627,10 +1625,9 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); - bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV); /* if there's no existing Grease-Pencil data there, add some */ if (gpd == NULL) { @@ -1681,14 +1678,13 @@ static bool gp_actframe_delete_all_poll(bContext *C) static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); bool success = false; CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { /* try to get the "active" frame - but only if it actually occurs on this frame */ - bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV); if (gpf == NULL) { continue; @@ -1940,9 +1936,11 @@ static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode) *ndvert = *dvert; ndvert->dw = MEM_dupallocN(dvert->dw); ndvert++; - dvert++; } } + if (gps->dvert != NULL) { + dvert++; + } } break; case GP_DISSOLVE_BETWEEN: @@ -1970,9 +1968,11 @@ static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode) *ndvert = *dvert; ndvert->dw = MEM_dupallocN(dvert->dw); ndvert++; - dvert++; } } + if (gps->dvert != NULL) { + dvert++; + } } /* copy last segment */ (gps->dvert != NULL) ? dvert = gps->dvert + last : NULL; @@ -2001,9 +2001,11 @@ static int gp_dissolve_selected_points(bContext *C, eGP_DissolveMode mode) *ndvert = *dvert; ndvert->dw = MEM_dupallocN(dvert->dw); ndvert++; - dvert++; } } + if (gps->dvert != NULL) { + dvert++; + } } break; } @@ -3142,10 +3144,7 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, /* 3rd: add all points */ for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) { - /* check if still room in buffer */ - if (gps_a->totpoints <= GP_STROKE_BUFFER_MAX - 2) { - gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime); - } + gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime); } } @@ -3401,12 +3400,6 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; int i; - float inverse_diff_mat[4][4]; - - /* Compute inverse matrix for unapplying parenting once instead of doing per-point */ - /* TODO: add this bit to the iteration macro? */ - invert_m4_m4(inverse_diff_mat, gpstroke_iter.diff_mat); - /* Adjust each point */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { float xy[2]; @@ -3493,7 +3486,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) /* Unapply parent corrections */ if (!ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP)) { - mul_m4_v3(inverse_diff_mat, &pt->x); + mul_m4_v3(gpstroke_iter.inverse_diff_mat, &pt->x); } } } diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index d914cdea442..1ac4471547e 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -135,7 +135,7 @@ typedef struct tGPDfill { short fill_factor; /** number of elements currently in cache */ - short sbuffer_size; + short sbuffer_used; /** temporary points */ void *sbuffer; /** depth array for reproject */ @@ -918,7 +918,7 @@ static void gpencil_get_depth_array(tGPDfill *tgpf) { tGPspoint *ptc; ToolSettings *ts = tgpf->scene->toolsettings; - int totpoints = tgpf->sbuffer_size; + int totpoints = tgpf->sbuffer_used; int i = 0; if (totpoints == 0) { @@ -984,7 +984,7 @@ static void gpencil_points_from_stack(tGPDfill *tgpf) return; } - tgpf->sbuffer_size = (short)totpoints; + tgpf->sbuffer_used = (short)totpoints; tgpf->sbuffer = MEM_callocN(sizeof(tGPspoint) * totpoints, __func__); point2D = tgpf->sbuffer; @@ -1020,7 +1020,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) MDeformVert *dvert = NULL; tGPspoint *point2D; - if (tgpf->sbuffer_size == 0) { + if (tgpf->sbuffer_used == 0) { return; } @@ -1041,8 +1041,8 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) gps->mat_nr = BKE_gpencil_object_material_ensure(tgpf->bmain, tgpf->ob, tgpf->mat); /* allocate memory for storage points */ - gps->totpoints = tgpf->sbuffer_size; - gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_size, "gp_stroke_points"); + gps->totpoints = tgpf->sbuffer_used; + gps->points = MEM_callocN(sizeof(bGPDspoint) * tgpf->sbuffer_used, "gp_stroke_points"); /* initialize triangle memory to dummy data */ gps->tot_triangles = 0; @@ -1069,7 +1069,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) dvert = gps->dvert; } - for (int i = 0; i < tgpf->sbuffer_size && point2D; i++, point2D++, pt++) { + for (int i = 0; i < tgpf->sbuffer_used && point2D; i++, point2D++, pt++) { /* convert screen-coordinates to 3D coordinates */ gp_stroke_convertcoords_tpoint(tgpf->scene, tgpf->ar, @@ -1120,7 +1120,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) } /* if parented change position relative to parent object */ - for (int a = 0; a < tgpf->sbuffer_size; a++) { + for (int a = 0; a < tgpf->sbuffer_used; a++) { pt = &gps->points[a]; gp_apply_parent_point(tgpf->depsgraph, tgpf->ob, tgpf->gpd, tgpf->gpl, pt); } @@ -1225,7 +1225,7 @@ static tGPDfill *gp_session_init_fill(bContext *C, wmOperator *UNUSED(op)) tgpf->lock_axis = ts->gp_sculpt.lock_axis; tgpf->oldkey = -1; - tgpf->sbuffer_size = 0; + tgpf->sbuffer_used = 0; tgpf->sbuffer = NULL; tgpf->depth_arr = NULL; diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index df9cb2e9a01..e28e83b23b0 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -378,8 +378,8 @@ typedef enum eGPencil_PaintModes { GP_PAINTMODE_SET_CP, } eGPencil_PaintModes; -/* maximum sizes of gp-session buffer */ -#define GP_STROKE_BUFFER_MAX 5000 +/* chunk size for gp-session buffer (the total size is a multiple of this number) */ +#define GP_STROKE_BUFFER_CHUNK 2048 /* stroke editing ----- */ @@ -583,6 +583,7 @@ typedef enum ACTCONT_TYPES { struct GP_EditableStrokes_Iter { float diff_mat[4][4]; + float inverse_diff_mat[4][4]; }; /** @@ -607,6 +608,7 @@ struct GP_EditableStrokes_Iter { for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \ + invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ for (bGPDstroke *gps = gpf_->strokes.first; gps; gps = gps->next) { \ /* skip strokes that are invalid for current view */ \ diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 4d5548dcdf3..698e508a2a5 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -511,8 +511,8 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent wmWindow *win = CTX_wm_window(C); bGPdata *gpd = CTX_data_gpencil_data(C); bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); + int cfra = CFRA; bGPDframe *actframe = gpl->actframe; tGPDinterpolate *tgpi = NULL; @@ -526,7 +526,7 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent } /* cannot interpolate in extremes */ - if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) { + if (ELEM(cfra, actframe->framenum, actframe->next->framenum)) { BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames"); @@ -949,8 +949,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); ToolSettings *ts = CTX_data_tool_settings(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); + int cfra = CFRA; GP_Interpolate_Settings *ipo_settings = &ts->gp_interpolate; eGP_Interpolate_SettingsFlag flag = ipo_settings->flag; @@ -964,7 +964,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } /* cannot interpolate in extremes */ - if (ELEM(cfra_eval, actframe->framenum, actframe->next->framenum)) { + if (ELEM(cfra, actframe->framenum, actframe->next->framenum)) { BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames"); diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index 93d8555e014..cb11bb4cd63 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -98,11 +98,10 @@ static void gpencil_insert_points_to_stroke(bGPDstroke *gps, static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpoints) { ToolSettings *ts = CTX_data_tool_settings(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); Object *ob = CTX_data_active_object(C); bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); const bool back = RNA_boolean_get(op->ptr, "back"); const bool additive = RNA_boolean_get(op->ptr, "additive"); @@ -124,7 +123,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo else { add_frame_mode = GP_GETFRAME_ADD_NEW; } - bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, add_frame_mode); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, add_frame_mode); /* stroke */ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index b49094c4fd6..5af355b908d 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -349,7 +349,7 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float mvalo[2 brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP; /* if buffer is empty, just let this go through (i.e. so that dots will work) */ - if (p->gpd->runtime.sbuffer_size == 0) { + if (p->gpd->runtime.sbuffer_used == 0) { return true; } /* if lazy mouse, check minimum distance */ @@ -486,7 +486,7 @@ static void gp_brush_jitter(bGPdata *gpd, /* Jitter is applied perpendicular to the mouse movement vector (2D space) */ float mvec[2], svec[2]; /* mouse movement in ints -> floats */ - if (gpd->runtime.sbuffer_size > 1) { + if (gpd->runtime.sbuffer_used > 1) { mvec[0] = (mval[0] - (pt - 1)->x); mvec[1] = (mval[1] - (pt - 1)->y); normalize_v2(mvec); @@ -524,7 +524,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa float v0[2] = {cos(angle), sin(angle)}; /* Apply to first point (only if there are 2 points because before no data to do it ) */ - if (gpd->runtime.sbuffer_size == 1) { + if (gpd->runtime.sbuffer_used == 1) { mvec[0] = (mval[0] - (pt - 1)->x); mvec[1] = (mval[1] - (pt - 1)->y); normalize_v2(mvec); @@ -537,7 +537,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa } /* apply from second point */ - if (gpd->runtime.sbuffer_size >= 1) { + if (gpd->runtime.sbuffer_used >= 1) { mvec[0] = (mval[0] - (pt - 1)->x); mvec[1] = (mval[1] - (pt - 1)->y); normalize_v2(mvec); @@ -563,7 +563,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) { bGPdata *gpd = p->gpd; - short num_points = gpd->runtime.sbuffer_size; + short num_points = gpd->runtime.sbuffer_used; /* Do nothing if not enough points to smooth out */ if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) { @@ -626,7 +626,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* check painting mode */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only - i.e. only store start and end point in buffer */ - if (gpd->runtime.sbuffer_size == 0) { + if (gpd->runtime.sbuffer_used == 0) { /* first point in buffer (start point) */ pt = (tGPspoint *)(gpd->runtime.sbuffer); @@ -638,7 +638,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure pt->time = (float)(curtime - p->inittime); /* increment buffer size */ - gpd->runtime.sbuffer_size++; + gpd->runtime.sbuffer_used++; } else { /* just reset the endpoint to the latest value @@ -654,20 +654,19 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure pt->time = (float)(curtime - p->inittime); /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */ - gpd->runtime.sbuffer_size = 2; + gpd->runtime.sbuffer_used = 2; } /* can keep carrying on this way :) */ return GP_STROKEADD_NORMAL; } else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */ - /* check if still room in buffer */ - if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX) { - return GP_STROKEADD_OVERFLOW; - } + /* check if still room in buffer or add more */ + gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure( + gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false); /* get pointer to destination point */ - pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size); + pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used); /* store settings */ /* pressure */ @@ -760,9 +759,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure pt->time = (float)(curtime - p->inittime); /* point uv (only 3d view) */ - if ((p->sa->spacetype == SPACE_VIEW3D) && (gpd->runtime.sbuffer_size > 0)) { + if ((p->sa->spacetype == SPACE_VIEW3D) && (gpd->runtime.sbuffer_used > 0)) { float pixsize = gp_style->texture_pixsize / 1000000.0f; - tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1; + tGPspoint *ptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1; bGPDspoint spt, spt2; /* get origin to reproject point */ @@ -787,24 +786,18 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure } /* increment counters */ - gpd->runtime.sbuffer_size++; + gpd->runtime.sbuffer_used++; /* smooth while drawing previous points with a reduction factor for previous */ if (brush->gpencil_settings->active_smooth > 0.0f) { for (int s = 0; s < 3; s++) { gp_smooth_buffer(p, brush->gpencil_settings->active_smooth * ((3.0f - s) / 3.0f), - gpd->runtime.sbuffer_size - s); + gpd->runtime.sbuffer_used - s); } } - /* check if another operation can still occur */ - if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX) { - return GP_STROKEADD_FULL; - } - else { - return GP_STROKEADD_NORMAL; - } + return GP_STROKEADD_NORMAL; } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { @@ -832,7 +825,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure MDeformVert *dvert = NULL; /* first time point is adding to temporary buffer -- need to allocate new point in stroke */ - if (gpd->runtime.sbuffer_size == 0) { + if (gpd->runtime.sbuffer_used == 0) { gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); if (gps->dvert != NULL) { gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1)); @@ -889,8 +882,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure } /* increment counters */ - if (gpd->runtime.sbuffer_size == 0) { - gpd->runtime.sbuffer_size++; + if (gpd->runtime.sbuffer_used == 0) { + gpd->runtime.sbuffer_used++; } return GP_STROKEADD_NORMAL; @@ -930,17 +923,17 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) * - drawing straight-lines only requires the endpoints */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { - totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size; + totelem = (gpd->runtime.sbuffer_used >= 2) ? 2 : gpd->runtime.sbuffer_used; } else { - totelem = gpd->runtime.sbuffer_size; + totelem = gpd->runtime.sbuffer_used; } /* exit with error if no valid points from this stroke */ if (totelem == 0) { if (G.debug & G_DEBUG) { printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", - gpd->runtime.sbuffer_size); + gpd->runtime.sbuffer_used); } return; } @@ -1024,7 +1017,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) if (totelem == 2) { /* last point if applicable */ - ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1); + ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_used - 1); /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); @@ -1105,9 +1098,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) int interp_depth = 0; int found_depth = 0; - depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points"); + depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_used, "depth_points"); - for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) { + for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used; i++, ptc++, pt++) { round_v2i_v2fl(mval_i, &ptc->x); @@ -1125,7 +1118,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) if (found_depth == false) { /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */ - for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) { + for (i = gpd->runtime.sbuffer_used - 1; i >= 0; i--) { depth_arr[i] = 0.9999f; } } @@ -1137,7 +1130,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) int last_valid = 0; /* find first valid contact point */ - for (i = 0; i < gpd->runtime.sbuffer_size; i++) { + for (i = 0; i < gpd->runtime.sbuffer_used; i++) { if (depth_arr[i] != FLT_MAX) { break; } @@ -1149,7 +1142,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) last_valid = first_valid; } else { - for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) { + for (i = gpd->runtime.sbuffer_used - 1; i >= 0; i--) { if (depth_arr[i] != FLT_MAX) { break; } @@ -1158,7 +1151,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } /* invalidate any other point, to interpolate between * first and last contact in an imaginary line between them */ - for (i = 0; i < gpd->runtime.sbuffer_size; i++) { + for (i = 0; i < gpd->runtime.sbuffer_used; i++) { if ((i != first_valid) && (i != last_valid)) { depth_arr[i] = FLT_MAX; } @@ -1167,7 +1160,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } if (interp_depth) { - interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX); + interp_sparse_array(depth_arr, gpd->runtime.sbuffer_used, FLT_MAX); } } } @@ -1176,7 +1169,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) dvert = gps->dvert; /* convert all points (normal behavior) */ - for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc; + for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_used && ptc; i++, ptc++, pt++) { /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); @@ -1725,18 +1718,8 @@ static void gp_session_validatebuffer(tGPsdata *p) Brush *brush = p->brush; /* clear memory of buffer (or allocate it if starting a new session) */ - if (gpd->runtime.sbuffer) { - /* printf("\t\tGP - reset sbuffer\n"); */ - memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX); - } - else { - /* printf("\t\tGP - allocate sbuffer\n"); */ - gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, - "gp_session_strokebuffer"); - } - - /* reset indices */ - gpd->runtime.sbuffer_size = 0; + gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure( + gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, true); /* reset flags */ gpd->runtime.sbuffer_sflag = 0; @@ -2070,6 +2053,7 @@ static void gp_session_cleanup(tGPsdata *p) } /* clear flags */ + gpd->runtime.sbuffer_used = 0; gpd->runtime.sbuffer_size = 0; gpd->runtime.sbuffer_sflag = 0; p->inittime = 0.0; @@ -2089,7 +2073,6 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps { Scene *scene = p->scene; ToolSettings *ts = scene->toolsettings; - int cfra_eval = (int)DEG_get_ctime(p->depsgraph); /* get active layer (or add a new one if non-existent) */ p->gpl = BKE_gpencil_layer_getactive(p->gpd); @@ -2131,7 +2114,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps * -> If there are no strokes in that frame, don't add a new empty frame */ if (gpl->actframe && gpl->actframe->strokes.first) { - gpl->actframe = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_ADD_COPY); + gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY); has_layer_to_erase = true; } @@ -2169,7 +2152,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps add_frame_mode = GP_GETFRAME_ADD_NEW; } - p->gpf = BKE_gpencil_layer_getframe(p->gpl, cfra_eval, add_frame_mode); + p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode); if (p->gpf == NULL) { p->status = GP_STATUS_ERROR; @@ -2624,14 +2607,14 @@ static void gpencil_draw_apply(bContext *C, wmOperator *op, tGPsdata *p, Depsgra p->opressure = p->pressure; p->ocurtime = p->curtime; - pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1; + pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1; if (p->paintmode != GP_PAINTMODE_ERASER) { ED_gpencil_toggle_brush_cursor(C, true, &pt->x); } } else if ((p->brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) && - (gpd->runtime.sbuffer_size > 0)) { - pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1; + (gpd->runtime.sbuffer_used > 0)) { + pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1; if (p->paintmode != GP_PAINTMODE_ERASER) { ED_gpencil_toggle_brush_cursor(C, true, &pt->x); } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index cca94925e6e..c79366e6a2b 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -114,16 +114,8 @@ static void gp_session_validatebuffer(tGPDprimitive *p) bGPdata *gpd = p->gpd; /* clear memory of buffer (or allocate it if starting a new session) */ - if (gpd->runtime.sbuffer) { - memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX); - } - else { - gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, - "gp_session_strokebuffer"); - } - - /* reset indices */ - gpd->runtime.sbuffer_size = 0; + gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure( + gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, true); /* reset flags */ gpd->runtime.sbuffer_sflag = 0; @@ -305,8 +297,8 @@ static void gpencil_primitive_allocate_memory(tGPDprimitive *tgpi) /* Helper: Create internal strokes primitives data */ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); + int cfra = CFRA; bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); @@ -318,7 +310,7 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) /* create a new temporary frame */ tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe"); - tgpi->gpf->framenum = tgpi->cframe = cfra_eval; + tgpi->gpf->framenum = tgpi->cframe = cfra; /* create new temp stroke */ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "Temp bGPDstroke"); @@ -828,7 +820,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) } /* Copy points to buffer */ - tGPspoint *tpt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size); + tGPspoint *tpt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used); /* Store original points */ float tmp_xyp[2]; @@ -927,10 +919,10 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) tpt->time = p2d->time; /* point uv */ - if (gpd->runtime.sbuffer_size > 0) { + if (gpd->runtime.sbuffer_used > 0) { MaterialGPencilStyle *gp_style = tgpi->mat->gp_style; const float pixsize = gp_style->texture_pixsize / 1000000.0f; - tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1; + tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1; bGPDspoint spt, spt2; /* get origin to reproject point */ @@ -958,7 +950,11 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) tpt->uv_rot = p2d->uv_rot; - gpd->runtime.sbuffer_size++; + gpd->runtime.sbuffer_used++; + + /* check if still room in buffer or add more */ + gpd->runtime.sbuffer = ED_gpencil_sbuffer_ensure( + gpd->runtime.sbuffer, &gpd->runtime.sbuffer_size, &gpd->runtime.sbuffer_used, false); /* add small offset to keep stroke over the surface */ if ((depth_arr) && (gpd->zdepth_offset > 0.0f)) { @@ -1078,6 +1074,7 @@ static void gpencil_primitive_exit(bContext *C, wmOperator *op) gpd->runtime.sbuffer = NULL; /* clear flags */ + gpd->runtime.sbuffer_used = 0; gpd->runtime.sbuffer_size = 0; gpd->runtime.sbuffer_sflag = 0; } @@ -1096,11 +1093,8 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) bGPdata *gpd = CTX_data_gpencil_data(C); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); Paint *paint = &ts->gp_paint->paint; - int cfra_eval = (int)DEG_get_ctime(depsgraph); - /* create temporary operator data */ tGPDprimitive *tgpi = MEM_callocN(sizeof(tGPDprimitive), "GPencil Primitive Data"); op->customdata = tgpi; @@ -1122,7 +1116,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) tgpi->orign_type = RNA_enum_get(op->ptr, "type"); /* set current frame number */ - tgpi->cframe = cfra_eval; + tgpi->cframe = CFRA; /* set GP datablock */ tgpi->gpd = gpd; diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index ba806022d3e..b1d9bcfbe16 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -302,11 +302,10 @@ typedef enum eGP_SelectGrouped { /* On each visible layer, check for selected strokes - if found, select all others */ static void gp_select_same_layer(bContext *C) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - int cfra_eval = (int)DEG_get_ctime(depsgraph); + Scene *scene = CTX_data_scene(C); CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { - bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, cfra_eval, GP_GETFRAME_USE_PREV); + bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV); bGPDstroke *gps; bool found = false; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 065c133bf97..ac8196f5ed0 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1740,7 +1740,7 @@ static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata) } /* while drawing hide */ - if ((gpd->runtime.sbuffer_size > 0) && + if ((gpd->runtime.sbuffer_used > 0) && ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) && ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0)) { return; @@ -2525,3 +2525,37 @@ void ED_gpencil_select_toggle_all(bContext *C, int action) CTX_DATA_END; } } + +/* Ensure the SBuffer (while drawing stroke) size is enough to save all points of the stroke */ +tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array, + short *buffer_size, + short *buffer_used, + const bool clear) +{ + tGPspoint *p = NULL; + + /* By default a buffer is created with one block with a predefined number of free points, + * if the size is not enough, the cache is reallocated adding a new block of free points. + * This is done in order to keep cache small and improve speed. */ + if (*buffer_used + 1 > *buffer_size) { + if ((*buffer_size == 0) || (buffer_array == NULL)) { + p = MEM_callocN(sizeof(struct tGPspoint) * GP_STROKE_BUFFER_CHUNK, "GPencil Sbuffer"); + *buffer_size = GP_STROKE_BUFFER_CHUNK; + } + else { + *buffer_size += GP_STROKE_BUFFER_CHUNK; + p = MEM_recallocN(buffer_array, sizeof(struct tGPspoint) * *buffer_size); + } + buffer_array = p; + } + + /* clear old data */ + if (clear) { + *buffer_used = 0; + if (buffer_array != NULL) { + memset(buffer_array, 0, sizeof(tGPspoint) * *buffer_size); + } + } + + return buffer_array; +} diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 0e3204b30c7..6410e6630a7 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -35,6 +35,7 @@ struct bGPDlayer; struct bGPDspoint; struct bGPDstroke; struct bGPdata; +struct tGPspoint; struct ARegion; struct Depsgraph; @@ -287,4 +288,9 @@ int ED_gpencil_select_stroke_segment(struct bGPDlayer *gpl, void ED_gpencil_select_toggle_all(struct bContext *C, int action); +/* Ensure stroke sbuffer size is enough */ +struct tGPspoint *ED_gpencil_sbuffer_ensure(struct tGPspoint *buffer_array, + short *buffer_size, + short *buffer_used, + const bool clear); #endif /* __ED_GPENCIL_H__ */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index ebeeea3fa4c..72efea32c38 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -512,26 +512,6 @@ int view3d_opengl_select(struct ViewContext *vc, eV3DSelectObjectFilter select_filter); /* view3d_select.c */ -struct EDSelectID_Context; -struct EDSelectID_Context *ED_view3d_select_id_context_create(struct ViewContext *vc, - struct Base **bases, - const uint bases_len, - short select_mode); - -void ED_view3d_select_id_context_destroy(struct EDSelectID_Context *sel_id_ctx); -void ED_view3d_select_id_validate_view_matrices(struct EDSelectID_Context *sel_id_ctx, - struct ViewContext *vc); - -uint ED_view3d_select_id_context_offset_for_object_elem( - const struct EDSelectID_Context *sel_id_ctx, int base_index, char elem_type); - -uint ED_view3d_select_id_context_elem_len(const struct EDSelectID_Context *sel_id_ctx); -bool ED_view3d_select_id_elem_get(struct EDSelectID_Context *sel_id_ctx, - const uint sel_id, - uint *r_elem, - uint *r_base_index, - char *r_elem_type); - float ED_view3d_select_dist_px(void); void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc); void ED_view3d_viewcontext_init_object(struct ViewContext *vc, struct Object *obact); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 3b2a80c1e05..5ef3e5d8987 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -562,7 +562,8 @@ int UI_popover_panel_invoke(struct bContext *C, bool keep_open, struct ReportList *reports); -uiPopover *UI_popover_begin(struct bContext *C, int menu_width) ATTR_NONNULL(1); +uiPopover *UI_popover_begin(struct bContext *C, int menu_width, bool from_active_button) + ATTR_NONNULL(1); void UI_popover_end(struct bContext *C, struct uiPopover *head, struct wmKeyMap *keymap); struct uiLayout *UI_popover_layout(uiPopover *head); void UI_popover_once_clear(uiPopover *pup); diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 7afdbe9d266..6a36bf364a3 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -1606,6 +1606,11 @@ void ui_draw_but_COLORBAND(uiBut *but, const uiWidgetColors *UNUSED(wcol), const float sizey_solid = sizey * 0.25f; float y1 = rect->ymin; + /* exit early if too narrow */ + if (sizex <= 0) { + return; + } + GPUVertFormat *format = immVertexFormat(); pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index a7fc0cfec25..d4e8b7548bc 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -10124,7 +10124,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE ui_region_winrct_get_no_margin(ar_temp, &winrct); - if (BLI_rcti_isect_pt_v(&winrct, &event->x)) { + if (BLI_rcti_isect_pt_v(&winrct, &event->x) || ui_region_find_active_but(ar_temp)) { BLI_assert(ar_temp->type->regionid == RGN_TYPE_TEMPORARY); is_inside_menu = true; diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c index 43afdc534ad..bba5103bc03 100644 --- a/source/blender/editors/interface/interface_region_hud.c +++ b/source/blender/editors/interface/interface_region_hud.c @@ -57,16 +57,32 @@ /* -------------------------------------------------------------------- */ /** \name Utilities * \{ */ +struct HudRegionData { + short regionid; +}; -static bool last_redo_poll(const bContext *C) +static bool last_redo_poll(const bContext *C, short region_type) { wmOperator *op = WM_operator_last_redo(C); if (op == NULL) { return false; } + bool success = false; - if (WM_operator_repeat_check(C, op) && WM_operator_check_ui_empty(op->type) == false) { - success = WM_operator_poll((bContext *)C, op->type); + { + /* Make sure that we are using the same region type as the originial + * operator call. Otherwise we would be polling the operator with the + * wrong context. + */ + ScrArea *sa = CTX_wm_area(C); + ARegion *ar_op = (region_type != -1) ? BKE_area_find_region_type(sa, region_type) : NULL; + ARegion *ar_prev = CTX_wm_region(C); + CTX_wm_region_set((bContext *)C, ar_op); + + if (WM_operator_repeat_check(C, op) && WM_operator_check_ui_empty(op->type) == false) { + success = WM_operator_poll((bContext *)C, op->type); + } + CTX_wm_region_set((bContext *)C, ar_prev); } return success; } @@ -87,7 +103,15 @@ static void hud_region_hide(ARegion *ar) static bool hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt)) { - return last_redo_poll(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD); + if (ar != NULL) { + struct HudRegionData *hrd = ar->regiondata; + if (hrd != NULL) { + return last_redo_poll(C, hrd->regionid); + } + } + return false; } static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *pa) @@ -132,10 +156,6 @@ static void hud_panels_register(ARegionType *art, int space_type, int region_typ /** \name Callbacks for Floating Region * \{ */ -struct HudRegionData { - short regionid; -}; - static void hud_region_init(wmWindowManager *wm, ARegion *ar) { ED_region_panels_init(wm, ar); @@ -150,21 +170,8 @@ static void hud_region_free(ARegion *ar) static void hud_region_layout(const bContext *C, ARegion *ar) { - bool ok = false; - - { - struct HudRegionData *hrd = ar->regiondata; - if (hrd != NULL) { - ScrArea *sa = CTX_wm_area(C); - ARegion *ar_op = (hrd->regionid != -1) ? BKE_area_find_region_type(sa, hrd->regionid) : NULL; - ARegion *ar_prev = CTX_wm_region(C); - CTX_wm_region_set((bContext *)C, ar_op); - ok = last_redo_poll(C); - CTX_wm_region_set((bContext *)C, ar_prev); - } - } - - if (!ok) { + struct HudRegionData *hrd = ar->regiondata; + if (hrd == NULL || !last_redo_poll(C, hrd->regionid)) { ED_region_tag_redraw(ar); hud_region_hide(ar); return; @@ -301,7 +308,9 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *sa) bool init = false; bool was_hidden = ar == NULL || ar->visible == false; - if (!last_redo_poll(C)) { + ARegion *ar_op = CTX_wm_region(C); + BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD)); + if (!last_redo_poll(C, ar_op ? ar_op->regiontype : -1)) { if (ar) { ED_region_tag_redraw(ar); hud_region_hide(ar); @@ -328,8 +337,6 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *sa) } { - ARegion *ar_op = CTX_wm_region(C); - BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD)); struct HudRegionData *hrd = ar->regiondata; if (hrd == NULL) { hrd = MEM_callocN(sizeof(*hrd), __func__); diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index 53c96fb72a7..028d99ac052 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -72,6 +72,7 @@ struct uiPopover { uiBlock *block; uiLayout *layout; uiBut *but; + ARegion *butregion; /* Needed for keymap removal. */ wmWindow *window; @@ -325,7 +326,7 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep block = pup->block; } else { - uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x); + uiPopover *pup = UI_popover_begin(C, U.widget_unit * pt->ui_units_x, false); layout = UI_popover_layout(pup); UI_paneltype_draw(C, pt, layout); UI_popover_end(C, pup, NULL); @@ -346,8 +347,11 @@ int UI_popover_panel_invoke(bContext *C, const char *idname, bool keep_open, Rep /** * Only return handler, and set optional title. + * + * \param from_active_button: Use the active button for positioning, + * use when the popover is activated from an operator instead of directly from the button. */ -uiPopover *UI_popover_begin(bContext *C, int ui_size_x) +uiPopover *UI_popover_begin(bContext *C, int ui_size_x, bool from_active_button) { uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu"); if (ui_size_x == 0) { @@ -355,6 +359,20 @@ uiPopover *UI_popover_begin(bContext *C, int ui_size_x) } pup->ui_size_x = ui_size_x; + ARegion *butregion = NULL; + uiBut *but = NULL; + + if (from_active_button) { + butregion = CTX_wm_region(C); + but = UI_region_active_but_get(butregion); + if (but == NULL) { + butregion = NULL; + } + } + + pup->but = but; + pup->butregion = butregion; + /* Operator context default same as menus, change if needed. */ ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN); @@ -387,7 +405,7 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap) } handle = ui_popup_block_create( - C, NULL, NULL, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER); + C, pup->butregion, pup->but, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER); /* Add handlers. */ UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c index 5164970198e..abc5224c4d6 100644 --- a/source/blender/editors/lattice/editlattice_undo.c +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -68,9 +68,19 @@ typedef struct UndoLattice { static void undolatt_to_editlatt(UndoLattice *ult, EditLatt *editlatt) { - int len = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw; + const int len_src = ult->pntsu * ult->pntsv * ult->pntsw; + const int len_dst = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw; + if (len_src != len_dst) { + MEM_freeN(editlatt->latt->def); + editlatt->latt->def = MEM_dupallocN(ult->def); + } + else { + memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len_src); + } - memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len); + editlatt->latt->pntsu = ult->pntsu; + editlatt->latt->pntsv = ult->pntsv; + editlatt->latt->pntsw = ult->pntsw; editlatt->latt->actbp = ult->actbp; } diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 57bf67e825e..9a779db4812 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blentranslation ../../bmesh ../../depsgraph + ../../draw ../../gpu ../../imbuf ../../makesdna diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 7b770f055b4..12b5a36c510 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -68,6 +68,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "DRW_engine.h" + #include "mesh_intern.h" /* own include */ /* use bmesh operator flags for a few operators */ @@ -197,15 +199,11 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag) /** \name Back-Buffer OpenGL Selection * \{ */ -static BMElem *EDBM_select_id_bm_elem_get(struct EDSelectID_Context *sel_id_ctx, - Base **bases, - const uint sel_id, - uint *r_base_index) +static BMElem *edbm_select_id_bm_elem_get(Base **bases, const uint sel_id, uint *r_base_index) { uint elem_id; char elem_type = 0; - bool success = ED_view3d_select_id_elem_get( - sel_id_ctx, sel_id, &elem_id, r_base_index, &elem_type); + bool success = DRW_select_elem_get(sel_id, &elem_id, r_base_index, &elem_type); if (success) { Object *obedit = bases[*r_base_index]->object; @@ -335,20 +333,17 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc, { FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX); - struct EDSelectID_Context *sel_id_ctx = ED_view3d_select_id_context_create( - vc, bases, bases_len, select_mode); + DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, select_mode); index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); if (index) { - eve = (BMVert *)EDBM_select_id_bm_elem_get(sel_id_ctx, bases, index, &base_index); + eve = (BMVert *)edbm_select_id_bm_elem_get(bases, index, &base_index); } else { eve = NULL; } - ED_view3d_select_id_context_destroy(sel_id_ctx); - FAKE_SELECT_MODE_END(vc, fake_select_mode); } @@ -564,20 +559,17 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc, { FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE); - struct EDSelectID_Context *sel_id_ctx = ED_view3d_select_id_context_create( - vc, bases, bases_len, select_mode); + DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, select_mode); index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px); if (index) { - eed = (BMEdge *)EDBM_select_id_bm_elem_get(sel_id_ctx, bases, index, &base_index); + eed = (BMEdge *)edbm_select_id_bm_elem_get(bases, index, &base_index); } else { eed = NULL; } - ED_view3d_select_id_context_destroy(sel_id_ctx); - FAKE_SELECT_MODE_END(vc, fake_select_mode); } @@ -777,20 +769,17 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, { FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE); - struct EDSelectID_Context *sel_id_ctx = ED_view3d_select_id_context_create( - vc, bases, bases_len, select_mode); + DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, select_mode); index = ED_select_buffer_sample_point(vc->mval); if (index) { - efa = (BMFace *)EDBM_select_id_bm_elem_get(sel_id_ctx, bases, index, &base_index); + efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, &base_index); } else { efa = NULL; } - ED_view3d_select_id_context_destroy(sel_id_ctx); - FAKE_SELECT_MODE_END(vc, fake_select_mode); } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 919de4cdb20..3b5c8e9f101 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4593,7 +4593,8 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op) /* Only reuse on redo because these settings need to match the current selection. * We never want to use them on other geometry, repeat last for eg, see: T60777. */ - if ((op->flag & OP_IS_REPEAT_LAST) == 0 && RNA_property_is_set(op->ptr, prop_span)) { + if (((op->flag & OP_IS_INVOKE) || (op->flag & OP_IS_REPEAT_LAST) == 0) && + RNA_property_is_set(op->ptr, prop_span)) { span = RNA_property_int_get(op->ptr, prop_span); span = min_ii(span, (clamp / 2) - 1); calc_span = false; @@ -8615,7 +8616,7 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op) switch (mode) { case EDBM_CLNOR_TOOLS_COPY: - if (bm->totfacesel == 0 || bm->totvertsel == 0) { + if (bm->totfacesel == 0 && bm->totvertsel == 0) { BM_loop_normal_editdata_array_free(lnors_ed_arr); continue; } diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index e823fb46140..7071258d8cf 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -699,7 +699,6 @@ typedef struct MeshUndoStep_Elem { typedef struct MeshUndoStep { UndoStep step; - struct UndoIDPtrMap *id_map; MeshUndoStep_Elem *elems; uint elems_len; } MeshUndoStep; @@ -788,10 +787,6 @@ static void mesh_undosys_step_free(UndoStep *us_p) undomesh_free_data(&elem->data); } MEM_freeN(us->elems); - - if (us->id_map != NULL) { - BKE_undosys_ID_map_destroy(us->id_map); - } } static void mesh_undosys_foreach_ID_ref(UndoStep *us_p, @@ -804,10 +799,6 @@ static void mesh_undosys_foreach_ID_ref(UndoStep *us_p, MeshUndoStep_Elem *elem = &us->elems[i]; foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref)); } - - if (us->id_map != NULL) { - BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data); - } } /* Export for ED_undo_sys. */ diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 690bc270605..465a60ba75c 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -760,7 +760,7 @@ void OBJECT_OT_data_transfer(wmOperatorType *ot) static bool datalayout_transfer_poll(bContext *C) { - return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH)) || + return (edit_modifier_poll_generic(C, &RNA_DataTransferModifier, (1 << OB_MESH), true) || data_transfer_poll(C)); } diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index c939cb0a61d..707489d588a 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -52,6 +52,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" #include "RNA_define.h" #include "RNA_access.h" @@ -527,6 +528,7 @@ static int add_hook_object(const bContext *C, int mode, ReportList *reports) { + Depsgraph *depsgraph = CTX_data_depsgraph(C); ModifierData *md = NULL; HookModifierData *hmd = NULL; float cent[3]; @@ -601,11 +603,13 @@ static int add_hook_object(const bContext *C, /* matrix calculus */ /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */ /* (parentinv ) */ - BKE_object_where_is_calc(CTX_data_depsgraph(C), scene, ob); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_transform_copy(ob_eval, ob); + BKE_object_where_is_calc(depsgraph, scene, ob_eval); - invert_m4_m4(ob->imat, ob->obmat); + invert_m4_m4(ob_eval->imat, ob_eval->obmat); /* apparently this call goes from right to left... */ - mul_m4_series(hmd->parentinv, pose_mat, ob->imat, obedit->obmat); + mul_m4_series(hmd->parentinv, pose_mat, ob_eval->imat, obedit->obmat); DEG_relations_tag_update(bmain); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index b9350052093..e697c25b37f 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -137,7 +137,10 @@ void COLLECTION_OT_objects_add_active(struct wmOperatorType *ot); void COLLECTION_OT_objects_remove_active(struct wmOperatorType *ot); /* object_modifier.c */ -bool edit_modifier_poll_generic(struct bContext *C, struct StructRNA *rna_type, int obtype_flag); +bool edit_modifier_poll_generic(struct bContext *C, + struct StructRNA *rna_type, + int obtype_flag, + const bool is_editmode_allowed); bool edit_modifier_poll(struct bContext *C); void edit_modifier_properties(struct wmOperatorType *ot); int edit_modifier_invoke_properties(struct bContext *C, struct wmOperator *op); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 08012842c37..d1d910021a6 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -99,7 +99,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object * BKE_object_eval_reset(ob_eval); if (ob->type == OB_MESH) { Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); - BKE_id_free(NULL, me_eval); + BKE_mesh_eval_delete(me_eval); } else if (ob->type == OB_LATTICE) { BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval); @@ -912,7 +912,10 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot) /********** generic functions for operators using mod names and data context *********************/ -bool edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag) +bool edit_modifier_poll_generic(bContext *C, + StructRNA *rna_type, + int obtype_flag, + const bool is_editmode_allowed) { PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type); Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); @@ -932,12 +935,17 @@ bool edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_fla return (((ModifierData *)ptr.data)->flag & eModifierFlag_OverrideLibrary_Local) != 0; } + if (!is_editmode_allowed && CTX_data_edit_object(C) != NULL) { + CTX_wm_operator_poll_msg_set(C, "This modifier operation is not allowed from Edit mode"); + return 0; + } + return 1; } bool edit_modifier_poll(bContext *C) { - return edit_modifier_poll_generic(C, &RNA_Modifier, 0); + return edit_modifier_poll_generic(C, &RNA_Modifier, 0, true); } void edit_modifier_properties(wmOperatorType *ot) @@ -1274,7 +1282,7 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot) static bool multires_poll(bContext *C) { - return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH)); + return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1 << OB_MESH), true); } static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op) @@ -1627,14 +1635,13 @@ static void modifier_skin_customdata_delete(Object *ob) static bool skin_poll(bContext *C) { - return (!CTX_data_edit_object(C) && - edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH))); + return (edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), false)); } static bool skin_edit_poll(bContext *C) { return (CTX_data_edit_object(C) && - edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH))); + edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH), true)); } static void skin_root_clear(BMVert *bm_vert, GSet *visited, const int cd_vert_skin_offset) @@ -1987,7 +1994,7 @@ void OBJECT_OT_skin_armature_create(wmOperatorType *ot) static bool correctivesmooth_poll(bContext *C) { - return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0); + return edit_modifier_poll_generic(C, &RNA_CorrectiveSmoothModifier, 0, true); } static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) @@ -2065,7 +2072,7 @@ void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot) static bool meshdeform_poll(bContext *C) { - return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0); + return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, 0, true); } static int meshdeform_bind_exec(bContext *C, wmOperator *op) @@ -2138,7 +2145,7 @@ void OBJECT_OT_meshdeform_bind(wmOperatorType *ot) static bool explode_poll(bContext *C) { - return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0); + return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0, true); } static int explode_refresh_exec(bContext *C, wmOperator *op) @@ -2188,7 +2195,7 @@ void OBJECT_OT_explode_refresh(wmOperatorType *ot) static bool ocean_bake_poll(bContext *C) { - return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0); + return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0, true); } typedef struct OceanBakeJob { @@ -2389,7 +2396,7 @@ void OBJECT_OT_ocean_bake(wmOperatorType *ot) static bool laplaciandeform_poll(bContext *C) { - return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0); + return edit_modifier_poll_generic(C, &RNA_LaplacianDeformModifier, 0, false); } static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) @@ -2464,7 +2471,7 @@ void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot) static bool surfacedeform_bind_poll(bContext *C) { - return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0); + return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0, true); } static int surfacedeform_bind_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index e6637265fbc..ff31cbc4590 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1582,6 +1582,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) id_us_plus(&ob_dst->instance_collection->id); ob_dst->transflag |= OB_DUPLICOLLECTION; } + DEG_id_tag_update(&ob_dst->id, ID_RECALC_COPY_ON_WRITE); break; case MAKE_LINKS_MODIFIERS: BKE_object_link_modifiers(scene, ob_dst, ob_src); diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 9c98fdc2a2e..3f7d5dba149 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -856,6 +856,7 @@ static int apply_objects_internal(bContext *C, BKE_object_where_is_calc(depsgraph, scene, ob_eval); if (ob->type == OB_ARMATURE) { /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); BKE_pose_where_is(depsgraph, scene, ob_eval); } @@ -1229,6 +1230,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); BKE_object_transform_copy(ob_eval, ob); + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); BKE_object_where_is_calc(depsgraph, scene, ob_eval); BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */ @@ -1370,6 +1372,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) BKE_object_where_is_calc(depsgraph, scene, ob_eval); if (ob->type == OB_ARMATURE) { /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); BKE_pose_where_is(depsgraph, scene, ob_eval); } @@ -1398,6 +1401,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) BKE_object_where_is_calc(depsgraph, scene, ob_other_eval); if (ob_other->type == OB_ARMATURE) { /* needed for bone parents */ + BKE_armature_copy_bone_transforms(ob_eval->data, ob->data); BKE_pose_where_is(depsgraph, scene, ob_other_eval); } ignore_parent_tx(bmain, depsgraph, scene, ob_other); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 4e6022cf18c..2f2516f2055 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -785,7 +785,7 @@ typedef struct KeyIterData { static void foreach_mouse_hit_key_iter(void *__restrict iter_data_v, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { KeyIterData *iter_data = (KeyIterData *)iter_data_v; PEData *data = iter_data->data; @@ -855,7 +855,7 @@ static void foreach_mouse_hit_key(PEData *data, ForHitKeyMatFunc func, int selec iter_data.selected = selected; iter_data.func = func; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, foreach_mouse_hit_key_iter, &settings); @@ -1152,7 +1152,7 @@ typedef struct DeflectEmitterIter { static void deflect_emitter_iter(void *__restrict iter_data_v, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { DeflectEmitterIter *iter_data = (DeflectEmitterIter *)iter_data_v; PTCacheEdit *edit = iter_data->edit; @@ -1246,7 +1246,7 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) iter_data.dist = dist; iter_data.emitterdist = pset->emitterdist; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, deflect_emitter_iter, &settings); @@ -1258,7 +1258,7 @@ typedef struct ApplyLengthsIterData { static void apply_lengths_iter(void *__restrict iter_data_v, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { ApplyLengthsIterData *iter_data = (ApplyLengthsIterData *)iter_data_v; PTCacheEdit *edit = iter_data->edit; @@ -1296,7 +1296,7 @@ static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit) ApplyLengthsIterData iter_data; iter_data.edit = edit; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, apply_lengths_iter, &settings); @@ -1309,7 +1309,7 @@ typedef struct IterateLengthsIterData { static void iterate_lengths_iter(void *__restrict iter_data_v, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { IterateLengthsIterData *iter_data = (IterateLengthsIterData *)iter_data_v; PTCacheEdit *edit = iter_data->edit; @@ -1371,7 +1371,7 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) iter_data.edit = edit; iter_data.pset = pset; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, iterate_lengths_iter, &settings); @@ -4116,7 +4116,7 @@ typedef struct BrushAddCountIterTLSData { static void brush_add_count_iter(void *__restrict iter_data_v, const int iter, - const ParallelRangeTLS *__restrict tls_v) + const TaskParallelTLS *__restrict tls_v) { BrushAddCountIterData *iter_data = (BrushAddCountIterData *)iter_data_v; Depsgraph *depsgraph = iter_data->depsgraph; @@ -4272,7 +4272,7 @@ static int brush_add(const bContext *C, PEData *data, short number) BrushAddCountIterTLSData tls = {NULL}; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; settings.userdata_chunk = &tls; diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index b03ec56c7e4..fcee2cde5b1 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -1090,7 +1090,6 @@ static bool copy_particle_systems_to_object(const bContext *C, ModifierData *md; ParticleSystem *psys_start = NULL, *psys, *psys_from; ParticleSystem **tmp_psys; - Mesh *final_mesh; CustomData_MeshMasks cdmask = {0}; int i, totpsys; @@ -1132,9 +1131,6 @@ static bool copy_particle_systems_to_object(const bContext *C, */ psys_start = totpsys > 0 ? tmp_psys[0] : NULL; - /* Get the evaluated mesh (psys and their modifiers have not been appended yet) */ - final_mesh = mesh_get_eval_final(depsgraph, scene, ob_to, &cdmask); - /* now append psys to the object and make modifiers */ for (i = 0, psys_from = PSYS_FROM_FIRST; i < totpsys; ++i, psys_from = PSYS_FROM_NEXT(psys_from)) { @@ -1155,10 +1151,6 @@ static bool copy_particle_systems_to_object(const bContext *C, modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd); psmd->psys = psys; - BKE_id_copy_ex(NULL, &final_mesh->id, (ID **)&psmd->mesh_final, LIB_ID_COPY_LOCALIZE); - - BKE_mesh_calc_normals(psmd->mesh_final); - BKE_mesh_tessface_ensure(psmd->mesh_final); if (psys_from->edit) { copy_particle_edit(depsgraph, scene, ob_to, psys, psys_from); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index fbabdc2f3c1..c646ef12846 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -153,7 +153,6 @@ typedef struct ShaderPreview { short *stop, *do_update; Scene *scene; - Depsgraph *depsgraph; ID *id, *id_copy; ID *parent; MTex *slot; @@ -185,7 +184,6 @@ typedef struct IconPreviewSize { typedef struct IconPreview { Main *bmain; Scene *scene; - Depsgraph *depsgraph; void *owner; ID *id, *id_copy; ListBase sizes; @@ -1229,7 +1227,6 @@ static void icon_preview_startjob_all_sizes(void *customdata, /* construct shader preview from image size and previewcustomdata */ sp->scene = ip->scene; - sp->depsgraph = ip->depsgraph; sp->owner = ip->owner; sp->sizex = cur_size->sizex; sp->sizey = cur_size->sizey; @@ -1372,7 +1369,6 @@ void ED_preview_icon_job(const bContext *C, /* customdata for preview thread */ ip->bmain = CTX_data_main(C); ip->scene = CTX_data_scene(C); - ip->depsgraph = CTX_data_depsgraph(C); ip->owner = owner; ip->id = id; ip->id_copy = duplicate_ids(id); @@ -1439,7 +1435,6 @@ void ED_preview_shader_job(const bContext *C, /* customdata for preview thread */ sp->scene = scene; - sp->depsgraph = CTX_data_depsgraph(C); sp->owner = owner; sp->sizex = sizex; sp->sizey = sizey; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index e59477fbe6e..dddc33e3ad0 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1457,6 +1457,8 @@ void ED_update_for_newframe(Main *bmain, Depsgraph *depsgraph) { Scene *scene = DEG_get_input_scene(depsgraph); + DEG_id_tag_update_ex(bmain, &scene->id, ID_RECALC_TIME); + #ifdef DURIAN_CAMERA_SWITCH void *camera = BKE_scene_camera_switch_find(scene); if (camera && scene->camera != camera) { diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 23617e687ea..2a8ff9d4f78 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -29,6 +29,7 @@ set(INC ../../makesrna ../../render/extern/include ../../windowmanager + ../../../../intern/atomic ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index ac74afce79e..576baf5794b 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -148,7 +148,7 @@ typedef struct LoadTexData { static void load_tex_task_cb_ex(void *__restrict userdata, const int j, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { LoadTexData *data = userdata; Brush *br = data->br; @@ -328,7 +328,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima .radius = radius, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); BLI_task_parallel_range(0, size, &data, load_tex_task_cb_ex, &settings); @@ -385,7 +385,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima static void load_tex_cursor_task_cb(void *__restrict userdata, const int j, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { LoadTexData *data = userdata; Brush *br = data->br; @@ -468,7 +468,7 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom) .size = size, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); BLI_task_parallel_range(0, size, &data, load_tex_cursor_task_cb, &settings); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 41dfd6f68c3..a0f578c04d0 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -1246,8 +1246,7 @@ static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene = CTX_data_scene(C); UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; - ViewLayer *view_layer = CTX_data_view_layer(C); - Paint *paint = BKE_paint_get_active(scene, view_layer); + Paint *paint = BKE_paint_get_active_from_context(C); Brush *br = BKE_paint_brush(paint); if (ups->flag & UNIFIED_PAINT_COLOR) { @@ -1256,6 +1255,10 @@ static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op)) else if (br) { swap_v3_v3(br->rgb, br->secondary_rgb); } + else { + return OPERATOR_CANCELLED; + } + WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, br); return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 474d3a8ceba..8f1156295a3 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -1251,7 +1251,7 @@ typedef struct Paint2DForeachData { static void paint_2d_op_foreach_do(void *__restrict data_v, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { Paint2DForeachData *data = (Paint2DForeachData *)data_v; paint_2d_do_making_brush(data->s, @@ -1360,7 +1360,7 @@ static int paint_2d_op(void *state, data.tilex = tilex; data.tilew = tilew; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); BLI_task_parallel_range(tiley, tileh + 1, &data, paint_2d_op_foreach_do, &settings); } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 22de22e8e59..f768a66a41c 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -44,6 +44,8 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "atomic_ops.h" + #include "BLT_translation.h" #include "IMB_imbuf.h" @@ -366,7 +368,7 @@ typedef struct ProjPaintState { int bucketMin[2]; int bucketMax[2]; /** must lock threads while accessing these. */ - int context_bucket_x, context_bucket_y; + int context_bucket_index; struct CurveMapping *cavity_curve; BlurKernel *blurkernel; @@ -4712,11 +4714,8 @@ static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2]) /* mouse outside the model areas? */ if (ps->bucketMin[0] == ps->bucketMax[0] || ps->bucketMin[1] == ps->bucketMax[1]) { - return 0; + return false; } - - ps->context_bucket_x = ps->bucketMin[0]; - ps->context_bucket_y = ps->bucketMin[1]; } else { /* reproject: PROJ_SRC_* */ ps->bucketMin[0] = 0; @@ -4724,11 +4723,10 @@ static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2]) ps->bucketMax[0] = ps->buckets_x; ps->bucketMax[1] = ps->buckets_y; - - ps->context_bucket_x = 0; - ps->context_bucket_y = 0; } - return 1; + + ps->context_bucket_index = ps->bucketMin[0] + ps->bucketMin[1] * ps->buckets_x; + return true; } static bool project_bucket_iter_next(ProjPaintState *ps, @@ -4738,37 +4736,28 @@ static bool project_bucket_iter_next(ProjPaintState *ps, { const int diameter = 2 * ps->brush_size; - if (ps->thread_tot > 1) { - BLI_thread_lock(LOCK_CUSTOM1); - } - - // printf("%d %d\n", ps->context_bucket_x, ps->context_bucket_y); + const int max_bucket_idx = ps->bucketMax[0] + (ps->bucketMax[1] - 1) * ps->buckets_x; - for (; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) { - for (; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) { + for (int bidx = atomic_fetch_and_add_int32(&ps->context_bucket_index, 1); bidx < max_bucket_idx; + bidx = atomic_fetch_and_add_int32(&ps->context_bucket_index, 1)) { + const int bucket_y = bidx / ps->buckets_x; + const int bucket_x = bidx - (bucket_y * ps->buckets_x); + BLI_assert(bucket_y >= ps->bucketMin[1] && bucket_y < ps->bucketMax[1]); + if (bucket_x >= ps->bucketMin[0] && bucket_x < ps->bucketMax[0]) { /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/ - project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds); + project_bucket_bounds(ps, bucket_x, bucket_y, bucket_bounds); if ((ps->source != PROJ_SRC_VIEW) || project_bucket_isect_circle(mval, (float)(diameter * diameter), bucket_bounds)) { - *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x); - ps->context_bucket_x++; - - if (ps->thread_tot > 1) { - BLI_thread_unlock(LOCK_CUSTOM1); - } + *bucket_index = bidx; - return 1; + return true; } } - ps->context_bucket_x = ps->bucketMin[0]; } - if (ps->thread_tot > 1) { - BLI_thread_unlock(LOCK_CUSTOM1); - } - return 0; + return false; } /* Each thread gets one of these, also used as an argument to pass to project_paint_op */ @@ -5733,6 +5722,7 @@ void paint_proj_stroke(const bContext *C, return; } + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); ED_region_tag_redraw(ar); return; diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c index e7f100ebacb..2a1158ec804 100644 --- a/source/blender/editors/sculpt_paint/paint_image_undo.c +++ b/source/blender/editors/sculpt_paint/paint_image_undo.c @@ -69,7 +69,10 @@ typedef struct UndoImageTile { int x, y; - Image *ima; + /* TODO(campbell): avoid storing the ID per tile, + * adds unnecessary overhead restoring undo steps when most tiles share the same image. */ + UndoRefID_Image image_ref; + short source, use_float; char gen_type; bool valid; @@ -245,7 +248,7 @@ void *image_undo_push_tile(ListBase *undo_tiles, tile->source = ima->source; tile->use_float = use_float; tile->valid = true; - tile->ima = ima; + tile->image_ref.ptr = ima; if (valid) { *valid = &tile->valid; @@ -284,7 +287,7 @@ static void image_undo_restore_runtime(ListBase *lb) tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect); for (tile = lb->first; tile; tile = tile->next) { - Image *ima = tile->ima; + Image *ima = tile->image_ref.ptr; ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); undo_copy_tile(tile, tmpibuf, ibuf, RESTORE); @@ -304,19 +307,15 @@ static void image_undo_restore_runtime(ListBase *lb) IMB_freeImBuf(tmpibuf); } -static void image_undo_restore_list(ListBase *lb, struct UndoIDPtrMap *id_map) +static void image_undo_restore_list(ListBase *lb) { ImBuf *tmpibuf = IMB_allocImBuf( IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect); - /* Store last found image. */ - ID *image_prev[2] = {NULL}; - for (UndoImageTile *tile = lb->first; tile; tile = tile->next) { short use_float; - Image *ima = (Image *)BKE_undosys_ID_map_lookup_with_prev(id_map, &tile->ima->id, image_prev); - + Image *ima = tile->image_ref.ptr; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) { @@ -398,33 +397,8 @@ typedef struct ImageUndoStep { ListBase tiles; bool is_encode_init; ePaintMode paint_mode; - - /* Use for all ID lookups (can be NULL). */ - struct UndoIDPtrMap *id_map; } ImageUndoStep; -static void image_undosys_step_encode_store_ids(ImageUndoStep *us) -{ - us->id_map = BKE_undosys_ID_map_create(); - - ID *image_prev = NULL; - for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) { - BKE_undosys_ID_map_add_with_prev(us->id_map, &tile->ima->id, &image_prev); - } -} - -/* Restore at runtime. */ -#if 0 -static void paint_undosys_step_decode_restore_ids(ImageUndoStep *us) -{ - ID *image_prev[2] = {NULL}; - for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) { - tile->ima = (Image *)BKE_undosys_ID_map_lookup_with_prev( - us->id_map, &tile->ima->id, image_prev); - } -} -#endif - static bool image_undosys_poll(bContext *C) { Object *obact = CTX_data_active_object(C); @@ -486,8 +460,6 @@ static bool image_undosys_step_encode(struct bContext *C, us->paint_mode = paint_mode; } - image_undosys_step_encode_store_ids(us); - us_p->is_applied = true; return true; @@ -496,18 +468,18 @@ static bool image_undosys_step_encode(struct bContext *C, static void image_undosys_step_decode_undo_impl(ImageUndoStep *us) { BLI_assert(us->step.is_applied == true); - image_undo_restore_list(&us->tiles, us->id_map); + image_undo_restore_list(&us->tiles); us->step.is_applied = false; } static void image_undosys_step_decode_redo_impl(ImageUndoStep *us) { BLI_assert(us->step.is_applied == false); - image_undo_restore_list(&us->tiles, us->id_map); + image_undo_restore_list(&us->tiles); us->step.is_applied = true; } -static void image_undosys_step_decode_undo(ImageUndoStep *us) +static void image_undosys_step_decode_undo(ImageUndoStep *us, bool is_final) { ImageUndoStep *us_iter = us; while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) { @@ -516,8 +488,11 @@ static void image_undosys_step_decode_undo(ImageUndoStep *us) } us_iter = (ImageUndoStep *)us_iter->step.next; } - while (us_iter != us) { + while (us_iter != us || (!is_final && us_iter == us)) { image_undosys_step_decode_undo_impl(us_iter); + if (us_iter == us) { + break; + } us_iter = (ImageUndoStep *)us_iter->step.prev; } } @@ -541,15 +516,11 @@ static void image_undosys_step_decode_redo(ImageUndoStep *us) } static void image_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final)) + struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool is_final) { ImageUndoStep *us = (ImageUndoStep *)us_p; -#if 0 - paint_undosys_step_decode_restore_ids(us); -#endif - if (dir < 0) { - image_undosys_step_decode_undo(us); + image_undosys_step_decode_undo(us, is_final); } else { image_undosys_step_decode_redo(us); @@ -567,7 +538,6 @@ static void image_undosys_step_free(UndoStep *us_p) { ImageUndoStep *us = (ImageUndoStep *)us_p; image_undo_free_list(&us->tiles); - BKE_undosys_ID_map_destroy(us->id_map); } static void image_undosys_foreach_ID_ref(UndoStep *us_p, @@ -575,8 +545,8 @@ static void image_undosys_foreach_ID_ref(UndoStep *us_p, void *user_data) { ImageUndoStep *us = (ImageUndoStep *)us_p; - if (us->id_map != NULL) { - BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data); + for (UndoImageTile *tile = us->tiles.first; tile; tile = tile->next) { + foreach_ID_ref_fn(user_data, ((UndoRefID *)&tile->image_ref)); } } diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index f60ea8410ef..c7e2b008d1f 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -101,7 +101,7 @@ typedef struct MaskTaskData { static void mask_flood_fill_task_cb(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { MaskTaskData *data = userdata; @@ -159,7 +159,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) .value = value, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range( @@ -243,7 +243,7 @@ static void flip_plane(float out[4], const float in[4], const char symm) static void mask_box_select_task_cb(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { MaskTaskData *data = userdata; @@ -328,7 +328,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti * .clip_planes_final = clip_planes_final, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); @@ -405,7 +405,7 @@ static void mask_lasso_px_cb(int x, int x_end, int y, void *user_data) static void mask_gesture_lasso_task_cb(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { LassoMaskData *lasso_data = userdata; MaskTaskData *data = &lasso_data->task_data; @@ -515,7 +515,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) data.task_data.mode = mode; data.task_data.value = value; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && (totnode > SCULPT_THREADED_LIMIT)); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 980b043bf8b..47fa2872ff9 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1713,7 +1713,7 @@ static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintIn static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; const MDeformVert *dv = &data->me->dvert[n]; @@ -1737,7 +1737,7 @@ static void precompute_weight_values( .me = me, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); BLI_task_parallel_range(0, me->totvert, &data, do_wpaint_precompute_weight_cb_ex, &settings); @@ -1746,7 +1746,7 @@ static void precompute_weight_values( static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -1838,7 +1838,7 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -1949,7 +1949,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2022,7 +2022,7 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, } static void do_wpaint_brush_calc_average_weight_cb_ex( - void *__restrict userdata, const int n, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2078,7 +2078,7 @@ static void calculate_average_weight(SculptThreadedTaskData *data, struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__); data->custom_data = accum; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((data->sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); @@ -2127,7 +2127,7 @@ static void wpaint_paint_leaves(bContext *C, /* Use this so average can modify its weight without touching the brush. */ data.strength = BKE_brush_weight_get(scene, brush); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); /* NOTE: current mirroring code cannot be run in parallel */ settings.use_threading = !(me->editflag & ME_EDIT_MIRROR_X); @@ -2706,7 +2706,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f } static void do_vpaint_brush_calc_average_color_cb_ex( - void *__restrict userdata, const int n, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2772,7 +2772,7 @@ static float tex_color_alpha_ubyte(SculptThreadedTaskData *data, static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2871,7 +2871,7 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata, static void do_vpaint_brush_blur_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2989,7 +2989,7 @@ static void do_vpaint_brush_blur_task_cb_ex(void *__restrict userdata, static void do_vpaint_brush_smear_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3139,7 +3139,7 @@ static void calculate_average_color(SculptThreadedTaskData *data, struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__); data->custom_data = accum; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); BLI_task_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings); @@ -3185,7 +3185,7 @@ static void vpaint_paint_leaves(bContext *C, .lcol = (uint *)me->mloopcol, .me = me, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) { case VPAINT_TOOL_AVERAGE: diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 173d6ed5085..4b35fdbd2ed 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -368,7 +368,7 @@ static bool sculpt_stroke_is_dynamic_topology(const SculptSession *ss, const Bru static void paint_mesh_restore_co_task_cb(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -438,7 +438,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) .nodes = nodes, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && !ss->bm && totnode > SCULPT_THREADED_LIMIT); @@ -801,7 +801,7 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) static void calc_area_normal_and_center_task_cb(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -961,7 +961,7 @@ static void calc_area_center( }; BLI_mutex_init(&data.mutex); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); @@ -1018,7 +1018,7 @@ void sculpt_pbvh_calc_area_normal(const Brush *brush, }; BLI_mutex_init(&data.mutex); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = use_threading; BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); @@ -1063,7 +1063,7 @@ static void calc_area_normal_and_center( }; BLI_mutex_init(&data.mutex); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); @@ -1758,7 +1758,7 @@ typedef struct { static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -1813,7 +1813,7 @@ static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata, static void do_smooth_brush_bmesh_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -1868,7 +1868,7 @@ static void do_smooth_brush_bmesh_task_cb_ex(void *__restrict userdata, static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -1925,7 +1925,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptDoBrushSmoothGridDataChunk *data_chunk = tls->userdata_chunk; @@ -2115,7 +2115,7 @@ static void smooth(Sculpt *sd, .strength = strength, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); @@ -2175,7 +2175,7 @@ static void bmesh_topology_rake( .nodes = nodes, .strength = factor, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); @@ -2191,7 +2191,7 @@ static void do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2233,7 +2233,7 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot .nodes = nodes, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings); @@ -2256,7 +2256,7 @@ static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) static void do_draw_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2320,7 +2320,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .offset = offset, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings); @@ -2331,7 +2331,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) */ static void do_crease_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2436,7 +2436,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .flippedbstrength = flippedbstrength, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings); @@ -2444,7 +2444,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod static void do_pinch_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2498,7 +2498,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .nodes = nodes, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); @@ -2506,7 +2506,7 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode static void do_grab_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2570,7 +2570,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .grab_delta = grab_delta, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); @@ -2578,7 +2578,7 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) static void do_nudge_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2637,7 +2637,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .cono = cono, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings); @@ -2645,7 +2645,7 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2758,7 +2758,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to .grab_delta = grab_delta, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings); @@ -2766,7 +2766,7 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to static void do_thumb_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2830,7 +2830,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .cono = cono, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings); @@ -2838,7 +2838,7 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode static void do_rotate_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -2903,7 +2903,7 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .angle = angle, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings); @@ -2911,7 +2911,7 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod static void do_layer_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3000,7 +3000,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode }; BLI_mutex_init(&data.mutex); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings); @@ -3010,7 +3010,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode static void do_inflate_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3068,7 +3068,7 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno .nodes = nodes, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings); @@ -3184,7 +3184,7 @@ static float get_offset(Sculpt *sd, SculptSession *ss) static void do_flatten_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3266,7 +3266,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno .area_co = area_co, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings); @@ -3274,7 +3274,7 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno static void do_clay_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3364,7 +3364,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .area_co = area_co, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings); @@ -3372,7 +3372,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3494,7 +3494,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t .mat = mat, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings); @@ -3502,7 +3502,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t static void do_fill_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3587,7 +3587,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .area_co = area_co, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings); @@ -3595,7 +3595,7 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) static void do_scrape_brush_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3679,7 +3679,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .area_co = area_co, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings); @@ -3687,7 +3687,7 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod static void do_gravity_task_cb_ex(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -3748,7 +3748,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl .offset = offset, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); @@ -3862,7 +3862,7 @@ static void sculpt_topology_update(Sculpt *sd, static void do_brush_action_task_cb(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; @@ -3896,7 +3896,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe .nodes = nodes, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); @@ -4021,7 +4021,7 @@ static void sculpt_flush_pbvhvert_deform(Object *ob, PBVHVertexIter *vd) static void sculpt_combine_proxies_task_cb(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -4093,7 +4093,7 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) .nodes = nodes, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); @@ -4130,7 +4130,7 @@ static void sculpt_update_keyblock(Object *ob) static void sculpt_flush_stroke_deform_task_cb(void *__restrict userdata, const int n, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; @@ -4186,7 +4186,7 @@ static void sculpt_flush_stroke_deform(Sculpt *sd, Object *ob) .vertCos = vertCos, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range(0, totnode, &data, sculpt_flush_stroke_deform_task_cb, &settings); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 81bb9c35817..e9d17b11ccc 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -323,7 +323,7 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode) } static void sculpt_undo_bmesh_restore_generic_task_cb( - void *__restrict userdata, const int n, const ParallelRangeTLS *__restrict UNUSED(tls)) + void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) { PBVHNode **nodes = userdata; @@ -351,7 +351,7 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C, BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); BLI_task_parallel_range( diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 7cc222ea529..9e2634b183a 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -1199,9 +1199,14 @@ static void select_moreless_action_keys(bAnimContext *ac, short mode) ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); for (ale = anim_data.first; ale; ale = ale->next) { - FCurve *fcu = (FCurve *)ale->key_data; + + /* TODO: other types. */ + if (ale->datatype != ALE_FCURVE) { + continue; + } /* only continue if F-Curve has keyframes */ + FCurve *fcu = (FCurve *)ale->key_data; if (fcu->bezt == NULL) { continue; } diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index ef5de1acee3..3f705aad89a 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -48,6 +48,7 @@ #include "clip_intern.h" // own include typedef struct TrackMotionCurveUserData { + SpaceClip *sc; MovieTrackingTrack *act_track; bool sel; float xscale, yscale, hsize; @@ -57,24 +58,43 @@ typedef struct TrackMotionCurveUserData { static void tracking_segment_point_cb(void *userdata, MovieTrackingTrack *UNUSED(track), MovieTrackingMarker *UNUSED(marker), - int UNUSED(coord), + eClipCurveValueSource value_source, int scene_framenr, float val) { TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata; + if (!clip_graph_value_visible(data->sc, value_source)) { + return; + } + immVertex2f(data->pos, scene_framenr, val); } static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, - int coord, + eClipCurveValueSource value_source, bool is_point) { TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata; + SpaceClip *sc = data->sc; float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - col[coord] = 1.0f; + if (!clip_graph_value_visible(sc, value_source)) { + return; + } + + switch (value_source) { + case CLIP_VALUE_SOURCE_SPEED_X: + col[0] = 1.0f; + break; + case CLIP_VALUE_SOURCE_SPEED_Y: + col[1] = 1.0f; + break; + case CLIP_VALUE_SOURCE_REPROJECTION_ERROR: + col[2] = 1.0f; + break; + } if (track == data->act_track) { col[3] = 1.0f; @@ -96,15 +116,20 @@ static void tracking_segment_start_cb(void *userdata, } } -static void tracking_segment_end_cb(void *UNUSED(userdata), int UNUSED(coord)) +static void tracking_segment_end_cb(void *userdata, eClipCurveValueSource value_source) { + TrackMotionCurveUserData *data = (TrackMotionCurveUserData *)userdata; + SpaceClip *sc = data->sc; + if (!clip_graph_value_visible(sc, value_source)) { + return; + } immEnd(); } static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int coord, + eClipCurveValueSource value_source, int scene_framenr, float val) { @@ -114,8 +139,11 @@ static void tracking_segment_knot_cb(void *userdata, if (track != data->act_track) { return; } + if (!ELEM(value_source, CLIP_VALUE_SOURCE_SPEED_X, CLIP_VALUE_SOURCE_SPEED_Y)) { + return; + } - sel_flag = coord == 0 ? MARKER_GRAPH_SEL_X : MARKER_GRAPH_SEL_Y; + sel_flag = value_source == CLIP_VALUE_SOURCE_SPEED_X ? MARKER_GRAPH_SEL_X : MARKER_GRAPH_SEL_Y; sel = (marker->flag & sel_flag) ? 1 : 0; if (sel == data->sel) { @@ -131,34 +159,39 @@ static void tracking_segment_knot_cb(void *userdata, } } -static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int pos) +static void draw_tracks_motion_and_error_curves(View2D *v2d, SpaceClip *sc, unsigned int pos) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); - int width, height; - TrackMotionCurveUserData userdata; + const bool draw_knots = (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) != 0; + int width, height; BKE_movieclip_get_size(clip, &sc->user, &width, &height); - if (!width || !height) { return; } - /* non-selected knot handles */ + TrackMotionCurveUserData userdata; + userdata.sc = sc; userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); userdata.sel = false; userdata.act_track = act_track; userdata.pos = pos; - UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale); - clip_graph_tracking_values_iterate(sc, - (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, - (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, - &userdata, - tracking_segment_knot_cb, - NULL, - NULL); - /* draw graph lines */ + + /* Non-selected knot handles. */ + if (draw_knots) { + UI_view2d_scale_get(v2d, &userdata.xscale, &userdata.yscale); + clip_graph_tracking_values_iterate(sc, + (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, + (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, + &userdata, + tracking_segment_knot_cb, + NULL, + NULL); + } + + /* Draw graph lines. */ GPU_blend(true); clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, @@ -169,138 +202,19 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int p tracking_segment_end_cb); GPU_blend(false); - /* selected knot handles on top of curves */ - userdata.sel = true; - clip_graph_tracking_values_iterate(sc, - (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, - (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, - &userdata, - tracking_segment_knot_cb, - NULL, - NULL); -} - -typedef struct TrackErrorCurveUserData { - MovieClip *clip; - MovieTracking *tracking; - MovieTrackingObject *tracking_object; - MovieTrackingTrack *active_track; - bool matrix_initialized; - int matrix_frame; - float projection_matrix[4][4]; - int width, height; - float aspy; - unsigned int pos; -} TrackErrorCurveUserData; - -static void tracking_error_segment_point_cb(void *userdata, - MovieTrackingTrack *track, - MovieTrackingMarker *marker, - int coord, - int scene_framenr, - float UNUSED(value)) -{ - if (coord == 1) { - TrackErrorCurveUserData *data = (TrackErrorCurveUserData *)userdata; - float reprojected_position[4], bundle_position[4], marker_position[2], delta[2]; - float reprojection_error; - float weight = BKE_tracking_track_get_weight_for_marker(data->clip, track, marker); - - if (!data->matrix_initialized || data->matrix_frame != scene_framenr) { - BKE_tracking_get_projection_matrix(data->tracking, - data->tracking_object, - scene_framenr, - data->width, - data->height, - data->projection_matrix); - } - - copy_v3_v3(bundle_position, track->bundle_pos); - bundle_position[3] = 1; - - mul_v4_m4v4(reprojected_position, data->projection_matrix, bundle_position); - reprojected_position[0] = (reprojected_position[0] / (reprojected_position[3] * 2.0f) + 0.5f) * - data->width; - reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) * - data->height * data->aspy; - - BKE_tracking_distort_v2(data->tracking, reprojected_position, reprojected_position); - - marker_position[0] = (marker->pos[0] + track->offset[0]) * data->width; - marker_position[1] = (marker->pos[1] + track->offset[1]) * data->height * data->aspy; - - sub_v2_v2v2(delta, reprojected_position, marker_position); - reprojection_error = len_v2(delta) * weight; - - immVertex2f(data->pos, scene_framenr, reprojection_error); - } -} - -static void tracking_error_segment_start_cb(void *userdata, - MovieTrackingTrack *track, - int coord, - bool is_point) -{ - if (coord == 1) { - TrackErrorCurveUserData *data = (TrackErrorCurveUserData *)userdata; - float col[4] = {0.0f, 0.0f, 1.0f, 1.0f}; - - if (track == data->active_track) { - col[3] = 1.0f; - GPU_line_width(2.0f); - } - else { - col[3] = 0.5f; - GPU_line_width(1.0f); - } - - immUniformColor4fv(col); - - if (is_point) { /* This probably never happens here, but just in case... */ - immBeginAtMost(GPU_PRIM_POINTS, 1); - } - else { - /* Graph can be composed of smaller segments, if any marker is disabled */ - immBeginAtMost(GPU_PRIM_LINE_STRIP, track->markersnr); - } - } -} - -static void tracking_error_segment_end_cb(void *UNUSED(userdata), int coord) -{ - if (coord == 1) { - immEnd(); + /* Selected knot handles on top of curves. */ + if (draw_knots) { + userdata.sel = true; + clip_graph_tracking_values_iterate(sc, + (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, + (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, + &userdata, + tracking_segment_knot_cb, + NULL, + NULL); } } -static void draw_tracks_error_curves(SpaceClip *sc, unsigned int pos) -{ - MovieClip *clip = ED_space_clip_get_clip(sc); - MovieTracking *tracking = &clip->tracking; - TrackErrorCurveUserData data; - - data.clip = clip; - data.tracking = tracking; - data.tracking_object = BKE_tracking_object_get_active(tracking); - data.active_track = BKE_tracking_track_get_active(tracking); - data.matrix_initialized = false; - data.pos = pos; - BKE_movieclip_get_size(clip, &sc->user, &data.width, &data.height); - data.aspy = 1.0f / tracking->camera.pixel_aspect; - - if (!data.width || !data.height) { - return; - } - - clip_graph_tracking_values_iterate(sc, - (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, - (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, - &data, - tracking_error_segment_point_cb, - tracking_error_segment_start_cb, - tracking_error_segment_end_cb); -} - static void draw_frame_curves(SpaceClip *sc, unsigned int pos) { MovieClip *clip = ED_space_clip_get_clip(sc); @@ -350,12 +264,8 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene) GPU_point_size(3.0f); - if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) { - draw_tracks_motion_curves(v2d, sc, pos); - } - - if (sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) { - draw_tracks_error_curves(sc, pos); + if (sc->flag & (SC_SHOW_GRAPH_TRACKS_MOTION | SC_SHOW_GRAPH_TRACKS_ERROR)) { + draw_tracks_motion_and_error_curves(v2d, sc, pos); } if (sc->flag & SC_SHOW_GRAPH_FRAMES) { diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index a3722433e33..58a00d2e6b9 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -64,7 +64,7 @@ static bool clip_graph_knots_poll(bContext *C) if (ED_space_clip_graph_poll(C)) { SpaceClip *sc = CTX_wm_space_clip(C); - return (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) != 0; + return (sc->flag & (SC_SHOW_GRAPH_TRACKS_MOTION | SC_SHOW_GRAPH_TRACKS_ERROR)) != 0; } return false; } @@ -93,13 +93,14 @@ static void toggle_selection_cb(void *userdata, MovieTrackingMarker *marker) /******************** mouse select operator ********************/ typedef struct { - int coord; /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */ + SpaceClip *sc; + eClipCurveValueSource value_source; bool has_prev; /* if there's valid coordinate of previous point of curve segment */ - float min_dist_sq, /* minimal distance between mouse and currently found entity */ - mouse_co[2], /* mouse coordinate */ - prev_co[2], /* coordinate of previeous point of segment */ - min_co[2]; /* coordinate of entity with minimal distance */ + float min_dist_sq; /* minimal distance between mouse and currently found entity */ + float mouse_co[2]; /* mouse coordinate */ + float prev_co[2]; /* coordinate of previous point of segment */ + float min_co[2]; /* coordinate of entity with minimal distance */ MovieTrackingTrack *track; /* nearest found track */ MovieTrackingMarker *marker; /* nearest found marker */ @@ -108,20 +109,24 @@ typedef struct { static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *UNUSED(marker), - int coord, + eClipCurveValueSource value_source, int scene_framenr, float val) { MouseSelectUserData *data = userdata; float co[2] = {scene_framenr, val}; + if (!clip_graph_value_visible(data->sc, value_source)) { + return; + } + if (data->has_prev) { float dist_sq = dist_squared_to_line_segment_v2(data->mouse_co, data->prev_co, co); if (data->track == NULL || dist_sq < data->min_dist_sq) { data->track = track; data->min_dist_sq = dist_sq; - data->coord = coord; + data->value_source = value_source; copy_v2_v2(data->min_co, co); } } @@ -130,7 +135,8 @@ static void find_nearest_tracking_segment_cb(void *userdata, copy_v2_v2(data->prev_co, co); } -static void find_nearest_tracking_segment_end_cb(void *userdata, int UNUSED(coord)) +static void find_nearest_tracking_segment_end_cb(void *userdata, + eClipCurveValueSource UNUSED(source_value)) { MouseSelectUserData *data = userdata; @@ -140,7 +146,7 @@ static void find_nearest_tracking_segment_end_cb(void *userdata, int UNUSED(coor static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int coord, + eClipCurveValueSource value_source, int scene_framenr, float val) { @@ -148,20 +154,26 @@ static void find_nearest_tracking_knot_cb(void *userdata, float mdiff[2] = {scene_framenr - data->mouse_co[0], val - data->mouse_co[1]}; float dist_sq = len_squared_v2(mdiff); + if (!clip_graph_value_visible(data->sc, value_source)) { + return; + } + if (data->marker == NULL || dist_sq < data->min_dist_sq) { float co[2] = {scene_framenr, val}; data->track = track; data->marker = marker; data->min_dist_sq = dist_sq; - data->coord = coord; + data->value_source = value_source; copy_v2_v2(data->min_co, co); } } -static void mouse_select_init_data(MouseSelectUserData *userdata, const float co[2]) +static void mouse_select_init_data(bContext *C, MouseSelectUserData *userdata, const float co[2]) { + SpaceClip *sc = CTX_wm_space_clip(C); memset(userdata, 0, sizeof(MouseSelectUserData)); + userdata->sc = sc; userdata->min_dist_sq = FLT_MAX; copy_v2_v2(userdata->mouse_co, co); } @@ -179,7 +191,7 @@ static bool mouse_select_knot(bContext *C, float co[2], bool extend) if (act_track) { MouseSelectUserData userdata; - mouse_select_init_data(&userdata, co); + mouse_select_init_data(C, &userdata, co); clip_graph_tracking_values_iterate_track( sc, act_track, &userdata, find_nearest_tracking_knot_cb, NULL, NULL); @@ -199,7 +211,7 @@ static bool mouse_select_knot(bContext *C, float co[2], bool extend) toggle_selection_cb); } - if (userdata.coord == 0) { + if (userdata.value_source == CLIP_VALUE_SOURCE_SPEED_X) { if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_X) != 0) { userdata.marker->flag &= ~MARKER_GRAPH_SEL_X; } @@ -207,7 +219,7 @@ static bool mouse_select_knot(bContext *C, float co[2], bool extend) userdata.marker->flag |= MARKER_GRAPH_SEL_X; } } - else { + else if (userdata.value_source == CLIP_VALUE_SOURCE_SPEED_Y) { if (extend && (userdata.marker->flag & MARKER_GRAPH_SEL_Y) != 0) { userdata.marker->flag &= ~MARKER_GRAPH_SEL_Y; } @@ -232,7 +244,7 @@ static bool mouse_select_curve(bContext *C, float co[2], bool extend) MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); MouseSelectUserData userdata; - mouse_select_init_data(&userdata, co); + mouse_select_init_data(C, &userdata, co); clip_graph_tracking_values_iterate(sc, (sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0, (sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0, @@ -281,7 +293,7 @@ static int mouse_select(bContext *C, float co[2], bool extend) sel = mouse_select_knot(C, co, extend); if (!sel) { - /* if there's no close enough knot to mouse osition, select nearest curve */ + /* if there's no close enough knot to mouse position, select nearest curve */ sel = mouse_select_curve(C, co, extend); } @@ -356,16 +368,19 @@ typedef struct BoxSelectuserData { static void box_select_cb(void *userdata, MovieTrackingTrack *UNUSED(track), MovieTrackingMarker *marker, - int coord, + eClipCurveValueSource value_source, int scene_framenr, float val) { BoxSelectuserData *data = (BoxSelectuserData *)userdata; + if (!ELEM(value_source, CLIP_VALUE_SOURCE_SPEED_X, CLIP_VALUE_SOURCE_SPEED_Y)) { + return; + } if (BLI_rctf_isect_pt(&data->rect, scene_framenr, val)) { int flag = 0; - if (coord == 0) { + if (value_source == CLIP_VALUE_SOURCE_SPEED_X) { flag = MARKER_GRAPH_SEL_X; } else { @@ -591,7 +606,7 @@ typedef struct { static void view_all_cb(void *userdata, MovieTrackingTrack *UNUSED(track), MovieTrackingMarker *UNUSED(marker), - int UNUSED(coord), + eClipCurveValueSource UNUSED(value_source), int UNUSED(scene_framenr), float val) { diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 7683823a79f..8599de9f16f 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -112,35 +112,44 @@ void CLIP_OT_cursor_set(struct wmOperatorType *ot); struct ARegion *ED_clip_has_properties_region(struct ScrArea *sa); /* clip_utils.c */ -void clip_graph_tracking_values_iterate_track( - struct SpaceClip *sc, - struct MovieTrackingTrack *track, - void *userdata, - void (*func)(void *userdata, - struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, - int coord, - int scene_framenr, - float val), - void (*segment_start)( - void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point), - void (*segment_end)(void *userdata, int coord)); + +typedef enum { + CLIP_VALUE_SOURCE_SPEED_X, + CLIP_VALUE_SOURCE_SPEED_Y, + CLIP_VALUE_SOURCE_REPROJECTION_ERROR, +} eClipCurveValueSource; + +typedef void (*ClipTrackValueCallback)(void *userdata, + struct MovieTrackingTrack *track, + struct MovieTrackingMarker *marker, + eClipCurveValueSource value_source, + int scene_framenr, + float val); + +typedef void (*ClipTrackValueSegmentStartCallback)(void *userdata, + struct MovieTrackingTrack *track, + eClipCurveValueSource value_source, + bool is_point); + +typedef void (*ClipTrackValueSegmentEndCallback)(void *userdata, + eClipCurveValueSource value_source); + +bool clip_graph_value_visible(struct SpaceClip *sc, eClipCurveValueSource value_source); + +void clip_graph_tracking_values_iterate_track(struct SpaceClip *sc, + struct MovieTrackingTrack *track, + void *userdata, + ClipTrackValueCallback func, + ClipTrackValueSegmentStartCallback segment_start, + ClipTrackValueSegmentEndCallback segment_end); void clip_graph_tracking_values_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata, - void (*func)(void *userdata, - struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, - int coord, - int scene_framenr, - float val), - void (*segment_start)(void *userdata, - struct MovieTrackingTrack *track, - int coord, - bool is_point), - void (*segment_end)(void *userdata, int coord)); + ClipTrackValueCallback func, + ClipTrackValueSegmentStartCallback segment_start, + ClipTrackValueSegmentEndCallback segment_end); void clip_graph_tracking_iterate(struct SpaceClip *sc, bool selected_only, diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 45479c4253d..e1af9728685 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1434,7 +1434,7 @@ static void proxy_endjob(void *pjv) if (pj->clip->source == MCLIP_SRC_MOVIE) { /* Timecode might have changed, so do a full reload to deal with this. */ - BKE_movieclip_reload(pj->main, pj->clip); + DEG_id_tag_update(&pj->clip->id, ID_RECALC_SOURCE); } else { /* For image sequences we'll preserve original cache. */ diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 3dfe529f8e8..48f788e2e3a 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -27,6 +27,7 @@ #include "BLI_utildefines.h" #include "BLI_listbase.h" +#include "BLI_math.h" #include "BKE_animsys.h" #include "BKE_context.h" @@ -52,18 +53,28 @@ #include "clip_intern.h" // own include -void clip_graph_tracking_values_iterate_track( +bool clip_graph_value_visible(SpaceClip *sc, eClipCurveValueSource value_source) +{ + if (ELEM(value_source, CLIP_VALUE_SOURCE_SPEED_X, CLIP_VALUE_SOURCE_SPEED_Y)) { + if ((sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) == 0) { + return false; + } + } + else if (value_source == CLIP_VALUE_SOURCE_REPROJECTION_ERROR) { + if ((sc->flag & SC_SHOW_GRAPH_TRACKS_ERROR) == 0) { + return false; + } + } + return true; +} + +static void clip_graph_tracking_values_iterate_track_speed_values( SpaceClip *sc, MovieTrackingTrack *track, void *userdata, - void (*func)(void *userdata, - MovieTrackingTrack *track, - MovieTrackingMarker *marker, - int coord, - int scene_framenr, - float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point), - void (*segment_end)(void *userdata, int coord)) + ClipTrackValueCallback func, + ClipTrackValueSegmentStartCallback segment_start, + ClipTrackValueSegmentEndCallback segment_end) { MovieClip *clip = ED_space_clip_get_clip(sc); int width, height, coord; @@ -71,6 +82,8 @@ void clip_graph_tracking_values_iterate_track( BKE_movieclip_get_size(clip, &sc->user, &width, &height); for (coord = 0; coord < 2; coord++) { + eClipCurveValueSource value_source = (coord == 0) ? CLIP_VALUE_SOURCE_SPEED_X : + CLIP_VALUE_SOURCE_SPEED_Y; int i, prevfra = track->markers[0].framenr; bool open = false; float prevval = 0.0f; @@ -82,7 +95,7 @@ void clip_graph_tracking_values_iterate_track( if (marker->flag & MARKER_DISABLED) { if (open) { if (segment_end) { - segment_end(userdata, coord); + segment_end(userdata, value_source); } open = false; @@ -94,10 +107,11 @@ void clip_graph_tracking_values_iterate_track( if (!open) { if (segment_start) { if ((i + 1) == track->markersnr) { - segment_start(userdata, track, coord, true); + segment_start(userdata, track, value_source, true); } else { - segment_start(userdata, track, coord, (track->markers[i + 1].flag & MARKER_DISABLED)); + segment_start( + userdata, track, value_source, (track->markers[i + 1].flag & MARKER_DISABLED)); } } @@ -112,7 +126,7 @@ void clip_graph_tracking_values_iterate_track( if (func) { int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); - func(userdata, track, marker, coord, scene_framenr, val); + func(userdata, track, marker, value_source, scene_framenr, val); } prevval = marker->pos[coord]; @@ -121,25 +135,139 @@ void clip_graph_tracking_values_iterate_track( if (open) { if (segment_end) { - segment_end(userdata, coord); + segment_end(userdata, value_source); } } } } -void clip_graph_tracking_values_iterate( +static float calculate_reprojection_error_at_marker(MovieClip *clip, + MovieTracking *tracking, + MovieTrackingObject *tracking_object, + MovieTrackingTrack *track, + MovieTrackingMarker *marker, + const int clip_width, + const int clip_height, + const int scene_framenr) +{ + float reprojected_position[4], bundle_position[4], marker_position[2], delta[2]; + float weight = BKE_tracking_track_get_weight_for_marker(clip, track, marker); + const float aspy = 1.0f / tracking->camera.pixel_aspect; + + float projection_matrix[4][4]; + BKE_tracking_get_projection_matrix( + tracking, tracking_object, scene_framenr, clip_width, clip_height, projection_matrix); + + copy_v3_v3(bundle_position, track->bundle_pos); + bundle_position[3] = 1; + + mul_v4_m4v4(reprojected_position, projection_matrix, bundle_position); + reprojected_position[0] = (reprojected_position[0] / (reprojected_position[3] * 2.0f) + 0.5f) * + clip_width; + reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) * + clip_height * aspy; + + BKE_tracking_distort_v2(tracking, reprojected_position, reprojected_position); + + marker_position[0] = (marker->pos[0] + track->offset[0]) * clip_width; + marker_position[1] = (marker->pos[1] + track->offset[1]) * clip_height * aspy; + + sub_v2_v2v2(delta, reprojected_position, marker_position); + return len_v2(delta) * weight; +} + +static void clip_graph_tracking_values_iterate_track_reprojection_error_values( SpaceClip *sc, - bool selected_only, - bool include_hidden, + MovieTrackingTrack *track, void *userdata, - void (*func)(void *userdata, - MovieTrackingTrack *track, - MovieTrackingMarker *marker, - int coord, - int scene_framenr, - float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point), - void (*segment_end)(void *userdata, int coord)) + ClipTrackValueCallback func, + ClipTrackValueSegmentStartCallback segment_start, + ClipTrackValueSegmentEndCallback segment_end) +{ + /* Tracks without bundle can not have any reprojection error curve. */ + if ((track->flag & TRACK_HAS_BUNDLE) == 0) { + return; + } + + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object = BKE_tracking_object_get_active(tracking); + + int clip_width, clip_height; + BKE_movieclip_get_size(clip, &sc->user, &clip_width, &clip_height); + + /* Iterate over segments. */ + bool is_segment_open = false; + for (int marker_index = 0; marker_index < track->markersnr; marker_index++) { + MovieTrackingMarker *marker = &track->markers[marker_index]; + + /* End of tracked segment, no reprojection error can be calculated here since the ground truth + * 2D position is not known. */ + if (marker->flag & MARKER_DISABLED) { + if (is_segment_open) { + if (segment_end != NULL) { + segment_end(userdata, CLIP_VALUE_SOURCE_REPROJECTION_ERROR); + } + is_segment_open = false; + } + continue; + } + + /* Begin new segment if it is not open yet. */ + if (!is_segment_open) { + if (segment_start != NULL) { + if ((marker_index + 1) == track->markersnr) { + segment_start(userdata, track, CLIP_VALUE_SOURCE_REPROJECTION_ERROR, true); + } + else { + segment_start(userdata, + track, + CLIP_VALUE_SOURCE_REPROJECTION_ERROR, + (track->markers[marker_index + 1].flag & MARKER_DISABLED)); + } + } + is_segment_open = true; + } + + if (func != NULL) { + const int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr); + const float reprojection_error = calculate_reprojection_error_at_marker( + clip, tracking, tracking_object, track, marker, clip_width, clip_height, scene_framenr); + func(userdata, + track, + marker, + CLIP_VALUE_SOURCE_REPROJECTION_ERROR, + scene_framenr, + reprojection_error); + } + } + + if (is_segment_open && segment_end != NULL) { + segment_end(userdata, CLIP_VALUE_SOURCE_REPROJECTION_ERROR); + } +} + +void clip_graph_tracking_values_iterate_track(SpaceClip *sc, + MovieTrackingTrack *track, + void *userdata, + ClipTrackValueCallback func, + ClipTrackValueSegmentStartCallback segment_start, + ClipTrackValueSegmentEndCallback segment_end) +{ + clip_graph_tracking_values_iterate_track_speed_values( + sc, track, userdata, func, segment_start, segment_end); + + clip_graph_tracking_values_iterate_track_reprojection_error_values( + sc, track, userdata, func, segment_start, segment_end); +} + +void clip_graph_tracking_values_iterate(SpaceClip *sc, + bool selected_only, + bool include_hidden, + void *userdata, + ClipTrackValueCallback func, + ClipTrackValueSegmentStartCallback segment_start, + ClipTrackValueSegmentEndCallback segment_end) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index d8d50ba72b5..1375b99bdaa 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1894,6 +1894,7 @@ static int tracking_object_new_exec(bContext *C, wmOperator *UNUSED(op)) BKE_tracking_object_add(tracking, "Object"); + DEG_id_tag_update(&clip->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); return OPERATOR_FINISHED; @@ -1932,6 +1933,7 @@ static int tracking_object_remove_exec(bContext *C, wmOperator *op) BKE_tracking_object_delete(tracking, object); + DEG_id_tag_update(&clip->id, ID_RECALC_COPY_ON_WRITE); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_clip/tracking_ops_solve.c b/source/blender/editors/space_clip/tracking_ops_solve.c index 4490655393e..806df4dbaff 100644 --- a/source/blender/editors/space_clip/tracking_ops_solve.c +++ b/source/blender/editors/space_clip/tracking_ops_solve.c @@ -122,8 +122,14 @@ static void solve_camera_freejob(void *scv) solved = BKE_tracking_reconstruction_finish(scj->context, tracking); if (!solved) { - BKE_report( - scj->reports, RPT_WARNING, "Some data failed to reconstruct (see console for details)"); + const char *error_message = BKE_tracking_reconstruction_error_message_get(scj->context); + if (error_message[0]) { + BKE_report(scj->reports, RPT_ERROR, error_message); + } + else { + BKE_report( + scj->reports, RPT_WARNING, "Some data failed to reconstruct (see console for details)"); + } } else { BKE_reportf(scj->reports, @@ -146,6 +152,7 @@ static void solve_camera_freejob(void *scv) int width, height; BKE_movieclip_get_size(clip, &scj->user, &width, &height); BKE_tracking_camera_to_blender(tracking, scene, camera, width, height); + DEG_id_tag_update(&camera->id, ID_RECALC_COPY_ON_WRITE); WM_main_add_notifier(NC_OBJECT, camera); } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 9004eaa7bf6..e06ee620ea7 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1317,6 +1317,9 @@ static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size) cache->size = cache_size; cache->flags = FLC_IS_INIT; + + /* We cannot translate from non-main thread, so init translated strings once from here. */ + IMB_thumb_ensure_translations(); } static void filelist_cache_free(FileListEntryCache *cache) diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 89eb3b9d953..f9905cc4fcd 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -747,6 +747,7 @@ static void clear_animdata_cb(int UNUSED(event), void *UNUSED(arg)) { BKE_animdata_free(tselem->id, true); + DEG_id_tag_update(tselem->id, ID_RECALC_ANIMATION); } static void unlinkact_animdata_cb(int UNUSED(event), @@ -756,6 +757,7 @@ static void unlinkact_animdata_cb(int UNUSED(event), { /* just set action to NULL */ BKE_animdata_set_action(NULL, tselem->id, NULL); + DEG_id_tag_update(tselem->id, ID_RECALC_ANIMATION); } static void cleardrivers_animdata_cb(int UNUSED(event), @@ -767,6 +769,7 @@ static void cleardrivers_animdata_cb(int UNUSED(event), /* just free drivers - stored as a list of F-Curves */ free_fcurves(&iat->adt->drivers); + DEG_id_tag_update(tselem->id, ID_RECALC_ANIMATION); } static void refreshdrivers_animdata_cb(int UNUSED(event), @@ -1899,7 +1902,6 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) SpaceOutliner *soops = CTX_wm_space_outliner(C); int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; eOutliner_AnimDataOps event; - short updateDeps = 0; /* check for invalid states */ if (soops == NULL) { @@ -1943,7 +1945,6 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL); // ED_undo_push(C, "Refresh Drivers"); /* no undo needed - shouldn't have any impact? */ - updateDeps = 1; break; case OUTLINER_ANIMOP_CLEAR_DRV: @@ -1952,7 +1953,6 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL); ED_undo_push(C, "Clear Drivers"); - updateDeps = 1; break; default: // invalid @@ -1960,10 +1960,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) } /* update dependencies */ - if (updateDeps) { - /* rebuild depsgraph for the new deps */ - DEG_relations_tag_update(CTX_data_main(C)); - } + DEG_relations_tag_update(CTX_data_main(C)); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index 2aebc6c97fb..c55d77800ff 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -452,7 +452,7 @@ typedef struct MakeHistogramViewData { static void make_histogram_view_from_ibuf_byte_cb_ex(void *__restrict userdata, const int y, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { MakeHistogramViewData *data = userdata; const ImBuf *ibuf = data->ibuf; @@ -498,7 +498,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) .ibuf = ibuf, .bins = bins, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y >= 256); settings.userdata_chunk = bins; @@ -553,7 +553,7 @@ BLI_INLINE int get_bin_float(float f) static void make_histogram_view_from_ibuf_float_cb_ex(void *__restrict userdata, const int y, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { const MakeHistogramViewData *data = userdata; const ImBuf *ibuf = data->ibuf; @@ -584,7 +584,7 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) .ibuf = ibuf, .bins = bins, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y >= 256); settings.userdata_chunk = bins; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 8d8b314e525..84012ee26cc 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -803,13 +803,19 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool a GPU_depth_test(true); + /* Needed in cases the view-port isn't already setup. */ + WM_draw_region_viewport_ensure(ar, SPACE_VIEW3D); + WM_draw_region_viewport_bind(ar); + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); /* When Blender is starting, a click event can trigger a depth test while the viewport is not * yet available. */ if (viewport != NULL) { - DRW_draw_depth_loop(depsgraph, ar, v3d, viewport); + DRW_draw_depth_loop(depsgraph, ar, v3d, viewport, false); } + WM_draw_region_viewport_unbind(ar); + if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_disable(); } diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 386c3164843..4c03995307a 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -155,11 +155,13 @@ void ED_view3d_clipping_enable(void) /** * \note Only use in object mode. */ -static void validate_object_select_id( - struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, Object *obact) +static void validate_object_select_id(struct Depsgraph *depsgraph, + Scene *scene, + ViewLayer *view_layer, + ARegion *ar, + View3D *v3d, + Object *obact) { - RegionView3D *rv3d = ar->regiondata; - Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); @@ -186,19 +188,8 @@ static void validate_object_select_id( } if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { - uint dummy_vert_ofs, dummy_edge_ofs, dummy_face_ofs; - DRW_framebuffer_select_id_setup(ar, true); - DRW_draw_select_id_object(scene_eval, - rv3d, - obact_eval, - scene->toolsettings->selectmode, - false, - 1, - &dummy_vert_ofs, - &dummy_edge_ofs, - &dummy_face_ofs); - - DRW_framebuffer_select_id_release(ar); + DRW_draw_select_id_object( + depsgraph, view_layer, ar, v3d, obact, scene->toolsettings->selectmode); } /* TODO: Create a flag in `DRW_manager` because the drawing is no longer @@ -233,7 +224,8 @@ void ED_view3d_select_id_validate(ViewContext *vc) /* TODO: Create a flag in `DRW_manager` because the drawing is no longer * made on the backbuffer in this case. */ if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - validate_object_select_id(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact); + validate_object_select_id( + vc->depsgraph, vc->scene, vc->view_layer, vc->ar, vc->v3d, vc->obact); } } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 7c4b35507b9..fd0d9c6891f 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2924,12 +2924,12 @@ static int viewselected_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); - bGPdata *gpd = CTX_data_gpencil_data(C); - const bool is_gp_edit = GPENCIL_ANY_MODE(gpd); - const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map && - WM_gizmomap_is_any_selected(ar->gizmo_map)); Object *ob_eval = OBACT(view_layer_eval); Object *obedit = CTX_data_edit_object(C); + const bGPdata *gpd_eval = ob_eval && (ob_eval->type == OB_GPENCIL) ? ob_eval->data : NULL; + const bool is_gp_edit = gpd_eval ? GPENCIL_ANY_MODE(gpd_eval) : false; + const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map && + WM_gizmomap_is_any_selected(ar->gizmo_map)); float min[3], max[3]; bool ok = false, ok_dist = true; const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 61de61c8e31..754c8359d28 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -111,192 +111,6 @@ // #include "PIL_time_utildefines.h" /* -------------------------------------------------------------------- */ -/** \name Selection Utilities - * \{ */ - -struct EDBaseOffset { - /* For convenience only. */ - union { - uint offset; - uint face_start; - }; - union { - uint face; - uint edge_start; - }; - union { - uint edge; - uint vert_start; - }; - uint vert; -}; - -struct EDSelectID_Context { - struct EDBaseOffset *base_array_index_offsets; - /** Borrow from caller (not freed). */ - struct Base **bases; - uint bases_len; - /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */ - uint base_array_index_len; - /** Used to check for changes. (Use depsgraph instead?). */ - float persmat[4][4]; - short select_mode; -}; - -static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt) -{ - if (select_mode & SCE_SELECT_FACE) { - if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) { - return true; - } - if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) { - return true; - } - if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) { - /* Since we can't deduce face selection when edges aren't visible - show dots. */ - return true; - } - } - return false; -} - -static void ed_select_id_draw_bases(struct EDSelectID_Context *sel_id_ctx, - ViewContext *vc, - short select_mode) -{ - Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id); - DRW_framebuffer_select_id_setup(vc->ar, true); - - uint offset = 1; - for (uint base_index = 0; base_index < sel_id_ctx->bases_len; base_index++) { - Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, - sel_id_ctx->bases[base_index]->object); - - struct EDBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index]; - bool draw_facedot = check_ob_drawface_dot(select_mode, vc->v3d, ob_eval->dt); - - DRW_draw_select_id_object(scene_eval, - vc->rv3d, - ob_eval, - select_mode, - draw_facedot, - offset, - &base_ofs->vert, - &base_ofs->edge, - &base_ofs->face); - - base_ofs->offset = offset; - offset = base_ofs->vert; - } - - sel_id_ctx->base_array_index_len = offset; - - DRW_framebuffer_select_id_release(vc->ar); -} - -void ED_view3d_select_id_validate_view_matrices(struct EDSelectID_Context *sel_id_ctx, - ViewContext *vc) -{ - if (!compare_m4m4(sel_id_ctx->persmat, vc->rv3d->persmat, FLT_EPSILON)) { - ed_select_id_draw_bases(sel_id_ctx, vc, sel_id_ctx->select_mode); - } -} - -uint ED_view3d_select_id_context_offset_for_object_elem( - const struct EDSelectID_Context *sel_id_ctx, int base_index, char elem_type) -{ - struct EDBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index]; - if (elem_type == SCE_SELECT_VERTEX) { - return base_ofs->vert_start - 1; - } - if (elem_type == SCE_SELECT_EDGE) { - return base_ofs->edge_start - 1; - } - if (elem_type == SCE_SELECT_FACE) { - return base_ofs->face_start - 1; - } - BLI_assert(0); - return 0; -} - -uint ED_view3d_select_id_context_elem_len(const struct EDSelectID_Context *sel_id_ctx) -{ - return sel_id_ctx->base_array_index_len; -} - -struct EDSelectID_Context *ED_view3d_select_id_context_create(ViewContext *vc, - Base **bases, - const uint bases_len, - short select_mode) -{ - struct EDSelectID_Context *sel_id_ctx = MEM_mallocN(sizeof(*sel_id_ctx), __func__); - sel_id_ctx->base_array_index_offsets = MEM_mallocN(sizeof(struct EDBaseOffset) * bases_len, - __func__); - sel_id_ctx->bases = bases; - sel_id_ctx->bases_len = bases_len; - copy_m4_m4(sel_id_ctx->persmat, vc->rv3d->persmat); - sel_id_ctx->select_mode = select_mode; - ed_select_id_draw_bases(sel_id_ctx, vc, select_mode); - - return sel_id_ctx; -} - -void ED_view3d_select_id_context_destroy(struct EDSelectID_Context *sel_id_ctx) -{ - MEM_freeN(sel_id_ctx->base_array_index_offsets); - MEM_freeN(sel_id_ctx); -} - -bool ED_view3d_select_id_elem_get(struct EDSelectID_Context *sel_id_ctx, - const uint sel_id, - uint *r_elem, - uint *r_base_index, - char *r_elem_type) -{ - char elem_type = 0; - uint elem_id; - uint base_index = 0; - - while (true) { - struct EDBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index]; - if (base_ofs->face > sel_id) { - elem_id = sel_id - base_ofs->face_start; - elem_type = SCE_SELECT_FACE; - break; - } - if (base_ofs->edge > sel_id) { - elem_id = sel_id - base_ofs->edge_start; - elem_type = SCE_SELECT_EDGE; - break; - } - if (base_ofs->vert > sel_id) { - elem_id = sel_id - base_ofs->vert_start; - elem_type = SCE_SELECT_VERTEX; - break; - } - - base_index++; - if (base_index >= sel_id_ctx->bases_len) { - return false; - } - } - - *r_elem = elem_id; - - if (r_base_index) { - *r_base_index = base_index; - } - - if (r_elem_type) { - *r_elem_type = elem_type; - } - - return true; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Public Utilities * \{ */ @@ -385,7 +199,6 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b) struct EditSelectBuf_Cache { Base **bases; uint bases_len; - struct EDSelectID_Context *sel_id_ctx; BLI_bitmap *select_bitmap; }; @@ -407,8 +220,12 @@ static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, ViewCont esel->bases_len = 0; } } - esel->sel_id_ctx = ED_view3d_select_id_context_create( - vc, esel->bases, esel->bases_len, vc->scene->toolsettings->selectmode); + DRW_draw_select_id(vc->depsgraph, + vc->ar, + vc->v3d, + esel->bases, + esel->bases_len, + vc->scene->toolsettings->selectmode); for (int i = 0; i < esel->bases_len; i++) { esel->bases[i]->object->runtime.select_id = i; } @@ -416,9 +233,6 @@ static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, ViewCont static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel) { - if (esel->sel_id_ctx) { - ED_view3d_select_id_context_destroy(esel->sel_id_ctx); - } MEM_SAFE_FREE(esel->select_bitmap); MEM_SAFE_FREE(esel->bases); } @@ -455,8 +269,7 @@ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = ED_view3d_select_id_context_offset_for_object_elem( - esel->sel_id_ctx, ob->runtime.select_id, SCE_SELECT_VERTEX); + uint index = DRW_select_context_offset_for_object_elem(ob->runtime.select_id, SCE_SELECT_VERTEX); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { @@ -483,8 +296,7 @@ static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = ED_view3d_select_id_context_offset_for_object_elem( - esel->sel_id_ctx, ob->runtime.select_id, SCE_SELECT_EDGE); + uint index = DRW_select_context_offset_for_object_elem(ob->runtime.select_id, SCE_SELECT_EDGE); BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { @@ -511,8 +323,7 @@ static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel bool changed = false; const BLI_bitmap *select_bitmap = esel->select_bitmap; - uint index = ED_view3d_select_id_context_offset_for_object_elem( - esel->sel_id_ctx, ob->runtime.select_id, SCE_SELECT_FACE); + uint index = DRW_select_context_offset_for_object_elem(ob->runtime.select_id, SCE_SELECT_FACE); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { @@ -1017,7 +828,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); esel = wm_userdata->data; - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); } } @@ -1036,10 +847,8 @@ static bool do_lasso_select_mesh(ViewContext *vc, struct LassoSelectUserData_ForMeshEdge data_for_edge = { .data = &data, .esel = use_zbuf ? esel : NULL, - .backbuf_offset = use_zbuf ? ED_view3d_select_id_context_offset_for_object_elem( - esel->sel_id_ctx, - vc->obedit->runtime.select_id, - SCE_SELECT_EDGE) : + .backbuf_offset = use_zbuf ? DRW_select_context_offset_for_object_elem( + vc->obedit->runtime.select_id, SCE_SELECT_EDGE) : 0, }; mesh_foreachScreenEdge( @@ -1327,7 +1136,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); esel = wm_userdata->data; - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); } } @@ -1386,7 +1195,7 @@ static bool do_lasso_select_paintface(ViewContext *vc, if (esel == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); esel = wm_userdata->data; - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect); } @@ -2742,7 +2551,7 @@ static bool do_paintvert_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); esel = wm_userdata->data; - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); } if (esel->select_bitmap != NULL) { @@ -2797,7 +2606,7 @@ static bool do_paintface_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); esel = wm_userdata->data; - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); } if (esel->select_bitmap != NULL) { @@ -2995,7 +2804,7 @@ static bool do_mesh_box_select(ViewContext *vc, if (wm_userdata->data == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc); esel = wm_userdata->data; - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect); } } @@ -3014,10 +2823,8 @@ static bool do_mesh_box_select(ViewContext *vc, struct BoxSelectUserData_ForMeshEdge cb_data = { .data = &data, .esel = use_zbuf ? esel : NULL, - .backbuf_offset = use_zbuf ? ED_view3d_select_id_context_offset_for_object_elem( - esel->sel_id_ctx, - vc->obedit->runtime.select_id, - SCE_SELECT_EDGE) : + .backbuf_offset = use_zbuf ? DRW_select_context_offset_for_object_elem( + vc->obedit->runtime.select_id, SCE_SELECT_EDGE) : 0, }; mesh_foreachScreenEdge( @@ -3582,8 +3389,7 @@ static bool mesh_circle_select(ViewContext *vc, struct EditSelectBuf_Cache *esel = wm_userdata->data; if (use_zbuf) { - ED_view3d_select_id_validate_view_matrices(esel->sel_id_ctx, vc); - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); } @@ -3660,7 +3466,7 @@ static bool paint_facesel_circle_select(ViewContext *vc, { struct EditSelectBuf_Cache *esel = wm_userdata->data; - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op); @@ -3715,7 +3521,7 @@ static bool paint_vertsel_circle_select(ViewContext *vc, if (use_zbuf) { struct EditSelectBuf_Cache *esel = wm_userdata->data; - const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx); + const uint buffer_len = DRW_select_context_elem_len(); esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f)); if (esel->select_bitmap != NULL) { changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a316567fc63..d8dd6aa97b5 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2157,16 +2157,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } - /* do we check for parameter? */ - if (transformModeUseSnap(t)) { - if (t->modifiers & MOD_SNAP) { - ts->snap_flag |= SCE_SNAP; - } - else { - ts->snap_flag &= ~SCE_SNAP; - } - } - if (t->spacetype == SPACE_VIEW3D) { if ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && !RNA_property_is_set(op->ptr, prop) && @@ -2180,6 +2170,18 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } + if (t->flag & T_MODAL) { + /* do we check for parameter? */ + if (transformModeUseSnap(t)) { + if (t->modifiers & MOD_SNAP) { + ts->snap_flag |= SCE_SNAP; + } + else { + ts->snap_flag &= ~SCE_SNAP; + } + } + } + if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) { RNA_property_boolean_set(op->ptr, prop, proportional & PROP_EDIT_USE); RNA_boolean_set(op->ptr, "use_proportional_connected", proportional & PROP_EDIT_CONNECTED); @@ -4581,17 +4583,42 @@ static void ElementRotation( ElementRotation_ex(t, tc, td, mat, center); } -static void applyRotationValue(TransInfo *t, float angle, float axis[3]) +static float large_rotation_limit(float angle) +{ + /* Limit rotation to 1001 turns max + * (otherwise iterative handling of 'large' rotations would become too slow). */ + const float angle_max = (float)(M_PI * 2000.0); + if (fabsf(angle) > angle_max) { + const float angle_sign = angle < 0.0f ? -1.0f : 1.0f; + angle = angle_sign * (fmodf(fabsf(angle), (float)(M_PI * 2.0)) + angle_max); + } + return angle; +} + +static void applyRotationValue(TransInfo *t, + float angle, + float axis[3], + const bool is_large_rotation) { float mat[3][3]; int i; + const float angle_sign = angle < 0.0f ? -1.0f : 1.0f; + /* We cannot use something too close to 180°, or 'continuous' rotation may fail + * due to computing error... */ + const float angle_step = angle_sign * (float)(0.9 * M_PI); + + if (is_large_rotation) { + /* Just in case, calling code should have already done that in practice + * (for UI feedback reasons). */ + angle = large_rotation_limit(angle); + } + axis_angle_normalized_to_mat3(mat, axis, angle); FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { break; } @@ -4600,14 +4627,32 @@ static void applyRotationValue(TransInfo *t, float angle, float axis[3]) continue; } + float angle_final = angle; if (t->con.applyRot) { t->con.applyRot(t, tc, td, axis, NULL); - axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); + angle_final = angle * td->factor; } else if (t->flag & T_PROP_EDIT) { - axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); + angle_final = angle * td->factor; } + /* Rotation is very likely to be above 180°, we need to do rotation by steps. + * Note that this is only needed when doing 'absolute' rotation + * (i.e. from initial rotation again, typically when using numinput). + * regular incremental rotation (from mouse/widget/...) will be called often enough, + * hence steps are small enough to be properly handled without that complicated trick. */ + if (is_large_rotation) { + copy_v3_v3(td->ext->rot, td->ext->irot); + for (float angle_progress = angle_step; fabsf(angle_progress) < fabsf(angle_final); + angle_progress += angle_step) { + axis_angle_normalized_to_mat3(mat, axis, angle_progress); + ElementRotation(t, tc, td, mat, t->around); + } + axis_angle_normalized_to_mat3(mat, axis, angle_final); + } + else if (angle_final != angle) { + axis_angle_normalized_to_mat3(mat, axis, angle_final); + } ElementRotation(t, tc, td, mat, t->around); } } @@ -4632,15 +4677,18 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) applySnapping(t, &final); - /* Used to clamp final result in [-PI, PI[ range, no idea why, - * inheritance from 2.4x area, see T48998. */ - applyNumInput(&t->num, &final); + if (applyNumInput(&t->num, &final)) { + /* We have to limit the amount of turns to a reasonable number here, + * to avoid things getting *very* slow, see how applyRotationValue() handles those... */ + final = large_rotation_limit(final); + } t->values[0] = final; headerRotation(t, str, final); - applyRotationValue(t, final, axis_final); + const bool is_large_rotation = hasNumInput(&t->num); + applyRotationValue(t, final, axis_final, is_large_rotation); recalcData(t); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index cb539c8d1a5..3a204d0d157 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -235,8 +235,7 @@ static void axisProjection(const TransInfo *t, normalize_v3_v3_length(out, axis, -factor); } else { - float v[3], i1[3], i2[3]; - float v2[3], v4[3]; + float v[3]; float norm_center[3]; float plane[3]; @@ -261,14 +260,16 @@ static void axisProjection(const TransInfo *t, } } else { - add_v3_v3v3(v2, t_con_center, axis); - add_v3_v3v3(v4, v, norm); - - isect_line_line_v3(t_con_center, v2, v, v4, i1, i2); - - sub_v3_v3v3(v, i2, v); - - sub_v3_v3v3(out, i1, t_con_center); + /* Use ray-ray intersection instead of line-line because this gave + * precision issues adding small values to large numbers. */ + float mul; + if (isect_ray_ray_v3(t_con_center, axis, v, norm, &mul, NULL)) { + mul_v3_v3fl(out, axis, mul); + } + else { + /* In practice this should never fail. */ + BLI_assert(0); + } /* possible some values become nan when * viewpoint and object are both zero */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index d13c0f8e8f1..5626e9b5c81 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -6133,6 +6133,8 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c MEM_freeN(custom_data->data); custom_data->data = NULL; } + + DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER_STRIPS); } static void createTransSeqData(bContext *C, TransInfo *t) diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c index 54218da9eb5..e0139eac6b2 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c @@ -85,6 +85,21 @@ static bool dependsOnTime(GpencilModifierData *md) return (mmd->flag & GP_NOISE_USE_RANDOM) != 0; } +/* Get the lower number of frame for all layers. */ +static int get_lower_frame(bGPdata *gpd) +{ + int init = 99999; + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->frames.first) { + bGPDframe *gpf = gpl->frames.first; + if (gpf->framenum < init) { + init = gpf->framenum; + } + } + } + return init; +} + /* aply noise effect based on stroke direction */ static void deformStroke( GpencilModifierData *md, Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDstroke *gps) @@ -103,6 +118,7 @@ static void deformStroke( Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); GpencilModifierData *md_eval = BKE_gpencil_modifiers_findByName(object_eval, md->name); NoiseGpencilModifierData *mmd_eval = (NoiseGpencilModifierData *)md_eval; + bGPdata *gpd = (bGPdata *)ob->data; /* Random generator, only init once. (it uses eval to get same value in render) */ if (mmd_eval->rng == NULL) { @@ -110,6 +126,9 @@ static void deformStroke( rng_seed ^= POINTER_AS_UINT(mmd); mmd_eval->rng = BLI_rng_new(rng_seed); mmd->rng = mmd_eval->rng; + /* Get lower frame number */ + mmd_eval->scene_frame = get_lower_frame(gpd); + mmd->scene_frame = mmd_eval->scene_frame; } if (!is_stroke_affected_by_modifier(ob, @@ -176,19 +195,17 @@ static void deformStroke( sub_v3_v3v3(vec1, &pt1->x, &pt0->x); } vran = len_v3(vec1); - /* vector orthogonal to normal */ + /* Vector orthogonal to normal. */ cross_v3_v3v3(vec2, vec1, normal); normalize_v3(vec2); - /* use random noise */ + /* Use random noise */ if (mmd->flag & GP_NOISE_USE_RANDOM) { - sc_diff = abs(mmd->scene_frame - sc_frame); - /* only recalc if the gp frame change or the number of scene frames is bigger than step */ - if ((!gpl->actframe) || (mmd->gp_frame != gpl->actframe->framenum) || - (sc_diff >= mmd->step)) { + sc_diff = abs(sc_frame - mmd->scene_frame) % mmd->step; + /* Only recalc if the gp frame change or is a step. */ + if ((mmd->gp_frame != sc_frame) && (sc_diff == 0)) { vran = mmd->vrand1 = BLI_rng_get_float(mmd->rng); vdir = mmd->vrand2 = BLI_rng_get_float(mmd->rng); - mmd->gp_frame = gpl->actframe->framenum; - mmd->scene_frame = sc_frame; + mmd->gp_frame = sc_frame; } else { vran = mmd->vrand1; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index f30eff1484b..c620644a5f8 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -221,9 +221,6 @@ data_to_c_simple(shaders/gpu_shader_2D_edituvs_edges_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_edituvs_faces_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_edituvs_stretch_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_3D_selection_id_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_selection_id_frag.glsl SRC) - data_to_c_simple(shaders/gpu_shader_text_simple_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_simple_geom.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index cae2392e503..124f1f1ff8a 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -355,11 +355,8 @@ typedef enum eGPUBuiltinShader { GPU_SHADER_2D_UV_FACES, GPU_SHADER_2D_UV_FACES_STRETCH_AREA, GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE, - /* Selection */ - GPU_SHADER_3D_FLAT_SELECT_ID, - GPU_SHADER_3D_UNIFORM_SELECT_ID, } eGPUBuiltinShader; -#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_3D_UNIFORM_SELECT_ID + 1) +#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE + 1) /** Support multiple configurations. */ typedef enum eGPUShaderConfig { diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index c142d8ccba2..3e930d19696 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -139,9 +139,6 @@ extern char datatoc_gpu_shader_2D_edituvs_edges_vert_glsl[]; extern char datatoc_gpu_shader_2D_edituvs_faces_vert_glsl[]; extern char datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl[]; -extern char datatoc_gpu_shader_3D_selection_id_vert_glsl[]; -extern char datatoc_gpu_shader_selection_id_frag_glsl[]; - extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[]; extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[]; extern char datatoc_gpu_shader_2D_line_dashed_geom_glsl[]; @@ -1312,18 +1309,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .defs = "#define STRETCH_ANGLE\n", }, - [GPU_SHADER_3D_FLAT_SELECT_ID] = - { - .vert = datatoc_gpu_shader_3D_selection_id_vert_glsl, - .frag = datatoc_gpu_shader_selection_id_frag_glsl, - }, - [GPU_SHADER_3D_UNIFORM_SELECT_ID] = - { - .vert = datatoc_gpu_shader_3D_selection_id_vert_glsl, - .frag = datatoc_gpu_shader_selection_id_frag_glsl, - .defs = "#define UNIFORM_ID\n", - }, - [GPU_SHADER_GPENCIL_STROKE] = { .vert = datatoc_gpu_shader_gpencil_stroke_vert_glsl, @@ -1370,9 +1355,7 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, GPU_SHADER_3D_GROUNDLINE, GPU_SHADER_3D_GROUNDPOINT, GPU_SHADER_DISTANCE_LINES, - GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, - GPU_SHADER_3D_FLAT_SELECT_ID, - GPU_SHADER_3D_UNIFORM_SELECT_ID) || + GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR) || ELEM(shader, GPU_SHADER_3D_FLAT_COLOR, GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR, diff --git a/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl deleted file mode 100644 index 0d58909efd8..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl +++ /dev/null @@ -1,26 +0,0 @@ - -uniform mat4 ModelViewProjectionMatrix; - -in vec3 pos; - -#ifndef UNIFORM_ID -uniform uint offset; -in uint color; - -flat out uint id; -#endif - -void main() -{ -#ifndef UNIFORM_ID - id = offset + color; -#endif - - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; - -#ifdef USE_WORLD_CLIP_PLANES - /* Warning: ModelMatrix is typically used but select drawing is different. */ - world_clip_planes_calc_clip_distance(pos); -#endif -} diff --git a/source/blender/imbuf/IMB_thumbs.h b/source/blender/imbuf/IMB_thumbs.h index bac408e869b..5c7a60bbdcf 100644 --- a/source/blender/imbuf/IMB_thumbs.h +++ b/source/blender/imbuf/IMB_thumbs.h @@ -59,27 +59,34 @@ typedef enum ThumbSource { #define THUMB_DEFAULT_HASH "00000000000000000000000000000000" /* create thumbnail for file and returns new imbuf for thumbnail */ -ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *ibuf); +struct ImBuf *IMB_thumb_create(const char *path, + ThumbSize size, + ThumbSource source, + struct ImBuf *ibuf); /* read thumbnail for file and returns new imbuf for thumbnail */ -ImBuf *IMB_thumb_read(const char *path, ThumbSize size); +struct ImBuf *IMB_thumb_read(const char *path, ThumbSize size); /* delete all thumbs for the file */ void IMB_thumb_delete(const char *path, ThumbSize size); /* return the state of the thumb, needed to determine how to manage the thumb */ -ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source); +struct ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source); /* create the necessary dirs to store the thumbnails */ void IMB_thumb_makedirs(void); /* special function for loading a thumbnail embedded into a blend file */ -ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const char *blen_id); +struct ImBuf *IMB_thumb_load_blend(const char *blen_path, + const char *blen_group, + const char *blen_id); void IMB_thumb_overlay_blend(unsigned int *thumb, int width, int height, float aspect); /* special function for previewing fonts */ -ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y); +struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y); bool IMB_thumb_load_font_get_hash(char *r_hash); +void IMB_thumb_clear_translations(void); +void IMB_thumb_ensure_translations(void); /* Threading */ void IMB_thumb_locks_acquire(void); diff --git a/source/blender/imbuf/intern/thumbs_font.c b/source/blender/imbuf/intern/thumbs_font.c index 1213927d329..ddb1eb62006 100644 --- a/source/blender/imbuf/intern/thumbs_font.c +++ b/source/blender/imbuf/intern/thumbs_font.c @@ -32,14 +32,28 @@ #include "../../blenfont/BLF_api.h" #include "../../blentranslation/BLT_translation.h" -static const char *thumb_str[] = { - N_("AaBbCc"), +#define THUMB_TXT_ITEMS \ + N_("AaBbCc"), N_("The quick"), N_("brown fox"), N_("jumps over"), N_("the lazy dog"), - N_("The quick"), - N_("brown fox"), - N_("jumps over"), - N_("the lazy dog"), -}; +static const char *thumb_str[] = {THUMB_TXT_ITEMS}; + +static const char *i18n_thumb_str[] = {THUMB_TXT_ITEMS}; + +#undef THUMB_TXT_ITEMS + +void IMB_thumb_clear_translations(void) +{ + for (int i = ARRAY_SIZE(thumb_str); i-- > 0;) { + i18n_thumb_str[i] = NULL; + } +} + +void IMB_thumb_ensure_translations(void) +{ + for (int i = ARRAY_SIZE(thumb_str); i-- > 0;) { + i18n_thumb_str[i] = BLT_translate_do(BLT_I18NCONTEXT_DEFAULT, thumb_str[i]); + } +} struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y) { @@ -62,6 +76,7 @@ struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned BLF_thumb_preview(filename, thumb_str, + i18n_thumb_str, ARRAY_SIZE(thumb_str), font_color, font_size, @@ -87,8 +102,9 @@ bool IMB_thumb_load_font_get_hash(char *r_hash) len += BLI_strncpy_rlen(str + len, THUMB_DEFAULT_HASH, sizeof(buf) - len); for (i = 0; (i < draw_str_lines) && (len < sizeof(buf)); i++) { - len += BLI_strncpy_rlen( - str + len, BLT_translate_do(BLT_I18NCONTEXT_DEFAULT, thumb_str[i]), sizeof(buf) - len); + len += BLI_strncpy_rlen(str + len, + i18n_thumb_str[i] != NULL ? i18n_thumb_str[i] : thumb_str[i], + sizeof(buf) - len); } BLI_hash_md5_buffer(str, len, digest); diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index cad1af8eb50..ef9069acb78 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -616,6 +616,15 @@ typedef enum IDRecalcFlag { ID_RECALC_PARAMETERS = (1 << 21), + /* Makes it so everything what depends on time. + * Basically, the same what changing frame in a timeline will do. */ + ID_RECALC_TIME = (1 << 22), + + /* Input has changed and datablock is to be reload from disk. + * Applies to movie clips to inform that copy-on-written version is to be refreshed for the new + * input file or for color space changes. */ + ID_RECALC_SOURCE = (1 << 23), + /*************************************************************************** * Pseudonyms, to have more semantic meaning in the actual code without * using too much low-level and implementation specific tags. */ diff --git a/source/blender/makesdna/DNA_collection_types.h b/source/blender/makesdna/DNA_collection_types.h index c7f3ef4156d..af543864536 100644 --- a/source/blender/makesdna/DNA_collection_types.h +++ b/source/blender/makesdna/DNA_collection_types.h @@ -57,7 +57,9 @@ typedef struct Collection { float instance_offset[3]; short flag; - char _pad[6]; + /* Runtime-only, always cleared on file load. */ + short tag; + char _pad[4]; /* Runtime. Cache of objects in this collection and all its * children. This is created on demand when e.g. some physics @@ -84,4 +86,12 @@ enum { COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */ }; +/* Collection->tag */ +enum { + /* That code (BKE_main_collections_parent_relations_rebuild and the like) + * is called from very low-level places, like e.g ID remapping... + * Using a generic tag like LIB_TAG_DOIT for this is just impossible, we need our very own. */ + COLLECTION_TAG_RELATION_REBUILD = (1 << 0), +}; + #endif /* __DNA_COLLECTION_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 8b756ff2937..c2a9d3cf296 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -92,7 +92,7 @@ typedef struct NoiseGpencilModifierData { int step; /** Last gp frame used. */ int gp_frame; - /** Last scene frame used. */ + /** First scene frame used. */ int scene_frame; /** Random values. */ float vrand1, vrand2; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 307a6f2fe16..9134e603a87 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -412,7 +412,7 @@ typedef enum eGPLayerBlendModes { typedef struct bGPdata_Runtime { /** Last region where drawing was originated. */ struct ARegion *ar; - /** Stroke buffer (can hold GP_STROKE_BUFFER_MAX). */ + /** Stroke buffer. */ void *sbuffer; /* GP Object drawing */ @@ -431,11 +431,13 @@ typedef struct bGPdata_Runtime { * - buffer must be initialized before use, but freed after * whole paint operation is over */ - /** Number of elements currently in cache. */ - short sbuffer_size; + /** Number of elements currently used in cache. */ + short sbuffer_used; /** Flags for stroke that cache represents. */ short sbuffer_sflag; - char _pad[6]; + /** Number of total elements available in cache. */ + short sbuffer_size; + char _pad[4]; /** Number of control-points for stroke. */ int tot_cp_points; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 43df1d8e1aa..d221b7005f6 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -597,7 +597,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain, else if (GS(id->name) == ID_MC) { MovieClip *clip = (MovieClip *)id; - BKE_movieclip_reload(bmain, clip); + DEG_id_tag_update(&clip->id, ID_RECALC_SOURCE); BKE_sequence_invalidate_movieclip_strips(bmain, clip); WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, &clip->id); diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index 92a32ec8ab5..743bac2b709 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -332,6 +332,7 @@ static void rna_def_metaball(BlenderRNA *brna) /* number values */ prop = RNA_def_property(srna, "resolution", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "wiresize"); + RNA_def_property_float_default(prop, 0.4f); RNA_def_property_range(prop, 0.005f, 10000.0f); RNA_def_property_ui_range(prop, 0.05f, 1000.0f, 2.5f, 3); RNA_def_property_ui_text(prop, "Wire Size", "Polygonization resolution in the 3D viewport"); @@ -339,6 +340,7 @@ static void rna_def_metaball(BlenderRNA *brna) prop = RNA_def_property(srna, "render_resolution", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "rendersize"); + RNA_def_property_float_default(prop, 0.2f); RNA_def_property_range(prop, 0.005f, 10000.0f); RNA_def_property_ui_range(prop, 0.025f, 1000.0f, 2.5f, 3); RNA_def_property_ui_text(prop, "Render Size", "Polygonization resolution in rendering"); diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 247c4c69019..10e19b92dda 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -51,12 +51,11 @@ # include "DNA_screen_types.h" # include "DNA_space_types.h" -static void rna_MovieClip_reload_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_MovieClip_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { MovieClip *clip = (MovieClip *)ptr->id.data; - BKE_movieclip_reload(bmain, clip); - DEG_id_tag_update(&clip->id, 0); + DEG_id_tag_update(&clip->id, ID_RECALC_SOURCE); } static void rna_MovieClip_size_get(PointerRNA *ptr, int *values) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index d3b532dd11d..7fa1544d809 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -441,7 +441,7 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct Report return; } - if ((id->tag & LIB_TAG_NO_MAIN) != (ob->id.tag & LIB_TAG_NO_MAIN)) { + if (id && ((id->tag & LIB_TAG_NO_MAIN) != (ob->id.tag & LIB_TAG_NO_MAIN))) { BKE_report(reports, RPT_ERROR, "Can only assign evaluated data to evaluated object, or original data to " diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 1fea87df10c..d9306ba7a65 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -471,12 +471,12 @@ static void rna_PopMenuEnd(bContext *C, PointerRNA *handle) } /* popover wrapper */ -static PointerRNA rna_PopoverBegin(bContext *C, int ui_units_x) +static PointerRNA rna_PopoverBegin(bContext *C, int ui_units_x, bool from_active_button) { PointerRNA r_ptr; void *data; - data = (void *)UI_popover_begin(C, U.widget_unit * ui_units_x); + data = (void *)UI_popover_begin(C, U.widget_unit * ui_units_x, from_active_button); RNA_pointer_create(NULL, &RNA_UIPopover, data, &r_ptr); @@ -821,6 +821,8 @@ void RNA_api_wm(StructRNA *srna) parm = RNA_def_pointer(func, "menu", "UIPopover", "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR); RNA_def_function_return(func, parm); + RNA_def_boolean( + func, "from_active_button", 0, "Use Button", "Use the active button for positioning"); /* wrap UI_popover_end */ func = RNA_def_function(srna, "popover_end__internal", "rna_PopoverEnd"); diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 50447ae0376..ac0d72214c8 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -169,7 +169,7 @@ typedef struct DisplaceUserdata { static void displaceModifier_do_task(void *__restrict userdata, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { DisplaceUserdata *data = (DisplaceUserdata *)userdata; DisplaceModifierData *dmd = data->dmd; @@ -348,7 +348,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd, data.pool = BKE_image_pool_new(); BKE_texture_fetch_images_for_pool(tex_target, data.pool); } - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (numVerts > 512); BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, &settings); diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index e27d2786751..abb4c5cae32 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -671,8 +671,9 @@ static void LaplacianDeformModifier_do( &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) { - modifier_setError( - &lmd->modifier, "Vertex group '%s' is not valid", sys->anchor_grp_name); + modifier_setError(&lmd->modifier, + "Vertex group '%s' is not valid, or maybe empty", + sys->anchor_grp_name); } } } @@ -683,7 +684,8 @@ static void LaplacianDeformModifier_do( } else { if (!isValidVertexGroup(lmd, ob, mesh)) { - modifier_setError(&lmd->modifier, "Vertex group '%s' is not valid", lmd->anchor_grp_name); + modifier_setError( + &lmd->modifier, "Vertex group '%s' is not valid, or maybe empty", lmd->anchor_grp_name); lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND; } else if (lmd->total_verts > 0 && lmd->total_verts == numVerts) { diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index d89a47f4cf3..da261b4f835 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -259,7 +259,7 @@ typedef struct MeshdeformUserdata { static void meshdeform_vert_task(void *__restrict userdata, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { MeshdeformUserdata *data = userdata; /*const*/ MeshDeformModifierData *mmd = data->mmd; @@ -435,7 +435,7 @@ static void meshdeformModifier_do(ModifierData *md, data.icagemat = icagemat; /* Do deformation. */ - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.min_iter_per_thread = 16; BLI_task_parallel_range(0, totvert, &data, meshdeform_vert_task, &settings); diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 5cded96efe2..aff5b8b071b 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -196,7 +196,7 @@ typedef struct GenerateOceanGeometryData { static void generate_ocean_geometry_vertices(void *__restrict userdata, const int y, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { GenerateOceanGeometryData *gogd = userdata; int x; @@ -212,7 +212,7 @@ static void generate_ocean_geometry_vertices(void *__restrict userdata, static void generate_ocean_geometry_polygons(void *__restrict userdata, const int y, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { GenerateOceanGeometryData *gogd = userdata; int x; @@ -241,7 +241,7 @@ static void generate_ocean_geometry_polygons(void *__restrict userdata, static void generate_ocean_geometry_uvs(void *__restrict userdata, const int y, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { GenerateOceanGeometryData *gogd = userdata; int x; @@ -301,7 +301,7 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd) gogd.mpolys = result->mpoly; gogd.mloops = result->mloop; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = use_threading; diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 47c0114f02f..c428325e42b 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -796,7 +796,7 @@ BLI_INLINE float computeNormalDisplacement(const float point_co[3], static void bindVert(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SDefBindCalcData *const data = (SDefBindCalcData *)userdata; float point_co[3]; @@ -1076,7 +1076,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co); } - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (numverts > 10000); BLI_task_parallel_range(0, numverts, &data, bindVert, &settings); @@ -1116,7 +1116,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, static void deformVert(void *__restrict userdata, const int index, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const SDefDeformData *const data = (SDefDeformData *)userdata; const SDefBind *sdbind = data->bind_verts[index].binds; @@ -1247,7 +1247,7 @@ static void surfacedeformModifier_do(ModifierData *md, mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co); } - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (numverts > 10000); BLI_task_parallel_range(0, numverts, &data, deformVert, &settings); diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 995f3d06fcb..2c5f4b66c23 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -98,7 +98,7 @@ typedef struct UVWarpData { static void uv_warp_compute(void *__restrict userdata, const int i, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { const UVWarpData *data = userdata; @@ -202,7 +202,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes .axis_u = axis_u, .axis_v = axis_v, }; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (numPolys > 1000); BLI_task_parallel_range(0, numPolys, &data, uv_warp_compute, &settings); diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 37f25fd7c89..86d1b310d0c 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -92,7 +92,7 @@ typedef struct Vert2GeomDataChunk { */ static void vert2geom_task_cb_ex(void *__restrict userdata, const int iter, - const ParallelRangeTLS *__restrict tls) + const TaskParallelTLS *__restrict tls) { Vert2GeomData *data = userdata; Vert2GeomDataChunk *data_chunk = tls->userdata_chunk; @@ -188,7 +188,7 @@ static void get_vert2geom_distance(int numVerts, data.dist[1] = dist_e; data.dist[2] = dist_f; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (numVerts > 10000); settings.userdata_chunk = &data_chunk; diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 92ba7704b19..b8a83d0588d 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -184,6 +184,49 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj return PyC_UnicodeFromByte(path ? path : ""); } +PyDoc_STRVAR(bpy_system_resource_doc, + ".. function:: system_resource(type, path=\"\")\n" + "\n" + " Return a system resource path.\n" + "\n" + " :arg type: string in ['DATAFILES', 'SCRIPTS', 'PYTHON'].\n" + " :type type: string\n" + " :arg path: Optional subdirectory.\n" + " :type path: string\n"); +static PyObject *bpy_system_resource(PyObject *UNUSED(self), PyObject *args, PyObject *kw) +{ + const char *type; + const char *subdir = NULL; + int folder_id; + + const char *path; + + static const char *_keywords[] = {"type", "path", NULL}; + static _PyArg_Parser _parser = {"s|s:system_resource", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &type, &subdir)) { + return NULL; + } + + /* stupid string compare */ + if (STREQ(type, "DATAFILES")) { + folder_id = BLENDER_SYSTEM_DATAFILES; + } + else if (STREQ(type, "SCRIPTS")) { + folder_id = BLENDER_SYSTEM_SCRIPTS; + } + else if (STREQ(type, "PYTHON")) { + folder_id = BLENDER_SYSTEM_PYTHON; + } + else { + PyErr_SetString(PyExc_ValueError, "invalid resource argument"); + return NULL; + } + + path = BKE_appdir_folder_id(folder_id, subdir); + + return PyC_UnicodeFromByte(path ? path : ""); +} + PyDoc_STRVAR( bpy_resource_path_doc, ".. function:: resource_path(type, major=bpy.app.version[0], minor=bpy.app.version[1])\n" @@ -292,6 +335,12 @@ static PyMethodDef meth_bpy_user_resource = { METH_VARARGS | METH_KEYWORDS, NULL, }; +static PyMethodDef meth_bpy_system_resource = { + "system_resource", + (PyCFunction)bpy_system_resource, + METH_VARARGS | METH_KEYWORDS, + bpy_system_resource_doc, +}; static PyMethodDef meth_bpy_resource_path = { "resource_path", (PyCFunction)bpy_resource_path, @@ -398,6 +447,9 @@ void BPy_init_modules(void) meth_bpy_user_resource.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL)); PyModule_AddObject(mod, + meth_bpy_system_resource.ml_name, + (PyObject *)PyCFunction_New(&meth_bpy_system_resource, NULL)); + PyModule_AddObject(mod, meth_bpy_resource_path.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL)); PyModule_AddObject(mod, diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index c9c9e4adafb..06d8b645ac7 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -143,7 +143,6 @@ void python_script_error_jump(const char *filepath, int *lineno, int *offset) /* no traceback available when SyntaxError. * python has no api's to this. reference parse_syntax_error() from pythonrun.c */ PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); - PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ if (value) { /* should always be true */ PyObject *message; @@ -165,6 +164,7 @@ void python_script_error_jump(const char *filepath, int *lineno, int *offset) *lineno = -1; } } + PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ } else { PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index ab8146c6626..63c6245ced5 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -895,7 +895,7 @@ typedef struct SampleCallbackData { static void point_density_sample_func(void *__restrict data_v, const int iter, - const ParallelRangeTLS *__restrict UNUSED(tls)) + const TaskParallelTLS *__restrict UNUSED(tls)) { SampleCallbackData *data = (SampleCallbackData *)data_v; @@ -966,7 +966,7 @@ void RE_point_density_sample(Depsgraph *depsgraph, data.min = min; data.dim = dim; data.values = values; - ParallelRangeSettings settings; + TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (resolution > 32); BLI_task_parallel_range(0, resolution, &data, point_density_sample_func, &settings); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index f3a4bce392f..6fc73268a38 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -747,6 +747,10 @@ void *WM_draw_cb_activate(struct wmWindow *win, void WM_draw_cb_exit(struct wmWindow *win, void *handle); void WM_redraw_windows(struct bContext *C); +void WM_draw_region_viewport_ensure(struct ARegion *ar, short space_type); +void WM_draw_region_viewport_bind(struct ARegion *ar); +void WM_draw_region_viewport_unbind(struct ARegion *ar); + /* Region drawing */ void WM_draw_region_free(struct ARegion *ar); struct GPUViewport *WM_draw_region_get_viewport(struct ARegion *ar, int view); diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index 534474a6221..ee96515c27f 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -973,7 +973,8 @@ bool WM_gizmomap_cursor_set(const wmGizmoMap *gzmap, wmWindow *win) bool wm_gizmomap_highlight_set(wmGizmoMap *gzmap, const bContext *C, wmGizmo *gz, int part) { if ((gz != gzmap->gzmap_context.highlight) || (gz && part != gz->highlight_part)) { - const bool init_last_cursor = (gzmap->gzmap_context.highlight == NULL); + const bool init_last_cursor = !(gzmap->gzmap_context.highlight && + gzmap->gzmap_context.last_cursor != -1); if (gzmap->gzmap_context.highlight) { gzmap->gzmap_context.highlight->state &= ~WM_GIZMO_STATE_HIGHLIGHT; gzmap->gzmap_context.highlight->highlight_part = -1; diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 8e15eb71395..b0b89fa074f 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -240,9 +240,14 @@ static void wm_region_test_render_do_draw(const Scene *scene, } } +static bool wm_region_use_viewport_by_type(short space_type, short region_type) +{ + return (ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE) && region_type == RGN_TYPE_WINDOW); +} + static bool wm_region_use_viewport(ScrArea *sa, ARegion *ar) { - return (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && ar->regiontype == RGN_TYPE_WINDOW); + return wm_region_use_viewport_by_type(sa->spacetype, ar->regiontype); } /********************** draw all **************************/ @@ -1065,3 +1070,31 @@ void WM_redraw_windows(bContext *C) CTX_wm_area_set(C, area_prev); CTX_wm_region_set(C, ar_prev); } + +/* -------------------------------------------------------------------- */ +/** \name Region Viewport Drawing + * + * This is needed for viewport drawing for operator use + * (where the viewport may not have drawn yet). + * + * Otherwise avoid using these sine they're exposing low level logic externally. + * + * \{ */ + +void WM_draw_region_viewport_ensure(ARegion *ar, short space_type) +{ + bool use_viewport = wm_region_use_viewport_by_type(space_type, ar->regiontype); + wm_draw_region_buffer_create(ar, false, use_viewport); +} + +void WM_draw_region_viewport_bind(ARegion *ar) +{ + wm_draw_region_bind(ar, 0); +} + +void WM_draw_region_viewport_unbind(ARegion *ar) +{ + wm_draw_region_unbind(ar, 0); +} + +/** \} */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 48b09b0d329..3e965fc2f55 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -605,7 +605,6 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) /* assume automated tasks with background, don't write recent file list */ const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0); bool success = false; - int retval; /* so we can get the error message */ errno = 0; @@ -619,7 +618,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) /* first try to append data from exotic file formats... */ /* it throws error box when file doesn't exist and returns -1 */ /* note; it should set some error message somewhere... (ton) */ - retval = wm_read_exotic(filepath); + const int retval = wm_read_exotic(filepath); /* we didn't succeed, now try to read Blender file */ if (retval == BKE_READ_EXOTIC_OK_BLEND) { @@ -632,7 +631,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) /* confusing this global... */ G.relbase_valid = 1; - retval = BKE_blendfile_read( + success = BKE_blendfile_read( C, filepath, /* Loading preferences when the user intended to load a regular file is a security risk, @@ -668,7 +667,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm); WM_check(C); /* opens window(s), checks keymaps */ - if (retval != BKE_BLENDFILE_READ_FAIL) { + if (success) { if (do_history) { wm_history_file_update(); } @@ -677,8 +676,6 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) const bool use_data = true; const bool use_userdef = false; wm_file_read_post(C, false, false, use_data, use_userdef, false); - - success = true; } #if 0 else if (retval == BKE_READ_EXOTIC_OK_OTHER) { @@ -941,7 +938,7 @@ void wm_homefile_read(bContext *C, .is_startup = true, .skip_flags = skip_flags, }, - NULL) != BKE_BLENDFILE_READ_FAIL; + NULL); } if (BLI_listbase_is_empty(&U.themes)) { if (G.debug & G_DEBUG) { @@ -1053,7 +1050,7 @@ void wm_homefile_read(bContext *C, wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm); } - if (use_factory_settings) { + if (use_userdef) { /* Clear keymaps because the current default keymap may have been initialized * from user preferences, which have been reset. */ for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { @@ -2956,7 +2953,8 @@ static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_dat wmWindow *win = CTX_wm_window(C); UI_popup_block_close(C, win, arg_block); - if (save_images_when_file_is_closed) { + int modified_images_count = ED_image_save_all_modified_info(C, NULL); + if (modified_images_count > 0 && save_images_when_file_is_closed) { if (ED_image_should_save_modified(C)) { ReportList *reports = CTX_wm_reports(C); ED_image_save_all_modified(C, reports); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 6d8c7d045c0..df14609d29b 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -80,6 +80,8 @@ #include "RE_engine.h" #include "RE_pipeline.h" /* RE_ free stuff */ +#include "IMB_thumbs.h" + #ifdef WITH_PYTHON # include "BPY_extern.h" #endif @@ -302,6 +304,9 @@ void WM_init(bContext *C, int argc, const char **argv) /* Call again to set from userpreferences... */ BLT_lang_set(NULL); + /* That one is generated on demand, we need to be sure it's clear on init. */ + IMB_thumb_clear_translations(); + if (!G.background) { #ifdef WITH_INPUT_NDOF diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index c471cb6f922..f22b5d07686 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -340,8 +340,11 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo */ void WM_operator_properties_use_cursor_init(wmOperatorType *ot) { - PropertyRNA *prop = RNA_def_boolean( - ot->srna, "use_cursor_init", true, "Cursor Init", "Use initial cursor position"); + PropertyRNA *prop = RNA_def_boolean(ot->srna, + "use_cursor_init", + true, + "Use Mouse Position", + "Allow the initial mouse position to be used"); RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } |