diff options
author | João Araújo <jaraujo98@gmail.com> | 2017-07-26 13:25:24 +0300 |
---|---|---|
committer | João Araújo <jaraujo98@gmail.com> | 2017-07-26 13:25:24 +0300 |
commit | 59908f5eb73670c97c5bb817290a0dac99089900 (patch) | |
tree | 709de097c1fac2ff7b172a8b50dc8a91d7b74860 /source/blender | |
parent | 595f2ca2e06e07acaccc473982bde7a5ed644b50 (diff) | |
parent | edc6bec9d60204cb81d2e7533402630b076d0d32 (diff) |
Merge remote-tracking branch 'origin/master' into gsoc2016-improved_extrusiongsoc2016-improved_extrusion
Diffstat (limited to 'source/blender')
612 files changed, 12856 insertions, 8072 deletions
diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h index e92d5f2d9f7..70250310213 100644 --- a/source/blender/alembic/ABC_alembic.h +++ b/source/blender/alembic/ABC_alembic.h @@ -47,47 +47,63 @@ struct AlembicExportParams { double frame_start; double frame_end; - double frame_step_xform; - double frame_step_shape; + unsigned int frame_samples_xform; + unsigned int frame_samples_shape; double shutter_open; double shutter_close; - /* bools */ - unsigned int selected_only : 1; - unsigned int uvs : 1; - unsigned int normals : 1; - unsigned int vcolors : 1; - unsigned int apply_subdiv : 1; - unsigned int flatten_hierarchy : 1; - unsigned int visible_layers_only : 1; - unsigned int renderable_only : 1; - unsigned int face_sets : 1; - unsigned int use_subdiv_schema : 1; - unsigned int packuv : 1; - unsigned int triangulate : 1; + bool selected_only; + bool uvs; + bool normals; + bool vcolors; + bool apply_subdiv; + bool flatten_hierarchy; + bool visible_layers_only; + bool renderable_only; + bool face_sets; + bool use_subdiv_schema; + bool packuv; + bool triangulate; + bool export_hair; + bool export_particles; unsigned int compression_type : 1; + /* See MOD_TRIANGULATE_NGON_xxx and MOD_TRIANGULATE_QUAD_xxx + * in DNA_modifier_types.h */ int quad_method; int ngon_method; + float global_scale; }; -void ABC_export( +/* The ABC_export and ABC_import functions both take a as_background_job + * parameter, and return a boolean. + * + * When as_background_job=true, returns false immediately after scheduling + * a background job. + * + * When as_background_job=false, performs the export synchronously, and returns + * true when the export was ok, and false if there were any errors. + */ + +bool ABC_export( struct Scene *scene, struct bContext *C, const char *filepath, - const struct AlembicExportParams *params); + const struct AlembicExportParams *params, + bool as_background_job); -void ABC_import(struct bContext *C, +bool ABC_import(struct bContext *C, const char *filepath, float scale, bool is_sequence, bool set_frame_range, int sequence_len, int offset, - bool validate_meshes); + bool validate_meshes, + bool as_background_job); AbcArchiveHandle *ABC_create_handle(const char *filename, struct ListBase *object_paths); @@ -105,6 +121,7 @@ struct DerivedMesh *ABC_read_mesh(struct CacheReader *reader, const char **err_str, int flags); +void CacheReader_incref(struct CacheReader *reader); void CacheReader_free(struct CacheReader *reader); struct CacheReader *CacheReader_open_alembic_object(struct AbcArchiveHandle *handle, diff --git a/source/blender/alembic/intern/abc_archive.cc b/source/blender/alembic/intern/abc_archive.cc index 5f8fc1a3739..bd16196cb78 100644 --- a/source/blender/alembic/intern/abc_archive.cc +++ b/source/blender/alembic/intern/abc_archive.cc @@ -23,11 +23,17 @@ */ #include "abc_archive.h" +extern "C" +{ + #include "BKE_blender_version.h" +} #ifdef WIN32 # include "utfconv.h" #endif +#include <fstream> + using Alembic::Abc::Exception; using Alembic::Abc::ErrorHandler; using Alembic::Abc::IArchive; @@ -38,8 +44,9 @@ static IArchive open_archive(const std::string &filename, const std::vector<std::istream *> &input_streams, bool &is_hdf5) { + is_hdf5 = false; + try { - is_hdf5 = false; Alembic::AbcCoreOgawa::ReadArchive archive_reader(input_streams); return IArchive(archive_reader(filename), @@ -63,6 +70,27 @@ static IArchive open_archive(const std::string &filename, return IArchive(); } #else + /* Inspect the file to see whether it's really a HDF5 file. */ + char header[4]; /* char(0x89) + "HDF" */ + std::ifstream the_file(filename.c_str(), std::ios::in | std::ios::binary); + if (!the_file) { + std::cerr << "Unable to open " << filename << std::endl; + } + else if (!the_file.read(header, sizeof(header))) { + std::cerr << "Unable to read from " << filename << std::endl; + } + else if (strncmp(header + 1, "HDF", 3)) { + std::cerr << filename << " has an unknown file format, unable to read." << std::endl; + } + else { + is_hdf5 = true; + std::cerr << filename << " is in the obsolete HDF5 format, unable to read." << std::endl; + } + + if (the_file.is_open()) { + the_file.close(); + } + return IArchive(); #endif } @@ -83,16 +111,20 @@ ArchiveReader::ArchiveReader(const char *filename) m_streams.push_back(&m_infile); - bool is_hdf5; - m_archive = open_archive(filename, m_streams, is_hdf5); + m_archive = open_archive(filename, m_streams, m_is_hdf5); /* We can't open an HDF5 file from a stream, so close it. */ - if (is_hdf5) { + if (m_is_hdf5) { m_infile.close(); m_streams.clear(); } } +bool ArchiveReader::is_hdf5() const +{ + return m_is_hdf5; +} + bool ArchiveReader::valid() const { return m_archive.valid(); @@ -115,6 +147,7 @@ static OArchive create_archive(std::ostream *ostream, { md.set(Alembic::Abc::kApplicationNameKey, "Blender"); md.set(Alembic::Abc::kUserDescriptionKey, scene_name); + md.set("blender_version", versionstr); time_t raw_time; time(&raw_time); diff --git a/source/blender/alembic/intern/abc_archive.h b/source/blender/alembic/intern/abc_archive.h index d412574b736..84309fbc9df 100644 --- a/source/blender/alembic/intern/abc_archive.h +++ b/source/blender/alembic/intern/abc_archive.h @@ -44,12 +44,21 @@ class ArchiveReader { Alembic::Abc::IArchive m_archive; std::ifstream m_infile; std::vector<std::istream *> m_streams; + bool m_is_hdf5; public: explicit ArchiveReader(const char *filename); bool valid() const; + /** + * Returns true when either Blender is compiled with HDF5 support and + * the archive was succesfully opened (valid() will also return true), + * or when Blender was built without HDF5 support but a HDF5 file was + * detected (valid() will return false). + */ + bool is_hdf5() const; + Alembic::Abc::IObject getTop(); }; diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_camera.cc index 4f70b2a972c..16416205983 100644 --- a/source/blender/alembic/intern/abc_camera.cc +++ b/source/blender/alembic/intern/abc_camera.cc @@ -117,11 +117,27 @@ bool AbcCameraReader::valid() const return m_schema.valid(); } -void AbcCameraReader::readObjectData(Main *bmain, float time) +bool AbcCameraReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const +{ + if (!Alembic::AbcGeom::ICamera::matches(alembic_header)) { + *err_str = "Object type mismatch, Alembic object path pointed to Camera when importing, but not any more."; + return false; + } + + if (ob->type != OB_CAMERA) { + *err_str = "Object type mismatch, Alembic object path points to Camera."; + return false; + } + + return true; +} + +void AbcCameraReader::readObjectData(Main *bmain, const ISampleSelector &sample_sel) { Camera *bcam = static_cast<Camera *>(BKE_camera_add(bmain, m_data_name.c_str())); - ISampleSelector sample_sel(time); CameraSample cam_sample; m_schema.get(cam_sample, sample_sel); diff --git a/source/blender/alembic/intern/abc_camera.h b/source/blender/alembic/intern/abc_camera.h index fafb4d3eb39..16c5cccd5ea 100644 --- a/source/blender/alembic/intern/abc_camera.h +++ b/source/blender/alembic/intern/abc_camera.h @@ -54,8 +54,11 @@ public: AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings); bool valid() const; + bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const; - void readObjectData(Main *bmain, float time); + void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); }; -#endif /* __ABC_CAMERA_H__ */
\ No newline at end of file +#endif /* __ABC_CAMERA_H__ */ diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc index 0542255d84b..f73fe957fea 100644 --- a/source/blender/alembic/intern/abc_curves.cc +++ b/source/blender/alembic/intern/abc_curves.cc @@ -49,19 +49,26 @@ using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::FloatArraySamplePtr; using Alembic::Abc::P3fArraySamplePtr; using Alembic::Abc::UcharArraySamplePtr; +using Alembic::Abc::PropertyHeader; +using Alembic::AbcGeom::ICompoundProperty; using Alembic::AbcGeom::ICurves; using Alembic::AbcGeom::ICurvesSchema; using Alembic::AbcGeom::IFloatGeomParam; +using Alembic::AbcGeom::IInt16Property; using Alembic::AbcGeom::ISampleSelector; using Alembic::AbcGeom::kWrapExisting; using Alembic::AbcGeom::CurvePeriodicity; +using Alembic::AbcGeom::OCompoundProperty; using Alembic::AbcGeom::OCurves; using Alembic::AbcGeom::OCurvesSchema; +using Alembic::AbcGeom::OInt16Property; using Alembic::AbcGeom::ON3fGeomParam; using Alembic::AbcGeom::OV2fGeomParam; +#define ABC_CURVE_RESOLUTION_U_PROPNAME "blender:resolution" + /* ************************************************************************** */ AbcCurveWriter::AbcCurveWriter(Scene *scene, @@ -73,6 +80,11 @@ AbcCurveWriter::AbcCurveWriter(Scene *scene, { OCurves curves(parent->alembicXform(), m_name, m_time_sampling); m_schema = curves.getSchema(); + + Curve *cu = static_cast<Curve *>(m_object->data); + OCompoundProperty user_props = m_schema.getUserProperties(); + OInt16Property user_prop_resolu(user_props, ABC_CURVE_RESOLUTION_U_PROPNAME); + user_prop_resolu.set(cu->resolu); } void AbcCurveWriter::do_write() @@ -95,7 +107,7 @@ void AbcCurveWriter::do_write() for (; nurbs; nurbs = nurbs->next) { if (nurbs->bp) { curve_basis = Alembic::AbcGeom::kNoBasis; - curve_type = Alembic::AbcGeom::kLinear; + curve_type = Alembic::AbcGeom::kVariableOrder; const int totpoint = nurbs->pntsu * nurbs->pntsv; @@ -160,7 +172,7 @@ void AbcCurveWriter::do_write() } } - orders.push_back(nurbs->orderu + 1); + orders.push_back(nurbs->orderu); vert_counts.push_back(verts.size()); } @@ -199,17 +211,44 @@ bool AbcCurveReader::valid() const return m_curves_schema.valid(); } -void AbcCurveReader::readObjectData(Main *bmain, float time) +bool AbcCurveReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const +{ + if (!Alembic::AbcGeom::ICurves::matches(alembic_header)) { + *err_str = "Object type mismatch, Alembic object path pointed to Curves when importing, but not any more."; + return false; + } + + if (ob->type != OB_CURVE) { + *err_str = "Object type mismatch, Alembic object path points to Curves."; + return false; + } + + return true; +} + +void AbcCurveReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) { Curve *cu = BKE_curve_add(bmain, m_data_name.c_str(), OB_CURVE); cu->flag |= CU_DEFORM_FILL | CU_3D; cu->actvert = CU_ACT_NONE; + cu->resolu = 1; + + ICompoundProperty user_props = m_curves_schema.getUserProperties(); + if (user_props) { + const PropertyHeader *header = user_props.getPropertyHeader(ABC_CURVE_RESOLUTION_U_PROPNAME); + if (header != NULL && header->isScalar() && IInt16Property::matches(*header)) { + IInt16Property resolu(user_props, header->getName()); + cu->resolu = resolu.getValue(sample_sel); + } + } m_object = BKE_object_add_only_object(bmain, OB_CURVE, m_object_name.c_str()); m_object->data = cu; - read_curve_sample(cu, m_curves_schema, time); + read_curve_sample(cu, m_curves_schema, sample_sel); if (has_animations(m_curves_schema, m_settings)) { addCacheModifier(); @@ -218,9 +257,8 @@ void AbcCurveReader::readObjectData(Main *bmain, float time) /* ************************************************************************** */ -void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) +void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const ISampleSelector &sample_sel) { - const ISampleSelector sample_sel(time); ICurvesSchema::Sample smp = schema.getValue(sample_sel); const Int32ArraySamplePtr num_vertices = smp.getCurvesNumVertices(); const P3fArraySamplePtr positions = smp.getPositions(); @@ -250,13 +288,19 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) nu->pntsv = 1; nu->flag |= CU_SMOOTH; - nu->orderu = num_verts; - - if (smp.getType() == Alembic::AbcGeom::kCubic) { - nu->orderu = 3; - } - else if (orders && orders->size() > i) { - nu->orderu = static_cast<short>((*orders)[i] - 1); + switch (smp.getType()) { + case Alembic::AbcGeom::kCubic: + nu->orderu = 4; + break; + case Alembic::AbcGeom::kVariableOrder: + if (orders && orders->size() > i) { + nu->orderu = static_cast<short>((*orders)[i]); + break; + } + ATTR_FALLTHROUGH; + case Alembic::AbcGeom::kLinear: + default: + nu->orderu = 2; } if (periodicity == Alembic::AbcGeom::kNonPeriodic) { @@ -361,9 +405,11 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) * object directly and create a new DerivedMesh from that. Also we might need to * create new or delete existing NURBS in the curve. */ -DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float time, int /*read_flag*/, const char ** /*err_str*/) +DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, + const ISampleSelector &sample_sel, + int /*read_flag*/, + const char ** /*err_str*/) { - ISampleSelector sample_sel(time); const ICurvesSchema::Sample sample = m_curves_schema.getValue(sample_sel); const P3fArraySamplePtr &positions = sample.getPositions(); @@ -377,7 +423,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float if (curve_count != num_vertices->size()) { BKE_nurbList_free(&curve->nurb); - read_curve_sample(curve, m_curves_schema, time); + read_curve_sample(curve, m_curves_schema, sample_sel); } else { Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first); diff --git a/source/blender/alembic/intern/abc_curves.h b/source/blender/alembic/intern/abc_curves.h index 2757d179a47..a9231f947b2 100644 --- a/source/blender/alembic/intern/abc_curves.h +++ b/source/blender/alembic/intern/abc_curves.h @@ -54,13 +54,21 @@ public: AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettings &settings); bool valid() const; + bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const; - void readObjectData(Main *bmain, float time); - DerivedMesh *read_derivedmesh(DerivedMesh *, const float time, int read_flag, const char **err_str); + void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); + DerivedMesh *read_derivedmesh(DerivedMesh *dm, + const Alembic::Abc::ISampleSelector &sample_sel, + int read_flag, + const char **err_str); }; /* ************************************************************************** */ -void read_curve_sample(Curve *cu, const Alembic::AbcGeom::ICurvesSchema &schema, const float time); +void read_curve_sample(Curve *cu, + const Alembic::AbcGeom::ICurvesSchema &schema, + const Alembic::Abc::ISampleSelector &sample_selector); #endif /* __ABC_CURVES_H__ */ diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc index 0d11ab79ddd..1d2bc689027 100644 --- a/source/blender/alembic/intern/abc_customdata.cc +++ b/source/blender/alembic/intern/abc_customdata.cc @@ -227,48 +227,6 @@ using Alembic::AbcGeom::IC3fGeomParam; using Alembic::AbcGeom::IC4fGeomParam; using Alembic::AbcGeom::IV2fGeomParam; -static void read_mcols(const CDStreamConfig &config, void *data, - const C3fArraySamplePtr &c3f_ptr, const C4fArraySamplePtr &c4f_ptr) -{ - MCol *cfaces = static_cast<MCol *>(data); - MPoly *polys = config.mpoly; - MLoop *mloops = config.mloop; - - if (c3f_ptr) { - for (int i = 0; i < config.totpoly; ++i) { - MPoly *p = &polys[i]; - MCol *cface = &cfaces[p->loopstart + p->totloop]; - MLoop *mloop = &mloops[p->loopstart + p->totloop]; - - for (int j = 0; j < p->totloop; ++j) { - cface--; - mloop--; - const Imath::C3f &color = (*c3f_ptr)[mloop->v]; - cface->a = FTOCHAR(color[0]); - cface->r = FTOCHAR(color[1]); - cface->g = FTOCHAR(color[2]); - cface->b = 255; - } - } - } - else if (c4f_ptr) { - for (int i = 0; i < config.totpoly; ++i) { - MPoly *p = &polys[i]; - MCol *cface = &cfaces[p->loopstart + p->totloop]; - MLoop *mloop = &mloops[p->loopstart + p->totloop]; - - for (int j = 0; j < p->totloop; ++j) { - cface--; - mloop--; - const Imath::C4f &color = (*c4f_ptr)[mloop->v]; - cface->a = FTOCHAR(color[0]); - cface->r = FTOCHAR(color[1]); - cface->g = FTOCHAR(color[2]); - cface->b = FTOCHAR(color[3]); - } - } - } -} static void read_uvs(const CDStreamConfig &config, void *data, const Alembic::AbcGeom::V2fArraySamplePtr &uvs, @@ -294,57 +252,108 @@ static void read_uvs(const CDStreamConfig &config, void *data, } } -static void read_custom_data_ex(const ICompoundProperty &prop, - const PropertyHeader &prop_header, - const CDStreamConfig &config, - const Alembic::Abc::ISampleSelector &iss, - int data_type) +static void read_custom_data_mcols(const ICompoundProperty &arbGeomParams, + const PropertyHeader &prop_header, + const CDStreamConfig &config, + const Alembic::Abc::ISampleSelector &iss) { - if (data_type == CD_MLOOPCOL) { - C3fArraySamplePtr c3f_ptr = C3fArraySamplePtr(); - C4fArraySamplePtr c4f_ptr = C4fArraySamplePtr(); + C3fArraySamplePtr c3f_ptr = C3fArraySamplePtr(); + C4fArraySamplePtr c4f_ptr = C4fArraySamplePtr(); + bool use_c3f_ptr; + bool is_facevarying; + + /* Find the correct interpretation of the data */ + if (IC3fGeomParam::matches(prop_header)) { + IC3fGeomParam color_param(arbGeomParams, prop_header.getName()); + IC3fGeomParam::Sample sample; + BLI_assert(!strcmp("rgb", color_param.getInterpretation())); + + color_param.getIndexed(sample, iss); + is_facevarying = sample.getScope() == kFacevaryingScope && + config.totloop == sample.getIndices()->size(); + + c3f_ptr = sample.getVals(); + use_c3f_ptr = true; + } + else if (IC4fGeomParam::matches(prop_header)) { + IC4fGeomParam color_param(arbGeomParams, prop_header.getName()); + IC4fGeomParam::Sample sample; + BLI_assert(!strcmp("rgba", color_param.getInterpretation())); - if (IC3fGeomParam::matches(prop_header)) { - IC3fGeomParam color_param(prop, prop_header.getName()); - IC3fGeomParam::Sample sample; - color_param.getIndexed(sample, iss); + color_param.getIndexed(sample, iss); + is_facevarying = sample.getScope() == kFacevaryingScope && + config.totloop == sample.getIndices()->size(); - c3f_ptr = sample.getVals(); - } - else if (IC4fGeomParam::matches(prop_header)) { - IC4fGeomParam color_param(prop, prop_header.getName()); - IC4fGeomParam::Sample sample; - color_param.getIndexed(sample, iss); + c4f_ptr = sample.getVals(); + use_c3f_ptr = false; + } + else { + /* this won't happen due to the checks in read_custom_data() */ + return; + } + BLI_assert(c3f_ptr || c4f_ptr); - c4f_ptr = sample.getVals(); - } + /* Read the vertex colors */ + void *cd_data = config.add_customdata_cb(config.user_data, + prop_header.getName().c_str(), + CD_MLOOPCOL); + MCol *cfaces = static_cast<MCol *>(cd_data); + MPoly *mpolys = config.mpoly; + MLoop *mloops = config.mloop; - void *cd_data = config.add_customdata_cb(config.user_data, - prop_header.getName().c_str(), - data_type); + size_t face_index = 0; + size_t color_index; + for (int i = 0; i < config.totpoly; ++i) { + MPoly *poly = &mpolys[i]; + MCol *cface = &cfaces[poly->loopstart + poly->totloop]; + MLoop *mloop = &mloops[poly->loopstart + poly->totloop]; - read_mcols(config, cd_data, c3f_ptr, c4f_ptr); - } - else if (data_type == CD_MLOOPUV) { - IV2fGeomParam uv_param(prop, prop_header.getName()); + for (int j = 0; j < poly->totloop; ++j, ++face_index) { + --cface; + --mloop; + color_index = is_facevarying ? face_index : mloop->v; - if (!uv_param.isIndexed()) { - return; + if (use_c3f_ptr) { + const Imath::C3f &color = (*c3f_ptr)[color_index]; + cface->a = FTOCHAR(color[0]); + cface->r = FTOCHAR(color[1]); + cface->g = FTOCHAR(color[2]); + cface->b = 255; + } + else { + const Imath::C4f &color = (*c4f_ptr)[color_index]; + cface->a = FTOCHAR(color[0]); + cface->r = FTOCHAR(color[1]); + cface->g = FTOCHAR(color[2]); + cface->b = FTOCHAR(color[3]); + } } + } +} - IV2fGeomParam::Sample sample; - uv_param.getIndexed(sample, iss); +static void read_custom_data_uvs(const ICompoundProperty &prop, + const PropertyHeader &prop_header, + const CDStreamConfig &config, + const Alembic::Abc::ISampleSelector &iss) +{ + IV2fGeomParam uv_param(prop, prop_header.getName()); - if (uv_param.getScope() != kFacevaryingScope) { - return; - } + if (!uv_param.isIndexed()) { + return; + } - void *cd_data = config.add_customdata_cb(config.user_data, - prop_header.getName().c_str(), - data_type); + IV2fGeomParam::Sample sample; + uv_param.getIndexed(sample, iss); - read_uvs(config, cd_data, sample.getVals(), sample.getIndices()); + if (uv_param.getScope() != kFacevaryingScope) { + return; } + + void *cd_data = config.add_customdata_cb(config.user_data, + prop_header.getName().c_str(), + CD_MLOOPUV); + + read_uvs(config, cd_data, sample.getVals(), sample.getIndices()); } void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss) @@ -367,7 +376,7 @@ void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &confi continue; } - read_custom_data_ex(prop, prop_header, config, iss, CD_MLOOPUV); + read_custom_data_uvs(prop, prop_header, config, iss); continue; } @@ -377,7 +386,7 @@ void read_custom_data(const ICompoundProperty &prop, const CDStreamConfig &confi continue; } - read_custom_data_ex(prop, prop_header, config, iss, CD_MLOOPCOL); + read_custom_data_mcols(prop, prop_header, config, iss); continue; } } diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index ec9504a2f3a..4fe65b96f36 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -72,8 +72,8 @@ ExportSettings::ExportSettings() , renderable_only(false) , frame_start(1) , frame_end(1) - , frame_step_xform(1) - , frame_step_shape(1) + , frame_samples_xform(1) + , frame_samples_shape(1) , shutter_open(0.0) , shutter_close(1.0) , global_scale(1.0f) @@ -83,6 +83,8 @@ ExportSettings::ExportSettings() , export_vcols(false) , export_face_sets(false) , export_vweigths(false) + , export_hair(true) + , export_particles(true) , apply_subdiv(false) , use_subdiv_schema(false) , export_child_hairs(true) @@ -106,7 +108,7 @@ static bool object_is_smoke_sim(Object *ob) return false; } -static bool object_is_shape(Object *ob) +static bool object_type_is_exportable(Object *ob) { switch (ob->type) { case OB_MESH: @@ -115,6 +117,7 @@ static bool object_is_shape(Object *ob) } return true; + case OB_EMPTY: case OB_CURVE: case OB_SURF: case OB_CAMERA: @@ -124,14 +127,31 @@ static bool object_is_shape(Object *ob) } } -static bool export_object(const ExportSettings * const settings, Object *ob) + +/** + * Returns whether this object should be exported into the Alembic file. + * + * \param settings: export settings, used for options like 'selected only'. + * \param ob: the object in question. + * \param is_duplicated: Normally false; true when the object is instanced + * into the scene by a dupli-object (e.g. part of a dupligroup). + * This ignores selection and layer visibility, + * and assumes that the dupli-object itself (e.g. the group-instantiating empty) is exported. + */ +static bool export_object(const ExportSettings * const settings, Object *ob, + bool is_duplicated) { - if (settings->selected_only && !parent_selected(ob)) { - return false; - } + if (!is_duplicated) { + /* These two tests only make sense when the object isn't being instanced + * into the scene. When it is, its exportability is determined by + * its dupli-object and the DupliObject::no_draw property. */ + if (settings->selected_only && !parent_selected(ob)) { + return false; + } - if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) { - return false; + if (settings->visible_layers_only && !(settings->scene->lay & ob->lay)) { + return false; + } } if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) { @@ -168,60 +188,56 @@ AbcExporter::~AbcExporter() delete m_writer; } -void AbcExporter::getShutterSamples(double step, bool time_relative, +void AbcExporter::getShutterSamples(unsigned int nr_of_samples, + bool time_relative, std::vector<double> &samples) { + Scene *scene = m_scene; /* for use in the FPS macro */ samples.clear(); - const double time_factor = time_relative ? m_scene->r.frs_sec : 1.0; - const double shutter_open = m_settings.shutter_open; - const double shutter_close = m_settings.shutter_close; + unsigned int frame_offset = time_relative ? m_settings.frame_start : 0; + double time_factor = time_relative ? FPS : 1.0; + double shutter_open = m_settings.shutter_open; + double shutter_close = m_settings.shutter_close; + double time_inc = (shutter_close - shutter_open) / nr_of_samples; - /* sample all frame */ - if (shutter_open == 0.0 && shutter_close == 1.0) { - for (double t = 0.0; t < 1.0; t += step) { - samples.push_back((t + m_settings.frame_start) / time_factor); - } - } - else { - /* sample between shutter open & close */ - const int nsamples = static_cast<int>(std::max((1.0 / step) - 1.0, 1.0)); - const double time_inc = (shutter_close - shutter_open) / nsamples; + /* sample between shutter open & close */ + for (int sample=0; sample < nr_of_samples; ++sample) { + double sample_time = shutter_open + time_inc * sample; + double time = (frame_offset + sample_time) / time_factor; - for (double t = shutter_open; t <= shutter_close; t += time_inc) { - samples.push_back((t + m_settings.frame_start) / time_factor); - } + samples.push_back(time); } } Alembic::Abc::TimeSamplingPtr AbcExporter::createTimeSampling(double step) { - TimeSamplingPtr time_sampling; std::vector<double> samples; if (m_settings.frame_start == m_settings.frame_end) { - time_sampling.reset(new Alembic::Abc::TimeSampling()); - return time_sampling; + return TimeSamplingPtr(new Alembic::Abc::TimeSampling()); } getShutterSamples(step, true, samples); - Alembic::Abc::TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / m_scene->r.frs_sec); - time_sampling.reset(new Alembic::Abc::TimeSampling(ts, samples)); + Alembic::Abc::TimeSamplingType ts( + static_cast<uint32_t>(samples.size()), + 1.0 / m_scene->r.frs_sec); - return time_sampling; + return TimeSamplingPtr(new Alembic::Abc::TimeSampling(ts, samples)); } -void AbcExporter::getFrameSet(double step, std::set<double> &frames) +void AbcExporter::getFrameSet(unsigned int nr_of_samples, + std::set<double> &frames) { frames.clear(); std::vector<double> shutter_samples; - getShutterSamples(step, false, shutter_samples); + getShutterSamples(nr_of_samples, false, shutter_samples); for (double frame = m_settings.frame_start; frame <= m_settings.frame_end; frame += 1.0) { - for (int j = 0, e = shutter_samples.size(); j < e; ++j) { + for (size_t j = 0; j < nr_of_samples; ++j) { frames.insert(frame + shutter_samples[j]); } } @@ -253,44 +269,37 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) /* Create time samplings for transforms and shapes. */ - TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform); + TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_samples_xform); m_trans_sampling_index = m_writer->archive().addTimeSampling(*trans_time); TimeSamplingPtr shape_time; - if ((m_settings.frame_step_shape == m_settings.frame_step_xform) || + if ((m_settings.frame_samples_shape == m_settings.frame_samples_xform) || (m_settings.frame_start == m_settings.frame_end)) { shape_time = trans_time; m_shape_sampling_index = m_trans_sampling_index; } else { - shape_time = createTimeSampling(m_settings.frame_step_shape); + shape_time = createTimeSampling(m_settings.frame_samples_shape); m_shape_sampling_index = m_writer->archive().addTimeSampling(*shape_time); } OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_writer->archive(), m_trans_sampling_index); - if (m_settings.flatten_hierarchy) { - createTransformWritersFlat(); - } - else { - createTransformWritersHierarchy(bmain->eval_ctx); - } - + createTransformWritersHierarchy(bmain->eval_ctx); createShapeWriters(bmain->eval_ctx); /* Make a list of frames to export. */ std::set<double> xform_frames; - getFrameSet(m_settings.frame_step_xform, xform_frames); + getFrameSet(m_settings.frame_samples_xform, xform_frames); std::set<double> shape_frames; - getFrameSet(m_settings.frame_step_shape, shape_frames); + getFrameSet(m_settings.frame_samples_shape, shape_frames); /* Merge all frames needed. */ - std::set<double> frames(xform_frames); frames.insert(shape_frames.begin(), shape_frames.end()); @@ -313,7 +322,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) const double frame = *begin; /* 'frame' is offset by start frame, so need to cancel the offset. */ - setCurrentFrame(bmain, frame - m_settings.frame_start); + setCurrentFrame(bmain, frame); if (shape_frames.count(frame) != 0) { for (int i = 0, e = m_shapes.size(); i != e; ++i) { @@ -349,34 +358,16 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx) while (base) { Object *ob = base->object; - if (export_object(&m_settings, ob)) { - switch (ob->type) { - case OB_LAMP: - case OB_LATTICE: - case OB_MBALL: - case OB_SPEAKER: - /* We do not export transforms for objects of these classes. */ - break; - - default: - exploreTransform(eval_ctx, ob, ob->parent, NULL); - } - } - - base = base->next; - } -} - -void AbcExporter::createTransformWritersFlat() -{ - Base *base = static_cast<Base *>(m_scene->base.first); + switch (ob->type) { + case OB_LAMP: + case OB_LATTICE: + case OB_MBALL: + case OB_SPEAKER: + /* We do not export transforms for objects of these classes. */ + break; - while (base) { - Object *ob = base->object; - - if (export_object(&m_settings, ob) && object_is_shape(ob)) { - std::string name = get_id_name(ob); - m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), 0, m_trans_sampling_index, m_settings); + default: + exploreTransform(eval_ctx, ob, ob->parent); } base = base->next; @@ -385,8 +376,13 @@ void AbcExporter::createTransformWritersFlat() void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent) { + /* If an object isn't exported itself, its duplilist shouldn't be + * exported either. */ + if (!export_object(&m_settings, ob, dupliObParent != NULL)) { + return; + } - if (export_object(&m_settings, ob) && object_is_shape(ob)) { + if (object_type_is_exportable(ob)) { createTransformWriter(ob, parent, dupliObParent); } @@ -397,15 +393,18 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Obje Object *dupli_ob = NULL; Object *dupli_parent = NULL; - while (link) { + for (; link; link = link->next) { + /* This skips things like custom bone shapes. */ + if (m_settings.renderable_only && link->no_draw) { + continue; + } + if (link->type == OB_DUPLIGROUP) { dupli_ob = link->ob; dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob; exploreTransform(eval_ctx, dupli_ob, dupli_parent, ob); } - - link = link->next; } } @@ -414,28 +413,44 @@ void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Obje AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent) { - const std::string name = get_object_dag_path_name(ob, dupliObParent); - /* An object should not be its own parent, or we'll get infinite loops. */ BLI_assert(ob != parent); BLI_assert(ob != dupliObParent); + std::string name; + if (m_settings.flatten_hierarchy) { + name = get_id_name(ob); + } + else { + name = get_object_dag_path_name(ob, dupliObParent); + } + /* check if we have already created a transform writer for this object */ AbcTransformWriter *my_writer = getXForm(name); - if (my_writer != NULL){ + if (my_writer != NULL) { return my_writer; } AbcTransformWriter *parent_writer = NULL; Alembic::Abc::OObject alembic_parent; - if (parent) { + if (m_settings.flatten_hierarchy || parent == NULL) { + /* Parentless objects still have the "top object" as parent + * in Alembic. */ + alembic_parent = m_writer->archive().getTop(); + } + else { /* Since there are so many different ways to find parents (as evident * in the number of conditions below), we can't really look up the * parent by name. We'll just call createTransformWriter(), which will * return the parent's AbcTransformWriter pointer. */ if (parent->parent) { - parent_writer = createTransformWriter(parent, parent->parent, dupliObParent); + if (parent == dupliObParent) { + parent_writer = createTransformWriter(parent, parent->parent, NULL); + } + else { + parent_writer = createTransformWriter(parent, parent->parent, dupliObParent); + } } else if (parent == dupliObParent) { if (dupliObParent->parent == NULL) { @@ -452,14 +467,15 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare BLI_assert(parent_writer); alembic_parent = parent_writer->alembicXform(); } - else { - /* Parentless objects still have the "top object" as parent - * in Alembic. */ - alembic_parent = m_writer->archive().getTop(); - } my_writer = new AbcTransformWriter(ob, alembic_parent, parent_writer, m_trans_sampling_index, m_settings); + + /* When flattening, the matrix of the dupliobject has to be added. */ + if (m_settings.flatten_hierarchy && dupliObParent) { + my_writer->m_proxy_from = dupliObParent; + } + m_xforms[name] = my_writer; return my_writer; } @@ -478,32 +494,60 @@ void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx) void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent) { - ListBase *lb = object_duplilist(eval_ctx, m_scene, ob); - + /* If an object isn't exported itself, its duplilist shouldn't be + * exported either. */ + if (!export_object(&m_settings, ob, dupliObParent != NULL)) { + return; + } + createShapeWriter(ob, dupliObParent); + ListBase *lb = object_duplilist(eval_ctx, m_scene, ob); + if (lb) { - DupliObject *dupliob = static_cast<DupliObject *>(lb->first); + DupliObject *link = static_cast<DupliObject *>(lb->first); - while (dupliob) { - if (dupliob->type == OB_DUPLIGROUP) { - exploreObject(eval_ctx, dupliob->ob, ob); + for (; link; link = link->next) { + /* This skips things like custom bone shapes. */ + if (m_settings.renderable_only && link->no_draw) { + continue; } - dupliob = dupliob->next; + if (link->type == OB_DUPLIGROUP) { + exploreObject(eval_ctx, link->ob, ob); + } } } free_object_duplilist(lb); } -void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent) +void AbcExporter::createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform) { - if (!object_is_shape(ob)) { + if (!m_settings.export_hair && !m_settings.export_particles) { return; } - if (!export_object(&m_settings, ob)) { + ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first); + + for (; psys; psys = psys->next) { + if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) { + continue; + } + + if (m_settings.export_hair && psys->part->type == PART_HAIR) { + m_settings.export_child_hairs = true; + m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys)); + } + else if (m_settings.export_particles && psys->part->type == PART_EMITTER) { + m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys)); + } + } +} + +void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent) +{ + if (!object_type_is_exportable(ob)) { return; } @@ -523,28 +567,14 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent) return; } - ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first); - - for (; psys; psys = psys->next) { - if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) { - continue; - } - - if (psys->part->type == PART_HAIR) { - m_settings.export_child_hairs = true; - m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys)); - } - else if (psys->part->type == PART_EMITTER) { - m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys)); - } - } + createParticleSystemsWriters(ob, xform); switch (ob->type) { case OB_MESH: { Mesh *me = static_cast<Mesh *>(ob->data); - if (!me || me->totvert == 0) { + if (!me) { return; } diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h index 0f08037fd17..f763922a73b 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -50,8 +50,8 @@ struct ExportSettings { bool renderable_only; double frame_start, frame_end; - double frame_step_xform; - double frame_step_shape; + double frame_samples_xform; + double frame_samples_shape; double shutter_open; double shutter_close; float global_scale; @@ -63,6 +63,8 @@ struct ExportSettings { bool export_vcols; bool export_face_sets; bool export_vweigths; + bool export_hair; + bool export_particles; bool apply_subdiv; bool use_subdiv_schema; @@ -101,20 +103,22 @@ public: void operator()(Main *bmain, float &progress, bool &was_canceled); -private: - void getShutterSamples(double step, bool time_relative, std::vector<double> &samples); +protected: + void getShutterSamples(unsigned int nr_of_samples, + bool time_relative, + std::vector<double> &samples); + void getFrameSet(unsigned int nr_of_samples, std::set<double> &frames); +private: Alembic::Abc::TimeSamplingPtr createTimeSampling(double step); - void getFrameSet(double step, std::set<double> &frames); - void createTransformWritersHierarchy(EvaluationContext *eval_ctx); - void createTransformWritersFlat(); AbcTransformWriter * createTransformWriter(Object *ob, Object *parent, Object *dupliObParent); void exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent = NULL); void exploreObject(EvaluationContext *eval_ctx, Object *ob, Object *dupliObParent); void createShapeWriters(EvaluationContext *eval_ctx); void createShapeWriter(Object *ob, Object *dupliObParent); + void createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform); AbcTransformWriter *getXForm(const std::string &name); diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc index e328df24e53..8f8ed2019d5 100644 --- a/source/blender/alembic/intern/abc_hair.cc +++ b/source/blender/alembic/intern/abc_hair.cc @@ -56,6 +56,7 @@ AbcHairWriter::AbcHairWriter(Scene *scene, ExportSettings &settings, ParticleSystem *psys) : AbcObjectWriter(scene, ob, time_sampling, settings, parent) + , m_uv_warning_shown(false) { m_psys = psys; @@ -75,7 +76,7 @@ void AbcHairWriter::do_write() return; } - DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH); + DerivedMesh *dm = mesh_create_derived_render(m_scene, m_object, CD_MASK_MESH); DM_ensure_tessface(dm); std::vector<Imath::V3f> verts; @@ -132,8 +133,10 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm, MFace *mface = dm->getTessFaceArray(dm); MVert *mverts = dm->getVertArray(dm); - if (!mtface || !mface) { - std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n"); + if ((!mtface || !mface) && !m_uv_warning_shown) { + std::fprintf(stderr, "Warning, no UV set found for underlying geometry of %s.\n", + m_object->id.name + 2); + m_uv_warning_shown = true; } ParticleData * pa = m_psys->particles; @@ -238,13 +241,8 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm, invert_m4_m4_safe(inv_mat, m_object->obmat); MTFace *mtface = static_cast<MTFace *>(CustomData_get_layer(&dm->faceData, CD_MTFACE)); - MFace *mface = dm->getTessFaceArray(dm); MVert *mverts = dm->getVertArray(dm); - if (!mtface || !mface) { - std::fprintf(stderr, "Warning, no UV set found for underlying geometry.\n"); - } - ParticleCacheKey **cache = m_psys->childcache; ParticleCacheKey *path; @@ -253,22 +251,37 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm, for (int p = 0; p < m_psys->totchild; ++p, ++pc) { path = cache[p]; - if (part->from == PART_FROM_FACE) { + if (part->from == PART_FROM_FACE && + part->childtype != PART_CHILD_PARTICLES && + mtface) { const int num = pc->num; + if (num < 0) { + ABC_LOG(m_settings.logger) + << "Warning, child particle of hair system " << m_psys->name + << " has unknown face index of geometry of "<< (m_object->id.name + 2) + << ", skipping child hair." << std::endl; + continue; + } MFace *face = static_cast<MFace *>(dm->getTessFaceData(dm, num, CD_MFACE)); MTFace *tface = mtface + num; - if (mface && mtface) { - float r_uv[2], tmpnor[3], mapfw[4], vec[3]; + float r_uv[2], tmpnor[3], mapfw[4], vec[3]; - psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv); - uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1])); + psys_interpolate_uvs(tface, face->v4, pc->fuv, r_uv); + uv_values.push_back(Imath::V2f(r_uv[0], r_uv[1])); - psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, tmpnor, NULL, NULL, NULL, NULL); + psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, tmpnor, NULL, NULL, NULL, NULL); - /* Convert Z-up to Y-up. */ - norm_values.push_back(Imath::V3f(tmpnor[0], tmpnor[2], -tmpnor[1])); + /* Convert Z-up to Y-up. */ + norm_values.push_back(Imath::V3f(tmpnor[0], tmpnor[2], -tmpnor[1])); + } + else { + if (uv_values.size()) { + uv_values.push_back(uv_values[pc->parent]); + } + if (norm_values.size()) { + norm_values.push_back(norm_values[pc->parent]); } } diff --git a/source/blender/alembic/intern/abc_hair.h b/source/blender/alembic/intern/abc_hair.h index d132b60be12..61f5fe361f8 100644 --- a/source/blender/alembic/intern/abc_hair.h +++ b/source/blender/alembic/intern/abc_hair.h @@ -37,6 +37,8 @@ class AbcHairWriter : public AbcObjectWriter { Alembic::AbcGeom::OCurvesSchema m_schema; Alembic::AbcGeom::OCurvesSchema::Sample m_sample; + bool m_uv_warning_shown; + public: AbcHairWriter(Scene *scene, Object *ob, diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index 5a57e43326a..9a4ca6f99a8 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -355,7 +355,7 @@ bool AbcMeshWriter::isAnimated() const md = md->next; } - return false; + return me->adt != NULL; } void AbcMeshWriter::do_write() @@ -897,19 +897,31 @@ static void *add_customdata_cb(void *user_data, const char *name, int data_type) { DerivedMesh *dm = static_cast<DerivedMesh *>(user_data); CustomDataType cd_data_type = static_cast<CustomDataType>(data_type); - void *cd_ptr = NULL; - - if (ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) { - cd_ptr = CustomData_get_layer_named(dm->getLoopDataLayout(dm), cd_data_type, name); - - if (cd_ptr == NULL) { - cd_ptr = CustomData_add_layer_named(dm->getLoopDataLayout(dm), - cd_data_type, - CD_DEFAULT, - NULL, - dm->getNumLoops(dm), - name); - } + void *cd_ptr; + CustomData *loopdata; + int numloops; + + /* unsupported custom data type -- don't do anything. */ + if (!ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) { + return NULL; + } + + loopdata = dm->getLoopDataLayout(dm); + cd_ptr = CustomData_get_layer_named(loopdata, cd_data_type, name); + if (cd_ptr != NULL) { + /* layer already exists, so just return it. */ + return cd_ptr; + } + + /* create a new layer, taking care to construct the hopefully-soon-to-be-removed + * CD_MTEXPOLY layer too, with the same name. */ + numloops = dm->getNumLoops(dm); + cd_ptr = CustomData_add_layer_named(loopdata, cd_data_type, CD_DEFAULT, + NULL, numloops, name); + if (cd_data_type == CD_MLOOPUV) { + CustomData_add_layer_named(dm->getPolyDataLayout(dm), + CD_MTEXPOLY, CD_DEFAULT, + NULL, numloops, name); } return cd_ptr; @@ -1009,17 +1021,15 @@ bool AbcMeshReader::valid() const return m_schema.valid(); } -void AbcMeshReader::readObjectData(Main *bmain, float time) +void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) { Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str()); m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str()); m_object->data = mesh; - const ISampleSelector sample_sel(time); - DerivedMesh *dm = CDDM_from_mesh(mesh); - DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL, NULL); + DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, MOD_MESHSEQ_READ_ALL, NULL); if (ndm != dm) { dm->release(dm); @@ -1038,9 +1048,28 @@ void AbcMeshReader::readObjectData(Main *bmain, float time) } } -DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str) +bool AbcMeshReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const +{ + if (!Alembic::AbcGeom::IPolyMesh::matches(alembic_header)) { + *err_str = "Object type mismatch, Alembic object path pointed to PolyMesh when importing, but not any more."; + return false; + } + + if (ob->type != OB_MESH) { + *err_str = "Object type mismatch, Alembic object path points to PolyMesh."; + return false; + } + + return true; +} + +DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, + const ISampleSelector &sample_sel, + int read_flag, + const char **err_str) { - ISampleSelector sample_sel(time); const IPolyMeshSchema::Sample sample = m_schema.getValue(sample_sel); const P3fArraySamplePtr &positions = sample.getPositions(); @@ -1080,7 +1109,7 @@ DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, const float time, } CDStreamConfig config = get_config(new_dm ? new_dm : dm); - config.time = time; + config.time = sample_sel.getRequestedTime(); bool do_normals = false; read_mesh_sample(&settings, m_schema, sample_sel, config, do_normals); @@ -1227,7 +1256,24 @@ bool AbcSubDReader::valid() const return m_schema.valid(); } -void AbcSubDReader::readObjectData(Main *bmain, float time) +bool AbcSubDReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const +{ + if (!Alembic::AbcGeom::ISubD::matches(alembic_header)) { + *err_str = "Object type mismatch, Alembic object path pointed to SubD when importing, but not any more."; + return false; + } + + if (ob->type != OB_MESH) { + *err_str = "Object type mismatch, Alembic object path points to SubD."; + return false; + } + + return true; +} + +void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) { Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str()); @@ -1235,7 +1281,7 @@ void AbcSubDReader::readObjectData(Main *bmain, float time) m_object->data = mesh; DerivedMesh *dm = CDDM_from_mesh(mesh); - DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL, NULL); + DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, MOD_MESHSEQ_READ_ALL, NULL); if (ndm != dm) { dm->release(dm); @@ -1243,7 +1289,6 @@ void AbcSubDReader::readObjectData(Main *bmain, float time) DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true); - const ISampleSelector sample_sel(time); const ISubDSchema::Sample sample = m_schema.getValue(sample_sel); Int32ArraySamplePtr indices = sample.getCreaseIndices(); Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses(); @@ -1274,9 +1319,11 @@ void AbcSubDReader::readObjectData(Main *bmain, float time) } } -DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str) +DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, + const ISampleSelector &sample_sel, + int read_flag, + const char **err_str) { - ISampleSelector sample_sel(time); const ISubDSchema::Sample sample = m_schema.getValue(sample_sel); const P3fArraySamplePtr &positions = sample.getPositions(); @@ -1316,7 +1363,7 @@ DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, const float time, /* Only read point data when streaming meshes, unless we need to create new ones. */ CDStreamConfig config = get_config(new_dm ? new_dm : dm); - config.time = time; + config.time = sample_sel.getRequestedTime(); read_subd_sample(&settings, m_schema, sample_sel, config); if (new_dm) { diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h index 64a3109232c..6bf1dde3d1d 100644 --- a/source/blender/alembic/intern/abc_mesh.h +++ b/source/blender/alembic/intern/abc_mesh.h @@ -99,10 +99,15 @@ public: AbcMeshReader(const Alembic::Abc::IObject &object, ImportSettings &settings); bool valid() const; + bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const; + void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); - void readObjectData(Main *bmain, float time); - - DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str); + DerivedMesh *read_derivedmesh(DerivedMesh *dm, + const Alembic::Abc::ISampleSelector &sample_sel, + int read_flag, + const char **err_str); private: void readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start, @@ -120,9 +125,14 @@ public: AbcSubDReader(const Alembic::Abc::IObject &object, ImportSettings &settings); bool valid() const; - - void readObjectData(Main *bmain, float time); - DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str); + bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const; + void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); + DerivedMesh *read_derivedmesh(DerivedMesh *dm, + const Alembic::Abc::ISampleSelector &sample_sel, + int read_flag, + const char **err_str); }; /* ************************************************************************** */ diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc index d0b9561f679..eaef06fd6d1 100644 --- a/source/blender/alembic/intern/abc_nurbs.cc +++ b/source/blender/alembic/intern/abc_nurbs.cc @@ -239,7 +239,7 @@ static bool set_knots(const FloatArraySamplePtr &knots, float *&nu_knots) return true; } -void AbcNurbsReader::readObjectData(Main *bmain, float time) +void AbcNurbsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) { Curve *cu = static_cast<Curve *>(BKE_curve_add(bmain, "abc_curve", OB_SURF)); cu->actvert = CU_ACT_NONE; @@ -253,7 +253,6 @@ void AbcNurbsReader::readObjectData(Main *bmain, float time) nu->resolu = cu->resolu; nu->resolv = cu->resolv; - const ISampleSelector sample_sel(time); const INuPatchSchema &schema = it->first; const INuPatchSchema::Sample smp = schema.getValue(sample_sel); diff --git a/source/blender/alembic/intern/abc_nurbs.h b/source/blender/alembic/intern/abc_nurbs.h index 1b2e7a8391f..abe460a8988 100644 --- a/source/blender/alembic/intern/abc_nurbs.h +++ b/source/blender/alembic/intern/abc_nurbs.h @@ -54,7 +54,7 @@ public: bool valid() const; - void readObjectData(Main *bmain, float time); + void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); private: void getNurbsPatches(const Alembic::Abc::IObject &obj); diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index c8716d55218..6c4cb60d63c 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -140,6 +140,38 @@ AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings else { m_object_name = m_data_name = parts[parts.size() - 1]; } + + determine_inherits_xform(); +} + +/* Determine whether we can inherit our parent's XForm */ +void AbcObjectReader::determine_inherits_xform() +{ + m_inherits_xform = false; + + IXform ixform = xform(); + if (!ixform) { + return; + } + + const IXformSchema & schema(ixform.getSchema()); + if (!schema.valid()) { + std::cerr << "Alembic object " << ixform.getFullName() + << " has an invalid schema." << std::endl; + return; + } + + m_inherits_xform = schema.getInheritsXforms(); + + IObject ixform_parent = ixform.getParent(); + if (!ixform_parent.getParent()) { + /* The archive top object certainly is not a transform itself, so handle + * it as "no parent". */ + m_inherits_xform = false; + } + else { + m_inherits_xform = ixform_parent && m_inherits_xform; + } } AbcObjectReader::~AbcObjectReader() @@ -215,6 +247,14 @@ Imath::M44d get_matrix(const IXformSchema &schema, const float time) return s0.getMatrix(); } +DerivedMesh *AbcObjectReader::read_derivedmesh(DerivedMesh *dm, + const Alembic::Abc::ISampleSelector &UNUSED(sample_sel), + int UNUSED(read_flag), + const char **UNUSED(err_str)) +{ + return dm; +} + void AbcObjectReader::setupObjectTransform(const float time) { bool is_constant = false; @@ -278,32 +318,10 @@ void AbcObjectReader::read_matrix(float r_mat[4][4], const float time, return; } - bool has_alembic_parent; - IObject ixform_parent = ixform.getParent(); - if (!ixform_parent.getParent()) { - /* The archive top object certainly is not a transform itself, so handle - * it as "no parent". */ - has_alembic_parent = false; - } - else { - has_alembic_parent = ixform_parent && schema.getInheritsXforms(); - - if (has_alembic_parent && m_object->parent == NULL) { - /* TODO Sybren: This happened in some files. I think I solved it, - * but I'll leave this check in here anyway until we've tested it - * more thoroughly. Better than crashing on a null parent anyway. */ - std::cerr << "Alembic object " << m_iobject.getFullName() - << " with transform " << ixform.getFullName() - << " has an Alembic parent but no parent Blender object." - << std::endl; - has_alembic_parent = false; - } - } - const Imath::M44d matrix = get_matrix(schema, time); convert_matrix(matrix, m_object, r_mat); - if (has_alembic_parent) { + if (m_inherits_xform) { /* In this case, the matrix in Alembic is in local coordinates, so * convert to world matrix. To prevent us from reading and accumulating * all parent matrices in the Alembic file, we assume that the Blender @@ -362,4 +380,5 @@ void AbcObjectReader::incref() void AbcObjectReader::decref() { --m_refcount; + BLI_assert(m_refcount >= 0); } diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h index d5344533b55..852ef451f23 100644 --- a/source/blender/alembic/intern/abc_object.h +++ b/source/blender/alembic/intern/abc_object.h @@ -90,7 +90,7 @@ struct ImportSettings { /* Length and frame offset of file sequences. */ int sequence_len; - int offset; + int sequence_offset; /* From MeshSeqCacheModifierData.read_flag */ int read_flag; @@ -107,7 +107,7 @@ struct ImportSettings { , is_sequence(false) , set_frame_range(false) , sequence_len(1) - , offset(0) + , sequence_offset(0) , read_flag(0) , validate_meshes(false) , cache_file(NULL) @@ -143,6 +143,8 @@ protected: * modifiers and/or constraints. */ int m_refcount; + bool m_inherits_xform; + public: AbcObjectReader *parent_reader; @@ -167,18 +169,19 @@ public: const std::string & name() const { return m_name; } const std::string & object_name() const { return m_object_name; } const std::string & data_name() const { return m_data_name; } + bool inherits_xform() const { return m_inherits_xform; } virtual bool valid() const = 0; + virtual bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const = 0; - virtual void readObjectData(Main *bmain, float time) = 0; + virtual void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) = 0; - virtual DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str) - { - (void)time; - (void)read_flag; - (void)err_str; - return dm; - } + virtual DerivedMesh *read_derivedmesh(DerivedMesh *dm, + const Alembic::Abc::ISampleSelector &sample_sel, + int read_flag, + const char **err_str); /** Reads the object matrix and sets up an object transform if animated. */ void setupObjectTransform(const float time); @@ -194,6 +197,9 @@ public: void read_matrix(float r_mat[4][4], const float time, const float scale, bool &is_constant); + +protected: + void determine_inherits_xform(); }; Imath::M44d get_matrix(const Alembic::AbcGeom::IXformSchema &schema, const float time); diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc index fc84759b1d9..80567cd6bf0 100644 --- a/source/blender/alembic/intern/abc_points.cc +++ b/source/blender/alembic/intern/abc_points.cc @@ -151,12 +151,29 @@ bool AbcPointsReader::valid() const return m_schema.valid(); } -void AbcPointsReader::readObjectData(Main *bmain, float time) +bool AbcPointsReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const +{ + if (!Alembic::AbcGeom::IPoints::matches(alembic_header)) { + *err_str = "Object type mismatch, Alembic object path pointed to Points when importing, but not any more."; + return false; + } + + if (ob->type != OB_MESH) { + *err_str = "Object type mismatch, Alembic object path points to Points."; + return false; + } + + return true; +} + +void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) { Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str()); DerivedMesh *dm = CDDM_from_mesh(mesh); - DerivedMesh *ndm = this->read_derivedmesh(dm, time, 0, NULL); + DerivedMesh *ndm = this->read_derivedmesh(dm, sample_sel, 0, NULL); if (ndm != dm) { dm->release(dm); @@ -178,8 +195,7 @@ void AbcPointsReader::readObjectData(Main *bmain, float time) void read_points_sample(const IPointsSchema &schema, const ISampleSelector &selector, - CDStreamConfig &config, - float time) + CDStreamConfig &config) { Alembic::AbcGeom::IPointsSchema::Sample sample = schema.getValue(selector); @@ -189,7 +205,7 @@ void read_points_sample(const IPointsSchema &schema, N3fArraySamplePtr vnormals; if (has_property(prop, "N")) { - const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(time); + const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(selector.getRequestedTime()); const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", itime); if (normals_prop) { @@ -200,9 +216,11 @@ void read_points_sample(const IPointsSchema &schema, read_mverts(config.mvert, positions, vnormals); } -DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char ** /*err_str*/) +DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, + const ISampleSelector &sample_sel, + int /*read_flag*/, + const char ** /*err_str*/) { - ISampleSelector sample_sel(time); const IPointsSchema::Sample sample = m_schema.getValue(sample_sel); const P3fArraySamplePtr &positions = sample.getPositions(); @@ -214,7 +232,7 @@ DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time } CDStreamConfig config = get_config(new_dm ? new_dm : dm); - read_points_sample(m_schema, sample_sel, config, time); + read_points_sample(m_schema, sample_sel, config); return new_dm ? new_dm : dm; } diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_points.h index cb68dbca4d5..369a802d763 100644 --- a/source/blender/alembic/intern/abc_points.h +++ b/source/blender/alembic/intern/abc_points.h @@ -58,15 +58,20 @@ public: AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings); bool valid() const; + bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const; - void readObjectData(Main *bmain, float time); + void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); - DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str); + DerivedMesh *read_derivedmesh(DerivedMesh *dm, + const Alembic::Abc::ISampleSelector &sample_sel, + int read_flag, + const char **err_str); }; void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema, const Alembic::AbcGeom::ISampleSelector &selector, - CDStreamConfig &config, - float time); + CDStreamConfig &config); #endif /* __ABC_POINTS_H__ */ diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index cad1eae4764..5392387663f 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -36,6 +36,7 @@ extern "C" { using Alembic::AbcGeom::OObject; using Alembic::AbcGeom::OXform; +using Alembic::Abc::ISampleSelector; /* ************************************************************************** */ @@ -62,6 +63,7 @@ AbcTransformWriter::AbcTransformWriter(Object *ob, unsigned int time_sampling, ExportSettings &settings) : AbcObjectWriter(NULL, ob, time_sampling, settings, parent) + , m_proxy_from(NULL) { m_is_animated = hasAnimation(m_object); @@ -71,6 +73,9 @@ AbcTransformWriter::AbcTransformWriter(Object *ob, m_xform = OXform(abc_parent, get_id_name(m_object), time_sampling); m_schema = m_xform.getSchema(); + + /* Blender objects can't have a parent without inheriting the transform. */ + m_inherits_xform = parent != NULL; } void AbcTransformWriter::do_write() @@ -86,28 +91,29 @@ void AbcTransformWriter::do_write() } float yup_mat[4][4]; - create_transform_matrix(m_object, yup_mat); + create_transform_matrix(m_object, yup_mat, + m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD, + m_proxy_from); /* Only apply rotation to root camera, parenting will propagate it. */ - if (m_object->type == OB_CAMERA && !has_parent_camera(m_object)) { + if (m_object->type == OB_CAMERA && (!m_inherits_xform || !has_parent_camera(m_object))) { float rot_mat[4][4]; axis_angle_to_mat4_single(rot_mat, 'X', -M_PI_2); mul_m4_m4m4(yup_mat, yup_mat, rot_mat); } - if (!m_object->parent) { + if (!m_object->parent || !m_inherits_xform) { /* Only apply scaling to root objects, parenting will propagate it. */ - /* TODO Sybren: when we're exporting as "flat", i.e. non-hierarchial, - * we should apply the scale even when the object has a parent - * Blender Object. */ float scale_mat[4][4]; scale_m4_fl(scale_mat, m_settings.global_scale); scale_mat[3][3] = m_settings.global_scale; /* also scale translation */ mul_m4_m4m4(yup_mat, yup_mat, scale_mat); + yup_mat[3][3] /= m_settings.global_scale; /* normalise the homogeneous component */ } m_matrix = convert_matrix(yup_mat); m_sample.setMatrix(m_matrix); + m_sample.setInheritsXforms(m_inherits_xform); m_schema.set(m_sample); } @@ -149,7 +155,24 @@ bool AbcEmptyReader::valid() const return m_schema.valid(); } -void AbcEmptyReader::readObjectData(Main *bmain, float /*time*/) +bool AbcEmptyReader::accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const +{ + if (!Alembic::AbcGeom::IXform::matches(alembic_header)) { + *err_str = "Object type mismatch, Alembic object path pointed to XForm when importing, but not any more."; + return false; + } + + if (ob->type != OB_EMPTY) { + *err_str = "Object type mismatch, Alembic object path points to XForm."; + return false; + } + + return true; +} + +void AbcEmptyReader::readObjectData(Main *bmain, const ISampleSelector &UNUSED(sample_sel)) { m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str()); diff --git a/source/blender/alembic/intern/abc_transform.h b/source/blender/alembic/intern/abc_transform.h index b55fa12dadf..753a4247e9f 100644 --- a/source/blender/alembic/intern/abc_transform.h +++ b/source/blender/alembic/intern/abc_transform.h @@ -38,6 +38,10 @@ class AbcTransformWriter : public AbcObjectWriter { bool m_is_animated; bool m_visible; + bool m_inherits_xform; + +public: + Object *m_proxy_from; public: AbcTransformWriter(Object *ob, @@ -64,8 +68,11 @@ public: AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings); bool valid() const; + bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, + const Object *const ob, + const char **err_str) const; - void readObjectData(Main *bmain, float time); + void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); }; #endif /* __ABC_TRANSFORM_H__ */ diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc index 224e0eccd00..26eb7620fb1 100644 --- a/source/blender/alembic/intern/abc_util.cc +++ b/source/blender/alembic/intern/abc_util.cc @@ -142,7 +142,7 @@ void create_swapped_rotation_matrix( float rz; /* Apply transformation */ - switch(mode) { + switch (mode) { case ABC_ZUP_FROM_YUP: ry = -euler[2]; rz = euler[1]; @@ -217,7 +217,7 @@ void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMod copy_m4_m3(dst_mat, dst_rot); /* Apply translation */ - switch(mode) { + switch (mode) { case ABC_ZUP_FROM_YUP: copy_zup_from_yup(dst_mat[3], src_trans); break; @@ -257,24 +257,27 @@ void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4]) /* Recompute transform matrix of object in new coordinate system * (from Z-Up to Y-Up). */ -void create_transform_matrix(Object *obj, float r_yup_mat[4][4]) +void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode mode, + Object *proxy_from) { float zup_mat[4][4]; - /* get local matrix. */ - /* TODO Sybren: when we're exporting as "flat", i.e. non-hierarchial, - * we should export the world matrix even when the object has a parent - * Blender Object. */ - if (obj->parent) { + /* get local or world matrix. */ + if (mode == ABC_MATRIX_LOCAL && obj->parent) { /* Note that this produces another matrix than the local matrix, due to * constraints and modifiers as well as the obj->parentinv matrix. */ invert_m4_m4(obj->parent->imat, obj->parent->obmat); mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat); - copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); } else { - copy_m44_axis_swap(r_yup_mat, obj->obmat, ABC_YUP_FROM_ZUP); + copy_m4_m4(zup_mat, obj->obmat); } + + if (proxy_from) { + mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat); + } + + copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); } bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name) diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h index 5b53c86a859..2526958111a 100644 --- a/source/blender/alembic/intern/abc_util.h +++ b/source/blender/alembic/intern/abc_util.h @@ -33,7 +33,7 @@ #endif /** - * @brief The CacheReader struct is only used for anonymous pointers, + * \brief The CacheReader struct is only used for anonymous pointers, * to interface between C and C++ code. This library only creates * pointers to AbcObjectReader (or subclasses thereof). */ @@ -57,7 +57,13 @@ bool object_selected(Object *ob); bool parent_selected(Object *ob); Imath::M44d convert_matrix(float mat[4][4]); -void create_transform_matrix(Object *obj, float r_transform_mat[4][4]); + +typedef enum { + ABC_MATRIX_WORLD = 1, + ABC_MATRIX_LOCAL = 2, +} AbcMatrixMode; +void create_transform_matrix(Object *obj, float r_transform_mat[4][4], + AbcMatrixMode mode, Object *proxy_from); void split(const std::string &s, const char delim, std::vector<std::string> &tokens); diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 9529b370928..bee8e92e969 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -172,7 +172,7 @@ static bool gather_objects_paths(const IObject &object, ListBase *object_paths) void *abc_path_void = MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath"); AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(abc_path_void); - BLI_strncpy(abc_path->path, object.getFullName().c_str(), PATH_MAX); + BLI_strncpy(abc_path->path, object.getFullName().c_str(), sizeof(abc_path->path)); BLI_addtail(object_paths, abc_path); } @@ -238,6 +238,7 @@ struct ExportJobData { float *progress; bool was_canceled; + bool export_ok; }; static void export_startjob(void *customdata, short *stop, short *do_update, float *progress) @@ -271,6 +272,8 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo BKE_scene_update_for_newframe(data->bmain->eval_ctx, data->bmain, scene, scene->lay); } + + data->export_ok = !data->was_canceled; } catch (const std::exception &e) { ABC_LOG(data->settings.logger) << "Abc Export error: " << e.what() << '\n'; @@ -297,15 +300,17 @@ static void export_endjob(void *customdata) BKE_spacedata_draw_locks(false); } -void ABC_export( +bool ABC_export( Scene *scene, bContext *C, const char *filepath, - const struct AlembicExportParams *params) + const struct AlembicExportParams *params, + bool as_background_job) { ExportJobData *job = static_cast<ExportJobData *>(MEM_mallocN(sizeof(ExportJobData), "ExportJobData")); job->scene = scene; job->bmain = CTX_data_main(C); + job->export_ok = false; BLI_strncpy(job->filename, filepath, 1024); /* Alright, alright, alright.... @@ -327,8 +332,8 @@ void ABC_export( job->settings.scene = job->scene; job->settings.frame_start = params->frame_start; job->settings.frame_end = params->frame_end; - job->settings.frame_step_xform = params->frame_step_xform; - job->settings.frame_step_shape = params->frame_step_shape; + job->settings.frame_samples_xform = params->frame_samples_xform; + job->settings.frame_samples_shape = params->frame_samples_shape; job->settings.shutter_open = params->shutter_open; job->settings.shutter_close = params->shutter_close; job->settings.selected_only = params->selected_only; @@ -336,6 +341,8 @@ void ABC_export( job->settings.export_normals = params->normals; job->settings.export_uvs = params->uvs; job->settings.export_vcols = params->vcolors; + job->settings.export_hair = params->export_hair; + job->settings.export_particles = params->export_particles; job->settings.apply_subdiv = params->apply_subdiv; job->settings.flatten_hierarchy = params->flatten_hierarchy; job->settings.visible_layers_only = params->visible_layers_only; @@ -352,19 +359,35 @@ void ABC_export( std::swap(job->settings.frame_start, job->settings.frame_end); } - wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), - CTX_wm_window(C), - job->scene, - "Alembic Export", - WM_JOB_PROGRESS, - WM_JOB_TYPE_ALEMBIC); + bool export_ok = false; + if (as_background_job) { + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + job->scene, + "Alembic Export", + WM_JOB_PROGRESS, + WM_JOB_TYPE_ALEMBIC); + + /* setup job */ + WM_jobs_customdata_set(wm_job, job, MEM_freeN); + WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME); + WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob); + + WM_jobs_start(CTX_wm_manager(C), wm_job); + } + else { + /* Fake a job context, so that we don't need NULL pointer checks while exporting. */ + short stop = 0, do_update = 0; + float progress = 0.f; + + export_startjob(job, &stop, &do_update, &progress); + export_endjob(job); + export_ok = job->export_ok; - /* setup job */ - WM_jobs_customdata_set(wm_job, job, MEM_freeN); - WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME); - WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob); + MEM_freeN(job); + } - WM_jobs_start(CTX_wm_manager(C), wm_job); + return export_ok; } /* ********************** Import file ********************** */ @@ -429,7 +452,8 @@ static std::pair<bool, AbcObjectReader *> visit_object( else { if (child_claims_this_object) { claiming_child_readers.push_back(child_reader); - } else { + } + else { nonclaiming_child_readers.push_back(child_reader); } } @@ -523,7 +547,7 @@ static std::pair<bool, AbcObjectReader *> visit_object( AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>( MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath")); - BLI_strncpy(abc_path->path, full_name.c_str(), PATH_MAX); + BLI_strncpy(abc_path->path, full_name.c_str(), sizeof(abc_path->path)); BLI_addtail(&settings.cache_file->object_paths, abc_path); /* We can now assign this reader as parent for our children. */ @@ -576,6 +600,7 @@ static std::pair<bool, AbcObjectReader *> visit_object( enum { ABC_NO_ERROR = 0, ABC_ARCHIVE_FAIL, + ABC_UNSUPPORTED_HDF5, }; struct ImportJobData { @@ -593,6 +618,7 @@ struct ImportJobData { char error_code; bool was_cancelled; + bool import_ok; }; ABC_INLINE bool is_mesh_and_strands(const IObject &object) @@ -639,8 +665,12 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa ArchiveReader *archive = new ArchiveReader(data->filename); if (!archive->valid()) { - delete archive; +#ifndef WITH_ALEMBIC_HDF5 + data->error_code = archive->is_hdf5() ? ABC_UNSUPPORTED_HDF5 : ABC_ARCHIVE_FAIL; +#else data->error_code = ABC_ARCHIVE_FAIL; +#endif + delete archive; return; } @@ -684,12 +714,13 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa chrono_t min_time = std::numeric_limits<chrono_t>::max(); chrono_t max_time = std::numeric_limits<chrono_t>::min(); + ISampleSelector sample_sel(0.0f); std::vector<AbcObjectReader *>::iterator iter; for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { AbcObjectReader *reader = *iter; if (reader->valid()) { - reader->readObjectData(data->bmain, 0.0f); + reader->readObjectData(data->bmain, sample_sel); min_time = std::min(min_time, reader->minTime()); max_time = std::max(max_time, reader->maxTime()); @@ -712,13 +743,13 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa Scene *scene = data->scene; if (data->settings.is_sequence) { - SFRA = data->settings.offset; + SFRA = data->settings.sequence_offset; EFRA = SFRA + (data->settings.sequence_len - 1); CFRA = SFRA; } else if (min_time < max_time) { - SFRA = static_cast<int>(min_time * FPS); - EFRA = static_cast<int>(max_time * FPS); + SFRA = static_cast<int>(round(min_time * FPS)); + EFRA = static_cast<int>(round(max_time * FPS)); CFRA = SFRA; } } @@ -729,7 +760,7 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa const AbcObjectReader *parent_reader = reader->parent_reader; Object *ob = reader->object(); - if (parent_reader == NULL) { + if (parent_reader == NULL || !reader->inherits_xform()) { ob->parent = NULL; } else { @@ -775,13 +806,16 @@ static void import_endjob(void *user_data) } else { /* Add object to scene. */ + Base *base; + BKE_scene_base_deselect_all(data->scene); for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { Object *ob = (*iter)->object(); ob->lay = data->scene->lay; - BKE_scene_base_add(data->scene, ob); + base = BKE_scene_base_add(data->scene, ob); + BKE_scene_base_select(data->scene, base); DAG_id_tag_update_ex(data->bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } @@ -801,10 +835,14 @@ static void import_endjob(void *user_data) switch (data->error_code) { default: case ABC_NO_ERROR: + data->import_ok = !data->was_cancelled; break; case ABC_ARCHIVE_FAIL: WM_report(RPT_ERROR, "Could not open Alembic archive for reading! See console for detail."); break; + case ABC_UNSUPPORTED_HDF5: + WM_report(RPT_ERROR, "Alembic archive in obsolete HDF5 format is not supported."); + break; } WM_main_add_notifier(NC_SCENE | ND_FRAME, data->scene); @@ -816,39 +854,58 @@ static void import_freejob(void *user_data) delete data; } -void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence, bool set_frame_range, int sequence_len, int offset, bool validate_meshes) +bool ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence, + bool set_frame_range, int sequence_len, int offset, + bool validate_meshes, bool as_background_job) { /* Using new here since MEM_* funcs do not call ctor to properly initialize * data. */ ImportJobData *job = new ImportJobData(); job->bmain = CTX_data_main(C); job->scene = CTX_data_scene(C); + job->import_ok = false; BLI_strncpy(job->filename, filepath, 1024); job->settings.scale = scale; job->settings.is_sequence = is_sequence; job->settings.set_frame_range = set_frame_range; job->settings.sequence_len = sequence_len; - job->settings.offset = offset; + job->settings.sequence_offset = offset; job->settings.validate_meshes = validate_meshes; job->error_code = ABC_NO_ERROR; job->was_cancelled = false; G.is_break = false; - wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), - CTX_wm_window(C), - job->scene, - "Alembic Import", - WM_JOB_PROGRESS, - WM_JOB_TYPE_ALEMBIC); + bool import_ok = false; + if (as_background_job) { + wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), + CTX_wm_window(C), + job->scene, + "Alembic Import", + WM_JOB_PROGRESS, + WM_JOB_TYPE_ALEMBIC); - /* setup job */ - WM_jobs_customdata_set(wm_job, job, import_freejob); - WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME); - WM_jobs_callbacks(wm_job, import_startjob, NULL, NULL, import_endjob); + /* setup job */ + WM_jobs_customdata_set(wm_job, job, import_freejob); + WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME); + WM_jobs_callbacks(wm_job, import_startjob, NULL, NULL, import_endjob); + + WM_jobs_start(CTX_wm_manager(C), wm_job); + } + else { + /* Fake a job context, so that we don't need NULL pointer checks while importing. */ + short stop = 0, do_update = 0; + float progress = 0.f; + + import_startjob(job, &stop, &do_update, &progress); + import_endjob(job); + import_ok = job->import_ok; + + import_freejob(job); + } - WM_jobs_start(CTX_wm_manager(C), wm_job); + return import_ok; } /* ************************************************************************** */ @@ -883,42 +940,15 @@ DerivedMesh *ABC_read_mesh(CacheReader *reader, } const ObjectHeader &header = iobject.getHeader(); - - if (IPolyMesh::matches(header)) { - if (ob->type != OB_MESH) { - *err_str = "Object type mismatch: object path points to a mesh!"; - return NULL; - } - - return abc_reader->read_derivedmesh(dm, time, read_flag, err_str); - } - else if (ISubD::matches(header)) { - if (ob->type != OB_MESH) { - *err_str = "Object type mismatch: object path points to a subdivision mesh!"; - return NULL; - } - - return abc_reader->read_derivedmesh(dm, time, read_flag, err_str); - } - else if (IPoints::matches(header)) { - if (ob->type != OB_MESH) { - *err_str = "Object type mismatch: object path points to a point cloud (requires a mesh object)!"; - return NULL; - } - - return abc_reader->read_derivedmesh(dm, time, read_flag, err_str); - } - else if (ICurves::matches(header)) { - if (ob->type != OB_CURVE) { - *err_str = "Object type mismatch: object path points to a curve!"; - return NULL; - } - - return abc_reader->read_derivedmesh(dm, time, read_flag, err_str); + if (!abc_reader->accepts_object_type(header, ob, err_str)) { + /* err_str is set by acceptsObjectType() */ + return NULL; } - *err_str = "Unsupported object type: verify object path"; // or poke developer - return NULL; + /* kFloorIndex is used to be compatible with non-interpolating + * properties; they use the floor. */ + ISampleSelector sample_sel(time, ISampleSelector::kFloorIndex); + return abc_reader->read_derivedmesh(dm, sample_sel, read_flag, err_str); } /* ************************************************************************** */ @@ -933,6 +963,12 @@ void CacheReader_free(CacheReader *reader) } } +void CacheReader_incref(CacheReader *reader) +{ + AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader); + abc_reader->incref(); +} + CacheReader *CacheReader_open_alembic_object(AbcArchiveHandle *handle, CacheReader *reader, Object *object, const char *object_path) { if (object_path[0] == '\0') { diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 1f38d64924c..8c8aef3de57 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -38,7 +38,7 @@ struct rctf; struct ColorManagedDisplay; struct ResultBLF; -int BLF_init(int points, int dpi); +int BLF_init(void); void BLF_exit(void); void BLF_default_dpi(int dpi); void BLF_default_set(int fontid); diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 132a0ec3808..5bd62980b6d 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -96,15 +96,16 @@ static FontBLF *blf_get(int fontid) return NULL; } -int BLF_init(int points, int dpi) +int BLF_init(void) { int i; for (i = 0; i < BLF_MAX_FONT; i++) global_font[i] = NULL; - global_font_points = points; - global_font_dpi = dpi; + global_font_points = 11; + global_font_dpi = 72; + return blf_font_init(); } diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index aa7d539538b..bbbabfb8ba2 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -135,6 +135,7 @@ void blf_glyph_cache_clear(FontBLF *font) while ((gc = BLI_pophead(&font->cache))) { blf_glyph_cache_free(gc); } + font->glyph_cache = NULL; } void blf_glyph_cache_free(GlyphCacheBLF *gc) diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 789bc8df7e5..63ff1149a68 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -201,7 +201,7 @@ struct DerivedMesh { /* use for converting to BMesh which doesn't store bevel weight and edge crease by default */ char cd_flag; - char tangent_mask; /* which tangent layers are calculated */ + short tangent_mask; /* which tangent layers are calculated */ /** Calculate vert and face normals */ void (*calcNormals)(DerivedMesh *dm); @@ -791,11 +791,13 @@ void DM_calc_tangents_names_from_gpu( void DM_add_named_tangent_layer_for_uv( CustomData *uv_data, CustomData *tan_data, int numLoopData, const char *layer_name); + +#define DM_TANGENT_MASK_ORCO (1 << 9) void DM_calc_loop_tangents_step_0( const CustomData *loopData, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME], int tangent_names_count, bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n, - char *ract_uv_name, char *rren_uv_name, char *rtangent_mask); + char *ract_uv_name, char *rren_uv_name, short *rtangent_mask); void DM_calc_loop_tangents( DerivedMesh *dm, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME], int tangent_names_count); diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 6527ba7f94f..5db0c3c9130 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -58,7 +58,7 @@ extern "C" { struct bAction *add_empty_action(struct Main *bmain, const char name[]); /* Allocate a copy of the given Action and all its data */ -struct bAction *BKE_action_copy(struct Main *bmain, struct bAction *src); +struct bAction *BKE_action_copy(struct Main *bmain, const struct bAction *src); /* Deallocate all of the Action's data, but not the Action itself */ void BKE_action_free(struct bAction *act); @@ -150,7 +150,7 @@ void BKE_pose_free_data_ex(struct bPose *pose, bool do_id_user); void BKE_pose_free_data(struct bPose *pose); void BKE_pose_free(struct bPose *pose); void BKE_pose_free_ex(struct bPose *pose, bool do_id_user); -void BKE_pose_copy_data(struct bPose **dst, struct bPose *src, const bool copy_constraints); +void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool copy_constraints); void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from); struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name); struct bPoseChannel *BKE_pose_channel_active(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index a67e903877a..420ae4bb12d 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -89,12 +89,6 @@ typedef enum eAnimData_MergeCopy_Modes { void BKE_animdata_merge_copy(struct ID *dst_id, struct ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers); -/* Make Local */ -void BKE_animdata_make_local(struct AnimData *adt); - -/* Re-Assign ID's */ -void BKE_animdata_relink(struct AnimData *adt); - /* ************************************* */ /* KeyingSets API */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 78d6f6c7cb9..6bfc8c918d6 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -77,7 +77,7 @@ int BKE_armature_bonelist_count(struct ListBase *lb); void BKE_armature_bonelist_free(struct ListBase *lb); void BKE_armature_free(struct bArmature *arm); void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool lib_local); -struct bArmature *BKE_armature_copy(struct Main *bmain, struct bArmature *arm); +struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature *arm); /* Bounding box. */ struct BoundBox *BKE_armature_boundbox_get(struct Object *ob); @@ -177,6 +177,7 @@ void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx, struct bPoseChannel *pchan); void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx, + struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan); diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index d55926ffb1e..ec0bfa6f5fa 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -50,7 +50,6 @@ void BKE_blender_version_string( void BKE_blender_userdef_set_data(struct UserDef *userdef); void BKE_blender_userdef_free_data(struct UserDef *userdef); -void BKE_blender_userdef_refresh(void); void BKE_blender_userdef_set_app_template(struct UserDef *userdef); diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 4f4787f9da5..207631d36bd 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -28,7 +28,7 @@ * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 278 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 6 diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h index 582cd0cef8d..24f19951efe 100644 --- a/source/blender/blenkernel/BKE_boids.h +++ b/source/blender/blenkernel/BKE_boids.h @@ -61,6 +61,6 @@ BoidRule *boid_new_rule(int type); BoidState *boid_new_state(BoidSettings *boids); BoidState *boid_duplicate_state(BoidSettings *boids, BoidState *state); void boid_free_settings(BoidSettings *boids); -BoidSettings *boid_copy_settings(BoidSettings *boids); +BoidSettings *boid_copy_settings(const BoidSettings *boids); BoidState *boid_get_current_state(BoidSettings *boids); #endif diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 8bd4bdf89e1..42e4e73f2d5 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -44,7 +44,7 @@ void BKE_brush_system_exit(void); void BKE_brush_init(struct Brush *brush); struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode); struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode); -struct Brush *BKE_brush_copy(struct Main *bmain, struct Brush *brush); +struct Brush *BKE_brush_copy(struct Main *bmain, const struct Brush *brush); void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local); void BKE_brush_unlink(struct Main *bmain, struct Brush *brush); void BKE_brush_free(struct Brush *brush); diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h index 0d4ed2083b1..f1e643c4a19 100644 --- a/source/blender/blenkernel/BKE_cachefile.h +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -47,7 +47,7 @@ void BKE_cachefile_init(struct CacheFile *cache_file); void BKE_cachefile_free(struct CacheFile *cache_file); -struct CacheFile *BKE_cachefile_copy(struct Main *bmain, struct CacheFile *cache_file); +struct CacheFile *BKE_cachefile_copy(struct Main *bmain, const struct CacheFile *cache_file); void BKE_cachefile_make_local(struct Main *bmain, struct CacheFile *cache_file, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 31a732cf7e5..b2f22aacb28 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -52,7 +52,7 @@ struct GPUFXSettings; void BKE_camera_init(struct Camera *cam); void *BKE_camera_add(struct Main *bmain, const char *name); -struct Camera *BKE_camera_copy(struct Main *bmain, struct Camera *cam); +struct Camera *BKE_camera_copy(struct Main *bmain, const struct Camera *cam); void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool lib_local); void BKE_camera_free(struct Camera *ca); diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 5b4f5910821..f68c4a2757b 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -46,8 +46,8 @@ void curvemapping_set_defaults(struct CurveMapping *cumap, int to struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); void curvemapping_free_data(struct CurveMapping *cumap); void curvemapping_free(struct CurveMapping *cumap); -void curvemapping_copy_data(struct CurveMapping *target, struct CurveMapping *cumap); -struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap); +void curvemapping_copy_data(struct CurveMapping *target, const struct CurveMapping *cumap); +struct CurveMapping *curvemapping_copy(const struct CurveMapping *cumap); void curvemapping_set_black_white_ex(const float black[3], const float white[3], float r_bwmul[3]); void curvemapping_set_black_white(struct CurveMapping *cumap, const float black[3], const float white[3]); diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index e111bd0e16b..635e999dd95 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -78,7 +78,7 @@ void BKE_curve_free(struct Curve *cu); void BKE_curve_editfont_free(struct Curve *cu); void BKE_curve_init(struct Curve *cu); struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type); -struct Curve *BKE_curve_copy(struct Main *bmain, struct Curve *cu); +struct Curve *BKE_curve_copy(struct Main *bmain, const struct Curve *cu); void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool lib_local); short BKE_curve_type_get(struct Curve *cu); void BKE_curve_type_test(struct Object *ob); @@ -142,7 +142,7 @@ int BKE_nurbList_verts_count(struct ListBase *nurb); int BKE_nurbList_verts_count_without_handles(struct ListBase *nurb); void BKE_nurbList_free(struct ListBase *lb); -void BKE_nurbList_duplicate(struct ListBase *lb1, struct ListBase *lb2); +void BKE_nurbList_duplicate(struct ListBase *lb1, const struct ListBase *lb2); void BKE_nurbList_handles_set(struct ListBase *editnurb, const char code); void BKE_nurbList_handles_recalculate(struct ListBase *editnurb, const bool calc_length, const char flag); @@ -150,7 +150,7 @@ void BKE_nurbList_handles_autocalc(ListBase *editnurb, int flag); void BKE_nurbList_flag_set(ListBase *editnurb, short flag); void BKE_nurb_free(struct Nurb *nu); -struct Nurb *BKE_nurb_duplicate(struct Nurb *nu); +struct Nurb *BKE_nurb_duplicate(const struct Nurb *nu); struct Nurb *BKE_nurb_copy(struct Nurb *src, int pntsu, int pntsv); void BKE_nurb_test2D(struct Nurb *nu); @@ -198,6 +198,7 @@ void BKE_nurb_bezt_calc_normal(struct Nurb *nu, struct BezTriple *bezt, float r_ void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3]); void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_normal[3]); +void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, struct BPoint *bp, float r_plane[3]); void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, const bool is_fcurve); diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 3ce08a14177..a20c5a4240c 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -44,8 +44,8 @@ struct MLoop; struct MPoly; struct bDeformGroup *BKE_defgroup_new(struct Object *ob, const char *name); -void defgroup_copy_list(struct ListBase *lb1, struct ListBase *lb2); -struct bDeformGroup *defgroup_duplicate(struct bDeformGroup *ingroup); +void defgroup_copy_list(struct ListBase *lb1, const struct ListBase *lb2); +struct bDeformGroup *defgroup_duplicate(const struct bDeformGroup *ingroup); struct bDeformGroup *defgroup_find_name(struct Object *ob, const char *name); int *defgroup_flip_map(struct Object *ob, int *flip_map_len, const bool use_default); int *defgroup_flip_map_single(struct Object *ob, int *flip_map_len, const bool use_default, int defgroup); diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 3a45097efc5..b38f1299763 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -92,7 +92,7 @@ void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt); /* ---------------------- */ void fcurve_free_driver(struct FCurve *fcu); -struct ChannelDriver *fcurve_copy_driver(struct ChannelDriver *driver); +struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver); void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list); @@ -138,7 +138,7 @@ typedef struct FModifierTypeInfo { /* free any data that is allocated separately (optional) */ void (*free_data)(struct FModifier *fcm); /* copy any special data that is allocated separately (optional) */ - void (*copy_data)(struct FModifier *fcm, struct FModifier *src); + void (*copy_data)(struct FModifier *fcm, const struct FModifier *src); /* set settings for data that will be used for FCuModifier.data (memory already allocated using MEM_callocN) */ void (*new_data)(void *mdata); /* verifies that the modifier settings are valid */ @@ -183,14 +183,14 @@ typedef enum eFMI_Requirement_Flags { } eFMI_Requirement_Flags; /* Function Prototypes for FModifierTypeInfo's */ -const FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm); -const FModifierTypeInfo *get_fmodifier_typeinfo(int type); +const FModifierTypeInfo *fmodifier_get_typeinfo(const struct FModifier *fcm); +const FModifierTypeInfo *get_fmodifier_typeinfo(const int type); /* ---------------------- */ struct FModifier *add_fmodifier(ListBase *modifiers, int type); -struct FModifier *copy_fmodifier(struct FModifier *src); -void copy_fmodifiers(ListBase *dst, ListBase *src); +struct FModifier *copy_fmodifier(const struct FModifier *src); +void copy_fmodifiers(ListBase *dst, const ListBase *src); bool remove_fmodifier(ListBase *modifiers, struct FModifier *fcm); void free_fmodifiers(ListBase *modifiers); @@ -216,7 +216,7 @@ int BKE_fcm_envelope_find_index(struct FCM_EnvelopeData *array, float frame, int /* -------- Data Management -------- */ void free_fcurve(struct FCurve *fcu); -struct FCurve *copy_fcurve(struct FCurve *fcu); +struct FCurve *copy_fcurve(const struct FCurve *fcu); void free_fcurves(ListBase *list); void copy_fcurves(ListBase *dst, ListBase *src); diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index 6775639125f..e7ae0f606e7 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -60,8 +60,9 @@ typedef struct EditFont { struct CharInfo *textbufinfo; /* array of rectangles & rotation */ - EditFontSelBox *selboxes; float textcurs[4][2]; + EditFontSelBox *selboxes; + int selboxes_len; /* positional vars relative to the textbuf, textbufinfo (not utf8 bytes) * a copy of these is kept in Curve, but use these in editmode */ diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 4bb2b950901..830518906ab 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -189,11 +189,6 @@ enum { # error Either __BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be defined. #endif -/* there is really no good place for this */ -#if defined(FREE_WINDOWS) && ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 6))) -# error "Mingw requires GCC 4.6 minimum" -#endif - #define L_ENDIAN 1 #define B_ENDIAN 0 diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 3378f4acc60..bdd28baf137 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -60,7 +60,7 @@ struct bGPdata *BKE_gpencil_data_addnew(const char name[]); struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src); struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src); -struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, struct bGPdata *gpd, bool internal_copy); +struct bGPdata *BKE_gpencil_data_duplicate(struct Main *bmain, const struct bGPdata *gpd, bool internal_copy); void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 09a069ee36f..684251c9561 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -42,7 +42,7 @@ struct Scene; void BKE_group_free(struct Group *group); struct Group *BKE_group_add(struct Main *bmain, const char *name); -struct Group *BKE_group_copy(struct Main *bmain, struct Group *group); +struct Group *BKE_group_copy(struct Main *bmain, const struct Group *group); void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local); bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 6944c5ccd28..39e6b145755 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -88,7 +88,7 @@ void BKE_previewimg_clear(struct PreviewImage *prv); void BKE_previewimg_clear_single(struct PreviewImage *prv, enum eIconSizes size); /* get the preview from any pointer */ -struct PreviewImage **BKE_previewimg_id_get_p(struct ID *id); +struct PreviewImage **BKE_previewimg_id_get_p(const struct ID *id); /* free the preview image belonging to the id */ void BKE_previewimg_id_free(struct ID *id); @@ -97,9 +97,9 @@ void BKE_previewimg_id_free(struct ID *id); struct PreviewImage *BKE_previewimg_create(void); /* create a copy of the preview image */ -struct PreviewImage *BKE_previewimg_copy(struct PreviewImage *prv); +struct PreviewImage *BKE_previewimg_copy(const struct PreviewImage *prv); -void BKE_previewimg_id_copy(struct ID *new_id, struct ID *old_id); +void BKE_previewimg_id_copy(struct ID *new_id, const struct ID *old_id); /* retrieve existing or create new preview image */ struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id); diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 5b10d7ebc06..ab8728faedb 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -60,8 +60,6 @@ typedef union IDPropertyTemplate { IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); IDProperty *IDP_CopyIDPArray(const IDProperty *array) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void IDP_FreeIDPArray(IDProperty *prop); - /* shallow copies item */ void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL(); struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -81,8 +79,8 @@ void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append) ATTR_N void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL(); /*-------- ID Type -------*/ -void IDP_LinkID(struct IDProperty *prop, ID *id); -void IDP_UnlinkID(struct IDProperty *prop); + +typedef void(*IDPWalkFunc)(void *userData, IDProperty *idp); /*-------- Group Functions -------*/ @@ -112,11 +110,12 @@ bool IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) AT struct IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void IDP_FreeProperty_ex(struct IDProperty *prop, const bool do_id_user); void IDP_FreeProperty(struct IDProperty *prop); void IDP_ClearProperty(IDProperty *prop); -void IDP_UnlinkProperty(struct IDProperty *prop); +void IDP_RelinkProperty(struct IDProperty *prop); #define IDP_Int(prop) ((prop)->data.val) #define IDP_Array(prop) ((prop)->data.pointer) @@ -134,11 +133,15 @@ void IDP_UnlinkProperty(struct IDProperty *prop); # define IDP_IDPArray(prop) _Generic((prop), \ IDProperty *: ((IDProperty *) (prop)->data.pointer), \ const IDProperty *: ((const IDProperty *) (prop)->data.pointer)) +# define IDP_Id(prop) _Generic((prop), \ + IDProperty *: ((ID *) (prop)->data.pointer), \ + const IDProperty *: ((const ID *) (prop)->data.pointer)) #else # define IDP_Float(prop) (*(float *)&(prop)->data.val) # define IDP_Double(prop) (*(double *)&(prop)->data.val) # define IDP_String(prop) ((char *) (prop)->data.pointer) # define IDP_IDPArray(prop) ((IDProperty *) (prop)->data.pointer) +# define IDP_Id(prop) ((ID *) (prop)->data.pointer) #endif #ifndef NDEBUG diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 132c73209d1..e155b0719cc 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -250,7 +250,7 @@ void BKE_image_packfiles_from_mem(struct ReportList *reports, struct Image *ima, void BKE_image_print_memlist(void); /* empty image block, of similar type and filename */ -struct Image *BKE_image_copy(struct Main *bmain, struct Image *ima); +struct Image *BKE_image_copy(struct Main *bmain, const struct Image *ima); /* merge source into dest, and free source */ void BKE_image_merge(struct Image *dest, struct Image *source); diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index e590ff148d7..94e8a24fbc5 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -51,7 +51,7 @@ extern "C" { void BKE_key_free(struct Key *sc); void BKE_key_free_nolib(struct Key *key); struct Key *BKE_key_add(struct ID *id); -struct Key *BKE_key_copy(struct Main *bmain, struct Key *key); +struct Key *BKE_key_copy(struct Main *bmain, const struct Key *key); struct Key *BKE_key_copy_nolib(struct Key *key); void BKE_key_sort(struct Key *key); diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 4d53850c572..713ca80fb1a 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -44,7 +44,7 @@ struct Scene; void BKE_lamp_init(struct Lamp *la); struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT; -struct Lamp *BKE_lamp_copy(struct Main *bmain, struct Lamp *la) ATTR_WARN_UNUSED_RESULT; +struct Lamp *BKE_lamp_copy(struct Main *bmain, const struct Lamp *la) ATTR_WARN_UNUSED_RESULT; struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT; void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local); void BKE_lamp_free(struct Lamp *la); diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 226c82da295..ec1cf79832d 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -47,7 +47,7 @@ struct MDeformVert; void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb); void BKE_lattice_init(struct Lattice *lt); struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name); -struct Lattice *BKE_lattice_copy(struct Main *bmain, struct Lattice *lt); +struct Lattice *BKE_lattice_copy(struct Main *bmain, const struct Lattice *lt); void BKE_lattice_free(struct Lattice *lt); void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool lib_local); void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 72ae2cf4efa..258dcc84449 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -50,11 +50,12 @@ struct bContext; struct PointerRNA; struct PropertyRNA; +size_t BKE_libblock_get_alloc_info(short type, const char **name); void *BKE_libblock_alloc_notest(short type); void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BKE_libblock_init_empty(struct ID *id); -void *BKE_libblock_copy(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void *BKE_libblock_copy_nolib(struct ID *id, const bool do_action) ATTR_NONNULL(); +void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void *BKE_libblock_copy_nolib(const struct ID *id, const bool do_action) ATTR_NONNULL(); void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action); void BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL(); void BLI_libblock_ensure_unique_name(struct Main *bmain, const char *name) ATTR_NONNULL(); @@ -64,9 +65,10 @@ struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_ /* library_remap.c (keep here since they're general functions) */ void BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL(); +void BKE_libblock_free_datablock(struct ID *id) ATTR_NONNULL(); void BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) ATTR_NONNULL(); void BKE_libblock_free_us(struct Main *bmain, void *idv) ATTR_NONNULL(); -void BKE_libblock_free_data(struct Main *bmain, struct ID *id) ATTR_NONNULL(); +void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL(); void BKE_libblock_delete(struct Main *bmain, void *idv) ATTR_NONNULL(); void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id); @@ -84,10 +86,10 @@ void BKE_id_clear_newpoin(struct ID *id); void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_in_mainlist, const bool lib_local); bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local); bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop); -bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test); +bool id_copy(struct Main *bmain, const struct ID *id, struct ID **newid, bool test); void id_sort_by_name(struct ListBase *lb, struct ID *id); void BKE_id_expand_local(struct Main *bmain, struct ID *id); -void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id); +void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id); bool new_id(struct ListBase *lb, struct ID *id, const char *name); void id_clear_lib_data(struct Main *bmain, struct ID *id); diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h index 1258e2fa72e..d6e7d98f371 100644 --- a/source/blender/blenkernel/BKE_library_query.h +++ b/source/blender/blenkernel/BKE_library_query.h @@ -51,6 +51,11 @@ enum { * This means callback shall not *do* anything, only use this as informative data if it needs it. */ IDWALK_CB_PRIVATE = (1 << 3), + /** That ID is not really used by its owner, it's just an internal hint/helper. + * This addresses Their Highest Ugliness the 'from' pointers: Object->from_proxy and Key->from. + * How to handle that kind of cases totally depends on what caller code is doing... */ + IDWALK_CB_LOOPBACK = (1 << 4), + /** * Adjusts #ID.us reference-count. * \note keep in sync with 'newlibadr_us' use in readfile.c @@ -78,6 +83,8 @@ enum { IDWALK_NOP = 0, IDWALK_READONLY = (1 << 0), IDWALK_RECURSE = (1 << 1), /* Also implies IDWALK_READONLY. */ + + IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */ }; /* Loop over all of the ID's this datablock links to. */ @@ -87,7 +94,7 @@ void BKE_library_update_ID_link_user(struct ID *id_dst, struct ID *id_src, const int BKE_library_ID_use_ID(struct ID *id_user, struct ID *id_used); -bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id_type_used); +bool BKE_library_id_can_use_idtype(struct ID *id_owner, const short id_type_used); bool BKE_library_ID_is_locally_used(struct Main *bmain, void *idv); bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv); diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h index 53d438a0fdd..fd37fd762f4 100644 --- a/source/blender/blenkernel/BKE_library_remap.h +++ b/source/blender/blenkernel/BKE_library_remap.h @@ -46,6 +46,11 @@ enum { /* This tells the callback func to force setting IDs using target one with a 'never NULL' pointer to NULL. * WARNING! Use with extreme care, this will leave database in broken state and can cause crashes very easily! */ ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3, + /* Do not consider proxy/_group pointers of local objects as indirect usages... + * Our oh-so-beloved proxies again... Do not consider data used by local proxy object as indirect usage. + * This is needed e.g. in reload scenario, since we have to ensure remapping of Armature data of local proxy + * is also performed. Usual nightmare... */ + ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4, }; /* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */ diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h index af9bf58ce77..c7b323d0f6e 100644 --- a/source/blender/blenkernel/BKE_linestyle.h +++ b/source/blender/blenkernel/BKE_linestyle.h @@ -52,7 +52,7 @@ struct bContext; void BKE_linestyle_init(struct FreestyleLineStyle *linestyle); FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name); void BKE_linestyle_free(FreestyleLineStyle *linestyle); -FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle); +FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle); void BKE_linestyle_make_local(struct Main *bmain, struct FreestyleLineStyle *linestyle, const bool lib_local); @@ -63,10 +63,10 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type); LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type); -LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m); -LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m); -LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m); -LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m); +LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m); +LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m); +LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m); +LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m); int BKE_linestyle_color_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier); int BKE_linestyle_alpha_modifier_remove(FreestyleLineStyle *linestyle, LineStyleModifier *modifier); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 3349bffac85..0735d2d97a1 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -77,14 +77,14 @@ void BKE_mask_layer_free(struct MaskLayer *masklay); void BKE_mask_layer_free_list(struct ListBase *masklayers); void BKE_mask_spline_free(struct MaskSpline *spline); void BKE_mask_spline_free_list(struct ListBase *splines); -struct MaskSpline *BKE_mask_spline_copy(struct MaskSpline *spline); +struct MaskSpline *BKE_mask_spline_copy(const struct MaskSpline *spline); void BKE_mask_point_free(struct MaskSplinePoint *point); void BKE_mask_layer_unique_name(struct Mask *mask, struct MaskLayer *masklay); void BKE_mask_layer_rename(struct Mask *mask, struct MaskLayer *masklay, char *oldname, char *newname); -struct MaskLayer *BKE_mask_layer_copy(struct MaskLayer *layer); -void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, struct ListBase *masklayers); +struct MaskLayer *BKE_mask_layer_copy(const struct MaskLayer *layer); +void BKE_mask_layer_copy_list(struct ListBase *masklayers_new, const struct ListBase *masklayers); /* splines */ struct MaskSpline *BKE_mask_spline_add(struct MaskLayer *masklay); @@ -123,7 +123,7 @@ void BKE_mask_point_select_set_handle(struct MaskSplinePoint *point, const eMask /* general */ struct Mask *BKE_mask_new(struct Main *bmain, const char *name); struct Mask *BKE_mask_copy_nolib(struct Mask *mask); -struct Mask *BKE_mask_copy(struct Main *bmain, struct Mask *mask); +struct Mask *BKE_mask_copy(struct Main *bmain, const struct Mask *mask); void BKE_mask_make_local(struct Main *bmain, struct Mask *mask, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 8ae5c2b3c45..7da962dd6d6 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -54,7 +54,7 @@ void BKE_material_init(struct Material *ma); void BKE_material_remap_object(struct Object *ob, const unsigned int *remap); void BKE_material_remap_object_calc(struct Object *ob_dst, struct Object *ob_src, short *remap_src_to_dst); struct Material *BKE_material_add(struct Main *bmain, const char *name); -struct Material *BKE_material_copy(struct Main *bmain, struct Material *ma); +struct Material *BKE_material_copy(struct Main *bmain, const struct Material *ma); struct Material *localize_material(struct Material *ma); struct Material *give_node_material(struct Material *ma); /* returns node material or self */ void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 64320a20281..c00a0743ebb 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -41,7 +41,7 @@ struct MetaElem; void BKE_mball_free(struct MetaBall *mb); void BKE_mball_init(struct MetaBall *mb); struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name); -struct MetaBall *BKE_mball_copy(struct Main *bmain, struct MetaBall *mb); +struct MetaBall *BKE_mball_copy(struct Main *bmain, const struct MetaBall *mb); void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool lib_local); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index b83bec5a302..b55b8b2dd3c 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -87,7 +87,7 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v); void BKE_mesh_free(struct Mesh *me); void BKE_mesh_init(struct Mesh *me); struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name); -struct Mesh *BKE_mesh_copy(struct Main *bmain, struct Mesh *me); +struct Mesh *BKE_mesh_copy(struct Main *bmain, const struct Mesh *me); void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd); void BKE_mesh_ensure_skin_customdata(struct Mesh *me); @@ -110,7 +110,8 @@ int BKE_mesh_nurbs_displist_to_mdata( struct MEdge **r_alledge, int *r_totedge, struct MLoop **r_allloop, struct MPoly **r_allpoly, struct MLoopUV **r_alluv, int *r_totloop, int *r_totpoly); -void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv); +void BKE_mesh_from_nurbs_displist( + struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv, const char *obdata_name); void BKE_mesh_from_nurbs(struct Object *ob); void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test); void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 3237c146bc5..69fdad5ef7b 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -41,7 +41,7 @@ struct MovieDistortion; void BKE_movieclip_free(struct MovieClip *clip); -struct MovieClip *BKE_movieclip_copy(struct Main *bmain, struct MovieClip *clip); +struct MovieClip *BKE_movieclip_copy(struct Main *bmain, const struct MovieClip *clip); void BKE_movieclip_make_local(struct Main *bmain, struct MovieClip *clip, const bool lib_local); struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 193f1154c54..d5279c5b0ce 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -335,8 +335,8 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char /* copy/free funcs, need to manage ID users */ void ntreeFreeTree(struct bNodeTree *ntree); -struct bNodeTree *ntreeCopyTree_ex(struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user); -struct bNodeTree *ntreeCopyTree(struct Main *bmain, struct bNodeTree *ntree); +struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user); +struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntree); /* node->id user count */ void ntreeUserIncrefID(struct bNodeTree *ntree); void ntreeUserDecrefID(struct bNodeTree *ntree); @@ -785,6 +785,7 @@ struct ShadeResult; #define SH_NODE_OUTPUT_LINESTYLE 190 #define SH_NODE_UVALONGSTROKE 191 #define SH_NODE_TEX_POINTDENSITY 192 +#define SH_NODE_BSDF_PRINCIPLED 193 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 @@ -972,7 +973,8 @@ void ntreeCompositExecTree(struct Scene *scene, struct bNodeTree *ntree, struct void ntreeCompositTagRender(struct Scene *sce); int ntreeCompositTagAnimated(struct bNodeTree *ntree); void ntreeCompositTagGenerators(struct bNodeTree *ntree); -void ntreeCompositForceHidden(struct bNodeTree *ntree); +void ntreeCompositUpdateRLayers(struct bNodeTree *ntree); +void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type); void ntreeCompositClearTags(struct bNodeTree *ntree); struct bNodeSocket *ntreeCompositOutputFileAddSocket(struct bNodeTree *ntree, struct bNode *node, diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index b6633ea6198..0a5035f9a9b 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -54,7 +54,7 @@ void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struc void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src); struct SoftBody *copy_softbody(const struct SoftBody *sb, bool copy_caches); -struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb); +struct BulletSoftBody *copy_bulletsoftbody(const struct BulletSoftBody *sb); struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys); void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src); void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src); @@ -105,8 +105,8 @@ bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene); struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene); struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene); -struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches); -struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob); +struct Object *BKE_object_copy_ex(struct Main *bmain, const struct Object *ob, bool copy_caches); +struct Object *BKE_object_copy(struct Main *bmain, const struct Object *ob); void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local); void BKE_object_make_local_ex(struct Main *bmain, struct Object *ob, const bool lib_local, const bool clear_proxy); bool BKE_object_is_libdata(struct Object *ob); @@ -189,10 +189,6 @@ void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx, struct Object *ob); void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob); -void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob, - struct ModifierData *md); void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 0a3cc950f32..821dc211591 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -99,7 +99,7 @@ void BKE_paint_set_overlay_override(enum OverlayFlags flag); /* palettes */ void BKE_palette_free(struct Palette *palette); struct Palette *BKE_palette_add(struct Main *bmain, const char *name); -struct Palette *BKE_palette_copy(struct Main *bmain, struct Palette *palette); +struct Palette *BKE_palette_copy(struct Main *bmain, const struct Palette *palette); void BKE_palette_make_local(struct Main *bmain, struct Palette *palette, const bool lib_local); struct PaletteColor *BKE_palette_color_add(struct Palette *palette); bool BKE_palette_is_empty(const struct Palette *palette); @@ -109,7 +109,7 @@ void BKE_palette_clear(struct Palette *palette); /* paint curves */ struct PaintCurve *BKE_paint_curve_add(struct Main *bmain, const char *name); void BKE_paint_curve_free(struct PaintCurve *pc); -struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, struct PaintCurve *pc); +struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, const struct PaintCurve *pc); void BKE_paint_curve_make_local(struct Main *bmain, struct PaintCurve *pc, const bool lib_local); void BKE_paint_init(struct Scene *sce, PaintMode mode, const char col[3]); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 2b6a84a2f87..470e2e468f0 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -324,7 +324,7 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name); void object_remove_particle_system(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(const char *name, struct Main *main); -struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, struct ParticleSettings *part); +struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, const struct ParticleSettings *part); void BKE_particlesettings_make_local(struct Main *bmain, struct ParticleSettings *part, const bool lib_local); void psys_reset(struct ParticleSystem *psys, int mode); @@ -473,9 +473,8 @@ typedef struct ParticleRenderData { struct EvaluationContext; -void BKE_particle_system_eval(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob, - struct ParticleSystem *psys); +void BKE_particle_system_eval_init(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); #endif diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h index 99e60757f15..c787e8e8ed1 100644 --- a/source/blender/blenkernel/BKE_property.h +++ b/source/blender/blenkernel/BKE_property.h @@ -37,8 +37,8 @@ struct Object; void BKE_bproperty_free(struct bProperty *prop); void BKE_bproperty_free_list(struct ListBase *lb); -struct bProperty *BKE_bproperty_copy(struct bProperty *prop); -void BKE_bproperty_copy_list(struct ListBase *lbn, struct ListBase *lbo); +struct bProperty *BKE_bproperty_copy(const struct bProperty *prop); +void BKE_bproperty_copy_list(struct ListBase *lbn, const struct ListBase *lbo); void BKE_bproperty_init(struct bProperty *prop); struct bProperty *BKE_bproperty_new(int type); void BKE_bproperty_unique(struct bProperty *first, struct bProperty *prop, int force); diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index 443c3b2b5b2..c72f067a111 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -49,8 +49,8 @@ void BKE_rigidbody_free_constraint(struct Object *ob); /* ...... */ -struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob); -struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob); +struct RigidBodyOb *BKE_rigidbody_copy_object(const struct Object *ob); +struct RigidBodyCon *BKE_rigidbody_copy_constraint(const struct Object *ob); /* Callback format for performing operations on ID-pointers for rigidbody world. */ typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cb_flag); diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h index 1579a0c7bb3..10cddd7b454 100644 --- a/source/blender/blenkernel/BKE_sca.h +++ b/source/blender/blenkernel/BKE_sca.h @@ -53,15 +53,15 @@ void free_actuators(struct ListBase *lb); void free_sensor(struct bSensor *sens); void free_sensors(struct ListBase *lb); struct bSensor *copy_sensor(struct bSensor *sens); -void copy_sensors(struct ListBase *lbn, struct ListBase *lbo); +void copy_sensors(struct ListBase *lbn, const struct ListBase *lbo); void init_sensor(struct bSensor *sens); struct bSensor *new_sensor(int type); struct bController *copy_controller(struct bController *cont); -void copy_controllers(struct ListBase *lbn, struct ListBase *lbo); +void copy_controllers(struct ListBase *lbn, const struct ListBase *lbo); void init_controller(struct bController *cont); struct bController *new_controller(int type); struct bActuator *copy_actuator(struct bActuator *act); -void copy_actuators(struct ListBase *lbn, struct ListBase *lbo); +void copy_actuators(struct ListBase *lbn, const struct ListBase *lbo); void init_actuator(struct bActuator *act); struct bActuator *new_actuator(int type); void clear_sca_new_poins_ob(struct Object *ob); @@ -70,7 +70,7 @@ void set_sca_new_poins_ob(struct Object *ob); void set_sca_new_poins(void); void BKE_sca_logic_links_remap(struct Main *bmain, struct Object *ob_old, struct Object *ob_new); -void BKE_sca_logic_copy(struct Object *ob_new, struct Object *ob); +void BKE_sca_logic_copy(struct Object *ob_new, const struct Object *ob); void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up); void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up); diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h index b91b64c4b74..907558f9203 100644 --- a/source/blender/blenkernel/BKE_speaker.h +++ b/source/blender/blenkernel/BKE_speaker.h @@ -33,7 +33,7 @@ struct Speaker; void BKE_speaker_init(struct Speaker *spk); void *BKE_speaker_add(struct Main *bmain, const char *name); -struct Speaker *BKE_speaker_copy(struct Main *bmain, struct Speaker *spk); +struct Speaker *BKE_speaker_copy(struct Main *bmain, const struct Speaker *spk); void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool lib_local); void BKE_speaker_free(struct Speaker *spk); diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 081b7589af6..c8fb483cdf2 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -52,7 +52,7 @@ bool BKE_text_reload(struct Text *text); struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const char *relpath, const bool is_internal); struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath); -struct Text *BKE_text_copy (struct Main *bmain, struct Text *ta); +struct Text *BKE_text_copy (struct Main *bmain, const struct Text *ta); void BKE_text_make_local (struct Main *bmain, struct Text *text, const bool lib_local); void BKE_text_clear (struct Text *text); void BKE_text_write (struct Text *text, const char *str); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 9a60eb29957..190fdeafaec 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -70,7 +70,7 @@ void colorband_update_sort(struct ColorBand *coba); void BKE_texture_free(struct Tex *tex); void BKE_texture_default(struct Tex *tex); -struct Tex *BKE_texture_copy(struct Main *bmain, struct Tex *tex); +struct Tex *BKE_texture_copy(struct Main *bmain, const struct Tex *tex); struct Tex *BKE_texture_add(struct Main *bmain, const char *name); struct Tex *BKE_texture_localize(struct Tex *tex); void BKE_texture_make_local(struct Main *bmain, struct Tex *tex, const bool lib_local); @@ -114,13 +114,13 @@ void BKE_texture_colormapping_default(struct ColorMapping *color void BKE_texture_envmap_free_data(struct EnvMap *env); void BKE_texture_envmap_free(struct EnvMap *env); struct EnvMap *BKE_texture_envmap_add(void); -struct EnvMap *BKE_texture_envmap_copy(struct EnvMap *env); +struct EnvMap *BKE_texture_envmap_copy(const struct EnvMap *env); void BKE_texture_pointdensity_init_data(struct PointDensity *pd); void BKE_texture_pointdensity_free_data(struct PointDensity *pd); void BKE_texture_pointdensity_free(struct PointDensity *pd); struct PointDensity *BKE_texture_pointdensity_add(void); -struct PointDensity *BKE_texture_pointdensity_copy(struct PointDensity *pd); +struct PointDensity *BKE_texture_pointdensity_copy(const struct PointDensity *pd); void BKE_texture_voxeldata_free_data(struct VoxelData *vd); void BKE_texture_voxeldata_free(struct VoxelData *vd); @@ -129,7 +129,7 @@ struct VoxelData *BKE_texture_voxeldata_copy(struct VoxelData *vd); void BKE_texture_ocean_free(struct OceanTex *ot); struct OceanTex *BKE_texture_ocean_add(void); -struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot); +struct OceanTex *BKE_texture_ocean_copy(const struct OceanTex *ot); bool BKE_texture_dependsOnTime(const struct Tex *texture); bool BKE_texture_is_image_user(const struct Tex *tex); @@ -144,6 +144,8 @@ void BKE_texture_get_value( const struct Scene *scene, struct Tex *texture, float *tex_co, struct TexResult *texres, bool use_color_management); +void BKE_texture_fetch_images_for_pool(struct Tex *texture, struct ImagePool *pool); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 30873567297..b48be382073 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -52,7 +52,7 @@ struct rcti; /* **** Common functions **** */ void BKE_tracking_free(struct MovieTracking *tracking); -void BKE_tracking_copy(struct MovieTracking *tracking_dst, struct MovieTracking *tracking_src); +void BKE_tracking_copy(struct MovieTracking *tracking_dst, const struct MovieTracking *tracking_src); void BKE_tracking_settings_init(struct MovieTracking *tracking); diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h index 23bf9ec3d22..18ae61f7653 100644 --- a/source/blender/blenkernel/BKE_world.h +++ b/source/blender/blenkernel/BKE_world.h @@ -39,7 +39,7 @@ struct World; void BKE_world_free(struct World *sc); void BKE_world_init(struct World *wrld); struct World *add_world(struct Main *bmian, const char *name); -struct World *BKE_world_copy(struct Main *bmain, struct World *wrld); +struct World *BKE_world_copy(struct Main *bmain, const struct World *wrld); struct World *localize_world(struct World *wrld); void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool lib_local); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 8b7329cf940..7eea8224ba1 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2123,6 +2123,8 @@ static void mesh_calc_modifiers( DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); append_mask |= CD_MASK_PREVIEW_MLOOPCOL; } + + dm->deformedOnly = false; } isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); @@ -2463,6 +2465,8 @@ static void editbmesh_calc_modifiers( deformedVerts = NULL; } } + + dm->deformedOnly = false; } /* In case of active preview modifier, make sure preview mask remains for following modifiers. */ @@ -3318,7 +3322,8 @@ void DM_calc_loop_tangents_step_0( const CustomData *loopData, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME], int tangent_names_count, bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n, - char *ract_uv_name, char *rren_uv_name, char *rtangent_mask) { + char *ract_uv_name, char *rren_uv_name, short *rtangent_mask) +{ /* Active uv in viewport */ int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV); *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV); @@ -3372,21 +3377,22 @@ void DM_calc_loop_tangents_step_0( if (add) *rtangent_mask |= 1 << n; } + + if (uv_layer_num == 0) + *rtangent_mask |= DM_TANGENT_MASK_ORCO; } void DM_calc_loop_tangents( DerivedMesh *dm, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME], int tangent_names_count) { - if (CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV) == 0) - return; int act_uv_n = -1; int ren_uv_n = -1; bool calc_act = false; bool calc_ren = false; char act_uv_name[MAX_NAME]; char ren_uv_name[MAX_NAME]; - char tangent_mask = 0; + short tangent_mask = 0; DM_calc_loop_tangents_step_0( &dm->loopData, calc_active_tangent, tangent_names, tangent_names_count, &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask); @@ -3399,6 +3405,8 @@ void DM_calc_loop_tangents( for (int i = 0; i < tangent_names_count; i++) if (tangent_names[i][0]) DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, tangent_names[i]); + if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1) + CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, ""); if (calc_act && act_uv_name[0]) DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, act_uv_name); if (calc_ren && ren_uv_name[0]) @@ -3456,23 +3464,28 @@ void DM_calc_loop_tangents( * have to check this is valid... */ mesh2tangent->precomputedLoopNormals = dm->getLoopDataArray(dm, CD_NORMAL); - mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->faceData, CD_NORMAL); + mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->polyData, CD_NORMAL); mesh2tangent->orco = NULL; mesh2tangent->mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name); + + /* Fill the resulting tangent_mask */ if (!mesh2tangent->mloopuv) { mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO); if (!mesh2tangent->orco) continue; + + dm->tangent_mask |= DM_TANGENT_MASK_ORCO; + } + else { + int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name); + int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV); + BLI_assert(uv_ind != -1 && uv_start != -1); + BLI_assert(uv_ind - uv_start < MAX_MTFACE); + dm->tangent_mask |= 1 << (uv_ind - uv_start); } - mesh2tangent->tangent = dm->loopData.layers[index].data; - /* Fill the resulting tangent_mask */ - int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name); - int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV); - BLI_assert(uv_ind != -1 && uv_start != -1); - BLI_assert(uv_ind - uv_start < MAX_MTFACE); - dm->tangent_mask |= 1 << (uv_ind - uv_start); + mesh2tangent->tangent = dm->loopData.layers[index].data; BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW); } @@ -3488,21 +3501,19 @@ void DM_calc_loop_tangents( #endif - int uv_index, tan_index; - /* Update active layer index */ - uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n); - if (uv_index != -1) { - tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name); + int act_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n); + if (act_uv_index != -1) { + int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[act_uv_index].name); CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index); - } + } /* else tangent has been built from orco */ /* Update render layer index */ - uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n); - if (uv_index != -1) { - tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[uv_index].name); + int ren_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n); + if (ren_uv_index != -1) { + int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[ren_uv_index].name); CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index); - } + } /* else tangent has been built from orco */ } } diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 1e33fe4ab46..885ea36d404 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -120,7 +120,7 @@ void BKE_action_free(bAction *act) /* .................................. */ -bAction *BKE_action_copy(Main *bmain, bAction *src) +bAction *BKE_action_copy(Main *bmain, const bAction *src) { bAction *dst = NULL; bActionGroup *dgrp, *sgrp; @@ -523,7 +523,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose) * * \param dst Should be freed already, makes entire duplicate. */ -void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints) +void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constraints) { bPose *outPose; bPoseChannel *pchan; diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 0b637355ecf..539901a59d5 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -397,73 +397,6 @@ void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes a } } -/* Make Local -------------------------------------------- */ - -static void make_local_strips(ListBase *strips) -{ - NlaStrip *strip; - - for (strip = strips->first; strip; strip = strip->next) { - if (strip->act) BKE_action_make_local(G.main, strip->act, false); - if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target, false); - - make_local_strips(&strip->strips); - } -} - -/* Use local copy instead of linked copy of various ID-blocks */ -void BKE_animdata_make_local(AnimData *adt) -{ - NlaTrack *nlt; - - /* Actions - Active and Temp */ - if (adt->action) BKE_action_make_local(G.main, adt->action, false); - if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact, false); - /* Remaps */ - if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target, false); - - /* Drivers */ - /* TODO: need to remap the ID-targets too? */ - - /* NLA Data */ - for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) - make_local_strips(&nlt->strips); -} - - -/* When duplicating data (i.e. objects), drivers referring to the original data will - * get updated to point to the duplicated data (if drivers belong to the new data) - */ -void BKE_animdata_relink(AnimData *adt) -{ - /* sanity check */ - if (adt == NULL) - return; - - /* drivers */ - if (adt->drivers.first) { - FCurve *fcu; - - /* check each driver against all the base paths to see if any should go */ - for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { - ChannelDriver *driver = fcu->driver; - DriverVar *dvar; - - /* driver variables */ - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - /* only change the used targets, since the others will need fixing manually anyway */ - DRIVER_TARGETS_USED_LOOPER(dvar) - { - if (dtar->id && dtar->id->newid) { - dtar->id = dtar->id->newid; - } - } - DRIVER_TARGETS_LOOPER_END - } - } - } -} - /* Sub-ID Regrouping ------------------------------------------- */ /** @@ -1586,7 +1519,8 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val } case PROP_INT: { - const int value_coerce = (int)value; + int value_coerce = (int)value; + RNA_property_int_clamp(ptr, prop, &value_coerce); if (array_index != -1) { if (RNA_property_int_get_index(ptr, prop, array_index) != value_coerce) { RNA_property_int_set_index(ptr, prop, array_index, value_coerce); @@ -1603,15 +1537,17 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val } case PROP_FLOAT: { + float value_coerce = value; + RNA_property_float_clamp(ptr, prop, &value_coerce); if (array_index != -1) { - if (RNA_property_float_get_index(ptr, prop, array_index) != value) { - RNA_property_float_set_index(ptr, prop, array_index, value); + if (RNA_property_float_get_index(ptr, prop, array_index) != value_coerce) { + RNA_property_float_set_index(ptr, prop, array_index, value_coerce); written = true; } } else { - if (RNA_property_float_get(ptr, prop) != value) { - RNA_property_float_set(ptr, prop, value); + if (RNA_property_float_get(ptr, prop) != value_coerce) { + RNA_property_float_set(ptr, prop, value_coerce); written = true; } } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 02cc31e5977..35b6fe113bd 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -150,7 +150,7 @@ void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local) BKE_id_make_local_generic(bmain, &arm->id, true, lib_local); } -static void copy_bonechildren(Bone *newBone, Bone *oldBone, Bone *actBone, Bone **newActBone) +static void copy_bonechildren(Bone *newBone, const Bone *oldBone, const Bone *actBone, Bone **newActBone) { Bone *curBone, *newChildBone; @@ -172,7 +172,7 @@ static void copy_bonechildren(Bone *newBone, Bone *oldBone, Bone *actBone, Bone } } -bArmature *BKE_armature_copy(Main *bmain, bArmature *arm) +bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm) { bArmature *newArm; Bone *oldBone, *newBone; @@ -982,6 +982,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float return; } + if ((armOb->pose->flag & POSE_RECALC) != 0) { + printf("ERROR! Trying to evaluate influence of armature '%s' which needs Pose recalc!", armOb->id.name); + BLI_assert(0); + } + invert_m4_m4(obinv, target->obmat); copy_m4_m4(premat, target->obmat); mul_m4_m4m4(postmat, obinv, armOb->obmat); @@ -1980,6 +1985,8 @@ void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones) if (counter > 1 && sort_bones) { DAG_pose_sort(ob); } +#else + UNUSED_VARS(sort_bones); #endif ob->pose->flag &= ~POSE_RECALC; diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 3bc81a69c86..a4714041edf 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -628,10 +628,10 @@ void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx), } void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, Object *ob, bPoseChannel *pchan) { - Scene *scene = G.main->scene.first; DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name); bArmature *arm = (bArmature *)ob->data; if (arm->flag & ARM_RESTPOS) { @@ -702,4 +702,8 @@ void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob) printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name + 2, ob->proxy_from->id.name + 2); } + /* Rest of operations are NO-OP in depsgraph, so can clear + * flag now. + */ + ob->recalc &= ~OB_RECALC_ALL; } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index ceb641073e0..2624019e63a 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -226,19 +226,6 @@ void BKE_blender_userdef_free_data(UserDef *userdef) } /** - * Handle changes in settings that need refreshing. - */ -void BKE_blender_userdef_refresh(void) -{ - /* prevent accidents */ - if (U.pixelsize == 0) U.pixelsize = 1; - - BLF_default_dpi(U.pixelsize * U.dpi); - U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72; - -} - -/** * Write U from userdef. * This function defines which settings a template will override for the user preferences. */ diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index a521d671ea4..05ea7983b8e 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -413,9 +413,9 @@ bool BKE_blendfile_read_from_memfile( if (bfd) { /* remove the unused screens and wm */ while (bfd->main->wm.first) - BKE_libblock_free_ex(bfd->main, bfd->main->wm.first, true, true); + BKE_libblock_free(bfd->main, bfd->main->wm.first); while (bfd->main->screen.first) - BKE_libblock_free_ex(bfd->main, bfd->main->screen.first, true, true); + BKE_libblock_free(bfd->main, bfd->main->screen.first); setup_app_data(C, bfd, "<memory1>", reports); } diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index b4bc83bf94c..7ca4e07076d 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -1581,7 +1581,7 @@ void boid_free_settings(BoidSettings *boids) MEM_freeN(boids); } } -BoidSettings *boid_copy_settings(BoidSettings *boids) +BoidSettings *boid_copy_settings(const BoidSettings *boids) { BoidSettings *nboids = NULL; diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 487b8ffa2b5..f210c6aa7f3 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -243,7 +243,7 @@ static bool missing_files_find__recursive( continue; /* cant stat, don't bother with this file, could print debug info here */ if (S_ISREG(status.st_mode)) { /* is file */ - if (STREQLEN(filename, de->d_name, FILE_MAX)) { /* name matches */ + if (BLI_path_ncmp(filename, de->d_name, FILE_MAX) == 0) { /* name matches */ /* open the file to read its size */ size = status.st_size; if ((size > 0) && (size > *r_filesize)) { /* find the biggest file */ diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 57b707a31d3..aae323a5056 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -172,7 +172,7 @@ struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode) return NULL; } -Brush *BKE_brush_copy(Main *bmain, Brush *brush) +Brush *BKE_brush_copy(Main *bmain, const Brush *brush) { Brush *brushn; @@ -195,7 +195,7 @@ Brush *BKE_brush_copy(Main *bmain, Brush *brush) brushn->curve = curvemapping_copy(brush->curve); /* enable fake user by default */ - id_fake_user_set(&brush->id); + id_fake_user_set(&brushn->id); BKE_id_copy_ensure_local(bmain, &brush->id, &brushn->id); diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index c0e4ef37a93..c1fad4f80c8 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -917,10 +917,10 @@ BVHTree *bvhtree_from_mesh_faces( /** * Builds a bvh tree where nodes are the given tessellated faces (note: does not copy given mfaces!). - * \param vert_allocated if true, vert freeing will be done when freeing data. - * \param face_allocated if true, face freeing will be done when freeing data. + * \param vert_allocated: if true, vert freeing will be done when freeing data. + * \param face_allocated: if true, face freeing will be done when freeing data. * \param faces_mask: if not null, true elements give which faces to add to BVH tree. - * \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask). + * \param faces_num_active: if >= 0, number of active faces to add to BVH tree (else will be computed from mask). */ BVHTree *bvhtree_from_mesh_faces_ex( BVHTreeFromMesh *data, const MVert *vert, const bool vert_allocated, diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index 3dce08eb756..cf619a32783 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -82,6 +82,7 @@ void BKE_cachefile_init(CacheFile *cache_file) cache_file->is_sequence = false; cache_file->scale = 1.0f; cache_file->handle_mutex = BLI_mutex_alloc(); + BLI_listbase_clear(&cache_file->object_paths); } /** Free (or release) any data used by this cachefile (does not free the cachefile itself). */ @@ -99,12 +100,12 @@ void BKE_cachefile_free(CacheFile *cache_file) BLI_freelistN(&cache_file->object_paths); } -CacheFile *BKE_cachefile_copy(Main *bmain, CacheFile *cache_file) +CacheFile *BKE_cachefile_copy(Main *bmain, const CacheFile *cache_file) { CacheFile *new_cache_file = BKE_libblock_copy(bmain, &cache_file->id); new_cache_file->handle = NULL; - BLI_listbase_clear(&cache_file->object_paths); + BLI_listbase_clear(&new_cache_file->object_paths); BKE_id_copy_ensure_local(bmain, &cache_file->id, &new_cache_file->id); @@ -165,10 +166,12 @@ void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, co const float time = BKE_cachefile_time_offset(cache_file, ctime, fps); if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) { + BKE_cachefile_clean(scene, cache_file); #ifdef WITH_ALEMBIC ABC_free_handle(cache_file->handle); cache_file->handle = ABC_create_handle(filename, NULL); #endif + break; } } } @@ -220,7 +223,6 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file) } #endif mcmd->reader = NULL; - mcmd->object_path[0] = '\0'; } } @@ -238,7 +240,6 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file) } #endif data->reader = NULL; - data->object_path[0] = '\0'; } } } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 9cb553aa27b..915c08674a4 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -93,7 +93,7 @@ void *BKE_camera_add(Main *bmain, const char *name) return cam; } -Camera *BKE_camera_copy(Main *bmain, Camera *cam) +Camera *BKE_camera_copy(Main *bmain, const Camera *cam) { Camera *camn; diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 7042b46330b..46a067ea0bc 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2992,9 +2992,12 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int STACK_DECLARE(mvert); STACK_DECLARE(oldv); - MEdge *med, *medge = MEM_mallocN(sizeof(*medge) * totedge, __func__); - int *olde = MEM_mallocN(sizeof(*olde) * totedge, __func__); - int *newe = MEM_mallocN(sizeof(*newe) * totedge, __func__); + /* Note: create (totedge + totloop) elements because partially invalid polys due to merge may require + * generating new edges, and while in 99% cases we'll still end with less final edges than totedge, + * cases can be forged that would end requiring more... */ + MEdge *med, *medge = MEM_mallocN(sizeof(*medge) * (totedge + totloop), __func__); + int *olde = MEM_mallocN(sizeof(*olde) * (totedge + totloop), __func__); + int *newe = MEM_mallocN(sizeof(*newe) * (totedge + totloop), __func__); STACK_DECLARE(medge); STACK_DECLARE(olde); @@ -3028,7 +3031,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int STACK_INIT(mloop, totloop); STACK_INIT(mpoly, totpoly); - /* fill newl with destination vertex indices */ + /* fill newv with destination vertex indices */ mv = cddm->mvert; c = 0; for (i = 0; i < totvert; i++, mv++) { @@ -3117,83 +3120,80 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int mp = cddm->mpoly; + mv = cddm->mvert; for (i = 0; i < totpoly; i++, mp++) { MPoly *mp_new; ml = cddm->mloop + mp->loopstart; /* check faces with all vertices merged */ - { - bool all_vertices_merged = true; + bool all_vertices_merged = true; - for (j = 0; j < mp->totloop; j++, ml++) { - if (vtargetmap[ml->v] == -1) { - all_vertices_merged = false; - break; - } + for (j = 0; j < mp->totloop; j++, ml++) { + if (vtargetmap[ml->v] == -1) { + all_vertices_merged = false; + /* This will be used to check for poly using several time the same vert. */ + mv[ml->v].flag &= ~ME_VERT_TMP_TAG; } + else { + /* This will be used to check for poly using several time the same vert. */ + mv[vtargetmap[ml->v]].flag &= ~ME_VERT_TMP_TAG; + } + } - if (UNLIKELY(all_vertices_merged)) { - if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_MAPPED) { - /* In this mode, all vertices merged is enough to dump face */ - continue; + if (UNLIKELY(all_vertices_merged)) { + if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_MAPPED) { + /* In this mode, all vertices merged is enough to dump face */ + continue; + } + else if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) { + /* Additional condition for face dump: target vertices must make up an identical face */ + /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */ + /* (2) second step is thorough but more costly poly compare */ + int i_poly, v_target; + bool found = false; + PolyKey pkey; + + /* Use poly_gset for fast (although not 100% certain) identification of same poly */ + /* First, make up a poly_summary structure */ + ml = cddm->mloop + mp->loopstart; + pkey.hash_sum = pkey.hash_xor = 0; + pkey.totloops = 0; + for (j = 0; j < mp->totloop; j++, ml++) { + v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */ + pkey.hash_sum += v_target; + pkey.hash_xor ^= v_target; + pkey.totloops++; } - else if (merge_mode == CDDM_MERGE_VERTS_DUMP_IF_EQUAL) { - /* Additional condition for face dump: target vertices must make up an identical face */ - /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */ - /* (2) second step is thorough but more costly poly compare */ - int i_poly, v_target, v_prev; - bool found = false; - PolyKey pkey; - - /* Use poly_gset for fast (although not 100% certain) identification of same poly */ - /* First, make up a poly_summary structure */ + if (BLI_gset_haskey(poly_gset, &pkey)) { + + /* There might be a poly that matches this one. + * We could just leave it there and say there is, and do a "continue". + * ... but we are checking whether there is an exact poly match. + * It's not so costly in terms of CPU since it's very rare, just a lot of complex code. + */ + + /* Consider current loop again */ ml = cddm->mloop + mp->loopstart; - pkey.hash_sum = pkey.hash_xor = 0; - pkey.totloops = 0; - v_prev = vtargetmap[(ml + mp->totloop -1)->v]; /* since it loops around, the prev of first is the last */ - for (j = 0; j < mp->totloop; j++, ml++) { - v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */ - if (v_target == v_prev) { - /* consecutive vertices in loop map to the same target: discard */ - /* but what about last to first ? */ - continue; + /* Consider the target of the loop's first vert */ + v_target = vtargetmap[ml->v]; + /* Now see if v_target belongs to a poly that shares all vertices with source poly, + * in same order, or reverse order */ + + for (i_poly = 0; i_poly < cddm->pmap[v_target].count; i_poly++) { + MPoly *target_poly = cddm->mpoly + *(cddm->pmap[v_target].indices + i_poly); + + if (cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, +1) || + cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1)) + { + found = true; + break; } - pkey.hash_sum += v_target; - pkey.hash_xor ^= v_target; - pkey.totloops++; - v_prev = v_target; } - if (BLI_gset_haskey(poly_gset, &pkey)) { - - /* There might be a poly that matches this one. - * We could just leave it there and say there is, and do a "continue". - * ... but we are checking whether there is an exact poly match. - * It's not so costly in terms of CPU since it's very rare, just a lot of complex code. - */ - - /* Consider current loop again */ - ml = cddm->mloop + mp->loopstart; - /* Consider the target of the loop's first vert */ - v_target = vtargetmap[ml->v]; - /* Now see if v_target belongs to a poly that shares all vertices with source poly, - * in same order, or reverse order */ - - for (i_poly = 0; i_poly < cddm->pmap[v_target].count; i_poly++) { - MPoly *target_poly = cddm->mpoly + *(cddm->pmap[v_target].indices + i_poly); - - if (cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, +1) || - cddm_poly_compare(cddm->mloop, mp, target_poly, vtargetmap, -1)) - { - found = true; - break; - } - } - if (found) { - /* Current poly's vertices are mapped to a poly that is strictly identical */ - /* Current poly is dumped */ - continue; - } + if (found) { + /* Current poly's vertices are mapped to a poly that is strictly identical */ + /* Current poly is dumped */ + continue; } } } @@ -3207,32 +3207,121 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int ml = cddm->mloop + mp->loopstart; c = 0; + MLoop *last_valid_ml = NULL; + MLoop *first_valid_ml = NULL; + bool need_edge_from_last_valid_ml = false; + bool need_edge_to_first_valid_ml = false; + int created_edges = 0; for (j = 0; j < mp->totloop; j++, ml++) { - unsigned int v1, v2; + const uint mlv = (vtargetmap[ml->v] != -1) ? vtargetmap[ml->v] : ml->v; +#ifndef NDEBUG + { + MLoop *next_ml = cddm->mloop + mp->loopstart + ((j + 1) % mp->totloop); + uint next_mlv = (vtargetmap[next_ml->v] != -1) ? vtargetmap[next_ml->v] : next_ml->v; + med = cddm->medge + ml->e; + uint v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; + uint v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + BLI_assert((mlv == v1 && next_mlv == v2) || (mlv == v2 && next_mlv == v1)); + } +#endif + /* A loop is only valid if its matching edge is, and it's not reusing a vertex already used by this poly. */ + if (LIKELY((newe[ml->e] != -1) && ((mv[mlv].flag & ME_VERT_TMP_TAG) == 0))) { + mv[mlv].flag |= ME_VERT_TMP_TAG; + + if (UNLIKELY(last_valid_ml != NULL && need_edge_from_last_valid_ml)) { + /* We need to create a new edge between last valid loop and this one! */ + void **val_p; + + uint v1 = (vtargetmap[last_valid_ml->v] != -1) ? vtargetmap[last_valid_ml->v] : last_valid_ml->v; + uint v2 = mlv; + BLI_assert(v1 != v2); + if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) { + last_valid_ml->e = GET_INT_FROM_POINTER(*val_p); + } + else { + const int new_eidx = STACK_SIZE(medge); + STACK_PUSH(olde, olde[last_valid_ml->e]); + STACK_PUSH(medge, cddm->medge[last_valid_ml->e]); + medge[new_eidx].v1 = last_valid_ml->v; + medge[new_eidx].v2 = ml->v; + /* DO NOT change newe mapping, could break actual values due to some deleted original edges. */ + *val_p = SET_INT_IN_POINTER(new_eidx); + created_edges++; + + last_valid_ml->e = new_eidx; + } + need_edge_from_last_valid_ml = false; + } - med = cddm->medge + ml->e; - v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; - v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; - if (LIKELY(v1 != v2)) { #ifdef USE_LOOPS newl[j + mp->loopstart] = STACK_SIZE(mloop); #endif STACK_PUSH(oldl, j + mp->loopstart); - STACK_PUSH(mloop, *ml); + last_valid_ml = STACK_PUSH_RET_PTR(mloop); + *last_valid_ml = *ml; + if (first_valid_ml == NULL) { + first_valid_ml = last_valid_ml; + } c++; + + /* We absolutely HAVE to handle edge index remapping here, otherwise potential newly created edges + * in that part of code make remapping later totally unreliable. */ + BLI_assert(newe[ml->e] != -1); + last_valid_ml->e = newe[ml->e]; + } + else { + if (last_valid_ml != NULL) { + need_edge_from_last_valid_ml = true; + } + else { + need_edge_to_first_valid_ml = true; + } } } + if (UNLIKELY(last_valid_ml != NULL && !ELEM(first_valid_ml, NULL, last_valid_ml) && + (need_edge_to_first_valid_ml || need_edge_from_last_valid_ml))) + { + /* We need to create a new edge between last valid loop and first valid one! */ + void **val_p; + + uint v1 = (vtargetmap[last_valid_ml->v] != -1) ? vtargetmap[last_valid_ml->v] : last_valid_ml->v; + uint v2 = (vtargetmap[first_valid_ml->v] != -1) ? vtargetmap[first_valid_ml->v] : first_valid_ml->v; + BLI_assert(v1 != v2); + if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) { + last_valid_ml->e = GET_INT_FROM_POINTER(*val_p); + } + else { + const int new_eidx = STACK_SIZE(medge); + STACK_PUSH(olde, olde[last_valid_ml->e]); + STACK_PUSH(medge, cddm->medge[last_valid_ml->e]); + medge[new_eidx].v1 = last_valid_ml->v; + medge[new_eidx].v2 = first_valid_ml->v; + /* DO NOT change newe mapping, could break actual values due to some deleted original edges. */ + *val_p = SET_INT_IN_POINTER(new_eidx); + created_edges++; + + last_valid_ml->e = new_eidx; + } + need_edge_to_first_valid_ml = need_edge_from_last_valid_ml = false; + } if (UNLIKELY(c == 0)) { + BLI_assert(created_edges == 0); continue; } else if (UNLIKELY(c < 3)) { STACK_DISCARD(oldl, c); STACK_DISCARD(mloop, c); + if (created_edges > 0) { + for (j = STACK_SIZE(medge) - created_edges; j < STACK_SIZE(medge); j++) { + BLI_edgehash_remove(ehash, medge[j].v1, medge[j].v2, NULL); + } + STACK_DISCARD(olde, created_edges); + STACK_DISCARD(medge, created_edges); + } continue; } - mp_new = STACK_PUSH_RET_PTR(mpoly); *mp_new = *mp; mp_new->totloop = c; @@ -3257,10 +3346,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int /*update edge indices and copy customdata*/ med = medge; for (i = 0; i < cddm2->dm.numEdgeData; i++, med++) { - if (newv[med->v1] != -1) - med->v1 = newv[med->v1]; - if (newv[med->v2] != -1) - med->v2 = newv[med->v2]; + BLI_assert(newv[med->v1] != -1); + med->v1 = newv[med->v1]; + BLI_assert(newv[med->v2] != -1); + med->v2 = newv[med->v2]; /* Can happen in case vtargetmap contains some double chains, we do not support that. */ BLI_assert(med->v1 != med->v2); @@ -3271,11 +3360,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int /*update loop indices and copy customdata*/ ml = mloop; for (i = 0; i < cddm2->dm.numLoopData; i++, ml++) { - if (newe[ml->e] != -1) - ml->e = newe[ml->e]; - if (newv[ml->v] != -1) - ml->v = newv[ml->v]; - + /* Edge remapping has already be done in main loop handling part above. */ + BLI_assert(newv[ml->v] != -1); + ml->v = newv[ml->v]; + CustomData_copy_data(&dm->loopData, &cddm2->dm.loopData, oldl[i], i, 1); } diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index b3a0895d063..ee0f904c3a6 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -130,7 +130,7 @@ void curvemapping_free(CurveMapping *cumap) } } -void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap) +void curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap) { int a; @@ -146,7 +146,7 @@ void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap) } } -CurveMapping *curvemapping_copy(CurveMapping *cumap) +CurveMapping *curvemapping_copy(const CurveMapping *cumap) { if (cumap) { CurveMapping *cumapn = MEM_dupallocN(cumap); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 58ad171ee20..07a6b304dff 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -790,7 +790,7 @@ static void default_get_tarmat(bConstraint *con, bConstraintOb *UNUSED(cob), bCo ct = ctn; \ } \ } (void)0 - + /* --------- ChildOf Constraint ------------ */ static void childof_new_data(void *cdata) @@ -4387,19 +4387,17 @@ static void transformcache_copy(bConstraint *con, bConstraint *srccon) BLI_strncpy(dst->object_path, src->object_path, sizeof(dst->object_path)); dst->cache_file = src->cache_file; - if (dst->cache_file) { - id_us_plus(&dst->cache_file->id); +#ifdef WITH_ALEMBIC + if (dst->reader) { + CacheReader_incref(dst->reader); } +#endif } static void transformcache_free(bConstraint *con) { bTransformCacheConstraint *data = con->data; - if (data->cache_file) { - id_us_min(&data->cache_file->id); - } - if (data->reader) { #ifdef WITH_ALEMBIC CacheReader_free(data->reader); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 4ba9ad281a3..1cecf41af55 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -187,7 +187,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type) return cu; } -Curve *BKE_curve_copy(Main *bmain, Curve *cu) +Curve *BKE_curve_copy(Main *bmain, const Curve *cu) { Curve *cun; int a; @@ -468,7 +468,7 @@ void BKE_nurbList_free(ListBase *lb) BLI_listbase_clear(lb); } -Nurb *BKE_nurb_duplicate(Nurb *nu) +Nurb *BKE_nurb_duplicate(const Nurb *nu) { Nurb *newnu; int len; @@ -532,7 +532,7 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv) return newnu; } -void BKE_nurbList_duplicate(ListBase *lb1, ListBase *lb2) +void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2) { Nurb *nu, *nun; @@ -744,6 +744,7 @@ BezTriple *BKE_nurb_bezt_get_prev(Nurb *nu, BezTriple *bezt) BezTriple *bezt_prev; BLI_assert(ARRAY_HAS_ITEM(bezt, nu->bezt, nu->pntsu)); + BLI_assert(nu->pntsv == 1); if (bezt == nu->bezt) { if (nu->flagu & CU_NURB_CYCLIC) { @@ -765,6 +766,7 @@ BPoint *BKE_nurb_bpoint_get_prev(Nurb *nu, BPoint *bp) BPoint *bp_prev; BLI_assert(ARRAY_HAS_ITEM(bp, nu->bp, nu->pntsu)); + BLI_assert(nu->pntsv == 1); if (bp == nu->bp) { if (nu->flagu & CU_NURB_CYCLIC) { @@ -781,7 +783,7 @@ BPoint *BKE_nurb_bpoint_get_prev(Nurb *nu, BPoint *bp) return bp_prev; } -void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), struct BezTriple *bezt, float r_normal[3]) +void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), BezTriple *bezt, float r_normal[3]) { /* calculate the axis matrix from the spline */ float dir_prev[3], dir_next[3]; @@ -796,7 +798,7 @@ void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), struct BezTriple *bezt, normalize_v3(r_normal); } -void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3]) +void BKE_nurb_bezt_calc_plane(struct Nurb *nu, BezTriple *bezt, float r_plane[3]) { float dir_prev[3], dir_next[3]; @@ -833,7 +835,7 @@ void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_p normalize_v3(r_plane); } -void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_normal[3]) +void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, BPoint *bp, float r_normal[3]) { BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp); BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp); @@ -856,6 +858,34 @@ void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_nor normalize_v3(r_normal); } +void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3]) +{ + BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp); + BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp); + + float dir_prev[3] = {0.0f}, dir_next[3] = {0.0f}; + + if (bp_prev) { + sub_v3_v3v3(dir_prev, bp_prev->vec, bp->vec); + normalize_v3(dir_prev); + } + if (bp_next) { + sub_v3_v3v3(dir_next, bp->vec, bp_next->vec); + normalize_v3(dir_next); + } + cross_v3_v3v3(r_plane, dir_prev, dir_next); + + /* matches with bones more closely */ + { + float dir_mid[3], tvec[3]; + add_v3_v3v3(dir_mid, dir_prev, dir_next); + cross_v3_v3v3(tvec, r_plane, dir_mid); + copy_v3_v3(r_plane, tvec); + } + + normalize_v3(r_plane); +} + /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */ diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 7c3f0ac630d..0939d35ed8d 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1944,11 +1944,15 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype, bool CustomData_free_layer(CustomData *data, int type, int totelem, int index) { - const int n = index - CustomData_get_layer_index(data, type); + const int index_first = CustomData_get_layer_index(data, type); + const int n = index - index_first; int i; - - if (index < 0) + + BLI_assert(index >= index_first); + if ((index_first == -1) || (n < 0)) { return false; + } + BLI_assert(data->layers[index].type == type); customData_free_layer__internal(&data->layers[index], totelem); @@ -1993,8 +1997,10 @@ bool CustomData_free_layer_active(CustomData *data, int type, int totelem) void CustomData_free_layers(CustomData *data, int type, int totelem) { - while (CustomData_has_layer(data, type)) - CustomData_free_layer_active(data, type, totelem); + const int index = CustomData_get_layer_index(data, type); + while (CustomData_free_layer(data, type, totelem, index)) { + /* pass */ + } } bool CustomData_has_layer(const CustomData *data, int type) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 13b1aab5e1c..69baaf5e58a 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -76,7 +76,7 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name) return defgroup; } -void defgroup_copy_list(ListBase *outbase, ListBase *inbase) +void defgroup_copy_list(ListBase *outbase, const ListBase *inbase) { bDeformGroup *defgroup, *defgroupn; @@ -88,7 +88,7 @@ void defgroup_copy_list(ListBase *outbase, ListBase *inbase) } } -bDeformGroup *defgroup_duplicate(bDeformGroup *ingroup) +bDeformGroup *defgroup_duplicate(const bDeformGroup *ingroup) { bDeformGroup *outgroup; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 302e55a1f5a..019e0df1623 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -3053,7 +3053,7 @@ void DAG_id_type_tag(Main *bmain, short idtype) DAG_id_type_tag(bmain, ID_SCE); } - atomic_fetch_and_or_uint8((uint8_t*)&bmain->id_tag_update[BKE_idcode_to_index(idtype)], 1); + atomic_fetch_and_or_uint8((uint8_t *)&bmain->id_tag_update[BKE_idcode_to_index(idtype)], 1); } int DAG_id_type_tagged(Main *bmain, short idtype) diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index f8a9d57f579..2a300cbe47b 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -167,10 +167,12 @@ void BKE_displist_normals_add(ListBase *lb) if (dl->nors == NULL) { dl->nors = MEM_callocN(sizeof(float) * 3, "dlnors"); - if (dl->verts[2] < 0.0f) + if (dl->flag & DL_BACK_CURVE) { dl->nors[2] = -1.0f; - else + } + else { dl->nors[2] = 1.0f; + } } } else if (dl->type == DL_SURF) { @@ -469,6 +471,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); while (cont) { + int dl_flag_accum = 0; cont = 0; totvert = 0; nextcol = 0; @@ -514,6 +517,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj nextcol = 1; } } + dl_flag_accum |= dl->flag; } dl = dl->next; } @@ -526,6 +530,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj if (tot) { dlnew = MEM_callocN(sizeof(DispList), "filldisplist"); dlnew->type = DL_INDEX3; + dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE)); dlnew->col = colnr; dlnew->nr = totvert; dlnew->parts = tot; @@ -603,6 +608,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) dlnew->nr = dl->parts; dlnew->parts = 1; dlnew->type = DL_POLY; + dlnew->flag = DL_BACK_CURVE; dlnew->col = dl->col; dlnew->charidx = dl->charidx; @@ -623,6 +629,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) dlnew->nr = dl->parts; dlnew->parts = 1; dlnew->type = DL_POLY; + dlnew->flag = DL_FRONT_CURVE; dlnew->col = dl->col; dlnew->charidx = dl->charidx; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index c525e75b825..1db69d23607 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1897,8 +1897,8 @@ static DerivedMesh *dynamicPaint_Modifier_apply( /* apply weights into a vertex group, if doesnt exists add a new layer */ if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) { - dvert = CustomData_add_layer_named(&result->vertData, CD_MDEFORMVERT, CD_CALLOC, - NULL, sData->total_points, surface->output_name); + dvert = CustomData_add_layer(&result->vertData, CD_MDEFORMVERT, CD_CALLOC, + NULL, sData->total_points); } if (defgrp_index != -1 && dvert) { int i; diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 2fffa0dea28..ab614b8f460 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -149,6 +149,8 @@ static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm) const float (*vertexCos)[3]; vertexCos = bmdm->vertexCos; + BM_mesh_elem_index_ensure(bm, BM_VERT); + BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { BM_face_calc_center_mean_vcos(bm, efa, polyCos[i], vertexCos); } @@ -487,8 +489,6 @@ static void emDM_calc_loop_tangents( EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; BMEditMesh *em = bmdm->em; BMesh *bm = bmdm->em->bm; - if (CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV) == 0) - return; int act_uv_n = -1; int ren_uv_n = -1; @@ -496,7 +496,7 @@ static void emDM_calc_loop_tangents( bool calc_ren = false; char act_uv_name[MAX_NAME]; char ren_uv_name[MAX_NAME]; - char tangent_mask = 0; + short tangent_mask = 0; DM_calc_loop_tangents_step_0( &bm->ldata, calc_active_tangent, tangent_names, tangent_names_count, @@ -506,6 +506,8 @@ static void emDM_calc_loop_tangents( for (int i = 0; i < tangent_names_count; i++) if (tangent_names[i][0]) DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, tangent_names[i]); + if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1) + CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, ""); if (calc_act && act_uv_name[0]) DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, act_uv_name); if (calc_ren && ren_uv_name[0]) @@ -572,7 +574,17 @@ static void emDM_calc_loop_tangents( continue; /* needed for orco lookups */ htype_index |= BM_VERT; + dm->tangent_mask |= DM_TANGENT_MASK_ORCO; + } + else { + /* Fill the resulting tangent_mask */ + int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name); + int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV); + BLI_assert(uv_ind != -1 && uv_start != -1); + BLI_assert(uv_ind - uv_start < MAX_MTFACE); + dm->tangent_mask |= 1 << (uv_ind - uv_start); } + if (mesh2tangent->precomputedFaceNormals) { /* needed for face normal lookups */ htype_index |= BM_FACE; @@ -582,12 +594,6 @@ static void emDM_calc_loop_tangents( mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris; mesh2tangent->tangent = dm->loopData.layers[index].data; - /* Fill the resulting tangent_mask */ - int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name); - int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV); - BLI_assert(uv_ind != -1 && uv_start != -1); - BLI_assert(uv_ind - uv_start < MAX_MTFACE); - dm->tangent_mask |= 1 << (uv_ind - uv_start); BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW); } @@ -602,15 +608,20 @@ static void emDM_calc_loop_tangents( #undef USE_LOOPTRI_DETECT_QUADS #endif } + /* Update active layer index */ - int uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n); - int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[uv_index].name); - CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index); + int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n); + if (act_uv_index >= 0) { + int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[act_uv_index].name); + CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index); + } /* else tangent has been built from orco */ /* Update render layer index */ - uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n); - tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[uv_index].name); - CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index); + int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n); + if (ren_uv_index >= 0) { + int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[ren_uv_index].name); + CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index); + } /* else tangent has been built from orco */ } /** \} */ @@ -2053,20 +2064,25 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type) /* layers are store per face for editmesh, we convert to a temporary * data layer array in the derivedmesh when these are requested */ if (type == CD_MTFACE || type == CD_MCOL) { - const int type_from = (type == CD_MTFACE) ? CD_MTEXPOLY : CD_MLOOPCOL; - int index; const char *bmdata; char *data; - index = CustomData_get_layer_index(&bm->pdata, type_from); + bool has_type_source = false; - if (index != -1) { + if (type == CD_MTFACE) { + has_type_source = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY); + } + else { + has_type_source = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL); + } + + if (has_type_source) { /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */ BMLoop *(*looptris)[3] = bmdm->em->looptris; const int size = CustomData_sizeof(type); int i, j; DM_add_tessface_layer(dm, type, CD_CALLOC, NULL); - index = CustomData_get_layer_index(&dm->faceData, type); + const int index = CustomData_get_layer_index(&dm->faceData, type); dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY; data = datalayer = DM_get_tessface_data_layer(dm, type); @@ -2625,7 +2641,7 @@ static void statvis_calc_distort( vertexCos[BM_elem_index_get(l_iter->next->v)]); } else { - BM_loop_calc_face_normal(l_iter, no_corner); + BM_loop_calc_face_normal_safe(l_iter, no_corner); } /* simple way to detect (what is most likely) concave */ if (dot_v3v3(f_no, no_corner) < 0.0f) { diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 4eee24b378f..38f5c00941c 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -986,19 +986,19 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected */ void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse) { -/* - * Modifies the force on a particle according to its - * relation with the effector object - * Different kind of effectors include: - * Forcefields: Gravity-like attractor - * (force power is related to the inverse of distance to the power of a falloff value) - * Vortex fields: swirling effectors - * (particles rotate around Z-axis of the object. otherwise, same relation as) - * (Forcefields, but this is not done through a force/acceleration) - * Guide: particles on a path - * (particles are guided along a curve bezier or old nurbs) - * (is independent of other effectors) - */ + /* + * Modifies the force on a particle according to its + * relation with the effector object + * Different kind of effectors include: + * Forcefields: Gravity-like attractor + * (force power is related to the inverse of distance to the power of a falloff value) + * Vortex fields: swirling effectors + * (particles rotate around Z-axis of the object. otherwise, same relation as) + * (Forcefields, but this is not done through a force/acceleration) + * Guide: particles on a path + * (particles are guided along a curve bezier or old nurbs) + * (is independent of other effectors) + */ EffectorCache *eff; EffectorData efd; int p=0, tot = 1, step = 1; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 7dbc43e0a32..db6c533ab57 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -126,7 +126,7 @@ void free_fcurves(ListBase *list) /* ---------------------- Copy --------------------------- */ /* duplicate an F-Curve */ -FCurve *copy_fcurve(FCurve *fcu) +FCurve *copy_fcurve(const FCurve *fcu) { FCurve *fcu_d; @@ -1805,7 +1805,7 @@ void fcurve_free_driver(FCurve *fcu) } /* This makes a copy of the given driver */ -ChannelDriver *fcurve_copy_driver(ChannelDriver *driver) +ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver) { ChannelDriver *ndriver; @@ -1945,7 +1945,7 @@ float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const fl BLI_mutex_unlock(&python_driver_lock); } #else /* WITH_PYTHON*/ - (void)evaltime; + UNUSED_VARS(anim_rna, evaltime); #endif /* WITH_PYTHON*/ break; } diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 2c301c04100..f1732ee7a9a 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -116,7 +116,7 @@ static void fcm_generator_free(FModifier *fcm) MEM_freeN(data->coefficients); } -static void fcm_generator_copy(FModifier *fcm, FModifier *src) +static void fcm_generator_copy(FModifier *fcm, const FModifier *src) { FMod_Generator *gen = (FMod_Generator *)fcm->data; FMod_Generator *ogen = (FMod_Generator *)src->data; @@ -386,7 +386,7 @@ static void fcm_envelope_free(FModifier *fcm) MEM_freeN(env->data); } -static void fcm_envelope_copy(FModifier *fcm, FModifier *src) +static void fcm_envelope_copy(FModifier *fcm, const FModifier *src) { FMod_Envelope *env = (FMod_Envelope *)fcm->data; FMod_Envelope *oenv = (FMod_Envelope *)src->data; @@ -877,7 +877,7 @@ static void fcm_python_new_data(void *mdata) data->prop->type = IDP_GROUP; } -static void fcm_python_copy(FModifier *fcm, FModifier *src) +static void fcm_python_copy(FModifier *fcm, const FModifier *src) { FMod_Python *pymod = (FMod_Python *)fcm->data; FMod_Python *opymod = (FMod_Python *)src->data; @@ -1040,7 +1040,7 @@ static void fmods_init_typeinfo(void) /* This function should be used for getting the appropriate type-info when only * a F-Curve modifier type is known */ -const FModifierTypeInfo *get_fmodifier_typeinfo(int type) +const FModifierTypeInfo *get_fmodifier_typeinfo(const int type) { /* initialize the type-info list? */ if (FMI_INIT) { @@ -1065,7 +1065,7 @@ const FModifierTypeInfo *get_fmodifier_typeinfo(int type) /* This function should always be used to get the appropriate type-info, as it * has checks which prevent segfaults in some weird cases. */ -const FModifierTypeInfo *fmodifier_get_typeinfo(FModifier *fcm) +const FModifierTypeInfo *fmodifier_get_typeinfo(const FModifier *fcm) { /* only return typeinfo for valid modifiers */ if (fcm) @@ -1117,7 +1117,7 @@ FModifier *add_fmodifier(ListBase *modifiers, int type) } /* Make a copy of the specified F-Modifier */ -FModifier *copy_fmodifier(FModifier *src) +FModifier *copy_fmodifier(const FModifier *src) { const FModifierTypeInfo *fmi = fmodifier_get_typeinfo(src); FModifier *dst; @@ -1142,7 +1142,7 @@ FModifier *copy_fmodifier(FModifier *src) } /* Duplicate all of the F-Modifiers in the Modifier stacks */ -void copy_fmodifiers(ListBase *dst, ListBase *src) +void copy_fmodifiers(ListBase *dst, const ListBase *src) { FModifier *fcm, *srcfcm; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 580842fe176..401fed74c52 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -695,10 +695,14 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase if (ef->selboxes) MEM_freeN(ef->selboxes); - if (BKE_vfont_select_get(ob, &selstart, &selend)) - ef->selboxes = MEM_callocN((selend - selstart + 1) * sizeof(EditFontSelBox), "font selboxes"); - else + if (BKE_vfont_select_get(ob, &selstart, &selend)) { + ef->selboxes_len = (selend - selstart) + 1; + ef->selboxes = MEM_callocN(ef->selboxes_len * sizeof(EditFontSelBox), "font selboxes"); + } + else { + ef->selboxes_len = 0; ef->selboxes = NULL; + } selboxes = ef->selboxes; } diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 30fc8915d46..758438bb051 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -754,7 +754,7 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src) } /* make a copy of a given gpencil datablock */ -bGPdata *BKE_gpencil_data_duplicate(Main *bmain, bGPdata *gpd_src, bool internal_copy) +bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy) { const bGPDlayer *gpl_src; bGPDlayer *gpl_dst; diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 9b011dbb003..932f41ac4ba 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -80,6 +80,8 @@ Group *BKE_group_add(Main *bmain, const char *name) Group *group; group = BKE_libblock_alloc(bmain, ID_GR, name); + id_us_min(&group->id); + id_us_ensure_real(&group->id); group->layer = (1 << 20) - 1; group->preview = NULL; @@ -87,7 +89,7 @@ Group *BKE_group_add(Main *bmain, const char *name) return group; } -Group *BKE_group_copy(Main *bmain, Group *group) +Group *BKE_group_copy(Main *bmain, const Group *group) { Group *groupn; diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 7669c4ba112..bccf9307912 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -204,7 +204,7 @@ void BKE_previewimg_clear(struct PreviewImage *prv) } } -PreviewImage *BKE_previewimg_copy(PreviewImage *prv) +PreviewImage *BKE_previewimg_copy(const PreviewImage *prv) { PreviewImage *prv_img = NULL; int i; @@ -222,7 +222,7 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv) } /** Duplicate preview image from \a id and clear icon_id, to be used by datablock copy functions. */ -void BKE_previewimg_id_copy(ID *new_id, ID *old_id) +void BKE_previewimg_id_copy(ID *new_id, const ID *old_id) { PreviewImage **old_prv_p = BKE_previewimg_id_get_p(old_id); PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id); @@ -239,7 +239,7 @@ void BKE_previewimg_id_copy(ID *new_id, ID *old_id) } } -PreviewImage **BKE_previewimg_id_get_p(ID *id) +PreviewImage **BKE_previewimg_id_get_p(const ID *id) { switch (GS(id->name)) { #define ID_PRV_CASE(id_code, id_struct) case id_code: { return &((id_struct *)id)->preview; } ((void)0) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 5e4e8eb34ad..e98181be444 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -117,14 +117,14 @@ IDProperty *IDP_CopyIDPArray(const IDProperty *array) return narray; } -void IDP_FreeIDPArray(IDProperty *prop) +static void IDP_FreeIDPArray(IDProperty *prop, const bool do_id_user) { int i; BLI_assert(prop->type == IDP_IDPARRAY); for (i = 0; i < prop->len; i++) - IDP_FreeProperty(GETPROP(prop, i)); + IDP_FreeProperty_ex(GETPROP(prop, i), do_id_user); if (prop->data.pointer) MEM_freeN(prop->data.pointer); @@ -437,22 +437,24 @@ void IDP_FreeString(IDProperty *prop) /* -------------------------------------------------------------------- */ -/* ID Type (not in use yet) */ +/* ID Type */ -/** \name IDProperty ID API (unused) +/** \name IDProperty ID API * \{ */ -void IDP_LinkID(IDProperty *prop, ID *id) -{ - if (prop->data.pointer) - id_us_min(((ID *)prop->data.pointer)); - prop->data.pointer = id; - id_us_plus(id); -} -void IDP_UnlinkID(IDProperty *prop) +static IDProperty *IDP_CopyID(const IDProperty *prop) { - id_us_min(((ID *)prop->data.pointer)); + IDProperty *newp; + + BLI_assert(prop->type == IDP_ID); + newp = idp_generic_copy(prop); + + newp->data.pointer = prop->data.pointer; + id_us_plus(IDP_Id(newp)); + + return newp; } + /** \} */ @@ -710,13 +712,13 @@ IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, con * This is because all ID Property freeing functions free only direct data (not the ID Property * struct itself), but for Groups the child properties *are* considered * direct data. */ -static void IDP_FreeGroup(IDProperty *prop) +static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user) { IDProperty *loop; BLI_assert(prop->type == IDP_GROUP); for (loop = prop->data.group.first; loop; loop = loop->next) { - IDP_FreeProperty(loop); + IDP_FreeProperty_ex(loop, do_id_user); } BLI_freelistN(&prop->data.group); } @@ -733,12 +735,51 @@ IDProperty *IDP_CopyProperty(const IDProperty *prop) switch (prop->type) { case IDP_GROUP: return IDP_CopyGroup(prop); case IDP_STRING: return IDP_CopyString(prop); + case IDP_ID: return IDP_CopyID(prop); case IDP_ARRAY: return IDP_CopyArray(prop); case IDP_IDPARRAY: return IDP_CopyIDPArray(prop); default: return idp_generic_copy(prop); } } +/* Updates ID pointers after an object has been copied */ +/* TODO Nuke this once its only user has been correctly converted to use generic ID management from BKE_library! */ +void IDP_RelinkProperty(struct IDProperty *prop) +{ + if (!prop) + return; + + switch (prop->type) { + case IDP_GROUP: + { + for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) { + IDP_RelinkProperty(loop); + } + break; + } + case IDP_IDPARRAY: + { + IDProperty *idp_array = IDP_Array(prop); + for (int i = 0; i < prop->len; i++) { + IDP_RelinkProperty(&idp_array[i]); + } + break; + } + case IDP_ID: + { + ID *id = IDP_Id(prop); + if (id && id->newid) { + id_us_min(IDP_Id(prop)); + prop->data.pointer = id->newid; + id_us_plus(IDP_Id(prop)); + } + break; + } + default: + break; /* Nothing to do for other IDProp types. */ + } +} + /** * Get the Group property that contains the id properties for ID id. Set create_if_needed * to create the Group property and attach it to id if it doesn't exist; otherwise @@ -835,6 +876,8 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is return false; return true; } + case IDP_ID: + return (IDP_Id(prop1) == IDP_Id(prop2)); default: /* should never get here */ BLI_assert(0); @@ -910,6 +953,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char * prop->len = prop->totallen = val->array.len; break; } + printf("%s: bad array type.\n", __func__); return NULL; } case IDP_STRING: @@ -956,6 +1000,14 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char * /* heh I think all needed values are set properly by calloc anyway :) */ break; } + case IDP_ID: + { + prop = MEM_callocN(sizeof(IDProperty), "IDProperty datablock"); + prop->data.pointer = (void *)val->id; + prop->type = IDP_ID; + id_us_plus(IDP_Id(prop)); + break; + } default: { prop = MEM_callocN(sizeof(IDProperty), "IDProperty array"); @@ -970,11 +1022,10 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char * } /** - * \note this will free all child properties of list arrays and groups! - * Also, note that this does NOT unlink anything! Plus it doesn't free - * the actual struct IDProperty struct either. + * \note This will free allocated data, all child properties of arrays and groups, and unlink IDs! + * But it does not free the actual IDProperty struct itself. */ -void IDP_FreeProperty(IDProperty *prop) +void IDP_FreeProperty_ex(IDProperty *prop, const bool do_id_user) { switch (prop->type) { case IDP_ARRAY: @@ -984,14 +1035,24 @@ void IDP_FreeProperty(IDProperty *prop) IDP_FreeString(prop); break; case IDP_GROUP: - IDP_FreeGroup(prop); + IDP_FreeGroup(prop, do_id_user); break; case IDP_IDPARRAY: - IDP_FreeIDPArray(prop); + IDP_FreeIDPArray(prop, do_id_user); + break; + case IDP_ID: + if (do_id_user) { + id_us_min(IDP_Id(prop)); + } break; } } +void IDP_FreeProperty(IDProperty *prop) +{ + IDP_FreeProperty_ex(prop, true); +} + void IDP_ClearProperty(IDProperty *prop) { IDP_FreeProperty(prop); @@ -999,18 +1060,4 @@ void IDP_ClearProperty(IDProperty *prop) prop->len = prop->totallen = 0; } -/** - * Unlinks any struct IDProperty<->ID linkage that might be going on. - * - * \note currently unused - */ -void IDP_UnlinkProperty(IDProperty *prop) -{ - switch (prop->type) { - case IDP_ID: - IDP_UnlinkID(prop); - break; - } -} - /** \} */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 318f6480aaf..abe08def197 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -62,6 +62,7 @@ #include "BLI_blenlib.h" #include "BLI_math_vector.h" +#include "BLI_mempool.h" #include "BLI_threads.h" #include "BLI_timecode.h" /* for stamp timecode format */ #include "BLI_utildefines.h" @@ -433,7 +434,7 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src) } /* empty image block, of similar type and filename */ -Image *BKE_image_copy(Main *bmain, Image *ima) +Image *BKE_image_copy(Main *bmain, const Image *ima) { Image *nima = image_alloc(bmain, ima->id.name + 2, ima->source, ima->type); @@ -1238,7 +1239,7 @@ char BKE_imtype_valid_channels(const char imtype, bool write_file) switch (imtype) { case R_IMF_IMTYPE_BMP: if (write_file) break; - /* fall-through */ + ATTR_FALLTHROUGH; case R_IMF_IMTYPE_TARGA: case R_IMF_IMTYPE_RAWTGA: case R_IMF_IMTYPE_IRIS: @@ -2216,8 +2217,10 @@ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf) ibuf->foptions.flag |= OPENEXR_HALF; ibuf->foptions.flag |= (imf->exr_codec & OPENEXR_COMPRESS); - if (!(imf->flag & R_IMF_FLAG_ZBUF)) - ibuf->zbuf_float = NULL; /* signal for exr saving */ + if (!(imf->flag & R_IMF_FLAG_ZBUF)) { + /* Signal for exr saving. */ + IMB_freezbuffloatImBuf(ibuf); + } } #endif @@ -2737,7 +2740,6 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } } -#define PASSTYPE_UNSET -1 /* return renderpass for a given pass index and active view */ /* fallback to available if there are missing passes for active view */ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex) @@ -2746,7 +2748,7 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const RenderPass *rpass; int rp_index = 0; - int rp_passtype = PASSTYPE_UNSET; + const char *rp_name = ""; for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) { if (rp_index == pass) { @@ -2756,12 +2758,12 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const break; } else { - rp_passtype = rpass->passtype; + rp_name = rpass->name; } } /* multiview */ - else if ((rp_passtype != PASSTYPE_UNSET) && - (rpass->passtype == rp_passtype) && + else if (rp_name[0] && + STREQ(rpass->name, rp_name) && (rpass->view_id == view)) { rpass_ret = rpass; @@ -2781,7 +2783,6 @@ static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const return rpass_ret; } -#undef PASSTYPE_UNSET /* if layer or pass changes, we need an index for the imbufs list */ /* note it is called for rendered results, but it doesnt use the index! */ @@ -2862,7 +2863,7 @@ bool BKE_image_is_stereo(Image *ima) { return BKE_image_is_multiview(ima) && (BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) && - BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name))); + BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name))); } static void image_init_multilayer_multiview(Image *ima, RenderResult *rr) @@ -3751,7 +3752,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc } for (rpass = rl->passes.first; rpass; rpass = rpass->next) - if (rpass->passtype == SCE_PASS_Z) + if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview) rectz = rpass->rect; } } @@ -4132,33 +4133,32 @@ typedef struct ImagePoolEntry { typedef struct ImagePool { ListBase image_buffers; + BLI_mempool *memory_pool; } ImagePool; ImagePool *BKE_image_pool_new(void) { ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool"); + pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolEntry), 0, 128, BLI_MEMPOOL_NOP); return pool; } void BKE_image_pool_free(ImagePool *pool) { - ImagePoolEntry *entry, *next_entry; - - /* use single lock to dereference all the image buffers */ + /* Use single lock to dereference all the image buffers. */ BLI_spin_lock(&image_spin); - - for (entry = pool->image_buffers.first; entry; entry = next_entry) { - next_entry = entry->next; - - if (entry->ibuf) + for (ImagePoolEntry *entry = pool->image_buffers.first; + entry != NULL; + entry = entry->next) + { + if (entry->ibuf) { IMB_freeImBuf(entry->ibuf); - - MEM_freeN(entry); + } } - BLI_spin_unlock(&image_spin); + BLI_mempool_destroy(pool->memory_pool); MEM_freeN(pool); } @@ -4210,7 +4210,7 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool ibuf = image_acquire_ibuf(ima, iuser, NULL); - entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry"); + entry = BLI_mempool_alloc(pool->memory_pool); entry->image = ima; entry->frame = frame; entry->index = index; diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index 2c8399adece..1f1f4c9d341 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -132,7 +132,7 @@ static void image_buf_fill_checker_slice(unsigned char *rect, float hsv[3] = {0.0f, 0.9f, 0.9f}; float rgb[3]; - float dark_linear_color, bright_linear_color; + float dark_linear_color = 0.0f, bright_linear_color = 0.0f; if (rect_float != NULL) { dark_linear_color = srgb_to_linearrgb(0.25f); bright_linear_color = srgb_to_linearrgb(0.58f); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 8a7c1dd2833..98b251294ae 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -151,7 +151,7 @@ Key *BKE_key_add(ID *id) /* common function */ return key; } -Key *BKE_key_copy(Main *bmain, Key *key) +Key *BKE_key_copy(Main *bmain, const Key *key) { Key *keyn; KeyBlock *kbn, *kb; diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 69a2067f4e6..2242ba379fb 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -116,7 +116,7 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name) return la; } -Lamp *BKE_lamp_copy(Main *bmain, Lamp *la) +Lamp *BKE_lamp_copy(Main *bmain, const Lamp *la) { Lamp *lan; int a; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 54cfae620a1..c9d7dddf25a 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -277,7 +277,7 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name) return lt; } -Lattice *BKE_lattice_copy(Main *bmain, Lattice *lt) +Lattice *BKE_lattice_copy(Main *bmain, const Lattice *lt) { Lattice *ltn; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index e380b5c17e0..2ea7342ff34 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -133,6 +133,12 @@ #include "atomic_ops.h" +//#define DEBUG_TIME + +#ifdef DEBUG_TIME +# include "PIL_time_utildefines.h" +#endif + /* GS reads the memory pointed at in a specific ordering. * only use this definition, makes little and big endian systems * work fine, in conjunction with MAKE_ID */ @@ -301,7 +307,7 @@ void BKE_id_expand_local(Main *bmain, ID *id) /** * Ensure new (copied) ID is fully made local. */ -void BKE_id_copy_ensure_local(Main *bmain, ID *old_id, ID *new_id) +void BKE_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id) { if (ID_IS_LINKED_DATABLOCK(old_id)) { BKE_id_expand_local(bmain, new_id); @@ -482,7 +488,7 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) * Invokes the appropriate copy method for the block and returns the result in * newid, unless test. Returns true if the block can be copied. */ -bool id_copy(Main *bmain, ID *id, ID **newid, bool test) +bool id_copy(Main *bmain, const ID *id, ID **newid, bool test) { if (!test) { *newid = NULL; @@ -852,118 +858,72 @@ int set_listbasepointers(Main *main, ListBase **lb) * **************************** */ /** + * Get allocation size fo a given datablock type and optionally allocation name. + */ +size_t BKE_libblock_get_alloc_info(short type, const char **name) +{ +#define CASE_RETURN(id_code, type) \ + case id_code: \ + do { \ + if (name != NULL) { \ + *name = #type; \ + } \ + return sizeof(type); \ + } while(0) + + switch ((ID_Type)type) { + CASE_RETURN(ID_SCE, Scene); + CASE_RETURN(ID_LI, Library); + CASE_RETURN(ID_OB, Object); + CASE_RETURN(ID_ME, Mesh); + CASE_RETURN(ID_CU, Curve); + CASE_RETURN(ID_MB, MetaBall); + CASE_RETURN(ID_MA, Material); + CASE_RETURN(ID_TE, Tex); + CASE_RETURN(ID_IM, Image); + CASE_RETURN(ID_LT, Lattice); + CASE_RETURN(ID_LA, Lamp); + CASE_RETURN(ID_CA, Camera); + CASE_RETURN(ID_IP, Ipo); + CASE_RETURN(ID_KE, Key); + CASE_RETURN(ID_WO, World); + CASE_RETURN(ID_SCR, bScreen); + CASE_RETURN(ID_VF, VFont); + CASE_RETURN(ID_TXT, Text); + CASE_RETURN(ID_SPK, Speaker); + CASE_RETURN(ID_SO, bSound); + CASE_RETURN(ID_GR, Group); + CASE_RETURN(ID_AR, bArmature); + CASE_RETURN(ID_AC, bAction); + CASE_RETURN(ID_NT, bNodeTree); + CASE_RETURN(ID_BR, Brush); + CASE_RETURN(ID_PA, ParticleSettings); + CASE_RETURN(ID_WM, wmWindowManager); + CASE_RETURN(ID_GD, bGPdata); + CASE_RETURN(ID_MC, MovieClip); + CASE_RETURN(ID_MSK, Mask); + CASE_RETURN(ID_LS, FreestyleLineStyle); + CASE_RETURN(ID_PAL, Palette); + CASE_RETURN(ID_PC, PaintCurve); + CASE_RETURN(ID_CF, CacheFile); + } + return 0; +#undef CASE_RETURN +} + +/** * Allocates and returns memory of the right size for the specified block type, * initialized to zero. */ void *BKE_libblock_alloc_notest(short type) { - ID *id = NULL; - - switch ((ID_Type)type) { - case ID_SCE: - id = MEM_callocN(sizeof(Scene), "scene"); - break; - case ID_LI: - id = MEM_callocN(sizeof(Library), "library"); - break; - case ID_OB: - id = MEM_callocN(sizeof(Object), "object"); - break; - case ID_ME: - id = MEM_callocN(sizeof(Mesh), "mesh"); - break; - case ID_CU: - id = MEM_callocN(sizeof(Curve), "curve"); - break; - case ID_MB: - id = MEM_callocN(sizeof(MetaBall), "mball"); - break; - case ID_MA: - id = MEM_callocN(sizeof(Material), "mat"); - break; - case ID_TE: - id = MEM_callocN(sizeof(Tex), "tex"); - break; - case ID_IM: - id = MEM_callocN(sizeof(Image), "image"); - break; - case ID_LT: - id = MEM_callocN(sizeof(Lattice), "latt"); - break; - case ID_LA: - id = MEM_callocN(sizeof(Lamp), "lamp"); - break; - case ID_CA: - id = MEM_callocN(sizeof(Camera), "camera"); - break; - case ID_IP: - id = MEM_callocN(sizeof(Ipo), "ipo"); - break; - case ID_KE: - id = MEM_callocN(sizeof(Key), "key"); - break; - case ID_WO: - id = MEM_callocN(sizeof(World), "world"); - break; - case ID_SCR: - id = MEM_callocN(sizeof(bScreen), "screen"); - break; - case ID_VF: - id = MEM_callocN(sizeof(VFont), "vfont"); - break; - case ID_TXT: - id = MEM_callocN(sizeof(Text), "text"); - break; - case ID_SPK: - id = MEM_callocN(sizeof(Speaker), "speaker"); - break; - case ID_SO: - id = MEM_callocN(sizeof(bSound), "sound"); - break; - case ID_GR: - id = MEM_callocN(sizeof(Group), "group"); - break; - case ID_AR: - id = MEM_callocN(sizeof(bArmature), "armature"); - break; - case ID_AC: - id = MEM_callocN(sizeof(bAction), "action"); - break; - case ID_NT: - id = MEM_callocN(sizeof(bNodeTree), "nodetree"); - break; - case ID_BR: - id = MEM_callocN(sizeof(Brush), "brush"); - break; - case ID_PA: - id = MEM_callocN(sizeof(ParticleSettings), "ParticleSettings"); - break; - case ID_WM: - id = MEM_callocN(sizeof(wmWindowManager), "Window manager"); - break; - case ID_GD: - id = MEM_callocN(sizeof(bGPdata), "Grease Pencil"); - break; - case ID_MC: - id = MEM_callocN(sizeof(MovieClip), "Movie Clip"); - break; - case ID_MSK: - id = MEM_callocN(sizeof(Mask), "Mask"); - break; - case ID_LS: - id = MEM_callocN(sizeof(FreestyleLineStyle), "Freestyle Line Style"); - break; - case ID_PAL: - id = MEM_callocN(sizeof(Palette), "Palette"); - break; - case ID_PC: - id = MEM_callocN(sizeof(PaintCurve), "Paint Curve"); - break; - case ID_CF: - id = MEM_callocN(sizeof(CacheFile), "Cache File"); - break; + const char *name; + size_t size = BKE_libblock_get_alloc_info(type, &name); + if (size != 0) { + return MEM_callocN(size, name); } - return id; + BLI_assert(!"Request to allocate unknown data type"); + return NULL; } /** @@ -1132,7 +1092,7 @@ void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action) } /* used everywhere in blenkernel */ -void *BKE_libblock_copy(Main *bmain, ID *id) +void *BKE_libblock_copy(Main *bmain, const ID *id) { ID *idn; size_t idn_len; @@ -1154,7 +1114,7 @@ void *BKE_libblock_copy(Main *bmain, ID *id) return idn; } -void *BKE_libblock_copy_nolib(ID *id, const bool do_action) +void *BKE_libblock_copy_nolib(const ID *id, const bool do_action) { ID *idn; size_t idn_len; @@ -1716,10 +1676,19 @@ static void library_make_local_copying_check(ID *id, GSet *loop_tags, MainIDRela for (; entry != NULL; entry = entry->next) { ID *par_id = (ID *)entry->id_pointer; /* used_to_user stores ID pointer, not pointer to ID pointer... */ - /* Shapekeys are considered 'private' to their owner ID here, and never tagged (since they cannot be linked), - * so we have to switch effective parent to their owner. */ - if (GS(par_id->name) == ID_KE) { - par_id = ((Key *)par_id)->from; + /* Our oh-so-beloved 'from' pointers... */ + if (entry->usage_flag & IDWALK_CB_LOOPBACK) { + /* We totally disregard Object->proxy_from 'usage' here, this one would only generate fake positives. */ + if (GS(par_id->name) == ID_OB) { + BLI_assert(((Object *)par_id)->proxy_from == (Object *)id); + continue; + } + + /* Shapekeys are considered 'private' to their owner ID here, and never tagged (since they cannot be linked), + * so we have to switch effective parent to their owner. */ + if (GS(par_id->name) == ID_KE) { + par_id = ((Key *)par_id)->from; + } } if (par_id->lib == NULL) { @@ -1777,9 +1746,18 @@ void BKE_library_make_local( LinkNode *copied_ids = NULL; MemArena *linklist_mem = BLI_memarena_new(512 * sizeof(*todo_ids), __func__); + GSet *done_ids = BLI_gset_ptr_new(__func__); + +#ifdef DEBUG_TIME + TIMEIT_START(make_local); +#endif + BKE_main_relations_create(bmain); - GSet *done_ids = BLI_gset_ptr_new(__func__); +#ifdef DEBUG_TIME + printf("Pre-compute current ID relations: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); +#endif /* Step 1: Detect datablocks to make local. */ for (a = set_listbasepointers(bmain, lbarray); a--; ) { @@ -1830,6 +1808,11 @@ void BKE_library_make_local( } } +#ifdef DEBUG_TIME + printf("Step 1: Detect datablocks to make local: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); +#endif + /* Step 2: Check which datablocks we can directly make local (because they are only used by already, or future, * local data), others will need to be duplicated. */ GSet *loop_tags = BLI_gset_ptr_new(__func__); @@ -1843,6 +1826,11 @@ void BKE_library_make_local( /* Next step will most likely add new IDs, better to get rid of this mapping now. */ BKE_main_relations_free(bmain); +#ifdef DEBUG_TIME + printf("Step 2: Check which datablocks we can directly make local: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); +#endif + /* Step 3: Make IDs local, either directly (quick and simple), or using generic process, * which involves more complex checks and might instead create a local copy of original linked ID. */ for (LinkNode *it = todo_ids, *it_next; it; it = it_next) { @@ -1883,11 +1871,16 @@ void BKE_library_make_local( } } +#ifdef DEBUG_TIME + printf("Step 3: Make IDs local: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); +#endif + /* At this point, we are done with directly made local IDs. Now we have to handle duplicated ones, since their * remaining linked original counterpart may not be needed anymore... */ todo_ids = NULL; - /* Step 4: We have to remap local usages of old (linked) ID to new (local) id in a separated loop, + /* Step 4: We have to remap local usages of old (linked) ID to new (local) ID in a separated loop, * as lbarray ordering is not enough to ensure us we did catch all dependencies * (e.g. if making local a parent object before its child...). See T48907. */ /* TODO This is now the biggest step by far (in term of processing time). We may be able to gain here by @@ -1911,6 +1904,11 @@ void BKE_library_make_local( } } +#ifdef DEBUG_TIME + printf("Step 4: Remap local usages of old (linked) ID to new (local) ID: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); +#endif + /* Note: Keeping both version of the code (old one being safer, since it still has checks against unused IDs) * for now, we can remove old one once it has been tested for some time in master... */ #if 1 @@ -1955,6 +1953,12 @@ void BKE_library_make_local( } } } + +#ifdef DEBUG_TIME + printf("Step 5: Proxy 'remapping' hack: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); +#endif + #else LinkNode *linked_loop_candidates = NULL; @@ -2033,6 +2037,11 @@ void BKE_library_make_local( } } +#ifdef DEBUG_TIME + printf("Step 5: Remove linked datablocks that have been copied and ended fully localized: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); +#endif + /* Step 6: Try to find circle dependencies between indirectly-linked-only datablocks. * Those are fake 'usages' that prevent their deletion. See T49775 for nice ugly case. */ BKE_library_unused_linked_data_set_tag(bmain, false); @@ -2069,10 +2078,38 @@ void BKE_library_make_local( it->link = NULL; } } + +#ifdef DEBUG_TIME + printf("Step 6: Try to find circle dependencies between indirectly-linked-only datablocks: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); +#endif + +#endif + + /* This is probably more of a hack than something we should do here, but... + * Issue is, the whole copying + remapping done in complex cases above may leave pose channels of armatures + * in complete invalid state (more precisely, the bone pointers of the pchans - very crappy cross-datablocks + * relationship), se we tag it to be fully recomputed, but this does not seems to be enough in some cases, + * and evaluation code ends up trying to evaluate a not-yet-updated armature object's deformations. + * Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */ + for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL && ob->pose->flag & POSE_RECALC) { + BKE_pose_rebuild(ob, ob->data); + } + } + +#ifdef DEBUG_TIME + printf("Hack: Forcefully rebuild armature object poses: Done.\n"); + TIMEIT_VALUE_PRINT(make_local); #endif BKE_main_id_clear_newpoins(bmain); BLI_memarena_free(linklist_mem); + +#ifdef DEBUG_TIME + printf("Cleanup and finish: Done.\n"); + TIMEIT_END(make_local); +#endif } /** diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index 9685f1f5af6..d1f0c87183d 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -33,6 +33,7 @@ #include "DNA_actuator_types.h" #include "DNA_anim_types.h" +#include "DNA_armature_types.h" #include "DNA_brush_types.h" #include "DNA_camera_types.h" #include "DNA_constraint_types.h" @@ -70,10 +71,12 @@ #include "BKE_animsys.h" #include "BKE_constraint.h" #include "BKE_fcurve.h" +#include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_main.h" #include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_particle.h" #include "BKE_rigidbody.h" #include "BKE_sca.h" @@ -82,7 +85,9 @@ #define FOREACH_FINALIZE _finalize -#define FOREACH_FINALIZE_VOID FOREACH_FINALIZE: (void)0 +#define FOREACH_FINALIZE_VOID \ + if (0) { goto FOREACH_FINALIZE; } \ + FOREACH_FINALIZE: ((void)0) #define FOREACH_CALLBACK_INVOKE_ID_PP(_data, id_pp, _cb_flag) \ CHECK_TYPE(id_pp, ID **); \ @@ -140,6 +145,37 @@ typedef struct LibraryForeachIDData { BLI_LINKSTACK_DECLARE(ids_todo, ID *); } LibraryForeachIDData; +static void library_foreach_idproperty_ID_link(LibraryForeachIDData *data, IDProperty *prop, int flag) +{ + if (!prop) + return; + + switch (prop->type) { + case IDP_GROUP: + { + for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) { + library_foreach_idproperty_ID_link(data, loop, flag); + } + break; + } + case IDP_IDPARRAY: + { + IDProperty *loop = IDP_Array(prop); + for (int i = 0; i < prop->len; i++) { + library_foreach_idproperty_ID_link(data, &loop[i], flag); + } + break; + } + case IDP_ID: + FOREACH_CALLBACK_INVOKE_ID(data, prop->data.pointer, flag); + break; + default: + break; /* Nothing to do here with other types of IDProperties... */ + } + + FOREACH_FINALIZE_VOID; +} + static void library_foreach_rigidbodyworldSceneLooper( struct RigidBodyWorld *UNUSED(rbw), ID **id_pointer, void *user_data, int cb_flag) { @@ -265,6 +301,17 @@ static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint) FOREACH_FINALIZE_VOID; } +static void library_foreach_bone(LibraryForeachIDData *data, Bone *bone) +{ + library_foreach_idproperty_ID_link(data, bone->prop, IDWALK_CB_USER); + + for (Bone *curbone = bone->childbase.first; curbone; curbone = curbone->next) { + library_foreach_bone(data, curbone); + } + + FOREACH_FINALIZE_VOID; +} + static void library_foreach_ID_as_subdata_link( ID **id_pp, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data) { @@ -337,6 +384,8 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call continue; } + library_foreach_idproperty_ID_link(&data, id->properties, IDWALK_CB_USER); + AnimData *adt = BKE_animdata_from_id(id); if (adt) { library_foreach_animationData(&data, adt); @@ -402,6 +451,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER); CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER); CALLBACK_INVOKE(seq->sound, IDWALK_CB_USER); + library_foreach_idproperty_ID_link(&data, seq->prop, IDWALK_CB_USER); for (SequenceModifierData *smd = seq->modifiers.first; smd; smd = smd->next) { CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER); } @@ -462,7 +512,8 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call /* Object is special, proxies make things hard... */ const int data_cb_flag = data.cb_flag; - const int proxy_cb_flag = (object->proxy || object->proxy_group) ? IDWALK_CB_INDIRECT_USAGE : 0; + const int proxy_cb_flag = ((data.flag & IDWALK_NO_INDIRECT_PROXY_DATA_USAGE) == 0 && (object->proxy || object->proxy_group)) ? + IDWALK_CB_INDIRECT_USAGE : 0; /* object data special case */ data.cb_flag |= proxy_cb_flag; @@ -490,7 +541,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call if (object->proxy_from) { data.cb_flag = ID_IS_LINKED_DATABLOCK(object->proxy_from) ? IDWALK_CB_INDIRECT_USAGE : 0; } - CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_NOP); + CALLBACK_INVOKE(object->proxy_from, IDWALK_CB_LOOPBACK); data.cb_flag = data_cb_flag; CALLBACK_INVOKE(object->poselib, IDWALK_CB_USER); @@ -515,6 +566,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call data.cb_flag |= proxy_cb_flag; for (pchan = object->pose->chanbase.first; pchan; pchan = pchan->next) { + library_foreach_idproperty_ID_link(&data, pchan->prop, IDWALK_CB_USER); CALLBACK_INVOKE(pchan->custom, IDWALK_CB_USER); BKE_constraints_id_loop(&pchan->constraints, library_foreach_constraintObjectLooper, &data); } @@ -554,6 +606,16 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call break; } + case ID_AR: + { + bArmature *arm = (bArmature *)id; + + for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) { + library_foreach_bone(&data, bone); + } + break; + } + case ID_ME: { Mesh *mesh = (Mesh *) id; @@ -684,12 +746,8 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call case ID_KE: { - /* XXX Only ID pointer from shapekeys is the 'from' one, which is not actually ID usage. - * Maybe we should even nuke it from here, not 100% sure yet... - * (see also foreach_libblock_id_users_callback). - */ Key *key = (Key *) id; - CALLBACK_INVOKE_ID(key->from, IDWALK_CB_NOP); + CALLBACK_INVOKE_ID(key->from, IDWALK_CB_LOOPBACK); break; } @@ -736,9 +794,27 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call { bNodeTree *ntree = (bNodeTree *) id; bNode *node; + bNodeSocket *sock; + CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER); + for (node = ntree->nodes.first; node; node = node->next) { CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER); + + library_foreach_idproperty_ID_link(&data, node->prop, IDWALK_CB_USER); + for (sock = node->inputs.first; sock; sock = sock->next) { + library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER); + } + for (sock = node->outputs.first; sock; sock = sock->next) { + library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER); + } + } + + for (sock = ntree->inputs.first; sock; sock = sock->next) { + library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER); + } + for (sock = ntree->outputs.first; sock; sock = sock->next) { + library_foreach_idproperty_ID_link(&data, sock->prop, IDWALK_CB_USER); } break; } @@ -892,14 +968,21 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call } break; } + case ID_GD: + { + bGPdata *gpencil = (bGPdata *) id; + + for (bGPDlayer *gp_layer = gpencil->layers.first; gp_layer; gp_layer = gp_layer->next) { + CALLBACK_INVOKE(gp_layer->parent, IDWALK_CB_NOP); + } + break; + } /* Nothing needed for those... */ case ID_IM: case ID_VF: case ID_TXT: case ID_SO: - case ID_AR: - case ID_GD: case ID_WM: case ID_PAL: case ID_PC: @@ -948,9 +1031,25 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag) */ /* XXX This has to be fully rethink, basing check on ID type is not really working anymore (and even worth once * IDProps will support ID pointers), we'll have to do some quick checks on IDs themselves... */ -bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id_type_used) +bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) { - if (id_type_can_have_animdata(id_type_owner)) { + /* any type of ID can be used in custom props. */ + if (id_owner->properties) { + return true; + } + + const short id_type_owner = GS(id_owner->name); + + /* IDProps of armature bones and nodes, and bNode->id can use virtually any type of ID. */ + if (ELEM(id_type_owner, ID_NT, ID_AR)) { + return true; + } + + if (ntreeFromID(id_owner)) { + return true; + } + + if (BKE_animdata_from_id(id_owner)) { return true; /* AnimationData can use virtually any kind of datablocks, through drivers especially. */ } @@ -959,8 +1058,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id return ELEM(id_type_used, ID_LI); case ID_SCE: return (ELEM(id_type_used, ID_OB, ID_WO, ID_SCE, ID_MC, ID_MA, ID_GR, ID_TXT, - ID_LS, ID_MSK, ID_SO, ID_GD, ID_BR, ID_PAL, ID_IM, ID_NT) || - BKE_library_idtype_can_use_idtype(ID_NT, id_type_used)); + ID_LS, ID_MSK, ID_SO, ID_GD, ID_BR, ID_PAL, ID_IM, ID_NT)); case ID_OB: /* Could be the following, but simpler to just always say 'yes' here. */ #if 0 @@ -977,13 +1075,13 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id case ID_MB: return ELEM(id_type_used, ID_MA); case ID_MA: - return (ELEM(id_type_used, ID_TE, ID_GR) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used)); + return (ELEM(id_type_used, ID_TE, ID_GR)); case ID_TE: - return (ELEM(id_type_used, ID_IM, ID_OB) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used)); + return (ELEM(id_type_used, ID_IM, ID_OB)); case ID_LT: return ELEM(id_type_used, ID_KE); case ID_LA: - return (ELEM(id_type_used, ID_TE) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used)); + return (ELEM(id_type_used, ID_TE)); case ID_CA: return ELEM(id_type_used, ID_OB); case ID_KE: @@ -991,7 +1089,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id case ID_SCR: return ELEM(id_type_used, ID_SCE); case ID_WO: - return (ELEM(id_type_used, ID_TE) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used)); + return (ELEM(id_type_used, ID_TE)); case ID_SPK: return ELEM(id_type_used, ID_SO); case ID_GR: @@ -1012,7 +1110,7 @@ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id case ID_MSK: return ELEM(id_type_used, ID_MC); /* WARNING! mask->parent.id, not typed. */ case ID_LS: - return (ELEM(id_type_used, ID_TE, ID_OB) || BKE_library_idtype_can_use_idtype(ID_NT, id_type_used)); + return (ELEM(id_type_used, ID_TE, ID_OB)); case ID_IM: case ID_VF: case ID_TXT: @@ -1045,20 +1143,15 @@ typedef struct IDUsersIter { int count_direct, count_indirect; /* Set by callback. */ } IDUsersIter; -static int foreach_libblock_id_users_callback(void *user_data, ID *self_id, ID **id_p, int cb_flag) +static int foreach_libblock_id_users_callback(void *user_data, ID *UNUSED(self_id), ID **id_p, int cb_flag) { IDUsersIter *iter = user_data; if (*id_p) { - /* XXX This is actually some kind of hack... - * Issue is, shapekeys' 'from' ID pointer is not actually ID usage. - * Maybe we should even nuke it from BKE_library_foreach_ID_link, not 100% sure yet... + /* 'Loopback' ID pointers (the ugly 'from' ones, Object->proxy_from and Key->from). + * Those are not actually ID usage, we can ignore them here. */ - if ((GS(self_id->name) == ID_KE) && (((Key *)self_id)->from == *id_p)) { - return IDWALK_RET_NOP; - } - /* XXX another hack, for similar reasons as above one. */ - if ((GS(self_id->name) == ID_OB) && (((Object *)self_id)->proxy_from == (Object *)*id_p)) { + if (cb_flag & IDWALK_CB_LOOPBACK) { return IDWALK_RET_NOP; } @@ -1118,7 +1211,7 @@ static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked) while (i-- && !is_defined) { ID *id_curr = lb_array[i]->first; - if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(id->name))) { + if (!id_curr || !BKE_library_id_can_use_idtype(id_curr, GS(id->name))) { continue; } @@ -1170,7 +1263,7 @@ void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, boo while (i-- && !is_defined) { ID *id_curr = lb_array[i]->first; - if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(id->name))) { + if (!id_curr || !BKE_library_id_can_use_idtype(id_curr, GS(id->name))) { continue; } diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index b6f4621a0b3..5e5ba44f039 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -419,6 +419,7 @@ ATTR_NONNULL(1) static void libblock_remap_data( IDRemap id_remap_data; ListBase *lb_array[MAX_LIBARRAY]; int i; + const int foreach_id_flags = (remap_flags & ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE) != 0 ? IDWALK_NO_INDIRECT_PROXY_DATA_USAGE : IDWALK_NOP; if (r_id_remap_data == NULL) { r_id_remap_data = &id_remap_data; @@ -439,7 +440,7 @@ ATTR_NONNULL(1) static void libblock_remap_data( #endif r_id_remap_data->id = id; libblock_remap_data_preprocess(r_id_remap_data); - BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP); + BKE_library_foreach_ID_link(NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags); } else { i = set_listbasepointers(bmain, lb_array); @@ -448,20 +449,16 @@ ATTR_NONNULL(1) static void libblock_remap_data( * objects actually using given old_id... sounds rather unlikely currently, though, so this will do for now. */ while (i--) { - ID *id_curr = lb_array[i]->first; - - if (!id_curr || !BKE_library_idtype_can_use_idtype(GS(id_curr->name), GS(old_id->name))) { - continue; - } - - for (; id_curr; id_curr = id_curr->next) { - /* Note that we cannot skip indirect usages of old_id here (if requested), we still need to check it for - * the user count handling... - * XXX No more true (except for debug usage of those skipping counters). */ - r_id_remap_data->id = id_curr; - libblock_remap_data_preprocess(r_id_remap_data); - BKE_library_foreach_ID_link( - NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, IDWALK_NOP); + for (ID *id_curr = lb_array[i]->first; id_curr; id_curr = id_curr->next) { + if (BKE_library_id_can_use_idtype(id_curr, GS(old_id->name))) { + /* Note that we cannot skip indirect usages of old_id here (if requested), we still need to check it for + * the user count handling... + * XXX No more true (except for debug usage of those skipping counters). */ + r_id_remap_data->id = id_curr; + libblock_remap_data_preprocess(r_id_remap_data); + BKE_library_foreach_ID_link( + NULL, id_curr, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags); + } } } } @@ -530,8 +527,12 @@ void BKE_libblock_remap_locked( id_us_clear_real(old_id); } - BLI_assert(old_id->us - skipped_refcounted >= 0); - UNUSED_VARS_NDEBUG(skipped_refcounted); + if (old_id->us - skipped_refcounted < 0) { + printf("Error in remapping process from '%s' (%p) to '%s' (%p): " + "wrong user count in old ID after process (summing up to %d)\n", + old_id->name, old_id, new_id ? new_id->name : "<NULL>", new_id, old_id->us - skipped_refcounted); + BLI_assert(0); + } if (skipped_direct == 0) { /* old_id is assumed to not be used directly anymore... */ @@ -723,38 +724,17 @@ void BKE_libblock_relink_to_newid(ID *id) BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0); } -void BKE_libblock_free_data(Main *UNUSED(bmain), ID *id) +void BKE_libblock_free_data(ID *id, const bool do_id_user) { if (id->properties) { - IDP_FreeProperty(id->properties); + IDP_FreeProperty_ex(id->properties, do_id_user); MEM_freeN(id->properties); } } -/** - * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c - * - * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv. - * (only applies to main database) - * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to - * \a id. - */ -void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) +void BKE_libblock_free_datablock(ID *id) { - ID *id = idv; - short type = GS(id->name); - ListBase *lb = which_libbase(bmain, type); - - DAG_id_type_tag(bmain, type); - -#ifdef WITH_PYTHON - BPY_id_release(id); -#endif - - if (do_id_user) { - BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); - } - + const short type = GS(id->name); switch (type) { case ID_SCE: BKE_scene_free((Scene *)id); @@ -860,6 +840,33 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b BKE_cachefile_free((CacheFile *)id); break; } +} + +/** + * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c + * + * \param do_id_user: if \a true, try to release other ID's 'references' hold by \a idv. + * (only applies to main database) + * \param do_ui_user: similar to do_id_user but makes sure UI does not hold references to + * \a id. + */ +void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) +{ + ID *id = idv; + short type = GS(id->name); + ListBase *lb = which_libbase(bmain, type); + + DAG_id_type_tag(bmain, type); + +#ifdef WITH_PYTHON + BPY_id_release(id); +#endif + + if (do_id_user) { + BKE_libblock_relink_ex(bmain, id, NULL, NULL, true); + } + + BKE_libblock_free_datablock(id); /* avoid notifying on removed data */ BKE_main_lock(bmain); @@ -876,7 +883,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b BLI_remlink(lb, id); - BKE_libblock_free_data(bmain, id); + BKE_libblock_free_data(id, do_id_user); BKE_main_unlock(bmain); MEM_freeN(id); diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 1eb909bd9f9..771e81ddc4f 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -155,7 +155,7 @@ void BKE_linestyle_free(FreestyleLineStyle *linestyle) BKE_linestyle_geometry_modifier_remove(linestyle, m); } -FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle) +FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineStyle *linestyle) { FreestyleLineStyle *new_linestyle; LineStyleModifier *m; @@ -355,7 +355,7 @@ LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyl return m; } -LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_color_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m) { LineStyleModifier *new_m; @@ -594,7 +594,7 @@ LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyl return m; } -LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_alpha_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m) { LineStyleModifier *new_m; @@ -863,7 +863,7 @@ LineStyleModifier *BKE_linestyle_thickness_modifier_add(FreestyleLineStyle *line return m; } -LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_thickness_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m) { LineStyleModifier *new_m; @@ -1195,7 +1195,7 @@ LineStyleModifier *BKE_linestyle_geometry_modifier_add(FreestyleLineStyle *lines return m; } -LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, LineStyleModifier *m) +LineStyleModifier *BKE_linestyle_geometry_modifier_copy(FreestyleLineStyle *linestyle, const LineStyleModifier *m) { LineStyleModifier *new_m; diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 6f23b82c6df..ae27e9bcd34 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -192,7 +192,7 @@ void BKE_mask_layer_rename(Mask *mask, MaskLayer *masklay, char *oldname, char * BKE_animdata_fix_paths_rename_all(&mask->id, "layers", oldname, masklay->name); } -MaskLayer *BKE_mask_layer_copy(MaskLayer *masklay) +MaskLayer *BKE_mask_layer_copy(const MaskLayer *masklay) { MaskLayer *masklay_new; MaskSpline *spline; @@ -236,7 +236,7 @@ MaskLayer *BKE_mask_layer_copy(MaskLayer *masklay) return masklay_new; } -void BKE_mask_layer_copy_list(ListBase *masklayers_new, ListBase *masklayers) +void BKE_mask_layer_copy_list(ListBase *masklayers_new, const ListBase *masklayers) { MaskLayer *layer; @@ -840,7 +840,7 @@ Mask *BKE_mask_copy_nolib(Mask *mask) return mask_new; } -Mask *BKE_mask_copy(Main *bmain, Mask *mask) +Mask *BKE_mask_copy(Main *bmain, const Mask *mask) { Mask *mask_new; @@ -851,7 +851,7 @@ Mask *BKE_mask_copy(Main *bmain, Mask *mask) BKE_mask_layer_copy_list(&mask_new->masklayers, &mask->masklayers); /* enable fake user by default */ - id_fake_user_set(&mask->id); + id_fake_user_set(&mask_new->id); BKE_id_copy_ensure_local(bmain, &mask->id, &mask_new->id); @@ -906,7 +906,7 @@ void BKE_mask_spline_free_list(ListBase *splines) } } -static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot_point) +static MaskSplinePoint *mask_spline_points_copy(const MaskSplinePoint *points, int tot_point) { MaskSplinePoint *npoints; int i; @@ -923,7 +923,7 @@ static MaskSplinePoint *mask_spline_points_copy(MaskSplinePoint *points, int tot return npoints; } -MaskSpline *BKE_mask_spline_copy(MaskSpline *spline) +MaskSpline *BKE_mask_spline_copy(const MaskSpline *spline) { MaskSpline *nspline = MEM_callocN(sizeof(MaskSpline), "new spline"); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 54945242fe4..f21efb71180 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -220,7 +220,7 @@ Material *BKE_material_add(Main *bmain, const char *name) } /* XXX keep synced with next function */ -Material *BKE_material_copy(Main *bmain, Material *ma) +Material *BKE_material_copy(Main *bmain, const Material *ma) { Material *man; int a; diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 97033a9555d..b80579014d6 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -103,7 +103,7 @@ MetaBall *BKE_mball_add(Main *bmain, const char *name) return mb; } -MetaBall *BKE_mball_copy(Main *bmain, MetaBall *mb) +MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb) { MetaBall *mbn; int a; diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 5c0b09f0ff0..76965176be8 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -316,12 +316,12 @@ static float densfunc(const MetaElem *ball, float x, float y, float z) if (dvec[2] > ball->expz) dvec[2] -= ball->expz; else if (dvec[2] < -ball->expz) dvec[2] += ball->expz; else dvec[2] = 0.0; - /* fall through */ + ATTR_FALLTHROUGH; case MB_PLANE: if (dvec[1] > ball->expy) dvec[1] -= ball->expy; else if (dvec[1] < -ball->expy) dvec[1] += ball->expy; else dvec[1] = 0.0; - /* fall through */ + ATTR_FALLTHROUGH; case MB_TUBE: if (dvec[0] > ball->expx) dvec[0] -= ball->expx; else if (dvec[0] < -ball->expx) dvec[0] += ball->expx; @@ -660,7 +660,7 @@ static void makecubetable(void) for (i = 0; i < 256; i++) { for (e = 0; e < 12; e++) done[e] = 0; for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c); - for (e = 0; e < 12; e++) + for (e = 0; e < 12; e++) { if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) { INTLIST *ints = NULL; INTLISTS *lists = MEM_callocN(sizeof(INTLISTS), "mball_intlist"); @@ -687,6 +687,7 @@ static void makecubetable(void) lists->next = cubetable[i]; cubetable[i] = lists; } + } } for (i = 0; i < 256; i++) { @@ -1193,10 +1194,10 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen break; case MB_CUBE: /* cube is "expanded" by expz, expy and expx */ expz += ml->expz; - /* fall through */ + ATTR_FALLTHROUGH; case MB_PLANE: /* plane is "expanded" by expy and expx */ expy += ml->expy; - /* fall through */ + ATTR_FALLTHROUGH; case MB_TUBE: /* tube is "expanded" by expx */ expx += ml->expx; break; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index c12890a354e..6233caa43fa 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -501,7 +501,7 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name) return me; } -Mesh *BKE_mesh_copy(Main *bmain, Mesh *me) +Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me) { Mesh *men; int a; @@ -1339,7 +1339,7 @@ int BKE_mesh_nurbs_displist_to_mdata( /* this may fail replacing ob->data, be sure to check ob->type */ -void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv) +void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use_orco_uv, const char *obdata_name) { Main *bmain = G.main; Object *ob1; @@ -1366,7 +1366,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use } /* make mesh */ - me = BKE_mesh_add(bmain, "Mesh"); + me = BKE_mesh_add(bmain, obdata_name); me->totvert = totvert; me->totedge = totedge; me->totloop = totloop; @@ -1386,7 +1386,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use BKE_mesh_calc_normals(me); } else { - me = BKE_mesh_add(bmain, "Mesh"); + me = BKE_mesh_add(bmain, obdata_name); DM_to_mesh(dm, me, ob, CD_MASK_MESH, false); } @@ -1398,9 +1398,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use cu->mat = NULL; cu->totcol = 0; - if (ob->data) { - BKE_libblock_free(bmain, ob->data); - } + /* Do not decrement ob->data usercount here, it's done at end of func with BKE_libblock_free_us() call. */ ob->data = me; ob->type = OB_MESH; @@ -1410,11 +1408,14 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use if (ob1->data == cu) { ob1->type = OB_MESH; + id_us_min((ID *)ob1->data); ob1->data = ob->data; - id_us_plus((ID *)ob->data); + id_us_plus((ID *)ob1->data); } ob1 = ob1->id.next; } + + BKE_libblock_free_us(bmain, cu); } void BKE_mesh_from_nurbs(Object *ob) @@ -1427,7 +1428,7 @@ void BKE_mesh_from_nurbs(Object *ob) disp = ob->curve_cache->disp; } - BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv); + BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv, cu->id.name); } typedef struct EdgeLink { @@ -2486,7 +2487,7 @@ Mesh *BKE_mesh_new_from_object( /* convert object type to mesh */ uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0; - BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco); + BKE_mesh_from_nurbs_displist(tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2); tmpmesh = tmpobj->data; @@ -2522,7 +2523,7 @@ Mesh *BKE_mesh_new_from_object( if (ob != basis_ob) return NULL; /* only do basis metaball */ - tmpmesh = BKE_mesh_add(bmain, "Mesh"); + tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2); /* BKE_mesh_add gives us a user count we don't need */ id_us_min(&tmpmesh->id); @@ -2577,7 +2578,7 @@ Mesh *BKE_mesh_new_from_object( else dm = mesh_create_derived_view(sce, ob, mask); - tmpmesh = BKE_mesh_add(bmain, "Mesh"); + tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2); DM_to_mesh(dm, tmpmesh, ob, mask, true); /* Copy autosmooth settings from original mesh. */ diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 0d0055113b7..5dfcef9f9bf 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -1026,7 +1026,7 @@ static bool loop_split_generator_check_cyclic_smooth_fan( BLI_assert(!BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)); BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index); - while(true) { + while (true) { /* Find next loop of the smooth fan. */ loop_manifold_fan_around_vert_next( mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index, @@ -1629,8 +1629,8 @@ void BKE_mesh_normals_loop_custom_from_vertices_set( /** * Computes average per-vertex normals from given custom loop normals. * - * @param clnors The computed custom loop normals. - * @param r_vert_clnors The (already allocated) array where to store averaged per-vertex normals. + * \param clnors: The computed custom loop normals. + * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals. */ void BKE_mesh_normals_loop_to_vertex( const int numVerts, const MLoop *mloops, const int numLoops, @@ -1993,36 +1993,54 @@ float BKE_mesh_calc_poly_area( } } -/* note, results won't be correct if polygon is non-planar */ -static float mesh_calc_poly_planar_area_centroid( +/** + * Calculate the volume and volume-weighted centroid of the volume formed by the polygon and the origin. + * Results will be negative if the origin is "outside" the polygon + * (+ve normal side), but the polygon may be non-planar with no effect. + * + * Method from: + * - http://forums.cgsociety.org/archive/index.php?t-756235.html + * - http://www.globalspec.com/reference/52702/203279/4-8-the-centroid-of-a-tetrahedron + * + * \note volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid + * (so division can be done once at the end) + * \note results will have bias if polygon is non-planar. + */ +static float mesh_calc_poly_volume_and_weighted_centroid( const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray, float r_cent[3]) { - int i; - float tri_area; - float total_area = 0.0f; - float v1[3], v2[3], v3[3], normal[3], tri_cent[3]; + const float *v_pivot, *v_step1; + float total_volume = 0.0f; - BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, normal); - copy_v3_v3(v1, mvarray[loopstart[0].v].co); - copy_v3_v3(v2, mvarray[loopstart[1].v].co); zero_v3(r_cent); - for (i = 2; i < mpoly->totloop; i++) { - copy_v3_v3(v3, mvarray[loopstart[i].v].co); + v_pivot = mvarray[loopstart[0].v].co; + v_step1 = mvarray[loopstart[1].v].co; - tri_area = area_tri_signed_v3(v1, v2, v3, normal); - total_area += tri_area; + for (int i = 2; i < mpoly->totloop; i++) { + const float *v_step2 = mvarray[loopstart[i].v].co; - mid_v3_v3v3v3(tri_cent, v1, v2, v3); - madd_v3_v3fl(r_cent, tri_cent, tri_area); + /* Calculate the 6x volume of the tetrahedron formed by the 3 vertices + * of the triangle and the origin as the fourth vertex */ + float v_cross[3]; + cross_v3_v3v3(v_cross, v_pivot, v_step1); + const float tetra_volume = dot_v3v3 (v_cross, v_step2); + total_volume += tetra_volume; - copy_v3_v3(v2, v3); - } + /* Calculate the centroid of the tetrahedron formed by the 3 vertices + * of the triangle and the origin as the fourth vertex. + * The centroid is simply the average of the 4 vertices. + * + * Note that the vector is 4x the actual centroid so the division can be done once at the end. */ + for (uint j = 0; j < 3; j++) { + r_cent[j] += tetra_volume * (v_pivot[j] + v_step1[j] + v_step2[j]); + } - mul_v3_fl(r_cent, 1.0f / total_area); + v_step1 = v_step2; + } - return total_area; + return total_volume; } #if 0 /* slow version of the function below */ @@ -2143,25 +2161,28 @@ bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3]) { int i = me->totpoly; MPoly *mpoly; - float poly_area; - float total_area = 0.0f; + float poly_volume; + float total_volume = 0.0f; float poly_cent[3]; zero_v3(r_cent); - /* calculate a weighted average of polygon centroids */ + /* calculate a weighted average of polyhedron centroids */ for (mpoly = me->mpoly; i--; mpoly++) { - poly_area = mesh_calc_poly_planar_area_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent); + poly_volume = mesh_calc_poly_volume_and_weighted_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent); - madd_v3_v3fl(r_cent, poly_cent, poly_area); - total_area += poly_area; + /* poly_cent is already volume-weighted, so no need to multiply by the volume */ + add_v3_v3(r_cent, poly_cent); + total_volume += poly_volume; } /* otherwise we get NAN for 0 polys */ - if (me->totpoly) { - mul_v3_fl(r_cent, 1.0f / total_area); + if (total_volume != 0.0f) { + /* multipy by 0.25 to get the correct centroid */ + /* no need to divide volume by 6 as the centroid is weighted by 6x the volume, so it all cancels out */ + mul_v3_fl(r_cent, 0.25f / total_volume); } - /* zero area faces cause this, fallback to median */ + /* this can happen for non-manifold objects, fallback to median */ if (UNLIKELY(!is_finite_v3(r_cent))) { return BKE_mesh_center_median(me, r_cent); } diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index 8562988b5e1..525c0c9728e 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -165,7 +165,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create( vmap->vert[a] = newvlist; } - if (use_winding) { + if (use_winding) { MEM_freeN(winding); } diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index ba890b005d8..4aeddbb4c45 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -584,8 +584,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, int prev_e = ml->e; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2)); fix_flag.loops_edge = true; - PRINT_ERR("\tPoly %u has invalid edge reference (%d), fixed using edge %u\n", - sp->index, prev_e, ml->e); + PRINT_ERR("\tPoly %u has invalid edge reference (%d, is_removed: %d), fixed using edge %u\n", + sp->index, prev_e, IS_REMOVED_EDGE(me), ml->e); } else { PRINT_ERR("\tPoly %u has invalid edge reference (%u)\n", sp->index, ml->e); diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 6794a8e8f93..dfa8742a295 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1488,7 +1488,7 @@ void BKE_movieclip_free(MovieClip *clip) BKE_animdata_free((ID *) clip, false); } -MovieClip *BKE_movieclip_copy(Main *bmain, MovieClip *clip) +MovieClip *BKE_movieclip_copy(Main *bmain, const MovieClip *clip) { MovieClip *clip_new; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 3f3b4896653..5acfe4a0aa4 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -921,7 +921,7 @@ static void node_socket_copy(bNodeSocket *dst, bNodeSocket *src) /* keep socket listorder identical, for copying links */ /* ntree is the target tree */ -bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) +bNode *nodeCopyNode(bNodeTree *ntree, bNode *node) { bNode *nnode = MEM_callocN(sizeof(bNode), "dupli node"); bNodeSocket *sock, *oldsock; @@ -1200,7 +1200,9 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) * copying for internal use (threads for eg), where you wont want it to modify the * scene data. */ -static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool skip_database, bool do_id_user, bool do_make_extern, bool copy_previews) +static bNodeTree *ntreeCopyTree_internal( + const bNodeTree *ntree, Main *bmain, + bool skip_database, bool do_id_user, bool do_make_extern, bool copy_previews) { bNodeTree *newtree; bNode *node /*, *nnode */ /* UNUSED */, *last; @@ -1299,11 +1301,11 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool ski return newtree; } -bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, Main *bmain, const bool do_id_user) +bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user) { return ntreeCopyTree_internal(ntree, bmain, false, do_id_user, true, true); } -bNodeTree *ntreeCopyTree(Main *bmain, bNodeTree *ntree) +bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree) { return ntreeCopyTree_ex(ntree, bmain, true); } @@ -1698,11 +1700,12 @@ static void node_free_node_ex(bNodeTree *ntree, bNode *node, bool remove_animdat ntreeTexEndExecTree(ntree->execdata); ntree->execdata = NULL; } - - if (node->typeinfo->freefunc) - node->typeinfo->freefunc(node); } - + + if (node->typeinfo->freefunc) { + node->typeinfo->freefunc(node); + } + for (sock = node->inputs.first; sock; sock = nextsock) { nextsock = sock->next; node_socket_free(ntree, sock, node); @@ -1828,7 +1831,7 @@ void ntreeFreeTree(bNodeTree *ntree) if (tntree == ntree) break; if (tntree == NULL) { - BKE_libblock_free_data(G.main, &ntree->id); + BKE_libblock_free_data(&ntree->id, true); } } @@ -3172,12 +3175,20 @@ void nodeSynchronizeID(bNode *node, bool copy_to_id) void nodeLabel(bNodeTree *ntree, bNode *node, char *label, int maxlen) { - if (node->label[0] != '\0') + if (node->label[0] != '\0') { BLI_strncpy(label, node->label, maxlen); - else if (node->typeinfo->labelfunc) + } + else if (node->typeinfo->labelfunc) { node->typeinfo->labelfunc(ntree, node, label, maxlen); - else - BLI_strncpy(label, IFACE_(node->typeinfo->ui_name), maxlen); + } + else { + /* Kind of hacky and weak... Ideally would be better to use RNA here. :| */ + const char *tmp = CTX_IFACE_(BLT_I18NCONTEXT_ID_NODETREE, node->typeinfo->ui_name); + if (tmp == node->typeinfo->ui_name) { + tmp = IFACE_(node->typeinfo->ui_name); + } + BLI_strncpy(label, tmp, maxlen); + } } static void node_type_base_defaults(bNodeType *ntype) @@ -3568,6 +3579,7 @@ static void registerShaderNodes(void) register_node_type_sh_background(); register_node_type_sh_bsdf_anisotropic(); register_node_type_sh_bsdf_diffuse(); + register_node_type_sh_bsdf_principled(); register_node_type_sh_bsdf_glossy(); register_node_type_sh_bsdf_glass(); register_node_type_sh_bsdf_translucent(); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6e754755cf3..f3086396c3a 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -127,6 +127,7 @@ #endif #include "CCGSubSurf.h" +#include "atomic_ops.h" #include "GPU_material.h" @@ -319,19 +320,24 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr /* free data derived from mesh, called when mesh changes or is freed */ void BKE_object_free_derived_caches(Object *ob) { - /* also serves as signal to remake texspace */ + /* Also serves as signal to remake texspace. + * + * NOTE: This function can be called from threads on different objects + * sharing same data datablock. So we need to ensure atomic nature of + * data modification here. + */ if (ob->type == OB_MESH) { Mesh *me = ob->data; if (me && me->bb) { - me->bb->flag |= BOUNDBOX_DIRTY; + atomic_fetch_and_or_uint32((uint*)&me->bb->flag, BOUNDBOX_DIRTY); } } else if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { Curve *cu = ob->data; if (cu && cu->bb) { - cu->bb->flag |= BOUNDBOX_DIRTY; + atomic_fetch_and_or_uint32((uint*)&cu->bb->flag, BOUNDBOX_DIRTY); } } @@ -876,7 +882,7 @@ SoftBody *copy_softbody(const SoftBody *sb, bool copy_caches) return sbn; } -BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb) +BulletSoftBody *copy_bulletsoftbody(const BulletSoftBody *bsb) { BulletSoftBody *bsbn; @@ -1008,7 +1014,7 @@ void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src) } } -static void copy_object_pose(Object *obn, Object *ob) +static void copy_object_pose(Object *obn, const Object *ob) { bPoseChannel *chan; @@ -1041,7 +1047,7 @@ static void copy_object_pose(Object *obn, Object *ob) } } -static void copy_object_lod(Object *obn, Object *ob) +static void copy_object_lod(Object *obn, const Object *ob) { BLI_duplicatelist(&obn->lodlevels, &ob->lodlevels); @@ -1092,7 +1098,7 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src) copy_v3_v3(ob_tar->size, ob_src->size); } -Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) +Object *BKE_object_copy_ex(Main *bmain, const Object *ob, bool copy_caches) { Object *obn; ModifierData *md; @@ -1139,6 +1145,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) /* increase user numbers */ id_us_plus((ID *)obn->data); + id_us_plus((ID *)obn->poselib); id_us_plus((ID *)obn->gpd); id_us_plus((ID *)obn->dup_group); @@ -1180,7 +1187,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) } /* copy objects, will re-initialize cached simulation data */ -Object *BKE_object_copy(Main *bmain, Object *ob) +Object *BKE_object_copy(Main *bmain, const Object *ob) { return BKE_object_copy_ex(bmain, ob, false); } diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index e3b801b3193..076bef71875 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -64,6 +64,7 @@ #include "BLI_strict_flags.h" +#include "BLI_hash.h" /* Dupli-Geometry */ @@ -180,6 +181,23 @@ static DupliObject *make_dupli(const DupliContext *ctx, if (ob->type == OB_MBALL) dob->no_draw = true; + /* random number */ + /* the logic here is designed to match Cycles */ + dob->random_id = BLI_hash_string(dob->ob->id.name + 2); + + if (dob->persistent_id[0] != INT_MAX) { + for (i = 0; i < MAX_DUPLI_RECUR * 2; i++) { + dob->random_id = BLI_hash_int_2d(dob->random_id, (unsigned int)dob->persistent_id[i]); + } + } + else { + dob->random_id = BLI_hash_int_2d(dob->random_id, 0); + } + + if (ctx->object != ob) { + dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2)); + } + return dob; } @@ -529,10 +547,15 @@ static void make_duplis_verts(const DupliContext *ctx) BMEditMesh *em = BKE_editmesh_from_object(parent); CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH); - if (em) + if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) { + vdd.dm = mesh_create_derived_render(scene, parent, dm_mask); + } + else if (em) { vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); - else + } + else { vdd.dm = mesh_get_derived_final(scene, parent, dm_mask); + } vdd.edit_btmesh = me->edit_btmesh; if (use_texcoords) @@ -792,10 +815,15 @@ static void make_duplis_faces(const DupliContext *ctx) BMEditMesh *em = BKE_editmesh_from_object(parent); CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); - if (em) + if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) { + fdd.dm = mesh_create_derived_render(scene, parent, dm_mask); + } + else if (em) { fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); - else + } + else { fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); + } if (use_texcoords) { CustomData *ml_data = fdd.dm->getLoopDataLayout(fdd.dm); diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index a531466294e..e03af585cf2 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -145,18 +145,6 @@ void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob) else ob->transflag &= ~OB_NEG_SCALE; } -void BKE_object_eval_modifier(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob, - struct ModifierData *md) -{ - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); - (void) eval_ctx; /* Ignored. */ - (void) scene; /* Ignored. */ - (void) ob; /* Ignored. */ - (void) md; /* Ignored. */ -} - void BKE_object_handle_data_update(EvaluationContext *eval_ctx, Scene *scene, Object *ob) diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 621ac9c2480..537c8926a5b 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -334,10 +334,10 @@ void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float i1 = i1 % oc->_M; j1 = j1 % oc->_N; - #define BILERP(m) (interpf(interpf(m[i1 * oc->_N + j1], m[i0 * oc->_N + j1], frac_x), \ interpf(m[i1 * oc->_N + j0], m[i0 * oc->_N + j0], frac_x), \ frac_z)) + { if (oc->_do_disp_y) { ocr->disp[1] = BILERP(oc->_disp_y); diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 489fc2f3710..64f90ef5c52 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -450,7 +450,7 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na break; } /* else create it */ - /* fall-through */ + ATTR_FALLTHROUGH; } case PF_WRITE_LOCAL: if (writePackedFile(reports, local_name, pf, 1) == RET_OK) { @@ -471,7 +471,7 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na break; } /* else create it */ - /* fall-through */ + ATTR_FALLTHROUGH; } case PF_WRITE_ORIGINAL: if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) { diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 6b954f060d3..c7cfe55f659 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -314,7 +314,7 @@ PaintCurve *BKE_paint_curve_add(Main *bmain, const char *name) return pc; } -PaintCurve *BKE_paint_curve_copy(Main *bmain, PaintCurve *pc) +PaintCurve *BKE_paint_curve_copy(Main *bmain, const PaintCurve *pc) { PaintCurve *pc_new; @@ -396,7 +396,7 @@ Palette *BKE_palette_add(Main *bmain, const char *name) return palette; } -Palette *BKE_palette_copy(Main *bmain, Palette *palette) +Palette *BKE_palette_copy(Main *bmain, const Palette *palette) { Palette *palette_new; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 228ae6afaba..416d63cfefb 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -253,11 +253,16 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData if (psys_in_edit_mode(sim->scene, sim->psys) == 0) { Object *lattice = NULL; ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys); + int mode = G.is_rendering ? eModifierMode_Render : eModifierMode_Realtime; for (; md; md = md->next) { if (md->type == eModifierType_Lattice) { - LatticeModifierData *lmd = (LatticeModifierData *)md; - lattice = lmd->object; + if (md->mode & mode) { + LatticeModifierData *lmd = (LatticeModifierData *)md; + lattice = lmd->object; + sim->psys->lattice_strength = lmd->strength; + } + break; } } @@ -590,7 +595,7 @@ void psys_free(Object *ob, ParticleSystem *psys) BLI_bvhtree_free(psys->bvhtree); BLI_kdtree_free(psys->tree); - + if (psys->fluid_springs) MEM_freeN(psys->fluid_springs); @@ -2706,7 +2711,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re /* lattices have to be calculated separately to avoid mixups between effector calculations */ if (psys->lattice_deform_data) { for (k = 0, ca = cache[p]; k <= segments; k++, ca++) - calc_latt_deform(psys->lattice_deform_data, ca->co, 1.0f); + calc_latt_deform(psys->lattice_deform_data, ca->co, psys->lattice_strength); } } @@ -3326,7 +3331,7 @@ void BKE_particlesettings_rough_curve_init(ParticleSettings *part) part->roughcurve = cumap; } -ParticleSettings *BKE_particlesettings_copy(Main *bmain, ParticleSettings *part) +ParticleSettings *BKE_particlesettings_copy(Main *bmain, const ParticleSettings *part) { ParticleSettings *partn; int a; @@ -3369,7 +3374,8 @@ void BKE_particlesettings_make_local(Main *bmain, ParticleSettings *part, const /* Textures */ /************************************************/ -static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, const float fuv[4], char *name, float *texco) +static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int index, const float fuv[4], + char *name, float *texco, bool from_vert) { MFace *mf; MTFace *tf; @@ -3385,11 +3391,15 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co if (pa) { i = ELEM(pa->num_dmcache, DMCACHE_NOTFOUND, DMCACHE_ISCHILD) ? pa->num : pa->num_dmcache; - if (i >= dm->getNumTessFaces(dm)) + if ((!from_vert && i >= dm->getNumTessFaces(dm)) || + (from_vert && i >= dm->getNumVerts(dm))) + { i = -1; + } + } + else { + i = index; } - else - i = face_index; if (i == -1) { texco[0] = 0.0f; @@ -3397,7 +3407,22 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co texco[2] = 0.0f; } else { - mf = dm->getTessFaceData(dm, i, CD_MFACE); + if (from_vert) { + mf = dm->getTessFaceDataArray(dm, CD_MFACE); + + /* This finds the first face to contain the emitting vertex, + * this is not ideal, but is mostly fine as UV seams generally + * map to equal-colored parts of a texture */ + for (int j = 0; j < dm->getNumTessFaces(dm); j++, mf++) { + if (ELEM(i, mf->v1, mf->v2, mf->v3, mf->v4)) { + i = j; + break; + } + } + } + else { + mf = dm->getTessFaceData(dm, i, CD_MFACE); + } psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco); @@ -3464,9 +3489,13 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti mul_m4_v3(mtex->object->imat, texvec); break; case TEXCO_UV: - if (fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec)) + if (fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, + texvec, (part->from == PART_FROM_VERT))) + { break; - /* no break, failed to get uv's, so let's try orco's */ + } + /* no break, failed to get uv's, so let's try orco's */ + ATTR_FALLTHROUGH; case TEXCO_ORCO: copy_v3_v3(texvec, orco); break; @@ -3536,9 +3565,13 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex mul_m4_v3(mtex->object->imat, texvec); break; case TEXCO_UV: - if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, texvec)) + if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, + texvec, (part->from == PART_FROM_VERT))) + { break; - /* no break, failed to get uv's, so let's try orco's */ + } + /* no break, failed to get uv's, so let's try orco's */ + ATTR_FALLTHROUGH; case TEXCO_ORCO: psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, 0, 0, 0, texvec, 0); @@ -3746,7 +3779,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * } if (psys->lattice_deform_data && edit == 0) - calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f); + calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength); } } } @@ -3985,7 +4018,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta do_child_modifiers(NULL, sim, NULL, key1->co, key1->vel, key1->rot, par_orco, cpa, cpa->fuv, mat, state, t); if (psys->lattice_deform_data) - calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f); + calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength); } else { if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) @@ -4044,7 +4077,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta } if (sim->psys->lattice_deform_data) - calc_latt_deform(sim->psys->lattice_deform_data, state->co, 1.0f); + calc_latt_deform(sim->psys->lattice_deform_data, state->co, psys->lattice_strength); } return 1; @@ -4291,7 +4324,7 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) hkey = pa->hair; for (h = 0; h < pa->totkey; h++, hkey++) { mul_m4_v3(hairmat, hkey->co); - calc_latt_deform(psys->lattice_deform_data, hkey->co, 1.0f); + calc_latt_deform(psys->lattice_deform_data, hkey->co, psys->lattice_strength); mul_m4_v3(imat, hkey->co); } } diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index 842de869291..bfcda89a635 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -355,9 +355,13 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod { const float step_length = 1.0f / (float)(totkeys - 1); - float cur_length = 0.0f; - + + if (max_length <= 0.0f) { + keys->segments = -1; + totkeys = 0; + } + /* we have to correct velocity because of kink & clump */ for (k = 0, key = keys; k < totkeys; ++k, ++key) { if (k >= 2) { diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 44cf5b119c1..4f758bde7f9 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -427,12 +427,38 @@ static int distribute_binary_search(float *sum, int n, float value) static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p) { ParticleThreadContext *ctx= thread->ctx; - int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ + MFace *mface; + + DM_ensure_tessface(ctx->dm); + mface = ctx->dm->getTessFaceDataArray(ctx->dm, CD_MFACE); + + int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ /* TODO_PARTICLE - use original index */ - pa->num= ctx->index[p]; - pa->fuv[0] = 1.0f; - pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; + pa->num = ctx->index[p]; + + zero_v4(pa->fuv); + + if (pa->num != DMCACHE_NOTFOUND && pa->num < ctx->dm->getNumVerts(ctx->dm)) { + + /* This finds the first face to contain the emitting vertex, + * this is not ideal, but is mostly fine as UV seams generally + * map to equal-colored parts of a texture */ + for (int i = 0; i < ctx->dm->getNumTessFaces(ctx->dm); i++, mface++) { + if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) { + unsigned int *vert = &mface->v1; + + for (int j = 0; j < 4; j++, vert++) { + if (*vert == pa->num) { + pa->fuv[j] = 1.0f; + break; + } + } + + break; + } + } + } #if ONLY_WORKING_WITH_PA_VERTS if (ctx->tree) { @@ -1092,7 +1118,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti /* For hair, sort by origindex (allows optimization's in rendering), */ /* however with virtual parents the children need to be in random order. */ - if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) { + if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents != 0.0f)) { int *orig_index = NULL; if (from == PART_FROM_VERT) { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 943dc781246..b61f6792c89 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1000,7 +1000,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, part=psys->part; /* get precise emitter matrix if particle is born */ - if (part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) { + if (part->type != PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) { evaluate_emitter_anim(sim->scene, sim->ob, pa->time); psys->flag |= PSYS_OB_ANIM_RESTORE; @@ -1183,7 +1183,7 @@ static void set_keyed_keys(ParticleSimulationData *sim) key->time = pa->time; } - if (psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f) + if (psys->flag & PSYS_KEYED_TIMING && pt->duration != 0.0f) k++; ksim.psys->flag |= keyed_flag; @@ -4350,13 +4350,12 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, /* **** Depsgraph evaluation **** */ -void BKE_particle_system_eval(EvaluationContext *UNUSED(eval_ctx), - Scene *scene, - Object *ob, - ParticleSystem *psys) +void BKE_particle_system_eval_init(EvaluationContext *UNUSED(eval_ctx), + Scene *scene, + Object *ob) { if (G.debug & G_DEBUG_DEPSGRAPH) { - printf("%s on %s:%s\n", __func__, ob->id.name, psys->name); + printf("%s on %s\n", __func__, ob->id.name); } BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH); } diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 4fe4d6e75a6..53dfffe2b97 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -620,7 +620,7 @@ void BKE_pbvh_free(PBVH *bvh) if (node->flag & PBVH_Leaf) { if (node->draw_buffers) - GPU_free_pbvh_buffers(node->draw_buffers); + GPU_pbvh_buffers_free(node->draw_buffers); if (node->vert_indices) MEM_freeN((void *)node->vert_indices); if (node->face_vert_indices) @@ -635,7 +635,7 @@ void BKE_pbvh_free(PBVH *bvh) BLI_gset_free(node->bm_other_verts, NULL); } } - GPU_free_pbvh_buffer_multires(&bvh->grid_common_gpu_buffer); + GPU_pbvh_multires_buffers_free(&bvh->grid_common_gpu_buffer); if (bvh->deformed) { if (bvh->verts) { @@ -1090,11 +1090,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) PBVHNode *node = nodes[n]; if (node->flag & PBVH_RebuildDrawBuffers) { - GPU_free_pbvh_buffers(node->draw_buffers); + GPU_pbvh_buffers_free(node->draw_buffers); switch (bvh->type) { case PBVH_GRIDS: node->draw_buffers = - GPU_build_grid_pbvh_buffers(node->prim_indices, + GPU_pbvh_grid_buffers_build(node->prim_indices, node->totprim, bvh->grid_hidden, bvh->gridkey.grid_size, @@ -1102,7 +1102,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) break; case PBVH_FACES: node->draw_buffers = - GPU_build_mesh_pbvh_buffers(node->face_vert_indices, + GPU_pbvh_mesh_buffers_build(node->face_vert_indices, bvh->mpoly, bvh->mloop, bvh->looptri, bvh->verts, node->prim_indices, @@ -1110,42 +1110,44 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) break; case PBVH_BMESH: node->draw_buffers = - GPU_build_bmesh_pbvh_buffers(bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING); + GPU_pbvh_bmesh_buffers_build(bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING); break; } - + node->flag &= ~PBVH_RebuildDrawBuffers; } if (node->flag & PBVH_UpdateDrawBuffers) { switch (bvh->type) { case PBVH_GRIDS: - GPU_update_grid_pbvh_buffers(node->draw_buffers, - bvh->grids, - bvh->grid_flag_mats, - node->prim_indices, - node->totprim, - &bvh->gridkey, - bvh->show_diffuse_color); + GPU_pbvh_grid_buffers_update( + node->draw_buffers, + bvh->grids, + bvh->grid_flag_mats, + node->prim_indices, + node->totprim, + &bvh->gridkey, + bvh->show_diffuse_color); break; case PBVH_FACES: - GPU_update_mesh_pbvh_buffers(node->draw_buffers, - bvh->verts, - node->vert_indices, - node->uniq_verts + - node->face_verts, - CustomData_get_layer(bvh->vdata, - CD_PAINT_MASK), - node->face_vert_indices, - bvh->show_diffuse_color); + GPU_pbvh_mesh_buffers_update( + node->draw_buffers, + bvh->verts, + node->vert_indices, + node->uniq_verts + + node->face_verts, + CustomData_get_layer(bvh->vdata, CD_PAINT_MASK), + node->face_vert_indices, + bvh->show_diffuse_color); break; case PBVH_BMESH: - GPU_update_bmesh_pbvh_buffers(node->draw_buffers, - bvh->bm, - node->bm_faces, - node->bm_unique_verts, - node->bm_other_verts, - bvh->show_diffuse_color); + GPU_pbvh_bmesh_buffers_update( + node->draw_buffers, + bvh->bm, + node->bm_faces, + node->bm_unique_verts, + node->bm_other_verts, + bvh->show_diffuse_color); break; } @@ -1156,15 +1158,15 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) static void pbvh_draw_BB(PBVH *bvh) { - GPU_init_draw_pbvh_BB(); + GPU_pbvh_BB_draw_init(); for (int a = 0; a < bvh->totnode; a++) { PBVHNode *node = &bvh->nodes[a]; - GPU_draw_pbvh_BB(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0)); + GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0)); } - GPU_end_draw_pbvh_BB(); + GPU_pbvh_BB_draw_end(); } static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) @@ -1756,7 +1758,7 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v) #endif if (!(node->flag & PBVH_FullyHidden)) { - GPU_draw_pbvh_buffers(node->draw_buffers, + GPU_pbvh_buffers_draw(node->draw_buffers, data->setMaterial, data->wireframe, data->fast); diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index a821578db1a..c5e49883dc6 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -352,7 +352,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde n->layer_disp = NULL; if (n->draw_buffers) { - GPU_free_pbvh_buffers(n->draw_buffers); + GPU_pbvh_buffers_free(n->draw_buffers); n->draw_buffers = NULL; } n->flag &= ~PBVH_Leaf; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 30eb8dcb287..a7e00a8103a 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3618,9 +3618,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); } - if ((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) && - (render || bake)) - { + if (((cache->flag & PTCACHE_BAKED) == 0) && (render || bake)) { BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); } diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c index dc4063b42ed..b163f623d21 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -65,7 +65,7 @@ void BKE_bproperty_free_list(ListBase *lb) } } -bProperty *BKE_bproperty_copy(bProperty *prop) +bProperty *BKE_bproperty_copy(const bProperty *prop) { bProperty *propn; @@ -80,7 +80,7 @@ bProperty *BKE_bproperty_copy(bProperty *prop) return propn; } -void BKE_bproperty_copy_list(ListBase *lbn, ListBase *lbo) +void BKE_bproperty_copy_list(ListBase *lbn, const ListBase *lbo) { bProperty *prop, *propn; BKE_bproperty_free_list(lbn); /* in case we are copying to an object with props */ diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 5353cc26295..e8c0cf53d0b 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -184,7 +184,7 @@ void BKE_rigidbody_free_constraint(Object *ob) * be added to relevant groups later... */ -RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) +RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob) { RigidBodyOb *rboN = NULL; @@ -204,7 +204,7 @@ RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) return rboN; } -RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) +RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob) { RigidBodyCon *rbcN = NULL; @@ -822,7 +822,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z); RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint); - /* fall-through */ + ATTR_FALLTHROUGH; case RBC_TYPE_6DOF: if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */ rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2); @@ -1486,24 +1486,60 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) { RigidBodyOb *rbo = ob->rigidbody_object; + bool correct_delta = !(rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE); /* return rigid body and object to their initial states */ copy_v3_v3(rbo->pos, ob->loc); copy_v3_v3(ob->loc, loc); + if (correct_delta) { + add_v3_v3(rbo->pos, ob->dloc); + } + if (ob->rotmode > 0) { - eulO_to_quat(rbo->orn, ob->rot, ob->rotmode); + float qt[4]; + eulO_to_quat(qt, ob->rot, ob->rotmode); + + if (correct_delta) { + float dquat[4]; + eulO_to_quat(dquat, ob->drot, ob->rotmode); + + mul_qt_qtqt(rbo->orn, dquat, qt); + } + else { + copy_qt_qt(rbo->orn, qt); + } + copy_v3_v3(ob->rot, rot); } else if (ob->rotmode == ROT_MODE_AXISANGLE) { - axis_angle_to_quat(rbo->orn, ob->rotAxis, ob->rotAngle); + float qt[4]; + axis_angle_to_quat(qt, ob->rotAxis, ob->rotAngle); + + if (correct_delta) { + float dquat[4]; + axis_angle_to_quat(dquat, ob->drotAxis, ob->drotAngle); + + mul_qt_qtqt(rbo->orn, dquat, qt); + } + else { + copy_qt_qt(rbo->orn, qt); + } + copy_v3_v3(ob->rotAxis, rotAxis); ob->rotAngle = rotAngle; } else { - copy_qt_qt(rbo->orn, ob->quat); + if (correct_delta) { + mul_qt_qtqt(rbo->orn, ob->dquat, ob->quat); + } + else { + copy_qt_qt(rbo->orn, ob->quat); + } + copy_qt_qt(ob->quat, quat); } + if (rbo->physics_object) { /* allow passive objects to return to original transform */ if (rbo->type == RBO_TYPE_PASSIVE) @@ -1515,8 +1551,9 @@ void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], flo void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) { - if (rbw) + if (rbw) { rbw->pointcache->flag |= PTCACHE_OUTDATED; + } } /* ------------------ */ @@ -1563,12 +1600,8 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL); cache = rbw->pointcache; - if (ctime <= startframe) { - rbw->ltime = startframe; - return; - } /* make sure we don't go out of cache frame range */ - else if (ctime > endframe) { + if (ctime > endframe) { ctime = endframe; } @@ -1582,9 +1615,12 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) // RB_TODO deal with interpolated, old and baked results bool can_simulate = (ctime == rbw->ltime + 1) && !(cache->flag & PTCACHE_BAKED); + if (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0) { + rbw->ltime = cache->startframe; + } + if (BKE_ptcache_read(&pid, ctime, can_simulate)) { BKE_ptcache_validate(cache, (int)ctime); - rbw->ltime = ctime; return; } @@ -1622,8 +1658,8 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) # pragma GCC diagnostic ignored "-Wunused-parameter" #endif -struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; } -struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; } +struct RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob) { return NULL; } +struct RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob) { return NULL; } void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {} void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) { if (r_vol) *r_vol = 0.0f; } void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3]) { zero_v3(r_center); } diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 7920d8b5696..19d646daf9f 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -87,7 +87,7 @@ bSensor *copy_sensor(bSensor *sens) return sensn; } -void copy_sensors(ListBase *lbn, ListBase *lbo) +void copy_sensors(ListBase *lbn, const ListBase *lbo) { bSensor *sens, *sensn; @@ -251,7 +251,7 @@ bController *copy_controller(bController *cont) return contn; } -void copy_controllers(ListBase *lbn, ListBase *lbo) +void copy_controllers(ListBase *lbn, const ListBase *lbo) { bController *cont, *contn; @@ -389,7 +389,7 @@ bActuator *copy_actuator(bActuator *act) return actn; } -void copy_actuators(ListBase *lbn, ListBase *lbo) +void copy_actuators(ListBase *lbn, const ListBase *lbo) { bActuator *act, *actn; @@ -783,7 +783,7 @@ void BKE_sca_logic_links_remap(Main *bmain, Object *ob_old, Object *ob_new) * Handle the copying of logic data into a new object, including internal logic links update. * External links (links between logic bricks of different objects) must be handled separately. */ -void BKE_sca_logic_copy(Object *ob_new, Object *ob) +void BKE_sca_logic_copy(Object *ob_new, const Object *ob) { copy_sensors(&ob_new->sensors, &ob->sensors); copy_controllers(&ob_new->controllers, &ob->controllers); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 906fa0134a0..a15f270a3ee 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -188,7 +188,9 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) scen = BKE_libblock_copy(bmain, &sce->id); BLI_duplicatelist(&(scen->base), &(sce->base)); - id_us_plus((ID *)scen->world); + if (type != SCE_COPY_FULL) { + id_us_plus((ID *)scen->world); + } id_us_plus((ID *)scen->set); /* id_us_plus((ID *)scen->gm.dome.warptext); */ /* XXX Not refcounted? see readfile.c */ @@ -233,11 +235,15 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) /* copy Freestyle settings */ new_srl = scen->r.layers.first; for (srl = sce->r.layers.first; srl; srl = srl->next) { + if (new_srl->prop != NULL) { + new_srl->prop = IDP_CopyProperty(new_srl->prop); + } BKE_freestyle_config_copy(&new_srl->freestyleConfig, &srl->freestyleConfig); if (type == SCE_COPY_FULL) { for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { if (lineset->linestyle) { - id_us_plus((ID *)lineset->linestyle); + /* Has been incremented by BKE_freestyle_config_copy(). */ + id_us_min(&lineset->linestyle->id); lineset->linestyle = BKE_linestyle_copy(bmain, lineset->linestyle); } } @@ -282,11 +288,19 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) ts->sculpt = MEM_dupallocN(ts->sculpt); BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint); } + if (ts->uvsculpt) { + ts->uvsculpt = MEM_dupallocN(ts->uvsculpt); + BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint); + } BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint); ts->imapaint.paintcursor = NULL; id_us_plus((ID *)ts->imapaint.stencil); + id_us_plus((ID *)ts->imapaint.clone); + id_us_plus((ID *)ts->imapaint.canvas); ts->particle.paintcursor = NULL; + ts->particle.scene = NULL; + ts->particle.object = NULL; /* duplicate Grease Pencil Drawing Brushes */ BLI_listbase_clear(&ts->gp_brushes); @@ -330,7 +344,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) /* world */ if (type == SCE_COPY_FULL) { if (scen->world) { - id_us_plus((ID *)scen->world); scen->world = BKE_world_copy(bmain, scen->world); BKE_animdata_copy_id_action((ID *)scen->world, false); } @@ -416,11 +429,15 @@ void BKE_scene_free(Scene *sce) MEM_freeN(sce->r.ffcodecdata.properties); sce->r.ffcodecdata.properties = NULL; } - + for (srl = sce->r.layers.first; srl; srl = srl->next) { + if (srl->prop != NULL) { + IDP_FreeProperty(srl->prop); + MEM_freeN(srl->prop); + } BKE_freestyle_config_free(&srl->freestyleConfig); } - + BLI_freelistN(&sce->markers); BLI_freelistN(&sce->transform_spaces); BLI_freelistN(&sce->r.layers); @@ -2063,6 +2080,11 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * BKE_freestyle_config_free(&srl->freestyleConfig); + if (srl->prop) { + IDP_FreeProperty(srl->prop); + MEM_freeN(srl->prop); + } + BLI_remlink(&scene->r.layers, srl); MEM_freeN(srl); @@ -2125,7 +2147,7 @@ bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv) int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render) { - if (r->mode & R_SIMPLIFY) { + if (r->mode & R_SIMPLIFY) { if (for_render) return min_ii(r->simplify_subsurf_render, lvl); else diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 298671beedb..e435d87024e 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -684,7 +684,7 @@ static float invGammaCorrect(float c) else if (i >= RE_GAMMA_TABLE_SIZE) res = powf(c, valid_inv_gamma); else res = inv_gamma_range_table[i] + ((c - color_domain_table[i]) * inv_gamfactor_table[i]); - + return res; } diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 89c2f76c661..e2f74dbab3c 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -202,21 +202,22 @@ static void whiteBalance_apply_threaded(int width, int height, unsigned char *re for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { int pixel_index = (y * width + x) * 4; - float result[4], mask[3] = {1.0f, 1.0f, 1.0f}; + float rgba[4], result[4], mask[3] = {1.0f, 1.0f, 1.0f}; if (rect_float) { - copy_v3_v3(result, rect_float + pixel_index); + copy_v3_v3(rgba, rect_float + pixel_index); } else { - straight_uchar_to_premul_float(result, rect + pixel_index); + straight_uchar_to_premul_float(rgba, rect + pixel_index); } + copy_v4_v4(result, rgba); #if 0 mul_v3_v3(result, multiplier); #else /* similar to division without the clipping */ for (int i = 0; i < 3; i++) { - result[i] = 1.0f - powf(1.0f - result[i], multiplier[i]); + result[i] = 1.0f - powf(1.0f - rgba[i], multiplier[i]); } #endif @@ -227,9 +228,9 @@ static void whiteBalance_apply_threaded(int width, int height, unsigned char *re rgb_uchar_to_float(mask, mask_rect + pixel_index); } - result[0] = result[0] * (1.0f - mask[0]) + result[0] * mask[0]; - result[1] = result[1] * (1.0f - mask[1]) + result[1] * mask[1]; - result[2] = result[2] * (1.0f - mask[2]) + result[2] * mask[2]; + result[0] = rgba[0] * (1.0f - mask[0]) + result[0] * mask[0]; + result[1] = rgba[1] * (1.0f - mask[1]) + result[1] * mask[1]; + result[2] = rgba[2] * (1.0f - mask[2]) + result[2] * mask[2]; if (rect_float) { copy_v3_v3(rect_float + pixel_index, result); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 2de7cd49901..669f76cf90b 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1775,7 +1775,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c if (proxy->anim == NULL) { return NULL; } - + seq_open_anim_file(context->scene, seq, true); sanim = seq->anims.first; @@ -1783,7 +1783,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c return IMB_anim_absolute(proxy->anim, frameno, IMB_TC_NONE, IMB_PROXY_NONE); } - + if (seq_proxy_get_fname(ed, seq, cfra, render_size, name, context->view_id) == 0) { return NULL; } @@ -2082,7 +2082,7 @@ void BKE_sequencer_proxy_set(struct Sequence *seq, bool value) } } else { - seq->flag ^= SEQ_USE_PROXY; + seq->flag &= ~SEQ_USE_PROXY; } } @@ -4190,9 +4190,10 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha if (free_imbuf) { if (ibuf_change) { - if (seq->type == SEQ_TYPE_MOVIE) + if (seq->type == SEQ_TYPE_MOVIE) { BKE_sequence_free_anim(seq); - if (seq->type == SEQ_TYPE_SPEED) { + } + else if (seq->type == SEQ_TYPE_SPEED) { BKE_sequence_effect_speed_rebuild_map(scene, seq, true); } } @@ -5182,6 +5183,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ if (sound->playback_handle == NULL) { + BKE_libblock_free(bmain, sound); #if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 03cf33083da..600bc3f453d 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1856,19 +1856,21 @@ static void dfdx_spring(int ia, int ic, int op, float dir[3], float L, float len float m, delta_ij; int i, j; if (L < len) { - for (i=0;i<3;i++) + for (i=0;i<3;i++) { for (j=0;j<3;j++) { delta_ij = (i==j ? (1.0f): (0.0f)); m=factor*(dir[i]*dir[j] + (1-L/len)*(delta_ij - dir[i]*dir[j])); EIG_linear_solver_matrix_add(ia+i, op+ic+j, m); } + } } else { - for (i=0;i<3;i++) + for (i=0;i<3;i++) { for (j=0;j<3;j++) { m=factor*dir[i]*dir[j]; EIG_linear_solver_matrix_add(ia+i, op+ic+j, m); } + } } } @@ -2233,9 +2235,9 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow) { -/* rule we never alter free variables :bp->vec bp->pos in here ! - * this will ruin adaptive stepsize AKA heun! (BM) - */ + /* rule we never alter free variables :bp->vec bp->pos in here ! + * this will ruin adaptive stepsize AKA heun! (BM) + */ SoftBody *sb= ob->soft; /* is supposed to be there */ /*BodyPoint *bproot;*/ /* UNUSED */ ListBase *do_effector = NULL; diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c index ee6886e3fb2..d00e4b1a0d2 100644 --- a/source/blender/blenkernel/intern/speaker.c +++ b/source/blender/blenkernel/intern/speaker.c @@ -68,7 +68,7 @@ void *BKE_speaker_add(Main *bmain, const char *name) return spk; } -Speaker *BKE_speaker_copy(Main *bmain, Speaker *spk) +Speaker *BKE_speaker_copy(Main *bmain, const Speaker *spk) { Speaker *spkn; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 298790a9e9b..466bef7ff36 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -449,7 +449,7 @@ Text *BKE_text_load(Main *bmain, const char *file, const char *relpath) return BKE_text_load_ex(bmain, file, relpath, false); } -Text *BKE_text_copy(Main *bmain, Text *ta) +Text *BKE_text_copy(Main *bmain, const Text *ta) { Text *tan; TextLine *line, *tmp; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 60990c03b0e..1e0659d3d67 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -549,11 +549,11 @@ int colorband_element_remove(struct ColorBand *coba, int index) if (index < 0 || index >= coba->tot) return 0; + coba->tot--; for (a = index; a < coba->tot; a++) { coba->data[a] = coba->data[a + 1]; } if (coba->cur) coba->cur--; - coba->tot--; return 1; } @@ -846,7 +846,7 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot) /* ------------------------------------------------------------------------- */ -Tex *BKE_texture_copy(Main *bmain, Tex *tex) +Tex *BKE_texture_copy(Main *bmain, const Tex *tex) { Tex *texn; @@ -1263,7 +1263,7 @@ EnvMap *BKE_texture_envmap_add(void) /* ------------------------------------------------------------------------- */ -EnvMap *BKE_texture_envmap_copy(EnvMap *env) +EnvMap *BKE_texture_envmap_copy(const EnvMap *env) { EnvMap *envn; int a; @@ -1336,7 +1336,7 @@ PointDensity *BKE_texture_pointdensity_add(void) return pd; } -PointDensity *BKE_texture_pointdensity_copy(PointDensity *pd) +PointDensity *BKE_texture_pointdensity_copy(const PointDensity *pd) { PointDensity *pdn; @@ -1430,7 +1430,7 @@ OceanTex *BKE_texture_ocean_add(void) return ot; } -OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot) +OceanTex *BKE_texture_ocean_copy(const OceanTex *ot) { OceanTex *otn = MEM_dupallocN(ot); @@ -1519,3 +1519,33 @@ void BKE_texture_get_value( { BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management); } + +static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePool *pool) +{ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_TEX_IMAGE && node->id != NULL) { + Image *image = (Image *)node->id; + BKE_image_pool_acquire_ibuf(image, NULL, pool); + } + else if (node->type == NODE_GROUP && node->id != NULL) { + /* TODO(sergey): Do we need to control recursion here? */ + bNodeTree *nested_tree = (bNodeTree *)node->id; + texture_nodes_fetch_images_for_pool(nested_tree, pool); + } + } +} + +/* Make sure all images used by texture are loaded into pool. */ +void BKE_texture_fetch_images_for_pool(Tex *texture, struct ImagePool *pool) +{ + if (texture->nodetree != NULL) { + texture_nodes_fetch_images_for_pool(texture->nodetree, pool); + } + else { + if (texture->type == TEX_IMAGE) { + if (texture->ima != NULL) { + BKE_image_pool_acquire_ibuf(texture->ima, NULL, pool); + } + } + } +} diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 990d250b854..9120d384a16 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -190,7 +190,7 @@ void BKE_tracking_free(MovieTracking *tracking) } /* Copy the whole list of tracks. */ -static void tracking_tracks_copy(ListBase *tracks_dst, ListBase *tracks_src, GHash *tracks_mapping) +static void tracking_tracks_copy(ListBase *tracks_dst, const ListBase *tracks_src, GHash *tracks_mapping) { MovieTrackingTrack *track_dst, *track_src; @@ -210,7 +210,7 @@ static void tracking_tracks_copy(ListBase *tracks_dst, ListBase *tracks_src, GHa /* copy the whole list of plane tracks (need whole MovieTracking structures due to embedded pointers to tracks). * WARNING: implies tracking_[dst/src] and their tracks have already been copied. */ -static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, ListBase *plane_tracks_src, GHash *tracks_mapping) +static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, const ListBase *plane_tracks_src, GHash *tracks_mapping) { MovieTrackingPlaneTrack *plane_track_dst, *plane_track_src; @@ -232,7 +232,7 @@ static void tracking_plane_tracks_copy(ListBase *plane_tracks_dst, ListBase *pla /* Copy reconstruction structure. */ static void tracking_reconstruction_copy( - MovieTrackingReconstruction *reconstruction_dst, MovieTrackingReconstruction *reconstruction_src) + MovieTrackingReconstruction *reconstruction_dst, const MovieTrackingReconstruction *reconstruction_src) { *reconstruction_dst = *reconstruction_src; if (reconstruction_src->cameras) { @@ -242,14 +242,14 @@ static void tracking_reconstruction_copy( /* Copy stabilization structure. */ static void tracking_stabilization_copy( - MovieTrackingStabilization *stabilization_dst, MovieTrackingStabilization *stabilization_src) + MovieTrackingStabilization *stabilization_dst, const MovieTrackingStabilization *stabilization_src) { *stabilization_dst = *stabilization_src; } /* Copy tracking object. */ static void tracking_object_copy( - MovieTrackingObject *object_dst, MovieTrackingObject *object_src, GHash *tracks_mapping) + MovieTrackingObject *object_dst, const MovieTrackingObject *object_src, GHash *tracks_mapping) { *object_dst = *object_src; tracking_tracks_copy(&object_dst->tracks, &object_src->tracks, tracks_mapping); @@ -258,7 +258,7 @@ static void tracking_object_copy( } /* Copy list of tracking objects. */ -static void tracking_objects_copy(ListBase *objects_dst, ListBase *objects_src, GHash *tracks_mapping) +static void tracking_objects_copy(ListBase *objects_dst, const ListBase *objects_src, GHash *tracks_mapping) { MovieTrackingObject *object_dst, *object_src; @@ -272,7 +272,7 @@ static void tracking_objects_copy(ListBase *objects_dst, ListBase *objects_src, } /* Copy tracking structure content. */ -void BKE_tracking_copy(MovieTracking *tracking_dst, MovieTracking *tracking_src) +void BKE_tracking_copy(MovieTracking *tracking_dst, const MovieTracking *tracking_src) { GHash *tracks_mapping = BLI_ghash_ptr_new(__func__); @@ -974,8 +974,11 @@ static void track_mask_set_pixel_cb(int x, int x_end, int y, void *user_data) } static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height, - MovieTrackingMarker *marker, bGPDlayer *layer, - float *mask, int mask_width, int mask_height) + const float region_min[2], + bGPDlayer *layer, + float *mask, + int mask_width, + int mask_height) { bGPDframe *frame = layer->frames.first; TrackMaskSetPixelData data; @@ -994,8 +997,8 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height point = mask_points = MEM_callocN(2 * stroke->totpoints * sizeof(int), "track mask rasterization points"); for (int i = 0; i < stroke->totpoints; i++, point += 2) { - point[0] = (stroke_points[i].x - marker->search_min[0]) * frame_width; - point[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height; + point[0] = stroke_points[i].x * frame_width - region_min[0]; + point[1] = stroke_points[i].y * frame_height - region_min[1]; } /* TODO: add an option to control whether AA is enabled or not */ BLI_bitmap_draw_2d_poly_v2i_n( @@ -1010,26 +1013,42 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height } } -float *BKE_tracking_track_get_mask(int frame_width, int frame_height, - MovieTrackingTrack *track, MovieTrackingMarker *marker) +/* Region is in pixel space, relative to marker's center. */ +float *tracking_track_get_mask_for_region(int frame_width, int frame_height, + const float region_min[2], + const float region_max[2], + MovieTrackingTrack *track) { float *mask = NULL; bGPDlayer *layer = track_mask_gpencil_layer_get(track); - int mask_width, mask_height; - - mask_width = (marker->search_max[0] - marker->search_min[0]) * frame_width; - mask_height = (marker->search_max[1] - marker->search_min[1]) * frame_height; - - if (layer) { + if (layer != NULL) { + const int mask_width = region_max[0] - region_min[0]; + const int mask_height = region_max[1] - region_min[1]; mask = MEM_callocN(mask_width * mask_height * sizeof(float), "track mask"); - - track_mask_gpencil_layer_rasterize(frame_width, frame_height, marker, layer, - mask, mask_width, mask_height); + track_mask_gpencil_layer_rasterize(frame_width, frame_height, + region_min, + layer, + mask, + mask_width, mask_height); } - return mask; } +float *BKE_tracking_track_get_mask(int frame_width, int frame_height, + MovieTrackingTrack *track, + MovieTrackingMarker *marker) +{ + /* Convert normalized space marker's search area to pixel-space region. */ + const float region_min[2] = {marker->search_min[0] * frame_width, + marker->search_min[1] * frame_height}; + const float region_max[2] = {marker->search_max[0] * frame_width, + marker->search_max[1] * frame_height}; + return tracking_track_get_mask_for_region(frame_width, frame_height, + region_min, + region_max, + track); +} + float BKE_tracking_track_get_weight_for_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker) { FCurve *weight_fcurve; diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 3b56ea271d0..9475925cdda 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -36,8 +36,9 @@ #include "DNA_movieclip_types.h" #include "DNA_object_types.h" /* SELECT */ -#include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_threads.h" #include "BLI_math.h" #include "BKE_movieclip.h" @@ -76,6 +77,9 @@ typedef struct AutoTrackContext { int num_tracks; /* Number of tracks being tracked. */ AutoTrackOptions *options; /* Per-tracking track options. */ + /* Array of all tracks, indexed by track_index. */ + MovieTrackingTrack **tracks; + bool backwards; bool sequence; int first_frame; @@ -306,8 +310,15 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, BLI_spin_init(&context->spin_lock); + int num_total_tracks = BLI_listbase_count(tracksbase); + context->tracks = + MEM_callocN(sizeof(MovieTrackingTrack*) * num_total_tracks, + "auto track pointers"); + context->image_accessor = - tracking_image_accessor_new(context->clips, 1, user->framenr); + tracking_image_accessor_new(context->clips, 1, + context->tracks, num_total_tracks, + user->framenr); context->autotrack = libmv_autoTrackNew(context->image_accessor->libmv_accessor); @@ -361,6 +372,7 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, options->use_keyframe_match = track->pattern_match == TRACK_MATCH_KEYFRAME; } + context->tracks[track_index] = track; ++track_index; } @@ -565,6 +577,7 @@ void BKE_autotrack_context_free(AutoTrackContext *context) libmv_autoTrackDestroy(context->autotrack); tracking_image_accessor_destroy(context->image_accessor); MEM_freeN(context->options); + MEM_freeN(context->tracks); BLI_spin_end(&context->spin_lock); MEM_freeN(context); } diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index 3dfaa1ed77d..b8dfb217c16 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -203,7 +203,7 @@ static float get_animated_scaleinf(StabContext *ctx, int framenr) static void get_animated_target_pos(StabContext *ctx, int framenr, - float target_pos[2]) + float target_pos[2]) { target_pos[0] = fetch_from_fcurve(ctx->target_pos[0], framenr, diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 1c056cda68d..a95399562d5 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -875,8 +875,64 @@ static void accessor_release_image_callback(libmv_CacheKey cache_key) IMB_freeImBuf(ibuf); } +static libmv_CacheKey accessor_get_mask_for_track_callback( + libmv_FrameAccessorUserData* user_data, + int clip_index, + int frame, + int track_index, + const libmv_Region *region, + float **r_destination, + int *r_width, + int *r_height) +{ + /* Perform sanity checks first. */ + TrackingImageAccessor *accessor = (TrackingImageAccessor *) user_data; + BLI_assert(clip_index < accessor->num_clips); + BLI_assert(track_index < accessor->num_tracks); + MovieTrackingTrack *track = accessor->tracks[track_index]; + /* Early output, track does not use mask. */ + if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) == 0) { + return NULL; + } + MovieClip *clip = accessor->clips[clip_index]; + /* Construct fake user so we can access movie clip. */ + MovieClipUser user; + int scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame); + BKE_movieclip_user_set_frame(&user, scene_frame); + user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; + user.render_flag = 0; + /* Get frame width and height so we can convert stroke coordinates + * and other things from normalized to pixel space. + */ + int frame_width, frame_height; + BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height); + /* Actual mask sampling. */ + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, frame); + const float region_min[2] = {region->min[0] - marker->pos[0] * frame_width, + region->min[1] - marker->pos[1] * frame_height}; + const float region_max[2] = {region->max[0] - marker->pos[0] * frame_width, + region->max[1] - marker->pos[1] * frame_height}; + *r_destination = tracking_track_get_mask_for_region(frame_width, frame_height, + region_min, + region_max, + track); + *r_width = region->max[0] - region->min[0]; + *r_height = region->max[1] - region->min[1]; + return *r_destination; +} + +static void accessor_release_mask_callback(libmv_CacheKey cache_key) +{ + if (cache_key != NULL) { + float *mask = (float *)cache_key; + MEM_freeN(mask); + } +} + TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP], int num_clips, + MovieTrackingTrack **tracks, + int num_tracks, int start_frame) { TrackingImageAccessor *accessor = @@ -891,12 +947,16 @@ TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *)); accessor->num_clips = num_clips; + accessor->tracks = tracks; + accessor->num_tracks = num_tracks; accessor->start_frame = start_frame; accessor->libmv_accessor = libmv_FrameAccessorNew((libmv_FrameAccessorUserData *) accessor, accessor_get_image_callback, - accessor_release_image_callback); + accessor_release_image_callback, + accessor_get_mask_for_track_callback, + accessor_release_mask_callback); return accessor; } diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index caa9a1e357f..363c36e644d 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -119,7 +119,7 @@ World *add_world(Main *bmain, const char *name) return wrld; } -World *BKE_world_copy(Main *bmain, World *wrld) +World *BKE_world_copy(Main *bmain, const World *wrld) { World *wrldn; int a; diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index 212af76a7e8..4757186f546 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -268,11 +268,7 @@ int BKE_frameserver_loop(void *context_v, RenderData *rd, ReportList *UNUSED(rep struct timeval tv; struct sockaddr_in addr; int len, rval; -#ifdef FREE_WINDOWS - int socklen; -#else unsigned int socklen; -#endif char buf[4096]; FrameserverContext *context = context_v; diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h index 591ee4d0d01..1a68a1cac6a 100644 --- a/source/blender/blenkernel/tracking_private.h +++ b/source/blender/blenkernel/tracking_private.h @@ -105,6 +105,13 @@ struct MovieTrackingMarker *tracking_get_keyframed_marker( int current_frame, bool backwards); +/*********************** Masking *************************/ + +float *tracking_track_get_mask_for_region(int frame_width, int frame_height, + const float region_min[2], + const float region_max[2], + MovieTrackingTrack *track); + /*********************** Frame accessr *************************/ struct libmv_FrameAccessor; @@ -114,12 +121,16 @@ typedef struct TrackingImageAccessor { struct MovieCache *cache; struct MovieClip *clips[MAX_ACCESSOR_CLIP]; int num_clips; + struct MovieTrackingTrack **tracks; + int num_tracks; int start_frame; struct libmv_FrameAccessor *libmv_accessor; } TrackingImageAccessor; TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP], int num_clips, + MovieTrackingTrack **tracks, + int num_tracks, int start_frame); void tracking_image_accessor_destroy(TrackingImageAccessor *accessor); diff --git a/source/blender/blenlib/BLI_alloca.h b/source/blender/blenlib/BLI_alloca.h index b44e6c66d2a..4fa69a24966 100644 --- a/source/blender/blenlib/BLI_alloca.h +++ b/source/blender/blenlib/BLI_alloca.h @@ -29,10 +29,6 @@ /* BLI_array_alloca / alloca */ -#if defined(__MINGW32__) -# include <malloc.h> /* mingw needs for alloca() */ -#endif - #if defined(__GNUC__) || defined(__clang__) #if defined(__cplusplus) && (__cplusplus > 199711L) #define BLI_array_alloca(arr, realsize) \ diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index c645ff06c00..74f24c808ff 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -137,8 +137,8 @@ void _bli_array_grow_func(void **arr_p, const void *arr_static, #define BLI_array_free(arr) \ if (arr && (char *)arr != _##arr##_static) { \ - BLI_array_fake_user(arr); \ - MEM_freeN(arr); \ + BLI_array_fake_user(arr); \ + MEM_freeN(arr); \ } (void)0 #define BLI_array_pop(arr) ( \ diff --git a/source/blender/blenlib/BLI_compiler_attrs.h b/source/blender/blenlib/BLI_compiler_attrs.h index f0d32670229..4c548654e33 100644 --- a/source/blender/blenlib/BLI_compiler_attrs.h +++ b/source/blender/blenlib/BLI_compiler_attrs.h @@ -92,4 +92,12 @@ # define ATTR_PRINTF_FORMAT(format_param, dots_param) #endif +/* Use to suppress '-Wimplicit-fallthrough' (in place of 'break'). */ +#if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */ +#define ATTR_FALLTHROUGH __attribute__((fallthrough)) +#else +#define ATTR_FALLTHROUGH ((void)0) +#endif + + #endif /* __BLI_COMPILER_ATTRS_H__ */ diff --git a/source/blender/blenlib/BLI_compiler_compat.h b/source/blender/blenlib/BLI_compiler_compat.h index 8edbc25bcbc..01fc9d70207 100644 --- a/source/blender/blenlib/BLI_compiler_compat.h +++ b/source/blender/blenlib/BLI_compiler_compat.h @@ -32,11 +32,6 @@ # define alloca _alloca #endif -/* alloca is defined here for MinGW32 */ -#ifdef __MINGW32__ -# include <malloc.h> -#endif - #if defined(__cplusplus) && ((__cplusplus >= 201103L) || defined(_MSC_VER)) # define HAS_CPP11_FEATURES #endif diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h index 7aa1c30e449..b26accc7f78 100644 --- a/source/blender/blenlib/BLI_dynstr.h +++ b/source/blender/blenlib/BLI_dynstr.h @@ -43,11 +43,14 @@ #include "BLI_compiler_attrs.h" struct DynStr; +struct MemArena; /** The abstract DynStr type */ typedef struct DynStr DynStr; DynStr *BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +DynStr *BLI_dynstr_new_memarena(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; + void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL(); void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) ATTR_NONNULL(); @@ -56,8 +59,9 @@ void BLI_dynstr_vappendf(DynStr *__restrict ds, const char *__restrict format int BLI_dynstr_get_len(DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); char *BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); - void BLI_dynstr_get_cstring_ex(DynStr *__restrict ds, char *__restrict str) ATTR_NONNULL(); + +void BLI_dynstr_clear(DynStr *ds) ATTR_NONNULL(); void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL(); #endif /* __BLI_DYNSTR_H__ */ diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 91d139c7085..5c1fa57886a 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -65,10 +65,8 @@ int BLI_create_symlink(const char *path, const char *to) ATTR_NONNULL(); /* keep in sync with the definition of struct direntry in BLI_fileops_types.h */ #ifdef WIN32 -# if defined(_MSC_VER) || defined(__MINGW64__) +# if defined(_MSC_VER) typedef struct _stat64 BLI_stat_t; -# elif defined(__MINGW32__) -typedef struct _stati64 BLI_stat_t; # else typedef struct _stat BLI_stat_t; # endif diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h index 0cf8c8ddb4a..0ffa3276f1f 100644 --- a/source/blender/blenlib/BLI_fileops_types.h +++ b/source/blender/blenlib/BLI_fileops_types.h @@ -35,7 +35,7 @@ #include <sys/stat.h> -#if defined(WIN32) && !defined(FREE_WINDOWS) +#if defined(WIN32) typedef unsigned int mode_t; #endif @@ -50,10 +50,8 @@ struct direntry { const char *relname; const char *path; #ifdef WIN32 /* keep in sync with the definition of BLI_stat_t in BLI_fileops.h */ -# if defined(_MSC_VER) || defined(__MINGW64__) +# if defined(_MSC_VER) struct _stat64 s; -# elif defined(__MINGW32__) - struct _stati64 s; # else struct _stat s; # endif diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 7e3a009ede8..7cf3e97bdc9 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -167,6 +167,8 @@ unsigned int BLI_ghashutil_inthash_p_murmur(const void *ptr); unsigned int BLI_ghashutil_inthash_p_simple(const void *ptr); bool BLI_ghashutil_intcmp(const void *a, const void *b); +size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b); + unsigned int BLI_ghashutil_uinthash_v4(const unsigned int key[4]); #define BLI_ghashutil_inthash_v4(key) ( \ @@ -294,6 +296,25 @@ double BLI_ghash_calc_quality(GHash *gh); double BLI_gset_calc_quality(GSet *gs); #endif /* GHASH_INTERNAL_API */ +#define GHASH_FOREACH_BEGIN(type, var, what) \ + do { \ + GHashIterator gh_iter##var; \ + GHASH_ITER(gh_iter##var, what) { \ + type var = (type)(BLI_ghashIterator_getValue(&gh_iter##var)); \ + +#define GHASH_FOREACH_END() \ + } \ + } while(0) + +#define GSET_FOREACH_BEGIN(type, var, what) \ + do { \ + GSetIterator gh_iter##var; \ + GSET_ITER(gh_iter##var, what) { \ + type var = (type)(BLI_gsetIterator_getKey(&gh_iter##var)); + +#define GSET_FOREACH_END() \ + } \ + } while(0) #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h new file mode 100644 index 00000000000..e849e5f8f61 --- /dev/null +++ b/source/blender/blenlib/BLI_hash.h @@ -0,0 +1,66 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_HASH_H__ +#define __BLI_HASH_H__ + +/** \file BLI_hash.h + * \ingroup bli + */ + +BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky) +{ +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) + + unsigned int a, b, c; + + a = b = c = 0xdeadbeef + (2 << 2) + 13; + a += kx; + b += ky; + + c ^= b; c -= rot(b, 14); + a ^= c; a -= rot(c, 11); + b ^= a; b -= rot(a, 25); + c ^= b; c -= rot(b, 16); + a ^= c; a -= rot(c, 4); + b ^= a; b -= rot(a, 14); + c ^= b; c -= rot(b, 24); + + return c; + +#undef rot +} + +BLI_INLINE unsigned int BLI_hash_string(const char *str) +{ + unsigned int i = 0, c; + + while ((c = *str++)) { + i = i * 37 + c; + } + return i; +} + +BLI_INLINE unsigned int BLI_hash_int(unsigned int k) +{ + return BLI_hash_int_2d(k, 0); +} + +#endif // __BLI_HASH_H__ diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index ba565fca522..564659ad21e 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -36,7 +36,7 @@ */ #ifdef __cplusplus -extern "C" { +extern "C" { #endif struct BVHTree; @@ -62,7 +62,7 @@ typedef struct BVHTreeNearest { int index; /* the index of the nearest found (untouched if none is found within a dist radius from the given coordinates) */ float co[3]; /* nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */ float no[3]; /* normal at nearest coordinates (untouched it none is found within a dist radius from the given coordinates) */ - float dist_sq; /* squared distance to search arround */ + float dist_sq; /* squared distance to search around */ int flags; } BVHTreeNearest; diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index 00e761b81bc..b06944e4985 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -125,6 +125,11 @@ if ((lb)->last && (lb_init || (lb_init = (lb)->last))) { \ (lb_iter != lb_init)); \ } +#define LINKLIST_FOREACH(type, var, list) \ + for (type var = (type)((list)->first); \ + var != NULL; \ + var = (type)(((Link*)(var))->next)) + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index d60be30e10d..e059327a490 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -218,8 +218,12 @@ float angle_wrap_deg(float angle); float angle_compat_rad(float angle, float angle_compat); -int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up, - float r_mat[3][3]); +bool mat3_from_axis_conversion( + int src_forward, int src_up, int dst_forward, int dst_up, + float r_mat[3][3]); +bool mat3_from_axis_conversion_single( + int src_axis, int dst_axis, + float r_mat[3][3]); #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 8e0884ba347..43f414f376a 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -286,6 +286,8 @@ float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT; float cos_v3v3v3(const float p1[3], const float p2[3], const float p3[3]) ATTR_WARN_UNUSED_RESULT; float cos_v2v2v2(const float p1[2], const float p2[2], const float p3[2]) ATTR_WARN_UNUSED_RESULT; +float angle_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT; +float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT; float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT; float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT; float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT; @@ -299,6 +301,8 @@ void project_v2_v2v2(float out[2], const float p[2], const float v_proj[2]); void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3]); void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3]); void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2]); +void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3]); +void project_plane_normalized_v2_v2v2(float out[2], const float p[2], const float v_plane[2]); void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3]); void reflect_v3_v3v3(float out[3], const float vec[3], const float normal[3]); void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]); diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index b6a55d34d14..b59e7f99d59 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -44,7 +44,7 @@ void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1); void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file); void BLI_make_exist(char *dir); -void BLI_make_existing_file(const char *name); +bool BLI_make_existing_file(const char *name); void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen); void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen); void BLI_split_file_part(const char *string, char *file, const size_t filelen); diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h index 041679ef876..21b9c75ac35 100644 --- a/source/blender/blenlib/BLI_rect.h +++ b/source/blender/blenlib/BLI_rect.h @@ -97,6 +97,7 @@ void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2); void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src); void BLI_rctf_rcti_copy(struct rctf *dst, const struct rcti *src); void BLI_rcti_rctf_copy_floor(struct rcti *dst, const struct rctf *src); +void BLI_rcti_rctf_copy_round(struct rcti *dst, const struct rctf *src); void BLI_rctf_rotate_expand(rctf *dst, const rctf *src, const float angle); diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h index 222005ee92e..d54f2a7bab2 100644 --- a/source/blender/blenlib/BLI_stack.h +++ b/source/blender/blenlib/BLI_stack.h @@ -30,6 +30,10 @@ #include "BLI_compiler_attrs.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct BLI_Stack BLI_Stack; BLI_Stack *BLI_stack_new_ex( @@ -55,4 +59,8 @@ size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONN bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +#ifdef __cplusplus +} +#endif + #endif /* __BLI_STACK_H__ */ diff --git a/source/blender/blenlib/BLI_strict_flags.h b/source/blender/blenlib/BLI_strict_flags.h index 964ee06469d..86b7285655e 100644 --- a/source/blender/blenlib/BLI_strict_flags.h +++ b/source/blender/blenlib/BLI_strict_flags.h @@ -30,6 +30,8 @@ #ifdef __GNUC__ # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ # pragma GCC diagnostic error "-Wsign-compare" +# endif +# if __GNUC__ >= 6 /* gcc6+ only */ # pragma GCC diagnostic error "-Wconversion" # endif # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h index 9d8222c575d..9477f61713c 100644 --- a/source/blender/blenlib/BLI_sys_types.h +++ b/source/blender/blenlib/BLI_sys_types.h @@ -65,8 +65,8 @@ typedef uint64_t u_int64_t; #include <inttypes.h> -/* MinGW and MSVC >= 2010 */ -#elif defined(FREE_WINDOWS) || defined(_MSC_VER) +/* MSVC >= 2010 */ +#elif defined(_MSC_VER) #include <stdint.h> #else diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index c3c587275e1..721327d26a8 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -106,6 +106,13 @@ void *BLI_task_pool_userdata(TaskPool *pool); /* optional mutex to use from run function */ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool); +/* Delayed push, use that to reduce thread overhead by accumulating + * all new tasks into local queue first and pushing it to scheduler + * from within a single mutex lock. + */ +void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id); +void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id); + /* Parallel for routines */ typedef void (*TaskParallelRangeFunc)(void *userdata, const int iter); typedef void (*TaskParallelRangeFuncEx)(void *userdata, void *userdata_chunk, const int iter, const int thread_id); diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index b421b7dbb90..6fbbed01400 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -37,15 +37,6 @@ # error "This include is for Windows only!" #endif -#ifdef FREE_WINDOWS -# ifdef WINVER -# undef WINVER -# endif - -/* Some stuff requires WINVER 0x500, but mingw's default is 0x400 */ -# define WINVER 0x0501 -#endif - #define WIN32_LEAN_AND_MEAN #ifndef WIN32_SKIP_HKEY_PROTECTION @@ -94,7 +85,7 @@ extern "C" { # define snprintf _snprintf #endif -#if defined(_MSC_VER) || (defined(FREE_WINDOWS) && !defined(FREE_WINDOWS64)) +#if defined(_MSC_VER) # define R_OK 4 # define W_OK 2 // not accepted by access() on windows @@ -102,28 +93,22 @@ extern "C" { # define F_OK 0 #endif -#ifndef FREE_WINDOWS typedef unsigned int mode_t; -#endif /* use functions that take a 64 bit offset for files larger than 4GB */ -#ifndef FREE_WINDOWS -# include <stdio.h> -# define fseek(stream, offset, origin) _fseeki64(stream, offset, origin) -# define ftell(stream) _ftelli64(stream) -# define lseek(fd, offset, origin) _lseeki64(fd, offset, origin) -# define tell(fd) _telli64(fd) -#endif +#include <stdio.h> +#define fseek(stream, offset, origin) _fseeki64(stream, offset, origin) +#define ftell(stream) _ftelli64(stream) +#define lseek(fd, offset, origin) _lseeki64(fd, offset, origin) +#define tell(fd) _telli64(fd) + -/* mingw using _SSIZE_T_ to declare ssize_t type */ #ifndef _SSIZE_T_ # define _SSIZE_T_ /* python uses HAVE_SSIZE_T */ # ifndef HAVE_SSIZE_T # define HAVE_SSIZE_T 1 -# ifndef FREE_WINDOWS64 typedef long ssize_t; -# endif # endif #endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 3277519c66e..fcb02a86a84 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -152,6 +152,7 @@ set(SRC BLI_ghash.h BLI_graph.h BLI_gsqueue.h + BLI_hash.h BLI_hash_md5.h BLI_hash_mm2a.h BLI_heap.h diff --git a/source/blender/blenlib/intern/BLI_dynstr.c b/source/blender/blenlib/intern/BLI_dynstr.c index ecd4a6e6b09..bce6614beb5 100644 --- a/source/blender/blenlib/intern/BLI_dynstr.c +++ b/source/blender/blenlib/intern/BLI_dynstr.c @@ -35,6 +35,7 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" +#include "BLI_memarena.h" #include "BLI_string.h" #include "BLI_dynstr.h" @@ -64,6 +65,7 @@ struct DynStrElem { struct DynStr { DynStrElem *elems, *last; int curlen; + MemArena *memarena; }; /***/ @@ -78,11 +80,32 @@ DynStr *BLI_dynstr_new(void) DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr"); ds->elems = ds->last = NULL; ds->curlen = 0; + ds->memarena = NULL; return ds; } /** + * Create a new DynStr. + * + * \return Pointer to a new DynStr. + */ +DynStr *BLI_dynstr_new_memarena(void) +{ + DynStr *ds = MEM_mallocN(sizeof(*ds), "DynStr"); + ds->elems = ds->last = NULL; + ds->curlen = 0; + ds->memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + + return ds; +} + +BLI_INLINE void *dynstr_alloc(DynStr *__restrict ds, size_t size) +{ + return ds->memarena ? BLI_memarena_alloc(ds->memarena, size) : malloc(size); +} + +/** * Append a c-string to a DynStr. * * \param ds The DynStr to append to. @@ -90,10 +113,10 @@ DynStr *BLI_dynstr_new(void) */ void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) { - DynStrElem *dse = malloc(sizeof(*dse)); + DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse)); int cstrlen = strlen(cstr); - dse->str = malloc(cstrlen + 1); + dse->str = dynstr_alloc(ds, cstrlen + 1); memcpy(dse->str, cstr, cstrlen + 1); dse->next = NULL; @@ -114,10 +137,10 @@ void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) */ void BLI_dynstr_nappend(DynStr *__restrict ds, const char *cstr, int len) { - DynStrElem *dse = malloc(sizeof(*dse)); + DynStrElem *dse = dynstr_alloc(ds, sizeof(*dse)); int cstrlen = BLI_strnlen(cstr, len); - dse->str = malloc(cstrlen + 1); + dse->str = dynstr_alloc(ds, cstrlen + 1); memcpy(dse->str, cstr, cstrlen); dse->str[cstrlen] = '\0'; dse->next = NULL; @@ -296,22 +319,41 @@ char *BLI_dynstr_get_cstring(DynStr *ds) } /** + * Clear the DynStr + * + * \param ds The DynStr to clear. + */ +void BLI_dynstr_clear(DynStr *ds) +{ + if (ds->memarena) { + BLI_memarena_clear(ds->memarena); + } + else { + for (DynStrElem *dse_next, *dse = ds->elems; dse; dse = dse_next) { + dse_next = dse->next; + + free(dse->str); + free(dse); + } + } + + ds->elems = ds->last = NULL; + ds->curlen = 0; +} + +/** * Free the DynStr * * \param ds The DynStr to free. */ void BLI_dynstr_free(DynStr *ds) { - DynStrElem *dse; - - for (dse = ds->elems; dse; ) { - DynStrElem *n = dse->next; - - free(dse->str); - free(dse); - - dse = n; + if (ds->memarena) { + BLI_memarena_free(ds->memarena); } - + else { + BLI_dynstr_clear(ds); + } + MEM_freeN(ds); } diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 944ee18e6b2..69dee12c713 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -116,6 +116,12 @@ struct GHash { }; +/* -------------------------------------------------------------------- */ +/* GHash API */ + +/** \name Internal Utility API + * \{ */ + BLI_INLINE void ghash_entry_copy( GHash *gh_dst, Entry *dst, GHash *gh_src, Entry *src, GHashKeyCopyFP keycopyfp, GHashValCopyFP valcopyfp) @@ -132,12 +138,6 @@ BLI_INLINE void ghash_entry_copy( } } -/* -------------------------------------------------------------------- */ -/* GHash API */ - -/** \name Internal Utility API - * \{ */ - /** * Get the full hash for a key. */ @@ -1225,6 +1225,11 @@ bool BLI_ghashutil_intcmp(const void *a, const void *b) return (a != b); } +size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b) +{ + return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); +} + /** * This function implements the widely used "djb" hash apparently posted * by Daniel Bernstein to comp.lang.c some time ago. The 32 bit diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 19d9711922e..e5ca53a0193 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -55,12 +55,20 @@ #include "BLI_stack.h" #include "BLI_kdopbvh.h" #include "BLI_math.h" -#include "BLI_strict_flags.h" #include "BLI_task.h" +#include "BLI_strict_flags.h" + /* used for iterative_raycast */ // #define USE_SKIP_LINKS +/* Use to print balanced output. */ +// #define USE_PRINT_TREE + +/* Check tree is valid. */ +// #define USE_VERIFY_TREE + + #define MAX_TREETYPE 32 /* Setting zero so we can catch bugs in BLI_task/KDOPBVH. @@ -129,7 +137,7 @@ typedef struct BVHOverlapData_Thread { } BVHOverlapData_Thread; typedef struct BVHNearestData { - BVHTree *tree; + const BVHTree *tree; const float *co; BVHTree_NearestPointCallback callback; void *userdata; @@ -139,7 +147,7 @@ typedef struct BVHNearestData { } BVHNearestData; typedef struct BVHRayCastData { - BVHTree *tree; + const BVHTree *tree; BVHTree_RayCastCallback callback; void *userdata; @@ -171,9 +179,9 @@ typedef struct BVHRayCastData { */ const float bvhtree_kdop_axes[13][3] = { - {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, - {1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, - {0, 1.0, -1.0} + {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, + {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0}, + {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, {0, 1.0, -1.0} }; @@ -321,11 +329,16 @@ static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode *x, int axis) { int i = lo, j = hi; while (1) { - while ((a[i])->bv[axis] < x->bv[axis]) i++; + while (a[i]->bv[axis] < x->bv[axis]) { + i++; + } j--; - while (x->bv[axis] < (a[j])->bv[axis]) j--; - if (!(i < j)) + while (x->bv[axis] < a[j]->bv[axis]) { + j--; + } + if (!(i < j)) { return i; + } SWAP(BVHNode *, a[i], a[j]); i++; } @@ -427,19 +440,18 @@ static void sort_along_axis(BVHTree *tree, int start, int end, int axis) * \note after a call to this function you can expect one of: * - every node to left of a[n] are smaller or equal to it * - every node to the right of a[n] are greater or equal to it */ -static int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis) +static void partition_nth_element(BVHNode **a, int begin, int end, const int n, const int axis) { - int begin = _begin, end = _end, cut; while (end - begin > 3) { - cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis); - if (cut <= n) + const int cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin + end) / 2, end - 1, axis), axis); + if (cut <= n) { begin = cut; - else + } + else { end = cut; + } } bvh_insertionsort(a, begin, end, axis); - - return n; } #ifdef USE_SKIP_LINKS @@ -464,7 +476,7 @@ static void build_skip_links(BVHTree *tree, BVHNode *node, BVHNode *left, BVHNod /* * BVHTree bounding volumes functions */ -static void create_kdop_hull(BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving) +static void create_kdop_hull(const BVHTree *tree, BVHNode *node, const float *co, int numpoints, int moving) { float newminmax; float *bv = node->bv; @@ -491,7 +503,7 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, const float *co, int /** * \note depends on the fact that the BVH's for each face is already build */ -static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) +static void refit_kdop_hull(const BVHTree *tree, BVHNode *node, int start, int end) { float newmin, newmax; float *bv = node->bv; @@ -566,10 +578,12 @@ static void node_join(BVHTree *tree, BVHNode *node) } } -/* +#ifdef USE_PRINT_TREE + +/** * Debug and information functions */ -#if 0 + static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { int i; @@ -592,26 +606,29 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) static void bvhtree_info(BVHTree *tree) { - printf("BVHTree info\n"); - printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon); - printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); - printf("Memory per node = %ldbytes\n", sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis); - printf("BV memory = %dbytes\n", (int)MEM_allocN_len(tree->nodebv)); - - printf("Total memory = %ldbytes\n", sizeof(BVHTree) + - MEM_allocN_len(tree->nodes) + - MEM_allocN_len(tree->nodearray) + - MEM_allocN_len(tree->nodechild) + - MEM_allocN_len(tree->nodebv)); - -// bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0); + printf("BVHTree Info: tree_type = %d, axis = %d, epsilon = %f\n", + tree->tree_type, tree->axis, tree->epsilon); + printf("nodes = %d, branches = %d, leafs = %d\n", + tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); + printf("Memory per node = %ubytes\n", + (uint)(sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis)); + printf("BV memory = %ubytes\n", + (uint)MEM_allocN_len(tree->nodebv)); + + printf("Total memory = %ubytes\n", + (uint)(sizeof(BVHTree) + + MEM_allocN_len(tree->nodes) + + MEM_allocN_len(tree->nodearray) + + MEM_allocN_len(tree->nodechild) + + MEM_allocN_len(tree->nodebv))); + + bvhtree_print_tree(tree, tree->nodes[tree->totleaf], 0); } -#endif - -#if 0 +#endif /* USE_PRINT_TREE */ +#ifdef USE_VERIFY_TREE -static void verify_tree(BVHTree *tree) +static void bvhtree_verify(BVHTree *tree) { int i, j, check = 0; @@ -649,12 +666,14 @@ static void verify_tree(BVHTree *tree) } } - printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); + printf("branches: %d, leafs: %d, total: %d\n", + tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); } -#endif +#endif /* USE_VERIFY_TREE */ /* Helper data and structures to build a min-leaf generalized implicit tree - * This code can be easily reduced (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that) */ + * This code can be easily reduced + * (basicly this is only method to calculate pow(k, n) in O(1).. and stuff like that) */ typedef struct BVHBuildHelper { int tree_type; /* */ int totleafs; /* */ @@ -666,7 +685,7 @@ typedef struct BVHBuildHelper { } BVHBuildHelper; -static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data) +static void build_implicit_tree_helper(const BVHTree *tree, BVHBuildHelper *data) { int depth = 0; int remain; @@ -696,7 +715,7 @@ static void build_implicit_tree_helper(BVHTree *tree, BVHBuildHelper *data) } // return the min index of all the leafs archivable with the given branch -static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index) +static int implicit_leafs_index(const BVHBuildHelper *data, const int depth, const int child_index) { int min_leaf_index = child_index * data->leafs_per_child[depth - 1]; if (min_leaf_index <= data->remain_leafs) @@ -711,8 +730,8 @@ static int implicit_leafs_index(BVHBuildHelper *data, int depth, int child_index * Generalized implicit tree build * * An implicit tree is a tree where its structure is implied, thus there is no need to store child pointers or indexs. - * Its possible to find the position of the child or the parent with simple maths (multiplication and adittion). This type - * of tree is for example used on heaps.. where node N has its childs at indexs N*2 and N*2+1. + * Its possible to find the position of the child or the parent with simple maths (multiplication and adittion). + * This type of tree is for example used on heaps.. where node N has its childs at indexs N*2 and N*2+1. * * Although in this case the tree type is general.. and not know until runtime. * tree_type stands for the maximum number of childs that a tree node can have. @@ -753,7 +772,7 @@ static int implicit_needed_branches(int tree_type, int leafs) * * TODO: This can be optimized a bit by doing a specialized nth_element instead of K nth_elements */ -static void split_leafs(BVHNode **leafs_array, int *nth, int partitions, int split_axis) +static void split_leafs(BVHNode **leafs_array, const int nth[], const int partitions, const int split_axis) { int i; for (i = 0; i < partitions - 1; i++) { @@ -765,14 +784,14 @@ static void split_leafs(BVHNode **leafs_array, int *nth, int partitions, int spl } typedef struct BVHDivNodesData { - BVHTree *tree; + const BVHTree *tree; BVHNode *branches_array; BVHNode **leafs_array; int tree_type; int tree_offset; - BVHBuildHelper *data; + const BVHBuildHelper *data; int depth; int i; @@ -785,7 +804,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *userdata, const int j) int k; const int parent_level_index = j - data->i; - BVHNode *parent = data->branches_array + j; + BVHNode *parent = &data->branches_array[j]; int nth_positions[MAX_TREETYPE + 1]; char split_axis; @@ -824,7 +843,7 @@ static void non_recursive_bvh_div_nodes_task_cb(void *userdata, const int j) const int child_leafs_end = implicit_leafs_index(data->data, data->depth + 1, child_level_index + 1); if (child_leafs_end - child_leafs_begin > 1) { - parent->children[k] = data->branches_array + child_index; + parent->children[k] = &data->branches_array[child_index]; parent->children[k]->parent = parent; } else if (child_leafs_end - child_leafs_begin == 1) { @@ -855,7 +874,8 @@ static void non_recursive_bvh_div_nodes_task_cb(void *userdata, const int j) * To archive this is necessary to find how much leafs are accessible from a certain branch, BVHBuildHelper * implicit_needed_branches and implicit_leafs_index are auxiliary functions to solve that "optimal-split". */ -static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs) +static void non_recursive_bvh_div_nodes( + const BVHTree *tree, BVHNode *branches_array, BVHNode **leafs_array, int num_leafs) { int i; @@ -867,13 +887,13 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, int depth; /* set parent from root node to NULL */ - BVHNode *tmp = branches_array + 0; + BVHNode *tmp = &branches_array[0]; tmp->parent = NULL; /* Most of bvhtree code relies on 1-leaf trees having at least one branch * We handle that special case here */ if (num_leafs == 1) { - BVHNode *root = branches_array + 0; + BVHNode *root = &branches_array[0]; refit_kdop_hull(tree, root, 0, num_leafs); root->main_axis = get_largest_axis(root->bv) / 2; root->totnode = 1; @@ -895,16 +915,24 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, /* Loop tree levels (log N) loops */ for (i = 1, depth = 1; i <= num_branches; i = i * tree_type + tree_offset, depth++) { const int first_of_next_level = i * tree_type + tree_offset; - const int end_j = min_ii(first_of_next_level, num_branches + 1); /* index of last branch on this level */ + const int i_stop = min_ii(first_of_next_level, num_branches + 1); /* index of last branch on this level */ /* Loop all branches on this level */ cb_data.first_of_next_level = first_of_next_level; cb_data.i = i; cb_data.depth = depth; - BLI_task_parallel_range( - i, end_j, &cb_data, non_recursive_bvh_div_nodes_task_cb, - num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD); + if (true) { + BLI_task_parallel_range( + i, i_stop, &cb_data, non_recursive_bvh_div_nodes_task_cb, + num_leafs > KDOPBVH_THREAD_LEAF_THRESHOLD); + } + else { + /* Less hassle for debugging. */ + for (int i_task = i; i_task < i_stop; i_task++) { + non_recursive_bvh_div_nodes_task_cb(&cb_data, i_task); + } + } } } @@ -1021,7 +1049,8 @@ void BLI_bvhtree_balance(BVHTree *tree) BVHNode *branches_array = tree->nodearray + tree->totleaf; BVHNode **leafs_array = tree->nodes; - /* This function should only be called once (some big bug goes here if its being called more than once per tree) */ + /* This function should only be called once + * (some big bug goes here if its being called more than once per tree) */ BLI_assert(tree->totbranch == 0); /* Build the implicit tree */ @@ -1037,7 +1066,13 @@ void BLI_bvhtree_balance(BVHTree *tree) build_skip_links(tree, tree->nodes[tree->totleaf], NULL, NULL); #endif - /* bvhtree_info(tree); */ +#ifdef USE_VERIFY_TREE + bvhtree_verify(tree); +#endif + +#ifdef USE_PRINT_TREE + bvhtree_info(tree); +#endif } void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints) @@ -1470,7 +1505,8 @@ static void bfs_find_nearest(BVHNearestData *data, BVHNode *node) else { /* adjust heap size */ if ((heap_size >= max_heap_size) && - ADJUST_MEMORY(default_heap, (void **)&heap, heap_size + 1, &max_heap_size, sizeof(heap[0])) == false) + ADJUST_MEMORY(default_heap, (void **)&heap, + heap_size + 1, &max_heap_size, sizeof(heap[0])) == false) { printf("WARNING: bvh_find_nearest got out of memory\n"); diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c index 295b39c1a2f..d3a63aceb89 100644 --- a/source/blender/blenlib/intern/array_store.c +++ b/source/blender/blenlib/intern/array_store.c @@ -878,7 +878,7 @@ static hash_key key_from_chunk_ref( { /* in C, will fill in a reusable array */ BChunk *chunk = cref->link; - BLI_assert(info->accum_read_ahead_bytes * info->chunk_stride); + BLI_assert((info->accum_read_ahead_bytes * info->chunk_stride) != 0); if (info->accum_read_ahead_bytes <= chunk->data_len) { hash_key key; @@ -1560,7 +1560,7 @@ BArrayState *BLI_array_store_state_add( const void *data, const size_t data_len, const BArrayState *state_reference) { - /* ensure we're aligned to the stride */ + /* ensure we're aligned to the stride */ BLI_assert((data_len % bs->info.chunk_stride) == 0); #ifdef USE_PARANOID_CHECKS diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index db4b3bcf20c..1df7f6f81e4 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -42,9 +42,6 @@ #include "zlib.h" #ifdef WIN32 -# ifdef __MINGW32__ -# include <ctype.h> -# endif # include <io.h> # include "BLI_winstuff.h" # include "BLI_callbacks.h" @@ -265,7 +262,7 @@ void *BLI_gzopen(const char *filename, const char *mode) /* temporary #if until we update all libraries to 1.2.7 * for correct wide char path handling */ -#if ZLIB_VERNUM >= 0x1270 && !defined(FREE_WINDOWS) +#if ZLIB_VERNUM >= 0x1270 UTF16_ENCODE(filename); gzfile = gzopen_w(filename_16, mode); diff --git a/source/blender/blenlib/intern/hash_mm2a.c b/source/blender/blenlib/intern/hash_mm2a.c index af6ef4f355f..e8ca9244f25 100644 --- a/source/blender/blenlib/intern/hash_mm2a.c +++ b/source/blender/blenlib/intern/hash_mm2a.c @@ -36,6 +36,8 @@ * for temporary data. */ +#include "BLI_compiler_attrs.h" + #include "BLI_hash_mm2a.h" /* own include */ /* Helpers. */ @@ -128,10 +130,10 @@ uint32_t BLI_hash_mm2(const unsigned char *data, size_t len, uint32_t seed) switch (len) { case 3: h ^= data[2] << 16; - /* fall through */ + ATTR_FALLTHROUGH; case 2: h ^= data[1] << 8; - /* fall through */ + ATTR_FALLTHROUGH; case 1: h ^= data[0]; h *= MM2A_M; diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index 6cb7b7d8e3e..46dcee48eda 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -664,7 +664,7 @@ void *BLI_rfindptr(const ListBase *listbase, const void *ptr, const int offset) } /** - * Returns the 1-based index of the first element of listbase which contains the specified + * Returns the 0-based index of the first element of listbase which contains the specified * null-terminated string at the specified offset, or -1 if not found. */ int BLI_findstringindex(const ListBase *listbase, const char *id, const int offset) diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c index 048ab71c6dc..dc3874f83a2 100644 --- a/source/blender/blenlib/intern/math_color_blend_inline.c +++ b/source/blender/blenlib/intern/math_color_blend_inline.c @@ -444,7 +444,7 @@ MINLINE void blend_color_vividlight_byte(unsigned char dst[4], unsigned const ch else if (src2[i] == 0) { temp = 0; } - else if (src2[i] > 127) { + else if (src2[i] > 127) { temp = min_ii(((src1[i]) * 255) / (2 * (255 - src2[i])), 255); } else { diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 58699a0593b..bfe1aefcbbd 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -572,8 +572,8 @@ float dist_squared_to_ray_v3( } /** * Find the closest point in a seg to a ray and return the distance squared. - * \param r_point : Is the point on segment closest to ray (or to ray_origin if the ray and the segment are parallel). - * \param depth: the distance of r_point projection on ray to the ray_origin. + * \param r_point: Is the point on segment closest to ray (or to ray_origin if the ray and the segment are parallel). + * \param r_depth: the distance of r_point projection on ray to the ray_origin. */ float dist_squared_ray_to_seg_v3( const float ray_origin[3], const float ray_direction[3], @@ -1828,7 +1828,7 @@ bool isect_tri_tri_epsilon_v3( (range[0].max < range[1].min)) == 0) { if (r_i1 && r_i2) { - project_plane_v3_v3v3(plane_co, plane_co, plane_no); + project_plane_normalized_v3_v3v3(plane_co, plane_co, plane_no); madd_v3_v3v3fl(r_i1, plane_co, plane_no, max_ff(range[0].min, range[1].min)); madd_v3_v3v3fl(r_i2, plane_co, plane_no, min_ff(range[0].max, range[1].max)); } diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 9a60c670ec7..f47f9ad76e6 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1738,16 +1738,16 @@ void blend_m4_m4m4(float out[4][4], float dst[4][4], float src[4][4], const floa /** * A polar-decomposition-based interpolation between matrix A and matrix B. * - * \note This code is about five times slower as the 'naive' interpolation done by \a blend_m3_m3m3 - * (it typically remains below 2 usec on an average i74700, while \a blend_m3_m3m3 remains below 0.4 usec). + * \note This code is about five times slower as the 'naive' interpolation done by #blend_m3_m3m3 + * (it typically remains below 2 usec on an average i74700, while #blend_m3_m3m3 remains below 0.4 usec). * However, it gives expected results even with non-uniformaly scaled matrices, see T46418 for an example. * * Based on "Matrix Animation and Polar Decomposition", by Ken Shoemake & Tom Duff * - * @return R the interpolated matrix. - * @param A the intput matrix which is totally effective with \a t = 0.0. - * @param B the intput matrix which is totally effective with \a t = 1.0. - * @param t the interpolation factor. + * \param R: Resulting interpolated matrix. + * \param A: Input matrix which is totally effective with `t = 0.0`. + * \param B: Input matrix which is totally effective with `t = 1.0`. + * \param t: Interpolation factor. */ void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t) { @@ -1777,12 +1777,12 @@ void interp_m3_m3m3(float R[3][3], float A[3][3], float B[3][3], const float t) } /** - * Complete transform matrix interpolation, based on polar-decomposition-based interpolation from interp_m3_m3m3. + * Complete transform matrix interpolation, based on polar-decomposition-based interpolation from #interp_m3_m3m3. * - * @return R the interpolated matrix. - * @param A the intput matrix which is totally effective with \a t = 0.0. - * @param B the intput matrix which is totally effective with \a t = 1.0. - * @param t the interpolation factor. + * \param R: Resulting interpolated matrix. + * \param A: Input matrix which is totally effective with `t = 0.0`. + * \param B: Input matrix which is totally effective with `t = 1.0`. + * \param t: Interpolation factor. */ void interp_m4_m4m4(float R[4][4], float A[4][4], float B[4][4], const float t) { diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 9b5dad3f767..23bd5e60e22 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -84,8 +84,6 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4]) * \note: * Assumes a unit quaternion? * - * \note: multiplying by 3x3 matrix is ~25% faster. - * * in fact not, but you may want to use a unit quat, read on... * * Shortcut for 'q v q*' when \a v is actually a quaternion. @@ -98,6 +96,8 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4]) * * For people used to python mathutils, its like: * def mul_qt_v3(q, v): (q * Quaternion((0.0, v[0], v[1], v[2])) * q.conjugated())[1:] + * + * \note: multiplying by 3x3 matrix is ~25% faster. */ void mul_qt_v3(const float q[4], float v[3]) { @@ -2147,38 +2147,37 @@ BLI_INLINE int _axis_signed(const int axis) return (axis < 3) ? axis : axis - 3; } -/* +/** * Each argument us an axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'] * where the first 2 are a source and the second 2 are the target. */ -int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up, - float r_mat[3][3]) +bool mat3_from_axis_conversion( + int src_forward, int src_up, int dst_forward, int dst_up, + float r_mat[3][3]) { // from functools import reduce int value; - unsigned int i; - if (from_forward == to_forward && from_up == to_up) { + if (src_forward == dst_forward && src_up == dst_up) { unit_m3(r_mat); return false; } - if ((_axis_signed(from_forward) == _axis_signed(from_up)) || - (_axis_signed(to_forward) == _axis_signed(to_up))) + if ((_axis_signed(src_forward) == _axis_signed(src_up)) || + (_axis_signed(dst_forward) == _axis_signed(dst_up))) { /* we could assert here! */ unit_m3(r_mat); return false; } - value = ((from_forward << (0 * 3)) | - (from_up << (1 * 3)) | - (to_forward << (2 * 3)) | - (to_up << (3 * 3))); + value = ((src_forward << (0 * 3)) | + (src_up << (1 * 3)) | + (dst_forward << (2 * 3)) | + (dst_up << (3 * 3))); - for (i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) { - unsigned int j; - for (j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) { + for (uint i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) { + for (uint j = 0; j < (sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0])); j++) { if (_axis_convert_lut[i][j] == value) { copy_m3_m3(r_mat, _axis_convert_matrix[i]); return true; @@ -2189,3 +2188,27 @@ int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int // BLI_assert(0); return false; } + +/** + * Use when the second axis can be guessed. + */ +bool mat3_from_axis_conversion_single( + int src_axis, int dst_axis, + float r_mat[3][3]) +{ + if (src_axis == dst_axis) { + unit_m3(r_mat); + return false; + } + + /* Pick predictable next axis. */ + int src_axis_next = (src_axis + 1) % 3; + int dst_axis_next = (dst_axis + 1) % 3; + + if ((src_axis < 3) != (dst_axis < 3)) { + /* Flip both axis so matrix sign remains positive. */ + dst_axis_next += 3; + } + + return mat3_from_axis_conversion(src_axis, src_axis_next, dst_axis, dst_axis_next, r_mat); +} diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index dfecc3b556a..c6e9b8229ba 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -518,38 +518,27 @@ float angle_normalized_v2v2(const float v1[2], const float v2[2]) } /** - * angle between 2 vectors defined by 3 coords, about an axis. */ -float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) + * Angle between 2 vectors, about an axis (axis can be considered a plane). + */ +float angle_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) { - float v1_proj[3], v2_proj[3], tproj[3]; - - sub_v3_v3v3(v1_proj, v1, v2); - sub_v3_v3v3(v2_proj, v3, v2); + float v1_proj[3], v2_proj[3]; /* project the vectors onto the axis */ - project_v3_v3v3(tproj, v1_proj, axis); - sub_v3_v3(v1_proj, tproj); - - project_v3_v3v3(tproj, v2_proj, axis); - sub_v3_v3(v2_proj, tproj); + project_plane_normalized_v3_v3v3(v1_proj, v1, axis); + project_plane_normalized_v3_v3v3(v2_proj, v2, axis); return angle_v3v3(v1_proj, v2_proj); } -float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) +float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) { float v1_proj[3], v2_proj[3], tproj[3]; float angle; - sub_v3_v3v3(v1_proj, v1, v2); - sub_v3_v3v3(v2_proj, v3, v2); - /* project the vectors onto the axis */ - project_v3_v3v3(tproj, v1_proj, axis); - sub_v3_v3(v1_proj, tproj); - - project_v3_v3v3(tproj, v2_proj, axis); - sub_v3_v3(v2_proj, tproj); + project_plane_normalized_v3_v3v3(v1_proj, v1, axis); + project_plane_normalized_v3_v3v3(v2_proj, v2, axis); angle = angle_v3v3(v1_proj, v2_proj); @@ -562,6 +551,29 @@ float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const return angle; } +/** + * Angle between 2 vectors defined by 3 coords, about an axis (axis can be considered a plane). + */ +float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) +{ + float vec1[3], vec2[3]; + + sub_v3_v3v3(vec1, v1, v2); + sub_v3_v3v3(vec2, v3, v2); + + return angle_on_axis_v3v3_v3(vec1, vec2, axis); +} + +float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) +{ + float vec1[3], vec2[3]; + + sub_v3_v3v3(vec1, v1, v2); + sub_v3_v3v3(vec2, v3, v2); + + return angle_signed_on_axis_v3v3_v3(vec1, vec2, axis); +} + void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3]) { float ed1[3], ed2[3], ed3[3]; @@ -669,6 +681,25 @@ void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2 out[1] = p[1] - (mul * v_plane[1]); } +void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3]) +{ + BLI_ASSERT_UNIT_V3(v_plane); + const float mul = dot_v3v3(p, v_plane); + + out[0] = p[0] - (mul * v_plane[0]); + out[1] = p[1] - (mul * v_plane[1]); + out[2] = p[2] - (mul * v_plane[2]); +} + +void project_plane_normalized_v2_v2v2(float out[2], const float p[2], const float v_plane[2]) +{ + BLI_ASSERT_UNIT_V2(v_plane); + const float mul = dot_v2v2(p, v_plane); + + out[0] = p[0] - (mul * v_plane[0]); + out[1] = p[1] - (mul * v_plane[1]); +} + /* project a vector on a plane defined by normal and a plane point p */ void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3]) { @@ -697,7 +728,19 @@ void bisect_v3_v3v3v3(float out[3], const float v1[3], const float v2[3], const /** * Returns a reflection vector from a vector and a normal vector - * reflect = vec - ((2 * DotVecs(vec, mirror)) * mirror) + * reflect = vec - ((2 * dot(vec, mirror)) * mirror). + * + * <pre> + * v + * + ^ + * \ | + * \| + * + normal: axis of reflection + * / + * / + * + + * out: result (negate for a 'bounce'). + * </pre> */ void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3]) { diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index f834c5b4c74..86c24307ae2 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -1394,6 +1394,11 @@ static float voronoi_CrS(float x, float y, float z) /* returns unsigned cellnoise */ static float cellNoiseU(float x, float y, float z) { + /* avoid precision issues on unit coordinates */ + x = (x + 0.000001f)*1.00001f; + y = (y + 0.000001f)*1.00001f; + z = (z + 0.000001f)*1.00001f; + int xi = (int)(floor(x)); int yi = (int)(floor(y)); int zi = (int)(floor(z)); @@ -1411,6 +1416,11 @@ float cellNoise(float x, float y, float z) /* returns a vector/point/color in ca, using point hasharray directly */ void cellNoiseV(float x, float y, float z, float ca[3]) { + /* avoid precision issues on unit coordinates */ + x = (x + 0.000001f)*1.00001f; + y = (y + 0.000001f)*1.00001f; + z = (z + 0.000001f)*1.00001f; + int xi = (int)(floor(x)); int yi = (int)(floor(y)); int zi = (int)(floor(z)); diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 7b765cfa939..4b3a74d02ae 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1173,22 +1173,10 @@ bool BLI_path_program_search( void BLI_setenv(const char *env, const char *val) { /* free windows */ -#if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS) - char *envstr; - if (val) - envstr = BLI_sprintfN("%s=%s", env, val); - else - envstr = BLI_sprintfN("%s=", env); - - putenv(envstr); - MEM_freeN(envstr); - - /* non-free windows */ -#elif (defined(WIN32) || defined(WIN64)) /* not free windows */ +#if (defined(WIN32) || defined(WIN64)) uputenv(env, val); - #else /* linux/osx/bsd */ if (val) @@ -1234,14 +1222,16 @@ void BLI_make_exist(char *dir) /** * Ensures that the parent directory of *name exists. + * + * \return true on success (i.e. given path now exists on FS), false otherwise. */ -void BLI_make_existing_file(const char *name) +bool BLI_make_existing_file(const char *name) { char di[FILE_MAX]; BLI_split_dir_part(name, di, sizeof(di)); /* make if the dir doesn't exist */ - BLI_dir_create_recursive(di); + return BLI_dir_create_recursive(di); } /** diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c index 2969b0eccf4..5f9b92198a5 100644 --- a/source/blender/blenlib/intern/polyfill2d.c +++ b/source/blender/blenlib/intern/polyfill2d.c @@ -105,24 +105,24 @@ typedef bool axis_t; /* use for sorting */ typedef struct KDTreeNode2D_head { - unsigned int neg, pos; - unsigned int index; + uint neg, pos; + uint index; } KDTreeNode2D_head; typedef struct KDTreeNode2D { - unsigned int neg, pos; - unsigned int index; + uint neg, pos; + uint index; axis_t axis; /* range is only (0-1) */ - unsigned short flag; - unsigned int parent; + ushort flag; + uint parent; } KDTreeNode2D; struct KDTree2D { KDTreeNode2D *nodes; const float (*coords)[2]; - unsigned int root; - unsigned int totnode; - unsigned int *nodes_map; /* index -> node lookup */ + uint root; + uint totnode; + uint *nodes_map; /* index -> node lookup */ }; struct KDRange2D { @@ -140,14 +140,14 @@ typedef struct PolyFill { struct PolyIndex *indices; /* vertex aligned */ const float (*coords)[2]; - unsigned int coords_tot; + uint coords_tot; #ifdef USE_CONVEX_SKIP - unsigned int coords_tot_concave; + uint coords_tot_concave; #endif /* A polygon with n vertices has a triangulation of n-2 triangles. */ - unsigned int (*tris)[3]; - unsigned int tris_tot; + uint (*tris)[3]; + uint tris_tot; #ifdef USE_KDTREE struct KDTree2D kdtree; @@ -158,7 +158,7 @@ typedef struct PolyFill { /* circular linklist */ typedef struct PolyIndex { struct PolyIndex *next, *prev; - unsigned int index; + uint index; eSign sign; } PolyIndex; @@ -212,7 +212,7 @@ static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float #ifdef USE_KDTREE -#define KDNODE_UNSET ((unsigned int)-1) +#define KDNODE_UNSET ((uint)-1) enum { KDNODE_FLAG_REMOVED = (1 << 0), @@ -220,7 +220,7 @@ enum { static void kdtree2d_new( struct KDTree2D *tree, - unsigned int tot, + uint tot, const float (*coords)[2]) { /* set by caller */ @@ -235,11 +235,11 @@ static void kdtree2d_new( */ static void kdtree2d_init( struct KDTree2D *tree, - const unsigned int coords_tot, + const uint coords_tot, const PolyIndex *indices) { KDTreeNode2D *node; - unsigned int i; + uint i; for (i = 0, node = tree->nodes; i < coords_tot; i++) { if (indices[i].sign != CONVEX) { @@ -251,15 +251,15 @@ static void kdtree2d_init( } } - BLI_assert(tree->totnode == (unsigned int)(node - tree->nodes)); + BLI_assert(tree->totnode == (uint)(node - tree->nodes)); } -static unsigned int kdtree2d_balance_recursive( - KDTreeNode2D *nodes, unsigned int totnode, axis_t axis, - const float (*coords)[2], const unsigned int ofs) +static uint kdtree2d_balance_recursive( + KDTreeNode2D *nodes, uint totnode, axis_t axis, + const float (*coords)[2], const uint ofs) { KDTreeNode2D *node; - unsigned int neg, pos, median, i, j; + uint neg, pos, median, i, j; if (totnode <= 0) { return KDNODE_UNSET; @@ -317,7 +317,7 @@ static void kdtree2d_balance( static void kdtree2d_init_mapping( struct KDTree2D *tree) { - unsigned int i; + uint i; KDTreeNode2D *node; for (i = 0, node = tree->nodes; i < tree->totnode; i++, node++) { @@ -338,9 +338,9 @@ static void kdtree2d_init_mapping( static void kdtree2d_node_remove( struct KDTree2D *tree, - unsigned int index) + uint index) { - unsigned int node_index = tree->nodes_map[index]; + uint node_index = tree->nodes_map[index]; KDTreeNode2D *node; if (node_index == KDNODE_UNSET) { @@ -362,7 +362,7 @@ static void kdtree2d_node_remove( { KDTreeNode2D *node_parent = &tree->nodes[node->parent]; - BLI_assert((unsigned int)(node - tree->nodes) == node_index); + BLI_assert((uint)(node - tree->nodes) == node_index); if (node_parent->neg == node_index) { node_parent->neg = KDNODE_UNSET; } @@ -383,7 +383,7 @@ static void kdtree2d_node_remove( static bool kdtree2d_isect_tri_recursive( const struct KDTree2D *tree, - const unsigned int tri_index[3], + const uint tri_index[3], const float *tri_coords[3], const float tri_center[2], const struct KDRange2D bounds[2], @@ -446,10 +446,10 @@ static bool kdtree2d_isect_tri_recursive( static bool kdtree2d_isect_tri( struct KDTree2D *tree, - const unsigned int ind[3]) + const uint ind[3]) { const float *vs[3]; - unsigned int i; + uint i; struct KDRange2D bounds[2] = { {FLT_MAX, -FLT_MAX}, {FLT_MAX, -FLT_MAX}, @@ -475,7 +475,7 @@ static bool kdtree2d_isect_tri( #endif /* USE_KDTREE */ -static unsigned int *pf_tri_add(PolyFill *pf) +static uint *pf_tri_add(PolyFill *pf) { return pf->tris[pf->tris_tot++]; } @@ -496,7 +496,7 @@ static void pf_coord_remove(PolyFill *pf, PolyIndex *pi) pf->indices = pi->next; } #ifdef DEBUG - pi->index = (unsigned int)-1; + pi->index = (uint)-1; pi->next = pi->prev = NULL; #endif @@ -594,7 +594,7 @@ static void pf_triangulate(PolyFill *pf) } if (pf->coords_tot == 3) { - unsigned int *tri = pf_tri_add(pf); + uint *tri = pf_tri_add(pf); pi_ear = pf->indices; tri[0] = pi_ear->index; pi_ear = pi_ear->next; tri[1] = pi_ear->index; pi_ear = pi_ear->next; @@ -627,10 +627,10 @@ static PolyIndex *pf_ear_tip_find( ) { /* localize */ - const unsigned int coords_tot = pf->coords_tot; + const uint coords_tot = pf->coords_tot; PolyIndex *pi_ear; - unsigned int i; + uint i; #ifdef USE_CLIP_EVEN pi_ear = pi_ear_init; @@ -688,7 +688,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) #endif #if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE) - unsigned int coords_tot_concave_checked = 0; + uint coords_tot_concave_checked = 0; #endif @@ -697,8 +697,8 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) #ifdef USE_CONVEX_SKIP_TEST /* check if counting is wrong */ { - unsigned int coords_tot_concave_test = 0; - unsigned int i = pf->coords_tot; + uint coords_tot_concave_test = 0; + uint i = pf->coords_tot; while (i--) { if (coords_sign[indices[i]] != CONVEX) { coords_tot_concave_test += 1; @@ -720,7 +720,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) #ifdef USE_KDTREE { - const unsigned int ind[3] = { + const uint ind[3] = { pi_ear_tip->index, pi_ear_tip->next->index, pi_ear_tip->prev->index}; @@ -771,7 +771,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip) static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip) { - unsigned int *tri = pf_tri_add(pf); + uint *tri = pf_tri_add(pf); tri[0] = pi_ear_tip->prev->index; tri[1] = pi_ear_tip->index; @@ -786,15 +786,15 @@ static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip) static void polyfill_prepare( PolyFill *pf, const float (*coords)[2], - const unsigned int coords_tot, + const uint coords_tot, int coords_sign, - unsigned int (*r_tris)[3], + uint (*r_tris)[3], PolyIndex *r_indices) { /* localize */ PolyIndex *indices = r_indices; - unsigned int i; + uint i; /* assign all polyfill members here */ pf->indices = r_indices; @@ -832,7 +832,7 @@ static void polyfill_prepare( } else { /* reversed */ - unsigned int n = coords_tot - 1; + uint n = coords_tot - 1; for (i = 0; i < coords_tot; i++) { indices[i].next = &indices[i + 1]; indices[i].prev = &indices[i - 1]; @@ -876,9 +876,9 @@ static void polyfill_calc( */ void BLI_polyfill_calc_arena( const float (*coords)[2], - const unsigned int coords_tot, + const uint coords_tot, const int coords_sign, - unsigned int (*r_tris)[3], + uint (*r_tris)[3], struct MemArena *arena) { @@ -932,9 +932,9 @@ void BLI_polyfill_calc_arena( */ void BLI_polyfill_calc( const float (*coords)[2], - const unsigned int coords_tot, + const uint coords_tot, const int coords_sign, - unsigned int (*r_tris)[3]) + uint (*r_tris)[3]) { PolyFill pf; PolyIndex *indices = BLI_array_alloca(indices, coords_tot); diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index fd24a00156d..e0c4cbe9990 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -693,6 +693,14 @@ void BLI_rcti_rctf_copy_floor(rcti *dst, const rctf *src) dst->ymax = floorf(src->ymax); } +void BLI_rcti_rctf_copy_round(rcti *dst, const rctf *src) +{ + dst->xmin = floorf(src->xmin + 0.5f); + dst->xmax = floorf(src->xmax + 0.5f); + dst->ymin = floorf(src->ymin + 0.5f); + dst->ymax = floorf(src->ymax + 0.5f); +} + void BLI_rctf_rcti_copy(rctf *dst, const rcti *src) { dst->xmin = src->xmin; diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 3edc00a8c1a..b819c513fbd 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -113,7 +113,7 @@ double BLI_dir_free_space(const char *dir) #ifdef WIN32 DWORD sectorspc, bytesps, freec, clusters; char tmp[4]; - + tmp[0] = '\\'; tmp[1] = 0; /* Just a failsafe */ if (dir[0] == '/' || dir[0] == '\\') { tmp[0] = '\\'; @@ -139,10 +139,10 @@ double BLI_dir_free_space(const char *dir) char name[FILE_MAXDIR], *slash; int len = strlen(dir); - + if (len >= FILE_MAXDIR) /* path too long */ return -1; - + strcpy(name, dir); if (len) { @@ -194,7 +194,7 @@ size_t BLI_file_size(const char *path) */ int BLI_exists(const char *name) { -#if defined(WIN32) +#if defined(WIN32) BLI_stat_t st; wchar_t *tmp_16 = alloc_utf16_from_8(name, 1); int len, res; @@ -253,10 +253,8 @@ int BLI_stat(const char *path, BLI_stat_t *buffer) int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer) { -#if defined(_MSC_VER) || defined(__MINGW64__) +#if defined(_MSC_VER) return _wstat64(path, buffer); -#elif defined(__MINGW32__) - return _wstati64(path, buffer); #else return _wstat(path, buffer); #endif @@ -372,7 +370,7 @@ LinkNode *BLI_file_read_as_lines(const char *name) size_t size; if (!fp) return NULL; - + fseek(fp, 0, SEEK_END); size = (size_t)ftell(fp); fseek(fp, 0, SEEK_SET); @@ -385,7 +383,7 @@ LinkNode *BLI_file_read_as_lines(const char *name) buf = MEM_mallocN(size, "file_as_lines"); if (buf) { size_t i, last = 0; - + /* * size = because on win32 reading * all the bytes in the file will return @@ -403,10 +401,10 @@ LinkNode *BLI_file_read_as_lines(const char *name) last = i + 1; } } - + MEM_freeN(buf); } - + fclose(fp); return lines.list; @@ -424,23 +422,13 @@ void BLI_file_free_lines(LinkNode *lines) bool BLI_file_older(const char *file1, const char *file2) { #ifdef WIN32 -#ifndef __MINGW32__ struct _stat st1, st2; -#else - struct _stati64 st1, st2; -#endif UTF16_ENCODE(file1); UTF16_ENCODE(file2); - -#ifndef __MINGW32__ + if (_wstat(file1_16, &st1)) return false; if (_wstat(file2_16, &st2)) return false; -#else - if (_wstati64(file1_16, &st1)) return false; - if (_wstati64(file2_16, &st2)) return false; -#endif - UTF16_UN_ENCODE(file2); UTF16_UN_ENCODE(file1); diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index f62ffe9e985..6022732025b 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -332,7 +332,7 @@ size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const siz goto escape_finish; case '\\': case '"': - /* fall-through */ + ATTR_FALLTHROUGH; /* less common but should also be support */ case '\t': @@ -346,7 +346,7 @@ size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const siz /* not enough space to escape */ break; } - /* fall-through */ + ATTR_FALLTHROUGH; default: *dst = *src; break; diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 83d4a75952f..229a97a2fa7 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -167,7 +167,7 @@ utf8_error: /** * Remove any invalid utf-8 byte (taking into account multi-bytes sequence of course). * - * @return number of stripped bytes. + * \return number of stripped bytes. */ int BLI_utf8_invalid_strip(char *str, size_t length) { @@ -205,11 +205,11 @@ int BLI_utf8_invalid_strip(char *str, size_t length) while (*src != '\0' && (utf8_size = utf8_skip_data[*src]) < maxncpy) {\ maxncpy -= utf8_size; \ switch (utf8_size) { \ - case 6: *dst ++ = *src ++; \ - case 5: *dst ++ = *src ++; \ - case 4: *dst ++ = *src ++; \ - case 3: *dst ++ = *src ++; \ - case 2: *dst ++ = *src ++; \ + case 6: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ + case 5: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ + case 4: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ + case 3: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ + case 2: *dst ++ = *src ++; ATTR_FALLTHROUGH; \ case 1: *dst ++ = *src ++; \ } \ } \ diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c index 297d0f0b310..e050f3148b8 100644 --- a/source/blender/blenlib/intern/task.c +++ b/source/blender/blenlib/intern/task.c @@ -52,7 +52,14 @@ * * This allows thread to fetch next task without locking the whole queue. */ -#define LOCALQUEUE_SIZE 1 +#define LOCAL_QUEUE_SIZE 1 + +/* Number of tasks which are allowed to be scheduled in a delayed manner. + * + * This allows to use less locks per graph node children schedule. More details + * could be found at TaskThreadLocalStorage::do_delayed_push. + */ +#define DELAYED_QUEUE_SIZE 4096 #ifndef NDEBUG # define ASSERT_THREAD_ID(scheduler, thread_id) \ @@ -129,9 +136,28 @@ typedef struct TaskMemPoolStats { #endif typedef struct TaskThreadLocalStorage { + /* Memory pool for faster task allocation. + * The idea is to re-use memory of finished/discarded tasks by this thread. + */ TaskMemPool task_mempool; + + /* Local queue keeps thread alive by keeping small amount of tasks ready + * to be picked up without causing global thread locks for synchronization. + */ int num_local_queue; - Task *local_queue[LOCALQUEUE_SIZE]; + Task *local_queue[LOCAL_QUEUE_SIZE]; + + /* Thread can be marked for delayed tasks push. This is helpful when it's + * know that lots of subsequent task pushed will happen from the same thread + * without "interrupting" for task execution. + * + * We try to accumulate as much tasks as possible in a local queue without + * any locks first, and then we push all of them into a scheduler's queue + * from within a single mutex lock. + */ + bool do_delayed_push; + int num_delayed_queue; + Task *delayed_queue[DELAYED_QUEUE_SIZE]; } TaskThreadLocalStorage; struct TaskPool { @@ -162,6 +188,16 @@ struct TaskPool { */ int thread_id; + /* For the pools which are created from non-main thread which is not a + * scheduler worker thread we can't re-use any of scheduler's threads TLS + * and have to use our own one. + */ + bool use_local_tls; + TaskThreadLocalStorage local_tls; +#ifndef NDEBUG + pthread_t creator_thread_id; +#endif + #ifdef DEBUG_STATS TaskMemPoolStats *mempool_stats; #endif @@ -202,13 +238,25 @@ BLI_INLINE void task_data_free(Task *task, const int thread_id) } } +BLI_INLINE void initialize_task_tls(TaskThreadLocalStorage *tls) +{ + memset(tls, 0, sizeof(TaskThreadLocalStorage)); +} + BLI_INLINE TaskThreadLocalStorage *get_task_tls(TaskPool *pool, const int thread_id) { TaskScheduler *scheduler = pool->scheduler; BLI_assert(thread_id >= 0); BLI_assert(thread_id <= scheduler->num_threads); + if (pool->use_local_tls && thread_id == 0) { + BLI_assert(pool->thread_id == 0); + BLI_assert(!BLI_thread_is_main()); + BLI_assert(pthread_equal(pthread_self(), pool->creator_thread_id)); + return &pool->local_tls; + } if (thread_id == 0) { + BLI_assert(BLI_thread_is_main()); return &scheduler->task_threads[pool->thread_id].tls; } return &scheduler->task_threads[thread_id].tls; @@ -252,6 +300,9 @@ static void task_free(TaskPool *pool, Task *task, const int thread_id) task_data_free(task, thread_id); BLI_assert(thread_id >= 0); BLI_assert(thread_id <= pool->scheduler->num_threads); + if (thread_id == 0) { + BLI_assert(pool->use_local_tls || BLI_thread_is_main()); + } TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); TaskMemPool *task_mempool = &tls->task_mempool; if (task_mempool->num_tasks < MEMPOOL_SIZE - 1) { @@ -353,6 +404,7 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, const int thread_id) { + BLI_assert(!tls->do_delayed_push); while (tls->num_local_queue > 0) { /* We pop task from queue before handling it so handler of the task can * push next job to the local queue. @@ -366,6 +418,7 @@ BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, local_task->run(local_pool, local_task->taskdata, thread_id); task_free(local_pool, local_task, thread_id); } + BLI_assert(!tls->do_delayed_push); } static void *task_scheduler_thread_run(void *thread_p) @@ -383,7 +436,9 @@ static void *task_scheduler_thread_run(void *thread_p) TaskPool *pool = task->pool; /* run task */ + BLI_assert(!tls->do_delayed_push); task->run(pool, task->taskdata, thread_id); + BLI_assert(!tls->do_delayed_push); /* delete task */ task_free(pool, task, thread_id); @@ -424,9 +479,12 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads) num_threads = 1; } - scheduler->task_threads = MEM_callocN(sizeof(TaskThread) * (num_threads + 1), + scheduler->task_threads = MEM_mallocN(sizeof(TaskThread) * (num_threads + 1), "TaskScheduler task threads"); + /* Initialize TLS for main thread. */ + initialize_task_tls(&scheduler->task_threads[0].tls); + pthread_key_create(&scheduler->tls_id_key, NULL); /* launch threads that will be waiting for work */ @@ -440,6 +498,7 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads) TaskThread *thread = &scheduler->task_threads[i + 1]; thread->scheduler = scheduler; thread->id = i + 1; + initialize_task_tls(&thread->tls); if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) { fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads); @@ -518,6 +577,27 @@ static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriori BLI_mutex_unlock(&scheduler->queue_mutex); } +static void task_scheduler_push_all(TaskScheduler *scheduler, + TaskPool *pool, + Task **tasks, + int num_tasks) +{ + if (num_tasks == 0) { + return; + } + + task_pool_num_increase(pool, num_tasks); + + BLI_mutex_lock(&scheduler->queue_mutex); + + for (int i = 0; i < num_tasks; i++) { + BLI_addhead(&scheduler->queue, tasks[i]); + } + + BLI_condition_notify_all(&scheduler->queue_cond); + BLI_mutex_unlock(&scheduler->queue_mutex); +} + static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool) { Task *task, *nexttask; @@ -572,6 +652,7 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, pool->num_suspended = 0; pool->suspended_queue.first = pool->suspended_queue.last = NULL; pool->run_in_background = is_background; + pool->use_local_tls = false; BLI_mutex_init(&pool->num_mutex); BLI_condition_init(&pool->num_cond); @@ -584,13 +665,18 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, } else { TaskThread *thread = pthread_getspecific(scheduler->tls_id_key); - /* NOTE: It is possible that pool is created from non-main thread - * which isn't a scheduler thread. In this case pthread's TLS will - * be NULL and we can safely consider thread id 0 for the main - * thread of this pool (the one which does wort_and_wait()). - */ if (thread == NULL) { + /* NOTE: Task pool is created from non-main thread which is not + * managed by the task scheduler. We identify ourselves as thread ID + * 0 but we do not use scheduler's TLS storage and use our own + * instead to avoid any possible threading conflicts. + */ pool->thread_id = 0; + pool->use_local_tls = true; +#ifndef NDEBUG + pool->creator_thread_id = pthread_self(); +#endif + initialize_task_tls(&pool->local_tls); } else { pool->thread_id = thread->id; @@ -670,43 +756,68 @@ void BLI_task_pool_free(TaskPool *pool) MEM_freeN(pool->mempool_stats); #endif + if (pool->use_local_tls) { + free_task_tls(&pool->local_tls); + } + MEM_freeN(pool); BLI_end_threaded_malloc(); } +BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id) +{ + return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work)); +} + static void task_pool_push( TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata, TaskPriority priority, int thread_id) { + /* Allocate task and fill it's properties. */ Task *task = task_alloc(pool, thread_id); - task->run = run; task->taskdata = taskdata; task->free_taskdata = free_taskdata; task->freedata = freedata; task->pool = pool; - + /* For suspended pools we put everything yo a global queue first + * and exit as soon as possible. + * + * This tasks will be moved to actual execution when pool is + * activated by work_and_wait(). + */ if (pool->is_suspended) { BLI_addhead(&pool->suspended_queue, task); atomic_fetch_and_add_z(&pool->num_suspended, 1); return; } - - if (thread_id != -1 && - (thread_id != pool->thread_id || pool->do_work)) - { + /* Populate to any local queue first, this is cheapest push ever. */ + if (task_can_use_local_queues(pool, thread_id)) { ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - if (tls->num_local_queue < LOCALQUEUE_SIZE) { + /* Try to push to a local execution queue. + * These tasks will be picked up next. + */ + if (tls->num_local_queue < LOCAL_QUEUE_SIZE) { tls->local_queue[tls->num_local_queue] = task; tls->num_local_queue++; return; } + /* If we are in the delayed tasks push mode, we push tasks to a + * temporary local queue first without any locks, and then move them + * to global execution queue with a single lock. + */ + if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) { + tls->delayed_queue[tls->num_delayed_queue] = task; + tls->num_delayed_queue++; + return; + } } - + /* Do push to a global execution ppol, slowest possible method, + * causes quite reasonable amount of threading overhead. + */ task_scheduler_push(pool->scheduler, task, priority); } @@ -777,7 +888,9 @@ void BLI_task_pool_work_and_wait(TaskPool *pool) /* if found task, do it, otherwise wait until other tasks are done */ if (found_task) { /* run task */ + BLI_assert(!tls->do_delayed_push); work_task->run(pool, work_task->taskdata, pool->thread_id); + BLI_assert(!tls->do_delayed_push); /* delete task */ task_free(pool, task, pool->thread_id); @@ -832,6 +945,30 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool) return &pool->user_mutex; } +void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id) +{ + if (task_can_use_local_queues(pool, thread_id)) { + ASSERT_THREAD_ID(pool->scheduler, thread_id); + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + tls->do_delayed_push = true; + } +} + +void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id) +{ + if (task_can_use_local_queues(pool, thread_id)) { + ASSERT_THREAD_ID(pool->scheduler, thread_id); + TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); + BLI_assert(tls->do_delayed_push); + task_scheduler_push_all(pool->scheduler, + pool, + tls->delayed_queue, + tls->num_delayed_queue); + tls->do_delayed_push = false; + tls->num_delayed_queue = 0; + } +} + /* Parallel range routines */ /** @@ -990,7 +1127,7 @@ static void task_parallel_range_ex( atomic_fetch_and_add_uint32((uint32_t *)(&state.iter), 0); if (use_userdata_chunk) { - userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); + userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); } for (i = 0; i < num_tasks; i++) { diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 77da3be0600..abf611d1245 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -813,6 +813,11 @@ void BLI_begin_threaded_malloc(void) unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); if (level == 0) { MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); + /* There is a little chance that two threads will meed to acces to a + * scheduler which was not yet created from main thread. which could + * cause scheduler created multiple times. + */ + BLI_task_scheduler_get(); } } diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c index 3b06b7df09a..d6834428376 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -160,8 +160,6 @@ void RegisterBlendExtension(void) GetSystemDirectory(SysDir, FILE_MAXDIR); #ifdef _WIN64 ThumbHandlerDLL = "BlendThumb64.dll"; -#elif defined(__MINGW32__) - ThumbHandlerDLL = "BlendThumb.dll"; #else IsWow64Process(GetCurrentProcess(), &IsWOW64); if (IsWOW64 == true) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 09c88ac945a..f224f0b5633 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -129,6 +129,7 @@ #include "BKE_library_idmap.h" #include "BKE_library_query.h" #include "BKE_idcode.h" +#include "BKE_idprop.h" #include "BKE_material.h" #include "BKE_main.h" // for Main #include "BKE_mesh.h" // for ME_ defines (patching) @@ -2001,7 +2002,7 @@ static void test_pointer_array(FileData *fd, void **mat) /* ************ READ ID Properties *************** */ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData *fd); -static void IDP_LibLinkProperty(IDProperty *prop, int switch_endian, FileData *fd); +static void IDP_LibLinkProperty(IDProperty *prop, FileData *fd); static void IDP_DirectLinkIDPArray(IDProperty *prop, int switch_endian, FileData *fd) { @@ -2106,8 +2107,19 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData BLI_endian_switch_int32(&prop->data.val2); BLI_endian_switch_int64((int64_t *)&prop->data.val); } - break; + case IDP_INT: + case IDP_FLOAT: + case IDP_ID: + break; /* Nothing special to do here. */ + default: + /* Unknown IDP type, nuke it (we cannot handle unknown types everywhere in code, + * IDP are way too polymorphic to do it safely. */ + printf("%s: found unknown IDProperty type %d, reset to Integer one !\n", __func__, prop->type); + /* Note: we do not attempt to free unknown prop, we have no way to know how to do that! */ + prop->type = IDP_INT; + prop->subtype = 0; + IDP_Int(prop) = 0; } } @@ -2132,10 +2144,39 @@ static void _IDP_DirectLinkGroup_OrFree(IDProperty **prop, int switch_endian, Fi } } -/* stub function */ -static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endian), FileData *UNUSED(fd)) +static void IDP_LibLinkProperty(IDProperty *prop, FileData *fd) { - /* Should we do something here, prop should be ensured to be non-NULL first... */ + if (!prop) + return; + + switch (prop->type) { + case IDP_ID: /* PointerProperty */ + { + void *newaddr = newlibadr_us(fd, NULL, IDP_Id(prop)); + if (IDP_Id(prop) && !newaddr && G.debug) { + printf("Error while loading \"%s\". Data not found in file!\n", prop->name); + } + prop->data.pointer = newaddr; + break; + } + case IDP_IDPARRAY: /* CollectionProperty */ + { + IDProperty *idp_array = IDP_IDPArray(prop); + for (int i = 0; i < prop->len; i++) { + IDP_LibLinkProperty(&(idp_array[i]), fd); + } + break; + } + case IDP_GROUP: /* PointerProperty */ + { + for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) { + IDP_LibLinkProperty(loop, fd); + } + break; + } + default: + break; /* Nothing to do for other IDProps. */ + } } /* ************ READ IMAGE PREVIEW *************** */ @@ -2195,7 +2236,7 @@ static void lib_link_brush(FileData *fd, Main *main) /* only link ID pointers */ for (Brush *brush = main->brush.first; brush; brush = brush->id.next) { if (brush->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(brush->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(brush->id.properties, fd); /* brush->(mask_)mtex.obj is ignored on purpose? */ brush->mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mtex.tex); @@ -2232,7 +2273,7 @@ static void lib_link_palette(FileData *fd, Main *main) /* only link ID pointers */ for (Palette *palette = main->palettes.first; palette; palette = palette->id.next) { if (palette->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(palette->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(palette->id.properties, fd); palette->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -2250,7 +2291,7 @@ static void lib_link_paint_curve(FileData *fd, Main *main) /* only link ID pointers */ for (PaintCurve *pc = main->paintcurves.first; pc; pc = pc->id.next) { if (pc->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(pc->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(pc->id.properties, fd); pc->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -2505,7 +2546,7 @@ static void lib_link_action(FileData *fd, Main *main) { for (bAction *act = main->action.first; act; act = act->id.next) { if (act->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(act->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(act->id.properties, fd); // XXX deprecated - old animation system <<< for (bActionChannel *chan = act->chanbase.first; chan; chan = chan->next) { @@ -2712,7 +2753,7 @@ static void lib_link_cachefiles(FileData *fd, Main *bmain) /* only link ID pointers */ for (CacheFile *cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) { if (cache_file->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(cache_file->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(cache_file->id.properties, fd); lib_link_animdata(fd, &cache_file->id, cache_file->adt); cache_file->id.tag &= ~LIB_TAG_NEED_LINK; @@ -2746,20 +2787,13 @@ static void direct_link_motionpath(FileData *fd, bMotionPath *mpath) /* ************ READ NODE TREE *************** */ -static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock) -{ - /* Link ID Properties -- and copy this comment EXACTLY for easy finding - * of library blocks that implement this.*/ - IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); -} - /* Single node tree (also used for material/scene trees), ntree is not NULL */ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree) { bNode *node; bNodeSocket *sock; - IDP_LibLinkProperty(ntree->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(ntree->id.properties, fd); lib_link_animdata(fd, &ntree->id, ntree->adt); ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd); @@ -2767,27 +2801,23 @@ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree) for (node = ntree->nodes.first; node; node = node->next) { /* Link ID Properties -- and copy this comment EXACTLY for easy finding * of library blocks that implement this.*/ - IDP_LibLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(node->prop, fd); node->id = newlibadr_us(fd, id->lib, node->id); for (sock = node->inputs.first; sock; sock = sock->next) { - IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - lib_link_node_socket(fd, id, sock); + IDP_LibLinkProperty(sock->prop, fd); } for (sock = node->outputs.first; sock; sock = sock->next) { - IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - lib_link_node_socket(fd, id, sock); + IDP_LibLinkProperty(sock->prop, fd); } } for (sock = ntree->inputs.first; sock; sock = sock->next) { - IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - lib_link_node_socket(fd, id, sock); + IDP_LibLinkProperty(sock->prop, fd); } for (sock = ntree->outputs.first; sock; sock = sock->next) { - IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - lib_link_node_socket(fd, id, sock); + IDP_LibLinkProperty(sock->prop, fd); } } @@ -3090,7 +3120,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) else if (ntree->type==NTREE_COMPOSIT) { if (ELEM(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) direct_link_curvemapping(fd, node->storage); - else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) + else if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) ((ImageUser *)node->storage)->ok = 1; } else if ( ntree->type==NTREE_TEXTURE) { @@ -3292,6 +3322,8 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name); + IDP_LibLinkProperty(pchan->prop, fd); + pchan->custom = newlibadr_us(fd, arm->id.lib, pchan->custom); if (UNLIKELY(pchan->bone == NULL)) { rebuild = true; @@ -3312,13 +3344,26 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) } } +static void lib_link_bones(FileData *fd, Bone *bone) +{ + IDP_LibLinkProperty(bone->prop, fd); + + for (Bone *curbone = bone->childbase.first; curbone; curbone = curbone->next) { + lib_link_bones(fd, curbone); + } +} + static void lib_link_armature(FileData *fd, Main *main) { for (bArmature *arm = main->armature.first; arm; arm = arm->id.next) { if (arm->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(arm->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(arm->id.properties, fd); lib_link_animdata(fd, &arm->id, arm->adt); + for (Bone *curbone = arm->bonebase.first; curbone; curbone = curbone->next) { + lib_link_bones(fd, curbone); + } + arm->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -3365,7 +3410,7 @@ static void lib_link_camera(FileData *fd, Main *main) { for (Camera *ca = main->camera.first; ca; ca = ca->id.next) { if (ca->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(ca->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(ca->id.properties, fd); lib_link_animdata(fd, &ca->id, ca->adt); ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX deprecated - old animation system @@ -3390,7 +3435,7 @@ static void lib_link_lamp(FileData *fd, Main *main) { for (Lamp *la = main->lamp.first; la; la = la->id.next) { if (la->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(la->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(la->id.properties, fd); lib_link_animdata(fd, &la->id, la->adt); for (int a = 0; a < MAX_MTEX; a++) { @@ -3455,7 +3500,7 @@ static void lib_link_key(FileData *fd, Main *main) BLI_assert((key->id.tag & LIB_TAG_EXTERN) == 0); if (key->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(key->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(key->id.properties, fd); lib_link_animdata(fd, &key->id, key->adt); key->ipo = newlibadr_us(fd, key->id.lib, key->ipo); // XXX deprecated - old animation system @@ -3520,7 +3565,7 @@ static void lib_link_mball(FileData *fd, Main *main) { for (MetaBall *mb = main->mball.first; mb; mb = mb->id.next) { if (mb->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(mb->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(mb->id.properties, fd); lib_link_animdata(fd, &mb->id, mb->adt); for (int a = 0; a < mb->totcol; a++) { @@ -3556,7 +3601,7 @@ static void lib_link_world(FileData *fd, Main *main) { for (World *wrld = main->world.first; wrld; wrld = wrld->id.next) { if (wrld->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(wrld->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(wrld->id.properties, fd); lib_link_animdata(fd, &wrld->id, wrld->adt); wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX deprecated - old animation system @@ -3607,7 +3652,7 @@ static void lib_link_vfont(FileData *fd, Main *main) { for (VFont *vf = main->vfont.first; vf; vf = vf->id.next) { if (vf->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(vf->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(vf->id.properties, fd); vf->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -3627,7 +3672,7 @@ static void lib_link_text(FileData *fd, Main *main) { for (Text *text = main->text.first; text; text = text->id.next) { if (text->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(text->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(text->id.properties, fd); text->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -3679,7 +3724,7 @@ static void lib_link_image(FileData *fd, Main *main) { for (Image *ima = main->image.first; ima; ima = ima->id.next) { if (ima->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(ima->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(ima->id.properties, fd); ima->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -3746,7 +3791,7 @@ static void lib_link_curve(FileData *fd, Main *main) { for (Curve *cu = main->curve.first; cu; cu = cu->id.next) { if (cu->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(cu->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(cu->id.properties, fd); lib_link_animdata(fd, &cu->id, cu->adt); for (int a = 0; a < cu->totcol; a++) { @@ -3838,7 +3883,7 @@ static void lib_link_texture(FileData *fd, Main *main) { for (Tex *tex = main->tex.first; tex; tex = tex->id.next) { if (tex->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(tex->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(tex->id.properties, fd); lib_link_animdata(fd, &tex->id, tex->adt); tex->ima = newlibadr_us(fd, tex->id.lib, tex->ima); @@ -3916,12 +3961,12 @@ static void lib_link_material(FileData *fd, Main *main) { for (Material *ma = main->mat.first; ma; ma = ma->id.next) { if (ma->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(ma->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(ma->id.properties, fd); lib_link_animdata(fd, &ma->id, ma->adt); /* Link ID Properties -- and copy this comment EXACTLY for easy finding * of library blocks that implement this.*/ - IDP_LibLinkProperty(ma->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(ma->id.properties, fd); ma->ipo = newlibadr_us(fd, ma->id.lib, ma->ipo); // XXX deprecated - old animation system ma->group = newlibadr_us(fd, ma->id.lib, ma->group); @@ -4060,7 +4105,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main) { for (ParticleSettings *part = main->particle.first; part; part = part->id.next) { if (part->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(part->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(part->id.properties, fd); lib_link_animdata(fd, &part->id, part->adt); part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX deprecated - old animation system @@ -4382,7 +4427,7 @@ static void lib_link_mesh(FileData *fd, Main *main) /* Link ID Properties -- and copy this comment EXACTLY for easy finding * of library blocks that implement this.*/ - IDP_LibLinkProperty(me->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(me->id.properties, fd); lib_link_animdata(fd, &me->id, me->adt); /* this check added for python created meshes */ @@ -4657,7 +4702,7 @@ static void lib_link_latt(FileData *fd, Main *main) { for (Lattice *lt = main->latt.first; lt; lt = lt->id.next) { if (lt->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(lt->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(lt->id.properties, fd); lib_link_animdata(fd, <->id, lt->adt); lt->ipo = newlibadr_us(fd, lt->id.lib, lt->ipo); // XXX deprecated - old animation system @@ -4707,7 +4752,7 @@ static void lib_link_object(FileData *fd, Main *main) if (ob->id.tag & LIB_TAG_NEED_LINK) { int a; - IDP_LibLinkProperty(ob->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(ob->id.properties, fd); lib_link_animdata(fd, &ob->id, ob->adt); // XXX deprecated - old animation system <<< @@ -5675,7 +5720,7 @@ static void lib_link_scene(FileData *fd, Main *main) if (sce->id.tag & LIB_TAG_NEED_LINK) { /* Link ID Properties -- and copy this comment EXACTLY for easy finding * of library blocks that implement this.*/ - IDP_LibLinkProperty(sce->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(sce->id.properties, fd); lib_link_animdata(fd, &sce->id, sce->adt); lib_link_keyingsets(fd, &sce->id, &sce->keyingsets); @@ -5728,6 +5773,8 @@ static void lib_link_scene(FileData *fd, Main *main) Sequence *seq; SEQ_BEGIN (sce->ed, seq) { + IDP_LibLinkProperty(seq->prop, fd); + if (seq->ipo) seq->ipo = newlibadr_us(fd, sce->id.lib, seq->ipo); // XXX deprecated - old animation system seq->scene_sound = NULL; if (seq->scene) { @@ -6049,9 +6096,13 @@ static void direct_link_scene(FileData *fd, Scene *sce) seq->strip->transform = NULL; } if (seq->flag & SEQ_USE_PROXY) { - seq->strip->proxy = newdataadr( - fd, seq->strip->proxy); - seq->strip->proxy->anim = NULL; + seq->strip->proxy = newdataadr(fd, seq->strip->proxy); + if (seq->strip->proxy) { + seq->strip->proxy->anim = NULL; + } + else { + BKE_sequencer_proxy_set(seq, true); + } } else { seq->strip->proxy = NULL; @@ -6126,6 +6177,11 @@ static void direct_link_scene(FileData *fd, Scene *sce) link_list(fd, &(sce->r.layers)); link_list(fd, &(sce->r.views)); + + for (srl = sce->r.layers.first; srl; srl = srl->next) { + srl->prop = newdataadr(fd, srl->prop); + IDP_DirectLinkGroup_OrFree(&srl->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + } for (srl = sce->r.layers.first; srl; srl = srl->next) { link_list(fd, &(srl->freestyleConfig.modules)); } @@ -6258,7 +6314,7 @@ static void lib_link_gpencil(FileData *fd, Main *main) { for (bGPdata *gpd = main->gpencil.first; gpd; gpd = gpd->id.next) { if (gpd->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(gpd->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(gpd->id.properties, fd); lib_link_animdata(fd, &gpd->id, gpd->adt); gpd->id.tag &= ~LIB_TAG_NEED_LINK; @@ -6325,7 +6381,7 @@ static void lib_link_screen(FileData *fd, Main *main) { for (bScreen *sc = main->screen.first; sc; sc = sc->id.next) { if (sc->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(sc->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(sc->id.properties, fd); id_us_ensure_real(&sc->id); sc->scene = newlibadr(fd, sc->id.lib, sc->scene); @@ -7411,7 +7467,7 @@ static void lib_link_speaker(FileData *fd, Main *main) { for (Speaker *spk = main->speaker.first; spk; spk = spk->id.next) { if (spk->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(spk->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(spk->id.properties, fd); lib_link_animdata(fd, &spk->id, spk->adt); spk->sound = newlibadr_us(fd, spk->id.lib, spk->sound); @@ -7467,7 +7523,7 @@ static void lib_link_sound(FileData *fd, Main *main) { for (bSound *sound = main->sound.first; sound; sound = sound->id.next) { if (sound->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(sound->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(sound->id.properties, fd); sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system @@ -7490,7 +7546,7 @@ static void lib_link_group(FileData *fd, Main *main) { for (Group *group = main->group.first; group; group = group->id.next) { if (group->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(group->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(group->id.properties, fd); bool add_us = false; @@ -7616,7 +7672,7 @@ static void lib_link_movieclip(FileData *fd, Main *main) if (clip->id.tag & LIB_TAG_NEED_LINK) { MovieTracking *tracking = &clip->tracking; - IDP_LibLinkProperty(clip->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(clip->id.properties, fd); lib_link_animdata(fd, &clip->id, clip->adt); clip->gpd = newlibadr_us(fd, clip->id.lib, clip->gpd); @@ -7703,7 +7759,7 @@ static void lib_link_mask(FileData *fd, Main *main) { for (Mask *mask = main->mask.first; mask; mask = mask->id.next) { if (mask->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(mask->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(mask->id.properties, fd); lib_link_animdata(fd, &mask->id, mask->adt); for (MaskLayer *masklay = mask->masklayers.first; masklay; masklay = masklay->next) { @@ -7738,7 +7794,7 @@ static void lib_link_linestyle(FileData *fd, Main *main) if (linestyle->id.tag & LIB_TAG_NEED_LINK) { LineStyleModifier *m; - IDP_LibLinkProperty(linestyle->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_LibLinkProperty(linestyle->id.properties, fd); lib_link_animdata(fd, &linestyle->id, linestyle->adt); for (m = linestyle->color_modifiers.first; m; m = m->next) { @@ -8633,7 +8689,8 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ case ID_SCRN: bhead->code = ID_SCR; - /* deliberate pass on to default */ + /* pass on to default */ + ATTR_FALLTHROUGH; default: if (fd->skip_flags & BLO_READ_SKIP_DATA) { bhead = blo_nextbhead(fd, bhead); @@ -8905,6 +8962,31 @@ static void expand_constraint_channels(FileData *fd, Main *mainvar, ListBase *ch } } +static void expand_idprops(FileData *fd, Main *mainvar, IDProperty *prop) +{ + if (!prop) + return; + + switch (prop->type) { + case IDP_ID: + expand_doit(fd, mainvar, IDP_Id(prop)); + break; + case IDP_IDPARRAY: + { + IDProperty *idp_array = IDP_IDPArray(prop); + for (int i = 0; i < prop->len; i++) { + expand_idprops(fd, mainvar, &idp_array[i]); + } + break; + } + case IDP_GROUP: + for (IDProperty *loop = prop->data.group.first; loop; loop = loop->next) { + expand_idprops(fd, mainvar, loop); + } + break; + } +} + static void expand_fmodifiers(FileData *fd, Main *mainvar, ListBase *list) { FModifier *fcm; @@ -9090,6 +9172,7 @@ static void expand_key(FileData *fd, Main *mainvar, Key *key) static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) { bNode *node; + bNodeSocket *sock; if (ntree->adt) expand_animdata(fd, mainvar, ntree->adt); @@ -9098,10 +9181,22 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) expand_doit(fd, mainvar, ntree->gpd); for (node = ntree->nodes.first; node; node = node->next) { - if (node->id && node->type != CMP_NODE_R_LAYERS) + if (node->id && node->type != CMP_NODE_R_LAYERS) { expand_doit(fd, mainvar, node->id); + } + + expand_idprops(fd, mainvar, node->prop); + + for (sock = node->inputs.first; sock; sock = sock->next) + expand_doit(fd, mainvar, sock->prop); + for (sock = node->outputs.first; sock; sock = sock->next) + expand_doit(fd, mainvar, sock->prop); } + for (sock = ntree->inputs.first; sock; sock = sock->next) + expand_doit(fd, mainvar, sock->prop); + for (sock = ntree->outputs.first; sock; sock = sock->next) + expand_doit(fd, mainvar, sock->prop); } static void expand_texture(FileData *fd, Main *mainvar, Tex *tex) @@ -9319,17 +9414,6 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb) } } -#if 0 /* Disabled as it doesn't actually do anything except recurse... */ -static void expand_bones(FileData *fd, Main *mainvar, Bone *bone) -{ - Bone *curBone; - - for (curBone = bone->childbase.first; curBone; curBone=curBone->next) { - expand_bones(fd, mainvar, curBone); - } -} -#endif - static void expand_pose(FileData *fd, Main *mainvar, bPose *pose) { bPoseChannel *chan; @@ -9339,24 +9423,28 @@ static void expand_pose(FileData *fd, Main *mainvar, bPose *pose) for (chan = pose->chanbase.first; chan; chan = chan->next) { expand_constraints(fd, mainvar, &chan->constraints); + expand_idprops(fd, mainvar, chan->prop); expand_doit(fd, mainvar, chan->custom); } } +static void expand_bones(FileData *fd, Main *mainvar, Bone *bone) +{ + expand_idprops(fd, mainvar, bone->prop); + + for (Bone *curBone = bone->childbase.first; curBone; curBone = curBone->next) { + expand_bones(fd, mainvar, curBone); + } +} + static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm) -{ +{ if (arm->adt) expand_animdata(fd, mainvar, arm->adt); - -#if 0 /* Disabled as this currently only recurses down the chain doing nothing */ - { - Bone *curBone; - - for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) { - expand_bones(fd, mainvar, curBone); - } + + for (Bone *curBone = arm->bonebase.first; curBone; curBone = curBone->next) { + expand_bones(fd, mainvar, curBone); } -#endif } static void expand_object_expandModifiers( @@ -9584,6 +9672,8 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) SEQ_BEGIN (sce->ed, seq) { + expand_idprops(fd, mainvar, seq->prop); + if (seq->scene) expand_doit(fd, mainvar, seq->scene); if (seq->scene_camera) expand_doit(fd, mainvar, seq->scene_camera); if (seq->clip) expand_doit(fd, mainvar, seq->clip); @@ -9741,6 +9831,8 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) id = lbarray[a]->first; while (id) { if (id->tag & LIB_TAG_NEED_EXPAND) { + expand_idprops(fd, mainvar, id->properties); + switch (GS(id->name)) { case ID_OB: expand_object(fd, mainvar, (Object *)id); @@ -10067,7 +10159,7 @@ void BLO_library_link_copypaste(Main *mainl, BlendHandle *bh) static ID *link_named_part_ex( Main *mainl, FileData *fd, const short idcode, const char *name, const short flag, - Scene *scene, View3D *v3d, const bool use_placeholders, const bool force_indirect) + Scene *scene, View3D *v3d, const bool use_placeholders, const bool force_indirect) { ID *id = link_named_part(mainl, fd, idcode, name, use_placeholders, force_indirect); diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index ab3d14af882..77542d8deb9 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -1000,7 +1000,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main) { /* convert extended ascii to utf-8 for text editor */ Text *text; - for (text = main->text.first; text; text = text->id.next) + for (text = main->text.first; text; text = text->id.next) { if (!(text->flags & TXT_ISEXT)) { TextLine *tl; @@ -1013,6 +1013,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *main) text->curc = 0; } } + } } { /* set new dynamic paint values */ diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index d3f33cf725f..94d335870ca 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -80,6 +80,7 @@ #include "NOD_common.h" #include "NOD_socket.h" +#include "NOD_composite.h" #include "readfile.h" @@ -248,6 +249,41 @@ static void do_version_hue_sat_node(bNodeTree *ntree, bNode *node) node->storage = NULL; } +static void do_versions_compositor_render_passes_storage(bNode *node) +{ + int pass_index = 0; + const char *sockname; + for (bNodeSocket *sock = node->outputs.first; sock && pass_index < 31; sock = sock->next, pass_index++) { + if (sock->storage == NULL) { + NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); + sock->storage = sockdata; + BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(pass_index), sizeof(sockdata->pass_name)); + + if (pass_index == 0) sockname = "Image"; + else if (pass_index == 1) sockname = "Alpha"; + else sockname = node_cmp_rlayers_sock_to_pass(pass_index); + BLI_strncpy(sock->name, sockname, sizeof(sock->name)); + } + } +} + +static void do_versions_compositor_render_passes(bNodeTree *ntree) +{ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS) { + /* First we make sure existing sockets have proper names. + * This is important because otherwise verification will + * drop links from sockets which were renamed. + */ + do_versions_compositor_render_passes_storage(node); + /* Make sure new sockets are properly created. */ + node_verify_socket_templates(ntree, node); + /* Make sure all possibly created sockets have proper storage. */ + do_versions_compositor_render_passes_storage(node); + } + } +} + void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) { if (!MAIN_VERSION_ATLEAST(main, 270, 0)) { @@ -1200,12 +1236,19 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) SEQ_BEGIN (scene->ed, seq) { - if (seq->type == SEQ_TYPE_TEXT) { - TextVars *data = seq->effectdata; - if (data->color[3] == 0.0f) { - copy_v4_fl(data->color, 1.0f); - data->shadow_color[3] = 1.0f; - } + if (seq->type != SEQ_TYPE_TEXT) { + continue; + } + + if (seq->effectdata == NULL) { + struct SeqEffectHandle effect_handle = BKE_sequence_get_effect(seq); + effect_handle.init(seq); + } + + TextVars *data = seq->effectdata; + if (data->color[3] == 0.0f) { + copy_v4_fl(data->color, 1.0f); + data->shadow_color[3] = 1.0f; } } SEQ_END @@ -1259,7 +1302,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) for (Camera *camera = main->camera.first; camera != NULL; camera = camera->id.next) { if (camera->stereo.pole_merge_angle_from == 0.0f && - camera->stereo.pole_merge_angle_to == 0.0f) + camera->stereo.pole_merge_angle_to == 0.0f) { camera->stereo.pole_merge_angle_from = DEG2RADF(60.0f); camera->stereo.pole_merge_angle_to = DEG2RADF(75.0f); @@ -1559,8 +1602,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } - /* To be added to next subversion bump! */ - { + if (!MAIN_VERSION_ATLEAST(main, 278, 5)) { /* Mask primitive adding code was not initializing correctly id_type of its points' parent. */ for (Mask *mask = main->mask.first; mask; mask = mask->id.next) { for (MaskLayer *mlayer = mask->masklayers.first; mlayer; mlayer = mlayer->next) { @@ -1609,6 +1651,25 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_COMPOSIT) { + do_versions_compositor_render_passes(ntree); + } + } FOREACH_NODETREE_END + } + + { + for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { + if (scene->r.im_format.exr_codec == R_IMF_EXR_CODEC_DWAB) { + scene->r.im_format.exr_codec = R_IMF_EXR_CODEC_DWAA; + } + } + + /* Fix related to VGroup modifiers creating named defgroup CD layers! See T51520. */ + for (Mesh *me = main->mesh.first; me; me = me->id.next) { + CustomData_set_layer_name(&me->vdata, CD_MDEFORMVERT, 0, ""); + } } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index e34f12b1cf9..e7e0054e7a1 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -242,13 +242,13 @@ void BLO_update_defaults_startup_blend(Main *bmain) /* remove polish brush (flatten/contrast does the same) */ br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Polish"); if (br) { - BKE_libblock_free(bmain, br); + BKE_libblock_delete(bmain, br); } /* remove brush brush (huh?) from some modes (draw brushes do the same) */ br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Brush"); if (br) { - BKE_libblock_free(bmain, br); + BKE_libblock_delete(bmain, br); } /* remove draw brush from texpaint (draw brushes do the same) */ diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index f2d42849bcc..c29ffbb76f2 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -2296,11 +2296,12 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) /* during 2.41 images with this name were used for viewer node output, lets fix that */ if (main->versionfile == 241) { Image *ima; - for (ima = main->image.first; ima; ima = ima->id.next) + for (ima = main->image.first; ima; ima = ima->id.next) { if (STREQ(ima->name, "Compositor")) { strcpy(ima->id.name + 2, "Viewer Node"); strcpy(ima->name, "Viewer Node"); } + } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 57be237be6f..ee9665dc834 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1052,7 +1052,7 @@ static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree) writestruct(wd, DATA, NodeImageMultiFileSocket, 1, sock->storage); } } - if (node->type == CMP_NODE_IMAGE) { + if (ELEM(node->type, CMP_NODE_IMAGE, CMP_NODE_R_LAYERS)) { /* write extra socket info */ for (sock = node->outputs.first; sock; sock = sock->next) { writestruct(wd, DATA, NodeImageLayer, 1, sock->storage); @@ -1317,8 +1317,8 @@ static void write_particlesettings(WriteData *wd, ParticleSettings *part) dw->index = 0; if (part->dup_group) { /* can be NULL if lining fails or set to None */ for (GroupObject *go = part->dup_group->gobject.first; - go && go->ob != dw->ob; - go = go->next, dw->index++); + go && go->ob != dw->ob; + go = go->next, dw->index++); } } writestruct(wd, DATA, ParticleDupliWeight, 1, dw); @@ -2244,8 +2244,9 @@ static void write_mesh(WriteData *wd, Mesh *mesh) * outside of save process itself. * Maybe we can live with this, though? */ - mesh->totface = BKE_mesh_mpoly_to_mface(&mesh->fdata, &old_mesh->ldata, &old_mesh->pdata, - mesh->totface, old_mesh->totloop, old_mesh->totpoly); + mesh->totface = BKE_mesh_mpoly_to_mface( + &mesh->fdata, &old_mesh->ldata, &old_mesh->pdata, + mesh->totface, old_mesh->totloop, old_mesh->totpoly); BKE_mesh_update_customdata_pointers(mesh, false); @@ -2654,8 +2655,8 @@ static void write_scene(WriteData *wd, Scene *sce) } if (seq->type == SEQ_TYPE_IMAGE) { writestruct(wd, DATA, StripElem, - MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem), - strip->stripdata); + MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem), + strip->stripdata); } else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) { writestruct(wd, DATA, StripElem, 1, strip->stripdata); @@ -2710,6 +2711,9 @@ static void write_scene(WriteData *wd, Scene *sce) for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) { writestruct(wd, DATA, SceneRenderLayer, 1, srl); + if (srl->prop) { + IDP_WriteProperty(srl->prop, wd); + } for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc); } @@ -3362,13 +3366,13 @@ static void write_mask(WriteData *wd, Mask *mask) } for (masklay_shape = masklay->splines_shapes.first; - masklay_shape; - masklay_shape = masklay_shape->next) + masklay_shape; + masklay_shape = masklay_shape->next) { writestruct(wd, DATA, MaskLayerShape, 1, masklay_shape); writedata(wd, DATA, - masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, - masklay_shape->data); + masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE, + masklay_shape->data); } } } @@ -3854,7 +3858,7 @@ static bool write_file_handle( write_scene(wd, (Scene *)id); break; case ID_CU: - write_curve(wd,(Curve *)id); + write_curve(wd, (Curve *)id); break; case ID_MB: write_mball(wd, (MetaBall *)id); diff --git a/source/blender/blentranslation/CMakeLists.txt b/source/blender/blentranslation/CMakeLists.txt index a3e85344027..c0dce5b4f0d 100644 --- a/source/blender/blentranslation/CMakeLists.txt +++ b/source/blender/blentranslation/CMakeLists.txt @@ -60,3 +60,5 @@ if(WIN32) endif() blender_add_lib(bf_blentranslation "${SRC}" "${INC}" "${INC_SYS}") + +add_subdirectory(msgfmt) diff --git a/source/blender/blentranslation/msgfmt/CMakeLists.txt b/source/blender/blentranslation/msgfmt/CMakeLists.txt new file mode 100644 index 00000000000..d2cb6f5a03b --- /dev/null +++ b/source/blender/blentranslation/msgfmt/CMakeLists.txt @@ -0,0 +1,50 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2017, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Bastien Montagne. +# +# ***** END GPL LICENSE BLOCK ***** + +# ----------------------------------------------------------------------------- +# Build msgfmt executable + +blender_include_dirs( + ../../../../intern/guardedalloc + ../../blenlib +) + +set(SRC + msgfmt.c +) + +add_cc_flags_custom_test(msgfmt) + +add_executable(msgfmt ${SRC}) + +target_link_libraries(msgfmt bf_blenlib) +target_link_libraries(msgfmt bf_intern_guardedalloc) + +if(WIN32) + target_link_libraries(msgfmt bf_intern_utfconv) +endif() + +target_link_libraries(msgfmt ${ZLIB_LIBRARIES}) +target_link_libraries(msgfmt ${PLATFORM_LINKLIBS}) diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c new file mode 100644 index 00000000000..487d9fee7b4 --- /dev/null +++ b/source/blender/blentranslation/msgfmt/msgfmt.c @@ -0,0 +1,464 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Bastien Montagne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/* + * Based on C++ version by Sergey Sharybin <sergey.vfx@gmail.com>. + * Based on Python script msgfmt.py from Python source code tree, which was written by + * Martin v. Löwis <loewis@informatik.hu-berlin.de> + * + * Generate binary message catalog from textual translation description. + * + * This program converts a textual Uniforum-style message catalog (.po file) into a binary GNU catalog (.mo file). + * This is essentially the same function as the GNU msgfmt program, however, it is a simpler implementation. + * + * Usage: msgfmt input.po output.po + */ + +#include <string.h> +#include <stdlib.h> + +#include "BLI_utildefines.h" +#include "BLI_dynstr.h" +#include "BLI_fileops.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_memarena.h" + +#include "MEM_guardedalloc.h" + + +/* Stupid stub necessary because some BLI files includes winstuff.h, which uses G a bit... */ +#ifdef WIN32 + typedef struct Global { + void *dummy; + } Global; + + Global G; +#endif + + +/* We cannot use NULL char until ultimate step, would give nightmare to our C string processing... + * Using one of the UTF-8 invalid bytes (as per our BLI string_utf8.c) */ +#define NULLSEP_STR "\xff" +#define NULLSEP_CHR '\xff' + +typedef enum { + SECTION_NONE = 0, + SECTION_CTX = 1, + SECTION_ID = 2, + SECTION_STR = 3, +} eSectionType; + +typedef struct Message { + DynStr *ctxt; + DynStr *id; + DynStr *str; + + bool is_fuzzy; +} Message; + +static char *trim(char *str) +{ + const size_t len = strlen(str); + size_t i; + + if (len == 0) { + return str; + } + + for (i = 0; i < len && ELEM(str[0], ' ', '\t', '\n'); str++, i++); + + char *end = &str[len - 1 - i]; + for (i = len; i > 0 && ELEM(end[0], ' ', '\t', '\n'); end--, i--); + end[1] = '\0'; + + return str; +} + +static char *unescape(char *str) +{ + char *curr, *next; + for (curr = next = str; next[0] != '\0'; curr++, next++) { + if (next[0] == '\\') { + switch (next[1]) { + case '\0': + /* Get rid of trailing escape char... */ + curr--; + break; + case '\\': + *curr = '\\'; + next++; + break; + case 'n': + *curr = '\n'; + next++; + break; + case 't': + *curr = '\t'; + next++; + break; + default: + /* Get rid of useless escape char. */ + next++; + *curr = *next; + } + } + else if (curr != next) { + *curr = *next; + } + } + *curr = '\0'; + + if (str[0] == '"' && *(curr - 1) == '"') { + *(curr - 1) = '\0'; + return str + 1; + } + return str; +} + +static int qsort_str_cmp(const void *a, const void *b) +{ + return strcmp(*(const char **)a, *(const char **)b); +} + +static char **get_keys_sorted(GHash *messages, const uint32_t num_keys) +{ + GHashIterator iter; + + char **keys = MEM_mallocN(sizeof(*keys) * num_keys, __func__); + char **k = keys; + + GHASH_ITER(iter, messages) { + *k = BLI_ghashIterator_getKey(&iter); + k++; + } + + qsort(keys, num_keys, sizeof(*keys), qsort_str_cmp); + + return keys; +} + +BLI_INLINE size_t uint32_to_bytes(const int value, char *bytes) { + size_t i; + for (i = 0; i < sizeof(value); i++) { + bytes[i] = (char) ((value >> ((int)i * 8)) & 0xff); + } + return i; +} + +BLI_INLINE size_t msg_to_bytes(char *msg, char *bytes, uint32_t size) { + /* Note that we also perform replacing of our NULLSEP placeholder by real NULL char... */ + size_t i; + for (i = 0; i < size; i++, msg++, bytes++) { + *bytes = (*msg == NULLSEP_CHR) ? '\0' : *msg; + } + return i; +} + +typedef struct Offset { + uint32_t key_offset, key_len, val_offset, val_len; +} Offset; + +/* Return the generated binary output. */ +static char *generate(GHash *messages, size_t *r_output_size) { + const uint32_t num_keys = BLI_ghash_size(messages); + + /* Get list of sorted keys. */ + char **keys = get_keys_sorted(messages, num_keys); + char **vals = MEM_mallocN(sizeof(*vals) * num_keys, __func__); + uint32_t tot_keys_len = 0; + uint32_t tot_vals_len = 0; + + Offset *offsets = MEM_mallocN(sizeof(*offsets) * num_keys, __func__); + + for (int i = 0; i < num_keys; i++) { + Offset *off = &offsets[i]; + + vals[i] = BLI_ghash_lookup(messages, keys[i]); + + /* For each string, we need size and file offset. + * Each string is NULL terminated; the NULL does not count into the size. */ + off->key_offset = tot_keys_len; + off->key_len = (uint32_t)strlen(keys[i]); + tot_keys_len += off->key_len + 1; + + off->val_offset = tot_vals_len; + off->val_len = (uint32_t)strlen(vals[i]); + tot_vals_len += off->val_len + 1; + } + + /* The header is 7 32-bit unsigned integers. then comes the keys index table, then the values index table. */ + const uint32_t idx_keystart = 7 * 4; + const uint32_t idx_valstart = idx_keystart + 8 * num_keys; + /* We don't use hash tables, so the keys start right after the index tables. */ + const uint32_t keystart = idx_valstart + 8 * num_keys; + /* and the values start after the keys */ + const uint32_t valstart = keystart + tot_keys_len; + + /* Final buffer representing the binary MO file. */ + *r_output_size = valstart + tot_vals_len; + char *output = MEM_mallocN(*r_output_size, __func__); + char *h = output; + char *ik = output + idx_keystart; + char *iv = output + idx_valstart; + char *k = output + keystart; + char *v = output + valstart; + + h += uint32_to_bytes(0x950412de, h); /* Magic */ + h += uint32_to_bytes(0x0, h); /* Version */ + h += uint32_to_bytes(num_keys, h); /* Number of entries */ + h += uint32_to_bytes(idx_keystart, h); /* Start of key index */ + h += uint32_to_bytes(idx_valstart, h); /* Start of value index */ + h += uint32_to_bytes(0, h); /* Size of hash table */ + h += uint32_to_bytes(0, h); /* Offset of hash table */ + + BLI_assert(h == ik); + + for (int i = 0; i < num_keys; i++) { + Offset *off = &offsets[i]; + + /* The index table first has the list of keys, then the list of values. + * Each entry has first the size of the string, then the file offset. */ + ik += uint32_to_bytes(off->key_len, ik); + ik += uint32_to_bytes(off->key_offset + keystart, ik); + iv += uint32_to_bytes(off->val_len, iv); + iv += uint32_to_bytes(off->val_offset + valstart, iv); + + k += msg_to_bytes(keys[i], k, off->key_len + 1); + v += msg_to_bytes(vals[i], v, off->val_len + 1); + } + + BLI_assert(ik == output + idx_valstart); + BLI_assert(iv == output + keystart); + BLI_assert(k == output + valstart); + + MEM_freeN(keys); + MEM_freeN(vals); + MEM_freeN(offsets); + + return output; +} + +/* Add a non-fuzzy translation to the dictionary. */ +static void add(GHash *messages, MemArena *memarena, const Message *msg) +{ + const size_t msgctxt_len = (size_t)BLI_dynstr_get_len(msg->ctxt); + const size_t msgid_len = (size_t)BLI_dynstr_get_len(msg->id); + const size_t msgstr_len = (size_t)BLI_dynstr_get_len(msg->str); + const size_t msgkey_len = msgid_len + ((msgctxt_len == 0) ? 0 : msgctxt_len + 1); + + if (!msg->is_fuzzy && msgstr_len != 0) { + char *msgkey = BLI_memarena_alloc(memarena, sizeof(*msgkey) * (msgkey_len + 1)); + char *msgstr = BLI_memarena_alloc(memarena, sizeof(*msgstr) * (msgstr_len + 1)); + + if (msgctxt_len != 0) { + BLI_dynstr_get_cstring_ex(msg->ctxt, msgkey); + msgkey[msgctxt_len] = '\x04'; /* Context/msgid separator */ + BLI_dynstr_get_cstring_ex(msg->id, &msgkey[msgctxt_len + 1]); + } + else { + BLI_dynstr_get_cstring_ex(msg->id, msgkey); + } + + BLI_dynstr_get_cstring_ex(msg->str, msgstr); + + BLI_ghash_insert(messages, msgkey, msgstr); + } +} + + +static void clear(Message *msg) +{ + BLI_dynstr_clear(msg->ctxt); + BLI_dynstr_clear(msg->id); + BLI_dynstr_clear(msg->str); + msg->is_fuzzy = false; +} + +static int make(const char *input_file_name, const char *output_file_name) +{ + GHash *messages = BLI_ghash_new(BLI_ghashutil_strhash_p_murmur, BLI_ghashutil_strcmp, __func__); + MemArena *msgs_memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + + const char *msgctxt_kw = "msgctxt"; + const char *msgid_kw = "msgid"; + const char *msgid_plural_kw = "msgid_plural"; + const char *msgstr_kw = "msgstr"; + const size_t msgctxt_len = strlen(msgctxt_kw); + const size_t msgid_len = strlen(msgid_kw); + const size_t msgid_plural_len = strlen(msgid_plural_kw); + const size_t msgstr_len = strlen(msgstr_kw); + + /* Note: For now, we assume file encoding is always utf-8. */ + + eSectionType section = SECTION_NONE; + bool is_plural = false; + + Message msg = { + .ctxt = BLI_dynstr_new_memarena(), + .id = BLI_dynstr_new_memarena(), + .str = BLI_dynstr_new_memarena(), + .is_fuzzy = false, + }; + + LinkNode *input_file_lines = BLI_file_read_as_lines(input_file_name); + LinkNode *ifl = input_file_lines; + + /* Parse the catalog. */ + for (int lno = 1; ifl; ifl = ifl->next, lno++) { + char *l = ifl->link; + const bool is_comment = (l[0] == '#'); + /* If we get a comment line after a msgstr, this is a new entry. */ + if (is_comment) { + if (section == SECTION_STR) { + add(messages, msgs_memarena, &msg); + clear(&msg); + section = SECTION_NONE; + } + /* Record a fuzzy mark. */ + if (l[1] == ',' && strstr(l, "fuzzy") != NULL) { + msg.is_fuzzy = true; + } + /* Skip comments */ + continue; + } + if (strstr(l, msgctxt_kw) == l) { + if (section == SECTION_STR) { + /* New message, output previous section. */ + add(messages, msgs_memarena, &msg); + } + if (!ELEM(section, SECTION_NONE, SECTION_STR)) { + printf("msgctxt not at start of new message on %s:%d\n", input_file_name, lno); + return EXIT_FAILURE; + } + section = SECTION_CTX; + l = l + msgctxt_len; + clear(&msg); + } + else if (strstr(l, msgid_plural_kw) == l) { + /* This is a message with plural forms. */ + if (section != SECTION_ID) { + printf("msgid_plural not preceeded by msgid on %s:%d\n", input_file_name, lno); + return EXIT_FAILURE; + } + l = l + msgid_plural_len; + BLI_dynstr_append(msg.id, NULLSEP_STR); /* separator of singular and plural */ + is_plural = true; + } + else if (strstr(l, msgid_kw) == l) { + if (section == SECTION_STR) { + add(messages, msgs_memarena, &msg); + } + if (section != SECTION_CTX) { + clear(&msg); + } + section = SECTION_ID; + l = l + msgid_len; + is_plural = false; + } + else if (strstr(l, msgstr_kw) == l) { + l = l + msgstr_len; + // Now we are in a msgstr section + section = SECTION_STR; + if (l[0] == '[') { + if (!is_plural) { + printf("plural without msgid_plural on %s:%d\n", input_file_name, lno); + return EXIT_FAILURE; + } + if ((l = strchr(l, ']')) == NULL) { + printf("Syntax error on %s:%d\n", input_file_name, lno); + return EXIT_FAILURE; + } + if (BLI_dynstr_get_len(msg.str) != 0) { + BLI_dynstr_append(msg.str, NULLSEP_STR); /* Separator of the various plural forms. */ + } + } + else { + if (is_plural) { + printf("indexed msgstr required for plural on %s:%d\n", input_file_name, lno); + return EXIT_FAILURE; + } + } + } + /* Skip empty lines. */ + l = trim(l); + if (l[0] == '\0') { + if (section == SECTION_STR) { + add(messages, msgs_memarena, &msg); + clear(&msg); + } + section = SECTION_NONE; + continue; + } + l = unescape(l); + if (section == SECTION_CTX) { + BLI_dynstr_append(msg.ctxt, l); + } + else if (section == SECTION_ID) { + BLI_dynstr_append(msg.id, l); + } + else if (section == SECTION_STR) { + BLI_dynstr_append(msg.str, l); + } + else { + printf("Syntax error on %s:%d\n", input_file_name, lno); + return EXIT_FAILURE; + } + } + /* Add last entry */ + if (section == SECTION_STR) { + add(messages, msgs_memarena, &msg); + } + + BLI_dynstr_free(msg.ctxt); + BLI_dynstr_free(msg.id); + BLI_dynstr_free(msg.str); + BLI_file_free_lines(input_file_lines); + + /* Compute output */ + size_t output_size; + char *output = generate(messages, &output_size); + + FILE *fp = BLI_fopen(output_file_name, "wb"); + fwrite(output, 1, output_size, fp); + fclose(fp); + + MEM_freeN(output); + BLI_ghash_free(messages, NULL, NULL); + BLI_memarena_free(msgs_memarena); + + return EXIT_SUCCESS; +} + +int main(int argc, char **argv) { + if (argc != 3) { + printf("Usage: %s <input.po> <output.mo>\n", argv[0]); + return EXIT_FAILURE; + } + const char *input_file = argv[1]; + const char *output_file = argv[2]; + + return make(input_file, output_file); +} diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 104df625ee6..64a5cad812a 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -225,7 +225,7 @@ typedef struct BMesh { /* operator api stuff (must be all NULL or all alloc'd) */ struct BLI_mempool *vtoolflagpool, *etoolflagpool, *ftoolflagpool; - unsigned int use_toolflags : 1; + uint use_toolflags : 1; int toolflag_index; struct BMOperator *currentop; @@ -382,7 +382,7 @@ typedef bool (*BMLoopFilterFunc)(const BMLoop *, void *user_data); (assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset)))) #define BM_ELEM_CD_GET_FLOAT_AS_UCHAR(ele, offset) \ - (assert(offset != -1), (unsigned char)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f)) + (assert(offset != -1), (uchar)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f)) /*forward declarations*/ diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.c b/source/blender/bmesh/intern/bmesh_callback_generic.c index 913255bfb33..e9304e8536f 100644 --- a/source/blender/bmesh/intern/bmesh_callback_generic.c +++ b/source/blender/bmesh/intern/bmesh_callback_generic.c @@ -32,7 +32,7 @@ bool BM_elem_cb_check_hflag_ex(BMElem *ele, void *user_data) { - const unsigned int hflag_pair = GET_INT_FROM_POINTER(user_data); + const uint hflag_pair = GET_INT_FROM_POINTER(user_data); const char hflag_p = (hflag_pair & 0xff); const char hflag_n = (hflag_pair >> 8); diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index e46a31cb2e9..f8ecbe1756b 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -154,7 +154,7 @@ void BM_face_copy_shared( if (l_other && l_other != l_iter) { BMLoop *l_src[2]; BMLoop *l_dst[2] = {l_iter, l_iter->next}; - unsigned int j; + uint j; if (l_other->v == l_iter->v) { l_src[0] = l_other; @@ -311,7 +311,7 @@ BMFace *BM_face_create_ngon_verts( const bool calc_winding, const bool create_edges) { BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); - unsigned int winding[2] = {0, 0}; + uint winding[2] = {0, 0}; int i, i_prev = len - 1; BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]}; diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c index 5e1d9c3a98d..5780dc57d78 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.c +++ b/source/blender/bmesh/intern/bmesh_edgeloop.c @@ -58,7 +58,7 @@ static int bm_vert_other_tag( { BMIter iter; BMEdge *e, *e_next = NULL; - unsigned int count = 0; + uint count = 0; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) { diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 0551d824131..ab066682081 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -211,12 +211,12 @@ void *BMO_iter_as_arrayN( int BM_iter_mesh_bitmap_from_filter( const char itype, BMesh *bm, - unsigned int *bitmap, + uint *bitmap, bool (*test_fn)(BMElem *, void *user_data), void *user_data); int BM_iter_mesh_bitmap_from_filter_tessface( BMesh *bm, - unsigned int *bitmap, + uint *bitmap, bool (*test_fn)(BMFace *, void *user_data), void *user_data); diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 2591c33fc73..1d16dbc1836 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -88,7 +88,7 @@ struct BMLog { /* Mapping from unique IDs to vertices and faces * - * Each vertex and face in the log gets a unique unsigned integer + * Each vertex and face in the log gets a unique uinteger * assigned. That ID is taken from the set managed by the * unused_ids range tree. * @@ -120,7 +120,7 @@ typedef struct { } BMLogVert; typedef struct { - unsigned int v_ids[3]; + uint v_ids[3]; char hflag; } BMLogFace; @@ -131,14 +131,14 @@ typedef struct { #define logkey_cmp BLI_ghashutil_intcmp /* Get the vertex's unique ID from the log */ -static unsigned int bm_log_vert_id_get(BMLog *log, BMVert *v) +static uint bm_log_vert_id_get(BMLog *log, BMVert *v) { BLI_assert(BLI_ghash_haskey(log->elem_to_id, v)); return GET_UINT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, v)); } /* Set the vertex's unique ID in the log */ -static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id) +static void bm_log_vert_id_set(BMLog *log, BMVert *v, uint id) { void *vid = SET_UINT_IN_POINTER(id); @@ -147,7 +147,7 @@ static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id) } /* Get a vertex from its unique ID */ -static BMVert *bm_log_vert_from_id(BMLog *log, unsigned int id) +static BMVert *bm_log_vert_from_id(BMLog *log, uint id) { void *key = SET_UINT_IN_POINTER(id); BLI_assert(BLI_ghash_haskey(log->id_to_elem, key)); @@ -155,14 +155,14 @@ static BMVert *bm_log_vert_from_id(BMLog *log, unsigned int id) } /* Get the face's unique ID from the log */ -static unsigned int bm_log_face_id_get(BMLog *log, BMFace *f) +static uint bm_log_face_id_get(BMLog *log, BMFace *f) { BLI_assert(BLI_ghash_haskey(log->elem_to_id, f)); return GET_UINT_FROM_POINTER(BLI_ghash_lookup(log->elem_to_id, f)); } /* Set the face's unique ID in the log */ -static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id) +static void bm_log_face_id_set(BMLog *log, BMFace *f, uint id) { void *fid = SET_UINT_IN_POINTER(id); @@ -171,7 +171,7 @@ static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id) } /* Get a face from its unique ID */ -static BMFace *bm_log_face_from_id(BMLog *log, unsigned int id) +static BMFace *bm_log_face_from_id(BMLog *log, uint id) { void *key = SET_UINT_IN_POINTER(id); BLI_assert(BLI_ghash_haskey(log->id_to_elem, key)); @@ -255,7 +255,7 @@ static void bm_log_verts_unmake(BMesh *bm, BMLog *log, GHash *verts) GHASH_ITER (gh_iter, verts) { void *key = BLI_ghashIterator_getKey(&gh_iter); BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); - unsigned int id = GET_UINT_FROM_POINTER(key); + uint id = GET_UINT_FROM_POINTER(key); BMVert *v = bm_log_vert_from_id(log, id); /* Ensure the log has the final values of the vertex before @@ -271,7 +271,7 @@ static void bm_log_faces_unmake(BMesh *bm, BMLog *log, GHash *faces) GHashIterator gh_iter; GHASH_ITER (gh_iter, faces) { void *key = BLI_ghashIterator_getKey(&gh_iter); - unsigned int id = GET_UINT_FROM_POINTER(key); + uint id = GET_UINT_FROM_POINTER(key); BMFace *f = bm_log_face_from_id(log, id); BMEdge *e_tri[3]; BMLoop *l_iter; @@ -333,7 +333,7 @@ static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts) GHASH_ITER (gh_iter, verts) { void *key = BLI_ghashIterator_getKey(&gh_iter); BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); - unsigned int id = GET_UINT_FROM_POINTER(key); + uint id = GET_UINT_FROM_POINTER(key); BMVert *v = bm_log_vert_from_id(log, id); float mask; short normal[3]; @@ -355,7 +355,7 @@ static void bm_log_face_values_swap(BMLog *log, GHash *faces) GHASH_ITER (gh_iter, faces) { void *key = BLI_ghashIterator_getKey(&gh_iter); BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter); - unsigned int id = GET_UINT_FROM_POINTER(key); + uint id = GET_UINT_FROM_POINTER(key); BMFace *f = bm_log_face_from_id(log, id); SWAP(char, f->head.hflag, lf->hflag); @@ -374,13 +374,13 @@ static void bm_log_assign_ids(BMesh *bm, BMLog *log) /* Generate vertex IDs */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - unsigned int id = range_tree_uint_take_any(log->unused_ids); + uint id = range_tree_uint_take_any(log->unused_ids); bm_log_vert_id_set(log, v, id); } /* Generate face IDs */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - unsigned int id = range_tree_uint_take_any(log->unused_ids); + uint id = range_tree_uint_take_any(log->unused_ids); bm_log_face_id_set(log, f, id); } } @@ -425,7 +425,7 @@ static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash) GHASH_ITER (gh_iter, id_ghash) { void *key = BLI_ghashIterator_getKey(&gh_iter); - unsigned int id = GET_UINT_FROM_POINTER(key); + uint id = GET_UINT_FROM_POINTER(key); range_tree_uint_retake(unused_ids, id); } @@ -433,8 +433,8 @@ static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash) static int uint_compare(const void *a_v, const void *b_v) { - const unsigned int *a = a_v; - const unsigned int *b = b_v; + const uint *a = a_v; + const uint *b = b_v; return (*a) < (*b); } @@ -446,10 +446,10 @@ static int uint_compare(const void *a_v, const void *b_v) * 10 -> 3 * 3 -> 1 */ -static GHash *bm_log_compress_ids_to_indices(unsigned int *ids, unsigned int totid) +static GHash *bm_log_compress_ids_to_indices(uint *ids, uint totid) { GHash *map = BLI_ghash_int_new_ex(__func__, totid); - unsigned int i; + uint i; qsort(ids, totid, sizeof(*ids), uint_compare); @@ -469,7 +469,7 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash) GHASH_ITER (gh_iter, id_ghash) { void *key = BLI_ghashIterator_getKey(&gh_iter); - unsigned int id = GET_UINT_FROM_POINTER(key); + uint id = GET_UINT_FROM_POINTER(key); range_tree_uint_release(log->unused_ids, id); } } @@ -480,7 +480,7 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash) BMLog *BM_log_create(BMesh *bm) { BMLog *log = MEM_callocN(sizeof(*log), __func__); - const unsigned int reserve_num = (unsigned int)(bm->totvert + bm->totface); + const uint reserve_num = (uint)(bm->totvert + bm->totface); log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1); log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num); @@ -593,8 +593,8 @@ int BM_log_length(const BMLog *log) /* Apply a consistent ordering to BMesh vertices */ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) { - unsigned int *varr; - unsigned int *farr; + uint *varr; + uint *farr; GHash *id_to_idx; @@ -602,7 +602,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) BMVert *v; BMFace *f; - unsigned int i; + uint i; /* Put all vertex IDs into an array */ varr = MEM_mallocN(sizeof(int) * (size_t)bm->totvert, __func__); @@ -617,7 +617,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) } /* Create BMVert index remap array */ - id_to_idx = bm_log_compress_ids_to_indices(varr, (unsigned int)bm->totvert); + id_to_idx = bm_log_compress_ids_to_indices(varr, (uint)bm->totvert); BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) { const unsigned id = bm_log_vert_id_get(log, v); const void *key = SET_UINT_IN_POINTER(id); @@ -627,7 +627,7 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log) BLI_ghash_free(id_to_idx, NULL, NULL); /* Create BMFace index remap array */ - id_to_idx = bm_log_compress_ids_to_indices(farr, (unsigned int)bm->totface); + id_to_idx = bm_log_compress_ids_to_indices(farr, (uint)bm->totface); BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) { const unsigned id = bm_log_face_id_get(log, f); const void *key = SET_UINT_IN_POINTER(id); @@ -835,7 +835,7 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o { BMLogEntry *entry = log->current_entry; BMLogVert *lv; - unsigned int v_id = bm_log_vert_id_get(log, v); + uint v_id = bm_log_vert_id_get(log, v); void *key = SET_UINT_IN_POINTER(v_id); void **val_p; @@ -859,7 +859,7 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset) { BMLogVert *lv; - unsigned int v_id = range_tree_uint_take_any(log->unused_ids); + uint v_id = range_tree_uint_take_any(log->unused_ids); void *key = SET_UINT_IN_POINTER(v_id); bm_log_vert_id_set(log, v, v_id); @@ -876,7 +876,7 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset) void BM_log_face_modified(BMLog *log, BMFace *f) { BMLogFace *lf; - unsigned int f_id = bm_log_face_id_get(log, f); + uint f_id = bm_log_face_id_get(log, f); void *key = SET_UINT_IN_POINTER(f_id); lf = bm_log_face_alloc(log, f); @@ -892,7 +892,7 @@ void BM_log_face_modified(BMLog *log, BMFace *f) void BM_log_face_added(BMLog *log, BMFace *f) { BMLogFace *lf; - unsigned int f_id = range_tree_uint_take_any(log->unused_ids); + uint f_id = range_tree_uint_take_any(log->unused_ids); void *key = SET_UINT_IN_POINTER(f_id); /* Only triangles are supported for now */ @@ -922,7 +922,7 @@ void BM_log_face_added(BMLog *log, BMFace *f) void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset) { BMLogEntry *entry = log->current_entry; - unsigned int v_id = bm_log_vert_id_get(log, v); + uint v_id = bm_log_vert_id_get(log, v); void *key = SET_UINT_IN_POINTER(v_id); /* if it has a key, it shouldn't be NULL */ @@ -963,7 +963,7 @@ void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset) void BM_log_face_removed(BMLog *log, BMFace *f) { BMLogEntry *entry = log->current_entry; - unsigned int f_id = bm_log_face_id_get(log, f); + uint f_id = bm_log_face_id_get(log, f); void *key = SET_UINT_IN_POINTER(f_id); /* if it has a key, it shouldn't be NULL */ @@ -991,11 +991,11 @@ void BM_log_all_added(BMesh *bm, BMLog *log) /* avoid unnecessary resizing on initialization */ if (BLI_ghash_size(log->current_entry->added_verts) == 0) { - BLI_ghash_reserve(log->current_entry->added_verts, (unsigned int)bm->totvert); + BLI_ghash_reserve(log->current_entry->added_verts, (uint)bm->totvert); } if (BLI_ghash_size(log->current_entry->added_faces) == 0) { - BLI_ghash_reserve(log->current_entry->added_faces, (unsigned int)bm->totface); + BLI_ghash_reserve(log->current_entry->added_faces, (uint)bm->totface); } /* Log all vertices as newly created */ diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index e9fb6a28154..d5d9e4abe2c 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -635,7 +635,7 @@ static void bm_mesh_loops_calc_normals( BM_elem_flag_disable(l_curr, BM_ELEM_TAG); } while ((l_curr = l_curr->next) != l_first); } - bm->elem_index_dirty &= ~(BM_FACE|BM_LOOP); + bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't). * Now, time to generate the normals. @@ -1527,9 +1527,9 @@ int BM_mesh_elem_count(BMesh *bm, const char htype) */ void BM_mesh_remap( BMesh *bm, - const unsigned int *vert_idx, - const unsigned int *edge_idx, - const unsigned int *face_idx) + const uint *vert_idx, + const uint *edge_idx, + const uint *face_idx) { /* Mapping old to new pointers. */ GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL; @@ -1552,7 +1552,7 @@ void BM_mesh_remap( if (vert_idx) { BMVert **verts_pool, *verts_copy, **vep; int i, totvert = bm->totvert; - const unsigned int *new_idx; + const uint *new_idx; /* Special case: Python uses custom - data layers to hold PyObject references. * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR); @@ -1600,7 +1600,7 @@ void BM_mesh_remap( if (edge_idx) { BMEdge **edges_pool, *edges_copy, **edp; int i, totedge = bm->totedge; - const unsigned int *new_idx; + const uint *new_idx; /* Special case: Python uses custom - data layers to hold PyObject references. * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR); @@ -1647,7 +1647,7 @@ void BM_mesh_remap( if (face_idx) { BMFace **faces_pool, *faces_copy, **fap; int i, totface = bm->totface; - const unsigned int *new_idx; + const uint *new_idx; /* Special case: Python uses custom - data layers to hold PyObject references. * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */ const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR); diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 6a9540c3b60..01f11f6f942 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -34,7 +34,7 @@ void BM_mesh_elem_toolflags_ensure(BMesh *bm); void BM_mesh_elem_toolflags_clear(BMesh *bm); struct BMeshCreateParams { - unsigned int use_toolflags : 1; + uint use_toolflags : 1; }; BMesh *BM_mesh_create( @@ -88,9 +88,9 @@ int BM_mesh_elem_count(BMesh *bm, const char htype); void BM_mesh_remap( BMesh *bm, - const unsigned int *vert_idx, - const unsigned int *edge_idx, - const unsigned int *face_idx); + const uint *vert_idx, + const uint *edge_idx, + const uint *face_idx); void BM_mesh_rebuild( BMesh *bm, const struct BMeshCreateParams *params, diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index 7cbfe2d9210..1974d364171 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -41,11 +41,11 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm); struct BMeshFromMeshParams { - unsigned int calc_face_normal : 1; + uint calc_face_normal : 1; /* add a vertex CD_SHAPE_KEYINDEX layer */ - unsigned int add_key_index : 1; + uint add_key_index : 1; /* set vertex coordinates from the shapekey */ - unsigned int use_shapekey : 1; + uint use_shapekey : 1; /* define the active shape key (index + 1) */ int active_shapekey; }; @@ -55,7 +55,7 @@ void BM_mesh_bm_from_me( ATTR_NONNULL(1, 3); struct BMeshToMeshParams { - unsigned int calc_tessface : 1; + uint calc_tessface : 1; int64_t cd_mask_extra; }; void BM_mesh_bm_to_me( diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 6b388a75436..a55df234264 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1037,7 +1037,7 @@ static BMOpDefine bmo_extrude_face_region_def = { /* slots_in */ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */ {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}}, - {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry */ + {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, @@ -1741,6 +1741,8 @@ static BMOpDefine bmo_bevel_def = { }, /* slots_out */ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */ + {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */ + {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */ {{'\0'}}, }, @@ -1912,7 +1914,6 @@ static BMOpDefine bmo_wireframe_def = { {"use_even_offset", BMO_OP_SLOT_BOOL}, {"use_crease", BMO_OP_SLOT_BOOL}, {"crease_weight", BMO_OP_SLOT_FLT}, - {"thickness", BMO_OP_SLOT_FLT}, {"use_relative_offset", BMO_OP_SLOT_BOOL}, {"material_offset", BMO_OP_SLOT_INT}, {{'\0'}}, diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 706a7f74ed2..44445aae25a 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -128,7 +128,7 @@ void BMO_pop(BMesh *bm) static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args) { BMOpSlot *slot; - unsigned int i; + uint i; for (i = 0; slot_types[i].type; i++) { slot = &slot_args[i]; slot->slot_name = slot_types[i].name; @@ -149,7 +149,7 @@ static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args) { BMOpSlot *slot; - unsigned int i; + uint i; for (i = 0; slot_types[i].type; i++) { slot = &slot_args[i]; switch (slot->slot_type) { @@ -311,9 +311,9 @@ void _bmo_slot_copy( } else { /* check types */ - const unsigned int tot = slot_src->len; - unsigned int i; - unsigned int out = 0; + const uint tot = slot_src->len; + uint i; + uint out = 0; BMElem **ele_src = (BMElem **)slot_src->data.buf; for (i = 0; i < tot; i++, ele_src++) { if ((*ele_src)->head.htype & dst_elem_flag) { @@ -333,8 +333,8 @@ void _bmo_slot_copy( } else { /* only copy compatible elements */ - const unsigned int tot = slot_src->len; - unsigned int i; + const uint tot = slot_src->len; + uint i; BMElem **ele_src = (BMElem **)slot_src->data.buf; BMElem **ele_dst = (BMElem **)slot_dst->data.buf; for (i = 0; i < tot; i++, ele_src++) { @@ -1639,8 +1639,8 @@ static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], cons int BMO_opcode_from_opname(const char *opname) { - const unsigned int tot = bmo_opdefines_total; - unsigned int i; + const uint tot = bmo_opdefines_total; + uint i; for (i = 0; i < tot; i++) { if (STREQ(bmo_opdefines[i]->opname, opname)) { return i; diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 0a4fb1d56a4..b670f31ad9f 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -141,12 +141,19 @@ void BM_mesh_esubdivide( const short use_only_quads, const int seed); -void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsigned int y_segments, const short oflag); -void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag); -void BM_mesh_calc_uvs_circle(BMesh *bm, float mat[4][4], const float radius, const short oflag); +void BM_mesh_calc_uvs_grid( + BMesh *bm, const uint x_segments, const uint y_segments, + const short oflag, const int cd_loop_uv_offset); +void BM_mesh_calc_uvs_sphere( + BMesh *bm, + const short oflag, const int cd_loop_uv_offset); +void BM_mesh_calc_uvs_circle( + BMesh *bm, float mat[4][4], const float radius, + const short oflag, const int cd_loop_uv_offset); void BM_mesh_calc_uvs_cone( BMesh *bm, float mat[4][4], - const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, const short oflag); + const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, + const short oflag, const int cd_loop_uv_offset); void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag); #include "intern/bmesh_operator_api_inline.h" diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 78ee7589d23..a4621b45fe6 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -132,7 +132,7 @@ static void bm_face_calc_poly_center_mean_vertex_cos( */ void BM_face_calc_tessellation( const BMFace *f, const bool use_fixed_quad, - BMLoop **r_loops, unsigned int (*r_index)[3]) + BMLoop **r_loops, uint (*r_index)[3]) { BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter; @@ -196,7 +196,7 @@ void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]) * but without this we can't be sure the point is inside a concave face. */ const int tottri = f->len - 2; BMLoop **loops = BLI_array_alloca(loops, f->len); - unsigned int (*index)[3] = BLI_array_alloca(index, tottri); + uint (*index)[3] = BLI_array_alloca(index, tottri); int j; int j_best = 0; /* use as fallback when unset */ float area_best = -1.0f; @@ -575,11 +575,11 @@ void BM_face_calc_center_mean_weighted(const BMFace *f, float r_cent[3]) * Rotates a polygon so that it's * normal is pointing towards the mesh Z axis */ -void poly_rotate_plane(const float normal[3], float (*verts)[3], const unsigned int nverts) +void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts) { float mat[3][3]; float co[3]; - unsigned int i; + uint i; co[2] = 0.0f; @@ -941,7 +941,7 @@ void BM_face_triangulate( { BMLoop **loops = BLI_array_alloca(loops, f->len); - unsigned int (*tris)[3] = BLI_array_alloca(tris, f->len); + uint (*tris)[3] = BLI_array_alloca(tris, f->len); const int totfilltri = f->len - 2; const int last_tri = f->len - 3; int i; @@ -1425,7 +1425,7 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptri float axis_mat[3][3]; float (*projverts)[2]; - unsigned int (*tris)[3]; + uint (*tris)[3]; const int totfilltri = efa->len - 2; @@ -1451,7 +1451,7 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptri for (j = 0; j < totfilltri; j++) { BMLoop **l_ptr = looptris[i++]; - unsigned int *tri = tris[j]; + uint *tri = tris[j]; l_ptr[0] = l_arr[tri[0]]; l_ptr[1] = l_arr[tri[1]]; diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 1e50a504875..d944f3a8bc5 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -36,7 +36,7 @@ void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptr void BM_face_calc_tessellation( const BMFace *f, const bool use_fixed_quad, - BMLoop **r_loops, unsigned int (*r_index)[3]); + BMLoop **r_loops, uint (*r_index)[3]); void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]); float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL(); float BM_face_calc_normal_vcos( diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 6ce7c100b0d..e515f9af63f 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -62,15 +62,16 @@ #define EDGE_NET _FLAG_WALK /* tag verts we've visit */ #define VERT_VISIT _FLAG_WALK +#define VERT_IN_QUEUE _FLAG_WALK_ALT struct VertOrder { float angle; BMVert *v; }; -static unsigned int bm_edge_flagged_radial_count(BMEdge *e) +static uint bm_edge_flagged_radial_count(BMEdge *e) { - unsigned int count = 0; + uint count = 0; BMLoop *l; if ((l = e->l)) { @@ -133,7 +134,7 @@ static bool bm_face_split_edgenet_find_loop_pair( e = e_first = v_init->e; do { if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) { - const unsigned int count = bm_edge_flagged_radial_count(e); + const uint count = bm_edge_flagged_radial_count(e); if (count == 1) { BLI_SMALLSTACK_PUSH(edges_boundary, e); edges_boundary_len++; @@ -238,7 +239,7 @@ static bool bm_face_split_edgenet_find_loop_pair_exists( e = e_first = v_init->e; do { if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) { - const unsigned int count = bm_edge_flagged_radial_count(e); + const uint count = bm_edge_flagged_radial_count(e); if (count == 1) { edges_boundary_len++; } @@ -274,7 +275,7 @@ static bool bm_face_split_edgenet_find_loop_pair_exists( static bool bm_face_split_edgenet_find_loop_walk( BMVert *v_init, const float face_normal[3], /* cache to avoid realloc every time */ - struct VertOrder *edge_order, const unsigned int edge_order_len, + struct VertOrder *edge_order, const uint edge_order_len, BMEdge *e_pair[2]) { /* fast-path for the common case (avoid push-pop). @@ -381,7 +382,7 @@ walk_nofork: /* sort by angle if needed */ if (STACK_SIZE(edge_order) > 1) { - unsigned int j; + uint j; BMVert *v_prev = BM_edge_other_vert(v->e, v); for (j = 0; j < STACK_SIZE(edge_order); j++) { @@ -420,7 +421,7 @@ finally: static bool bm_face_split_edgenet_find_loop( BMVert *v_init, const float face_normal[3], float face_normal_matrix[3][3], /* cache to avoid realloc every time */ - struct VertOrder *edge_order, const unsigned int edge_order_len, + struct VertOrder *edge_order, const uint edge_order_len, BMVert **r_face_verts, int *r_face_verts_len) { BMEdge *e_pair[2]; @@ -434,7 +435,7 @@ static bool bm_face_split_edgenet_find_loop( (bm_edge_flagged_radial_count(e_pair[1]) == 1)); if (bm_face_split_edgenet_find_loop_walk(v_init, face_normal, edge_order, edge_order_len, e_pair)) { - unsigned int i = 0; + uint i = 0; r_face_verts[i++] = v_init; v = BM_edge_other_vert(e_pair[1], v_init); @@ -474,7 +475,7 @@ bool BM_face_split_edgenet( int i; struct VertOrder *edge_order; - const unsigned int edge_order_len = edge_net_len + 2; + const uint edge_order_len = edge_net_len + 2; BMVert *v; @@ -512,13 +513,21 @@ bool BM_face_split_edgenet( } while ((l_iter = l_iter->next) != l_first); #endif + /* Note: 'VERT_IN_QUEUE' is often not needed at all, + * however in rare cases verts are added multiple times to the queue, + * that on it's own is harmless but in _very_ rare cases, + * the queue will overflow its maximum size, + * so we better be strict about this! see: T51539 */ for (i = 0; i < edge_net_len; i++) { BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET); + BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_IN_QUEUE); + BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_IN_QUEUE); } l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET); + BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_IN_QUEUE); } while ((l_iter = l_iter->next) != l_first); float face_normal_matrix[3][3]; @@ -527,8 +536,10 @@ bool BM_face_split_edgenet( /* any vert can be used to begin with */ STACK_PUSH(vert_queue, l_first->v); + BM_ELEM_API_FLAG_ENABLE(l_first->v, VERT_IN_QUEUE); while ((v = STACK_POP(vert_queue))) { + BM_ELEM_API_FLAG_DISABLE(v, VERT_IN_QUEUE); if (bm_face_split_edgenet_find_loop( v, f->no, face_normal_matrix, edge_order, edge_order_len, face_verts, &face_verts_len)) @@ -558,8 +569,12 @@ bool BM_face_split_edgenet( * (verts between boundary and manifold edges) */ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); do { - if (bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) { + /* Avoid adding to queue multiple times (not common but happens). */ + if (!BM_ELEM_API_FLAG_TEST(l_iter->v, VERT_IN_QUEUE) && + bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) + { STACK_PUSH(vert_queue, l_iter->v); + BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_IN_QUEUE); } } while ((l_iter = l_iter->next) != l_first); } @@ -721,13 +736,13 @@ BLI_INLINE bool edge_isect_verts_point_2d( */ struct EdgeGroupIsland { LinkNode edge_links; /* keep first */ - unsigned int vert_len, edge_len; + uint vert_len, edge_len; /* Set the following vars once we have >1 groups */ /* when when an edge in a previous group connects to this one, * so theres no need to create one pointing back. */ - unsigned int has_prev_edge : 1; + uint has_prev_edge : 1; /* verts in the group which has the lowest & highest values, * the lower vertex is connected to the first edge */ @@ -758,7 +773,7 @@ struct Edges_VertVert_BVHTreeTest { BMVert *v_origin; BMVert *v_other; - const unsigned int *vert_range; + const uint *vert_range; }; struct Edges_VertRay_BVHTreeTest { @@ -766,7 +781,7 @@ struct Edges_VertRay_BVHTreeTest { BMVert *v_origin; - const unsigned int *vert_range; + const uint *vert_range; }; static void bvhtree_test_edges_isect_2d_vert_cb( @@ -831,12 +846,12 @@ static void bvhtree_test_edges_isect_2d_ray_cb( struct EdgeGroup_FindConnection_Args { BVHTree *bvhtree; BMEdge **edge_arr; - unsigned int edge_arr_len; + uint edge_arr_len; BMEdge **edge_arr_new; - unsigned int edge_arr_new_len; + uint edge_arr_new_len; - const unsigned int *vert_range; + const uint *vert_range; }; static BMEdge *test_edges_isect_2d_vert( @@ -869,7 +884,7 @@ static BMEdge *test_edges_isect_2d_vert( /* check existing connections (no spatial optimization here since we're continually adding). */ if (LIKELY(index == -1)) { float t_best = 1.0f; - for (unsigned int i = 0; i < args->edge_arr_new_len; i++) { + for (uint i = 0; i < args->edge_arr_new_len; i++) { float co_isect[2]; if (UNLIKELY(edge_isect_verts_point_2d(args->edge_arr_new[i], v_origin, v_other, co_isect))) { const float t_test = line_point_factor_v2(co_isect, v_origin->co, v_other->co); @@ -914,7 +929,7 @@ static BMEdge *test_edges_isect_2d_ray( /* check existing connections (no spatial optimization here since we're continually adding). */ if (LIKELY(index != -1)) { - for (unsigned int i = 0; i < args->edge_arr_new_len; i++) { + for (uint i = 0; i < args->edge_arr_new_len; i++) { BMEdge *e = args->edge_arr_new[i]; float dist_new; if (isect_ray_seg_v2(v_origin->co, dir, e->v1->co, e->v2->co, &dist_new, NULL)) { @@ -1031,7 +1046,7 @@ static BMVert *bm_face_split_edgenet_partial_connect(BMesh *bm, BMVert *v_delimi /* initial check - see if we have 3+ flagged edges attached to 'v_delimit' * if not, we can early exit */ LinkNode *e_delimit_list = NULL; - unsigned int e_delimit_list_len = 0; + uint e_delimit_list_len = 0; #define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG #define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG @@ -1169,10 +1184,10 @@ static bool bm_vert_partial_connect_check_overlap( */ bool BM_face_split_edgenet_connect_islands( BMesh *bm, - BMFace *f, BMEdge **edge_net_init, const unsigned int edge_net_init_len, + BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len, bool use_partial_connect, MemArena *mem_arena, - BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len) + BMEdge ***r_edge_net_new, uint *r_edge_net_new_len) { /* -------------------------------------------------------------------- */ /* This function has 2 main parts. @@ -1186,7 +1201,7 @@ bool BM_face_split_edgenet_connect_islands( * (avoid thrashing the area when the initial check isn't so intensive on the stack). */ - const unsigned int edge_arr_len = (unsigned int)edge_net_init_len + (unsigned int)f->len; + const uint edge_arr_len = (uint)edge_net_init_len + (uint)f->len; BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len); bool ok = false; @@ -1197,7 +1212,7 @@ bool BM_face_split_edgenet_connect_islands( #define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG { - unsigned int i = edge_net_init_len; + uint i = edge_net_init_len; BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { @@ -1206,7 +1221,7 @@ bool BM_face_split_edgenet_connect_islands( BLI_assert(i == edge_arr_len); } - for (unsigned int i = 0; i < edge_arr_len; i++) { + for (uint i = 0; i < edge_arr_len; i++) { BM_elem_flag_enable(edge_arr[i], EDGE_NOT_IN_STACK); BM_elem_flag_enable(edge_arr[i]->v1, VERT_NOT_IN_STACK); BM_elem_flag_enable(edge_arr[i]->v2, VERT_NOT_IN_STACK); @@ -1224,12 +1239,12 @@ bool BM_face_split_edgenet_connect_islands( struct { struct TempVertPair *list; - unsigned int len; + uint len; int *remap; /* temp -> orig mapping */ } temp_vert_pairs = {NULL}; if (use_partial_connect) { - for (unsigned int i = 0; i < edge_net_init_len; i++) { + for (uint i = 0; i < edge_net_init_len; i++) { for (unsigned j = 0; j < 2; j++) { BMVert *v_delimit = (&edge_arr[i]->v1)[j]; BMVert *v_other; @@ -1254,19 +1269,19 @@ bool BM_face_split_edgenet_connect_islands( - unsigned int group_arr_len = 0; + uint group_arr_len = 0; LinkNode *group_head = NULL; { /* scan 'edge_arr' backwards so the outer face boundary is handled first * (since its likely to be the largest) */ - unsigned int edge_index = (edge_arr_len - 1); - unsigned int edge_in_group_tot = 0; + uint edge_index = (edge_arr_len - 1); + uint edge_in_group_tot = 0; BLI_SMALLSTACK_DECLARE(vstack, BMVert *); while (true) { LinkNode *edge_links = NULL; - unsigned int unique_verts_in_group = 0, unique_edges_in_group = 0; + uint unique_verts_in_group = 0, unique_edges_in_group = 0; /* list of groups */ BLI_assert(BM_elem_flag_test(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK)); @@ -1333,7 +1348,7 @@ bool BM_face_split_edgenet_connect_islands( #define VERT_IN_ARRAY BM_ELEM_INTERNAL_TAG struct EdgeGroupIsland **group_arr = BLI_memarena_alloc(mem_arena, sizeof(*group_arr) * group_arr_len); - unsigned int vert_arr_len = 0; + uint vert_arr_len = 0; /* sort groups by lowest value vertex */ { /* fill 'groups_arr' in reverse order so the boundary face is first */ @@ -1389,7 +1404,7 @@ bool BM_face_split_edgenet_connect_islands( /* we don't know how many unique verts there are connecting the edges, so over-alloc */ BMVert **vert_arr = BLI_memarena_alloc(mem_arena, sizeof(*vert_arr) * vert_arr_len); /* map vertex -> group index */ - unsigned int *verts_group_table = BLI_memarena_alloc(mem_arena, sizeof(*verts_group_table) * vert_arr_len); + uint *verts_group_table = BLI_memarena_alloc(mem_arena, sizeof(*verts_group_table) * vert_arr_len); float (*vert_coords_backup)[3] = BLI_memarena_alloc(mem_arena, sizeof(*vert_coords_backup) * vert_arr_len); @@ -1398,7 +1413,7 @@ bool BM_face_split_edgenet_connect_islands( const float f_co_ref[3] = {UNPACK3(BM_FACE_FIRST_LOOP(f)->v->co)}; int v_index = 0; /* global vert index */ - for (unsigned int g_index = 0; g_index < group_arr_len; g_index++) { + for (uint g_index = 0; g_index < group_arr_len; g_index++) { LinkNode *edge_links = group_arr[g_index]->edge_links.link; do { BMEdge *e = edge_links->link; @@ -1436,7 +1451,7 @@ bool BM_face_split_edgenet_connect_islands( /* Now create bvh tree*/ BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 0.0f, 8, 8); - for (unsigned int i = 0; i < edge_arr_len; i++) { + for (uint i = 0; i < edge_arr_len; i++) { const float e_cos[2][3] = { {UNPACK2(edge_arr[i]->v1->co), 0.0f}, {UNPACK2(edge_arr[i]->v2->co), 0.0f}, @@ -1465,15 +1480,15 @@ bool BM_face_split_edgenet_connect_islands( /* Create connections between groups */ /* may be an over-alloc, but not by much */ - unsigned int edge_net_new_len = (unsigned int)edge_net_init_len + ((group_arr_len - 1) * 2); + uint edge_net_new_len = (uint)edge_net_init_len + ((group_arr_len - 1) * 2); BMEdge **edge_net_new = BLI_memarena_alloc(mem_arena, sizeof(*edge_net_new) * edge_net_new_len); memcpy(edge_net_new, edge_net_init, sizeof(*edge_net_new) * (size_t)edge_net_init_len); { - unsigned int edge_net_new_index = edge_net_init_len; + uint edge_net_new_index = edge_net_init_len; /* start-end of the verts in the current group */ - unsigned int vert_range[2]; + uint vert_range[2]; vert_range[0] = 0; vert_range[1] = group_arr[0]->vert_len; @@ -1492,7 +1507,7 @@ bool BM_face_split_edgenet_connect_islands( .vert_range = vert_range, }; - for (unsigned int g_index = 1; g_index < group_arr_len; g_index++) { + for (uint g_index = 1; g_index < group_arr_len; g_index++) { struct EdgeGroupIsland *g = group_arr[g_index]; /* the range of verts this group uses in 'verts_arr' (not uncluding the last index) */ @@ -1551,7 +1566,7 @@ bool BM_face_split_edgenet_connect_islands( } /* tell the 'next' group it doesn't need to create its own back-link */ - unsigned int g_index_other = verts_group_table[index_other]; + uint g_index_other = verts_group_table[index_other]; group_arr[g_index_other]->has_prev_edge = true; } } @@ -1567,7 +1582,7 @@ bool BM_face_split_edgenet_connect_islands( *r_edge_net_new_len = edge_net_new_len; ok = true; - for (unsigned int i = 0; i < vert_arr_len; i++) { + for (uint i = 0; i < vert_arr_len; i++) { copy_v3_v3(vert_arr[i]->co, vert_coords_backup[i]); } @@ -1600,7 +1615,7 @@ finally: /* Remove edges which have become doubles since splicing vertices together, * its less trouble then detecting future-doubles on edge-creation. */ - for (unsigned int i = edge_net_init_len; i < edge_net_new_len; i++) { + for (uint i = edge_net_init_len; i < edge_net_new_len; i++) { while (BM_edge_find_double(edge_net_new[i])) { BM_edge_kill(bm, edge_net_new[i]); edge_net_new_len--; @@ -1616,7 +1631,7 @@ finally: #endif - for (unsigned int i = 0; i < edge_arr_len; i++) { + for (uint i = 0; i < edge_arr_len; i++) { BM_elem_flag_disable(edge_arr[i], EDGE_NOT_IN_STACK); BM_elem_flag_disable(edge_arr[i]->v1, VERT_NOT_IN_STACK); BM_elem_flag_disable(edge_arr[i]->v2, VERT_NOT_IN_STACK); diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h index 72ae7695f0f..bf5cea59e30 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h @@ -32,10 +32,10 @@ bool BM_face_split_edgenet( bool BM_face_split_edgenet_connect_islands( BMesh *bm, - BMFace *f, BMEdge **edge_net_init, const unsigned int edge_net_init_len, + BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len, bool use_partial_connect, struct MemArena *arena, - BMEdge ***r_edge_net_new, unsigned int *r_edge_net_new_len) + BMEdge ***r_edge_net_new, uint *r_edge_net_new_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 6, 7, 8); #endif /* __BMESH_POLYGON_EDGENET_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index d8d297c9298..4161fbe90fb 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -73,7 +73,7 @@ enum { }; #define BM_ELEM_API_FLAG_ENABLE(element, f) { ((element)->head.api_flag |= (f)); } (void)0 -#define BM_ELEM_API_FLAG_DISABLE(element, f) { ((element)->head.api_flag &= (unsigned char)~(f)); } (void)0 +#define BM_ELEM_API_FLAG_DISABLE(element, f) { ((element)->head.api_flag &= (uchar)~(f)); } (void)0 #define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f)) #define BM_ELEM_API_FLAG_CLEAR(element) { ((element)->head.api_flag = 0); } (void)0 diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 7ca5640578a..668fb998254 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1511,20 +1511,68 @@ float BM_loop_calc_face_angle(const BMLoop *l) * Calculate the normal at this loop corner or fallback to the face normal on straight lines. * * \param l The loop to calculate the normal at + * \param epsilon: Value to avoid numeric errors (1e-5f works well). * \param r_normal Resulting normal */ -void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) +float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3]) { - if (normal_tri_v3(r_normal, - l->prev->v->co, - l->v->co, - l->next->v->co) != 0.0f) - { - /* pass */ + /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line) + * from zero value, because it does not normalize both vectors before making crossproduct. + * Instead of adding two costly normalize computations, just check ourselves for colinear case. */ + /* Note: FEPSILON might need some finer tweaking at some point? Seems to be working OK for now though. */ + float v1[3], v2[3], v_tmp[3]; + sub_v3_v3v3(v1, l->prev->v->co, l->v->co); + sub_v3_v3v3(v2, l->next->v->co, l->v->co); + + const float fac = + ((v2[0] == 0.0f) ? + ((v2[1] == 0.0f) ? + ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0]); + + mul_v3_v3fl(v_tmp, v2, fac); + sub_v3_v3(v_tmp, v1); + if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) { + /* Not co-linear, we can compute crossproduct and normalize it into normal. */ + cross_v3_v3v3(r_normal, v1, v2); + return normalize_v3(r_normal); } else { copy_v3_v3(r_normal, l->f->no); + return 0.0f; + } +} + +/** + * #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon. + * + * Since this doesn't scale baed on triangle size, fixed value works well. + */ +float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) +{ + return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal); +} + +/** + * \brief BM_loop_calc_face_normal + * + * Calculate the normal at this loop corner or fallback to the face normal on straight lines. + * + * \param l The loop to calculate the normal at + * \param r_normal Resulting normal + * \return The length of the cross product (double the area). + */ +float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) +{ + float v1[3], v2[3]; + sub_v3_v3v3(v1, l->prev->v->co, l->v->co); + sub_v3_v3v3(v2, l->next->v->co, l->v->co); + + cross_v3_v3v3(r_normal, v1, v2); + const float len = normalize_v3(r_normal); + if (UNLIKELY(len == 0.0f)) { + copy_v3_v3(r_normal, l->f->no); } + return len; } /** @@ -2326,7 +2374,7 @@ static void bm_mesh_calc_volume_face(const BMFace *f, float *r_vol) { const int tottri = f->len - 2; BMLoop **loops = BLI_array_alloca(loops, f->len); - unsigned int (*index)[3] = BLI_array_alloca(index, tottri); + uint (*index)[3] = BLI_array_alloca(index, tottri); int j; BM_face_calc_tessellation(f, false, loops, index); @@ -2395,8 +2443,8 @@ int BM_mesh_calc_face_groups( int group_curr = 0; - unsigned int tot_faces = 0; - unsigned int tot_touch = 0; + uint tot_faces = 0; + uint tot_touch = 0; BMFace **stack; STACK_DECLARE(stack); @@ -2553,8 +2601,8 @@ int BM_mesh_calc_edge_groups( int group_curr = 0; - unsigned int tot_edges = 0; - unsigned int tot_touch = 0; + uint tot_edges = 0; + uint tot_touch = 0; BMEdge **stack; STACK_DECLARE(stack); diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 903fdc59cb8..83977fa8be0 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -113,7 +113,9 @@ BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq); float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3]) ATTR_NONNULL(); void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]); void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]); diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index d5afb39d7b7..2ae87b64286 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -66,5 +66,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) BM_mesh_bevel(bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material, loop_slide); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "verts.out", BM_VERT, BM_ELEM_TAG); } } diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index 5c9cd8dc3fa..c5c4ac959a9 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -55,7 +55,7 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera BMLoop *l_tag_prev = NULL, *l_tag_first = NULL; BMLoop *l_iter, *l_first; - unsigned int i; + uint i; STACK_INIT(loops_split, pair_split_max); STACK_INIT(verts_pair, pair_split_max); diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c index b8acc9d09b8..67590fe8ef9 100644 --- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c +++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c @@ -67,8 +67,8 @@ static bool bm_face_split_find(BMesh *bm, BMFace *f, BMLoop *l_pair[2], float *r { BMLoop *l_iter, *l_first; BMLoop **l_arr = BLI_array_alloca(l_arr, f->len); - const unsigned int f_len = f->len; - unsigned int i_a, i_b; + const uint f_len = f->len; + uint i_a, i_b; bool found = false; /* angle finding */ diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c index a73c86fd122..b474ad9fc7b 100644 --- a/source/blender/bmesh/operators/bmo_connect_pair.c +++ b/source/blender/bmesh/operators/bmo_connect_pair.c @@ -530,8 +530,8 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3]) float basis_nor_b[3]; /* align normal to direction */ - project_plane_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir); - project_plane_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir); + project_plane_normalized_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir); + project_plane_normalized_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir); /* don't normalize before combining so as normals approach the direction, they have less effect (T46784). */ @@ -569,7 +569,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3]) float angle_cos_test; /* project basis dir onto the normal to find its closest angle */ - project_plane_v3_v3v3(basis_dir_proj, basis_dir, l->f->no); + project_plane_normalized_v3_v3v3(basis_dir_proj, basis_dir, l->f->no); if (normalize_v3(basis_dir_proj) > eps) { angle_cos_test = dot_v3v3(basis_dir_proj, basis_dir); @@ -586,7 +586,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3]) * note: we could add the directions, * but this more often gives 45d rotated matrix, so just use the best one. */ copy_v3_v3(basis_nor, axis_pair[axis_pair[0].angle_cos < axis_pair[1].angle_cos].nor); - project_plane_v3_v3v3(basis_nor, basis_nor, basis_dir); + project_plane_normalized_v3_v3v3(basis_nor, basis_nor, basis_dir); cross_v3_v3v3(basis_tmp, basis_dir, basis_nor); diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index a980baf8626..fa08d009d40 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -74,13 +74,13 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMVert *verts[2]; BMEdge *e; - BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)verts, 2); - - /* create edge */ - e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); - BMO_edge_flag_enable(bm, e, ELE_OUT); - tote += 1; - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); + if (BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)verts, 2) == 2) { + /* create edge */ + e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); + BMO_edge_flag_enable(bm, e, ELE_OUT); + tote += 1; + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); + } return; } @@ -283,13 +283,13 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) */ if (totv > 2) { /* TODO, some of these vertes may be connected by edges, - * this connectivity could be used rather then treating + * this connectivity could be used rather than treating * them as a bunch of isolated verts. */ BMVert **vert_arr = MEM_mallocN(sizeof(BMVert *) * totv, __func__); BMFace *f; - BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv); + totv = BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv); BM_verts_sort_radial_plane(vert_arr, totv); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 6e3a8a1473d..2df8e73c2b8 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -309,7 +309,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) { BMFace *f_pair[2]; if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) { - unsigned int j; + uint j; for (j = 0; j < 2; j++) { BMLoop *l_first, *l_iter; l_iter = l_first = BM_FACE_FIRST_LOOP(f_pair[j]); diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 8048add84d4..e35c1f3b66c 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -83,7 +83,7 @@ static BMEdge *bmo_edge_copy( { BMEdge *e_dst; BMVert *e_dst_v1, *e_dst_v2; - unsigned int rlen; + uint rlen; /* see if any of the neighboring faces are * not being duplicated. in that case, diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c index 233ed746ed4..dcf2570dff4 100644 --- a/source/blender/bmesh/operators/bmo_fill_attribute.c +++ b/source/blender/bmesh/operators/bmo_fill_attribute.c @@ -91,7 +91,7 @@ static void bm_face_copy_shared_all( /** * Flood fill attributes. */ -static unsigned int bmesh_face_attribute_fill( +static uint bmesh_face_attribute_fill( BMesh *bm, const bool use_normals, const bool use_data) { @@ -102,7 +102,7 @@ static unsigned int bmesh_face_attribute_fill( BMIter iter; BMLoop *l; - unsigned int face_tot = 0; + uint face_tot = 0; BLI_LINKSTACK_INIT(loop_queue_prev); diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index 04ae915b707..dc4ebf50754 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -187,15 +187,15 @@ static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_ * Avoids calling #barycentric_weights_v2_quad often by caching weights into an array. */ static void barycentric_weights_v2_grid_cache( - const unsigned int xtot, const unsigned int ytot, + const uint xtot, const uint ytot, float (*weight_table)[4]) { float x_step = 1.0f / (float)(xtot - 1); float y_step = 1.0f / (float)(ytot - 1); - unsigned int i = 0; + uint i = 0; float xy_fl[2]; - unsigned int x, y; + uint x, y; for (y = 0; y < ytot; y++) { xy_fl[1] = y_step * (float)y; for (x = 0; x < xtot; x++) { @@ -219,13 +219,13 @@ static void barycentric_weights_v2_grid_cache( * \param v_grid 2d array of verts, all boundary verts must be set, we fill in the middle. */ static void bm_grid_fill_array( - BMesh *bm, BMVert **v_grid, const unsigned int xtot, unsigned const int ytot, + BMesh *bm, BMVert **v_grid, const uint xtot, unsigned const int ytot, const short mat_nr, const bool use_smooth, const bool use_flip, const bool use_interp_simple) { const bool use_vert_interp = CustomData_has_interp(&bm->vdata); const bool use_loop_interp = CustomData_has_interp(&bm->ldata); - unsigned int x, y; + uint x, y; /* for use_loop_interp */ BMLoop *((*larr_x_a)[2]), *((*larr_x_b)[2]), *((*larr_y_a)[2]), *((*larr_y_b)[2]); @@ -393,7 +393,7 @@ static void bm_grid_fill_array( BMLoop *l_quad[4]; BMLoop *l_bound[4]; BMLoop *l_tmp; - unsigned int x_side, y_side, i; + uint x_side, y_side, i; char interp_from; @@ -496,12 +496,12 @@ static void bm_grid_fill( { #define USE_FLIP_DETECT - const unsigned int xtot = (unsigned int)BM_edgeloop_length_get(estore_a); - const unsigned int ytot = (unsigned int)BM_edgeloop_length_get(estore_rail_a); + const uint xtot = (uint)BM_edgeloop_length_get(estore_a); + const uint ytot = (uint)BM_edgeloop_length_get(estore_rail_a); //BMVert *v; - unsigned int i; + uint i; #ifdef DEBUG - unsigned int x, y; + uint x, y; #endif LinkData *el; bool use_flip = false; diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c index eadfbdb1aa8..869994a98b9 100644 --- a/source/blender/bmesh/operators/bmo_fill_holes.c +++ b/source/blender/bmesh/operators/bmo_fill_holes.c @@ -36,7 +36,7 @@ void bmo_holes_fill_exec(BMesh *bm, BMOperator *op) { BMOperator op_attr; - const unsigned int sides = BMO_slot_int_get(op->slots_in, "sides"); + const uint sides = BMO_slot_int_get(op->slots_in, "sides"); BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false); diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index f0796e425fa..a64c6d74a93 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -275,7 +275,7 @@ static void bmo_face_inset_individual( BMLoop *l_iter, *l_first; BMLoop *l_other; - unsigned int i; + uint i; float e_length_prev; l_first = BM_FACE_FIRST_LOOP(f); diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 655fb346976..69198ff35ab 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -132,11 +132,11 @@ struct DelimitData_CD { }; struct DelimitData { - unsigned int do_seam : 1; - unsigned int do_sharp : 1; - unsigned int do_mat : 1; - unsigned int do_angle_face : 1; - unsigned int do_angle_shape : 1; + uint do_seam : 1; + uint do_sharp : 1; + uint do_mat : 1; + uint do_angle_face : 1; + uint do_angle_shape : 1; float angle_face; float angle_face__cos; @@ -272,7 +272,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) /* data: edge-to-join, sort_value: error weight */ struct SortPointerByFloat *jedges; unsigned i, totedge; - unsigned int totedge_tag = 0; + uint totedge_tag = 0; struct DelimitData delimit_data = {0}; diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index e5c3ff7a088..d8f83d786b4 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -760,11 +760,13 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) BMOpSlot *slot_verts_out = BMO_slot_get(op->slots_out, "verts.out"); const float dia = BMO_slot_float_get(op->slots_in, "size"); - const unsigned int xtot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments")); - const unsigned int ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments")); + const uint xtot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments")); + const uint ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments")); const float xtot_inv2 = 2.0f / (xtot - 1); const float ytot_inv2 = 2.0f / (ytot - 1); - const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); BMVert **varr; BMVert *vquad[4]; @@ -772,7 +774,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) float mat[4][4]; float vec[3], tvec[3]; - unsigned int x, y, i; + uint x, y, i; BMO_slot_mat4_get(op->slots_in, "matrix", mat); @@ -814,7 +816,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) #undef XY if (calc_uvs) { - BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK); + BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK, cd_loop_uv_offset); } } @@ -826,7 +828,9 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) * \param y_segments The y-resolution of the grid * \param oflag The flag to check faces with. */ -void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsigned int y_segments, const short oflag) +void BM_mesh_calc_uvs_grid( + BMesh *bm, const uint x_segments, const uint y_segments, + const short oflag, const int cd_loop_uv_offset) { BMFace *f; BMLoop *l; @@ -835,9 +839,7 @@ void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsig const float dx = 1.0f / (float)(x_segments - 1); const float dy = 1.0f / (float)(y_segments - 1); float x = 0.0f; - float y = 0.0f; - - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + float y = dy; int loop_index; @@ -852,16 +854,16 @@ void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsig switch (loop_index) { case 0: - x += dx; + y -= dy; break; case 1: - y += dy; + x += dx; break; case 2: - x -= dx; + y += dy; break; case 3: - y -= dy; + x -= dx; break; default: break; @@ -884,7 +886,9 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) const float dia = BMO_slot_float_get(op->slots_in, "diameter"); const int seg = BMO_slot_int_get(op->slots_in, "u_segments"); const int tot = BMO_slot_int_get(op->slots_in, "v_segments"); - const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); BMOperator bmop, prevop; BMVert *eve, *preveve; @@ -982,7 +986,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) } } - BM_mesh_calc_uvs_sphere(bm, FACE_MARK); + BM_mesh_calc_uvs_sphere(bm, FACE_MARK, cd_loop_uv_offset); } /* and now do imat */ @@ -1000,7 +1004,9 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) const float dia = BMO_slot_float_get(op->slots_in, "diameter"); const float dia_div = dia / 200.0f; const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions"); - const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); BMVert *eva[12]; BMVert *v; @@ -1026,7 +1032,6 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) } int uvi = 0; - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); for (a = 0; a < 20; a++) { BMFace *f; BMVert *v1, *v2, *v3; @@ -1157,13 +1162,13 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset) * \param bm The BMesh to operate on * \param oflag The flag to check faces with. */ -void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag) +void BM_mesh_calc_uvs_sphere( + BMesh *bm, + const short oflag, const int cd_loop_uv_offset) { BMFace *f; BMIter iter; - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { @@ -1206,7 +1211,9 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) int i; BMO_slot_mat4_get(op->slots_in, "matrix", mat); - const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); for (i = 0; i < monkeynv; i++) { float v[3]; @@ -1234,7 +1241,6 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) } int uvi = 0; - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); for (i = 0; i < monkeynf; i++) { BMFace *f_new_a = BM_face_create_quad_tri(bm, tv[monkeyf[i][0] + i - monkeyo], @@ -1283,7 +1289,9 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) const int segs = BMO_slot_int_get(op->slots_in, "segments"); const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); - const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL; float vec[3], mat[4][4], phi, phid; @@ -1343,7 +1351,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) BMO_face_flag_enable(bm, f, FACE_NEW); if (calc_uvs) { - BM_mesh_calc_uvs_circle(bm, mat, dia, FACE_NEW); + BM_mesh_calc_uvs_circle(bm, mat, dia, FACE_NEW, cd_loop_uv_offset); } } @@ -1362,14 +1370,14 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) * \param radius The size of the circle. * \param oflag The flag to check faces with. */ -void BM_mesh_calc_uvs_circle(BMesh *bm, float mat[4][4], const float radius, const short oflag) +void BM_mesh_calc_uvs_circle( + BMesh *bm, float mat[4][4], const float radius, + const short oflag, const int cd_loop_uv_offset) { BMFace *f; BMLoop *l; BMIter fiter, liter; - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const float uv_scale = 0.5f / radius; const float uv_center = 0.5f; @@ -1409,7 +1417,9 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) int segs = BMO_slot_int_get(op->slots_in, "segments"); const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); - const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); int a; if (!segs) @@ -1506,7 +1516,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) } if (calc_uvs) { - BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends, FACE_MARK); + BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends, FACE_MARK, cd_loop_uv_offset); } if (!cap_tris) { @@ -1530,12 +1540,12 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) */ void BM_mesh_calc_uvs_cone( BMesh *bm, float mat[4][4], - const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, const short oflag) + const float radius_top, const float radius_bottom, const int segments, const bool cap_ends, + const short oflag, const int cd_loop_uv_offset) { BMFace *f; BMLoop *l; BMIter fiter, liter; - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); const float uv_width = 1.0f / (float)segments; const float uv_height = cap_ends ? 0.5f : 1.0f; @@ -1627,8 +1637,10 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) BMVert *verts[8]; float mat[4][4]; float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f; - const bool calc_uvs = BMO_slot_bool_get(op->slots_in, "calc_uvs"); - int i, x, y, z; + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs"); + /* rotation order set to match 'BM_mesh_calc_uvs_cube' */ const char faces[6][4] = { {0, 1, 3, 2}, @@ -1642,11 +1654,11 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) BMO_slot_mat4_get(op->slots_in, "matrix", mat); if (!off) off = 0.5f; - i = 0; + int i = 0; - for (x = -1; x < 2; x += 2) { - for (y = -1; y < 2; y += 2) { - for (z = -1; z < 2; z += 2) { + for (int x = -1; x < 2; x += 2) { + for (int y = -1; y < 2; y += 2) { + for (int z = -1; z < 2; z += 2) { float vec[3] = {(float)x * off, (float)y * off, (float)z * off}; mul_m4_v3(mat, vec); verts[i] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 0ad8247e539..7d19d90807a 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -153,7 +153,7 @@ static BMFace *remdoubles_createface(BMesh *bm, BMFace *f, BMOpSlot *slot_target finally: { - unsigned int i; + uint i; for (i = 0; i < STACK_SIZE(verts); i++) { BMO_vert_flag_disable(bm, verts[i], VERT_IN_FACE); } @@ -165,7 +165,7 @@ finally: BLI_assert(f_new != f); if (f_new) { - unsigned int i = 0; + uint i = 0; BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); do { @@ -440,20 +440,24 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - float min[3], max[3], center[3]; + float center[3]; + int count = 0; BMVert *v_tar; + zero_v3(center); + if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) continue; BLI_assert(BLI_stack_is_empty(edge_stack)); - INIT_MINMAX(min, max); for (e = BMW_begin(&walker, e->v1); e; e = BMW_step(&walker)) { BLI_stack_push(edge_stack, &e); - minmax_v3v3_v3(min, max, e->v1->co); - minmax_v3v3_v3(min, max, e->v2->co); + add_v3_v3(center, e->v1->co); + add_v3_v3(center, e->v2->co); + + count += 2; /* prevent adding to slot_targetmap multiple times */ BM_elem_flag_disable(e->v1, BM_ELEM_TAG); @@ -461,15 +465,14 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) } if (!BLI_stack_is_empty(edge_stack)) { - - mid_v3_v3v3(center, min, max); + mul_v3_fl(center, 1.0f / count); /* snap edges to a point. for initial testing purposes anyway */ e = *(BMEdge **)BLI_stack_peek(edge_stack); v_tar = e->v1; while (!BLI_stack_is_empty(edge_stack)) { - unsigned int j; + uint j; BLI_stack_pop(edge_stack, &e); for (j = 0; j < 2; j++) { diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 1a83bafc074..2a7b85ac8fd 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -172,7 +172,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys) float w1, w2, w3, w4; int i, j; bool has_4_vert; - unsigned int idv1, idv2, idv3, idv4, idv[4]; + uint idv1, idv2, idv3, idv4, idv[4]; BMEdge *e; BMFace *f; BMIter eiter; @@ -289,7 +289,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) float w2, w3, w4; int i, j; bool has_4_vert; - unsigned int idv1, idv2, idv3, idv4, idv[4]; + uint idv1, idv2, idv3, idv4, idv[4]; BMEdge *e; BMFace *f; @@ -420,7 +420,7 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez float leni, lene; float vini, vend; float *vi1, *vi2, ve1[3], ve2[3]; - unsigned int idv1, idv2; + uint idv1, idv2; BMOIter siter; BMVert *v; BMEdge *e; diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c index ce031e1c230..94b60a51f68 100644 --- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c +++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c @@ -66,7 +66,7 @@ /* Specialized Utility Funcs */ #ifndef NDEBUG -static unsigned int bm_verts_tag_count(BMesh *bm) +static uint bm_verts_tag_count(BMesh *bm) { int count = 0; BMIter iter; @@ -390,9 +390,9 @@ static void bm_vert_calc_surface_tangent(BMesh *bm, BMVert *v, float r_no[3]) * Tag faces connected to an edge loop as FACE_SHARED * if all vertices are VERT_SHARED. */ -static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const unsigned int e_arr_len) +static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const uint e_arr_len) { - unsigned int i; + uint i; for (i = 0; i < e_arr_len; i++) { BMEdge *e = e_arr[i]; @@ -412,9 +412,9 @@ static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const unsigned i /** * Un-Tag faces connected to an edge loop, clearing FACE_SHARED */ -static void bm_faces_share_tag_clear(BMesh *bm, BMEdge **e_arr_iter, const unsigned int e_arr_len_iter) +static void bm_faces_share_tag_clear(BMesh *bm, BMEdge **e_arr_iter, const uint e_arr_len_iter) { - unsigned int i; + uint i; for (i = 0; i < e_arr_len_iter; i++) { BMEdge *e = e_arr_iter[i]; @@ -454,16 +454,16 @@ static LoopPairStore *bm_edgering_pair_store_create( LoopPairStore *lpair = MEM_mallocN(sizeof(*lpair), __func__); if (interp_mode == SUBD_RING_INTERP_SURF) { - const unsigned int len_a = BM_edgeloop_length_get(el_store_a); - const unsigned int len_b = BM_edgeloop_length_get(el_store_b); - const unsigned int e_arr_a_len = len_a - (BM_edgeloop_is_closed(el_store_a) ? 0 : 1); - const unsigned int e_arr_b_len = len_b - (BM_edgeloop_is_closed(el_store_b) ? 0 : 1); + const uint len_a = BM_edgeloop_length_get(el_store_a); + const uint len_b = BM_edgeloop_length_get(el_store_b); + const uint e_arr_a_len = len_a - (BM_edgeloop_is_closed(el_store_a) ? 0 : 1); + const uint e_arr_b_len = len_b - (BM_edgeloop_is_closed(el_store_b) ? 0 : 1); BMEdge **e_arr_a = BLI_array_alloca(e_arr_a, e_arr_a_len); BMEdge **e_arr_b = BLI_array_alloca(e_arr_b, e_arr_b_len); - unsigned int i; + uint i; struct BMEdgeLoopStore *el_store_pair[2] = {el_store_a, el_store_b}; - unsigned int side_index; + uint side_index; float (*nors_pair[2])[3]; GHash *nors_gh_pair[2]; @@ -768,8 +768,8 @@ static void bm_edgering_pair_interpolate( bm_vert_calc_surface_tangent(bm, v_b, no_b); #else { - const unsigned int index_a = GET_UINT_FROM_POINTER(BLI_ghash_lookup(lpair->nors_gh_a, v_a)); - const unsigned int index_b = GET_UINT_FROM_POINTER(BLI_ghash_lookup(lpair->nors_gh_b, v_b)); + const uint index_a = GET_UINT_FROM_POINTER(BLI_ghash_lookup(lpair->nors_gh_a, v_a)); + const uint index_b = GET_UINT_FROM_POINTER(BLI_ghash_lookup(lpair->nors_gh_b, v_b)); BLI_assert(BLI_ghash_haskey(lpair->nors_gh_a, v_a)); BLI_assert(BLI_ghash_haskey(lpair->nors_gh_b, v_b)); diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index 6bd3174d27a..4e8bace59e0 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -77,7 +77,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) GHash *sf_vert_map; float normal[3]; const int scanfill_flag = BLI_SCANFILL_CALC_HOLES | BLI_SCANFILL_CALC_POLYS | BLI_SCANFILL_CALC_LOOSE; - unsigned int nors_tot; + uint nors_tot; bool calc_winding = false; sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges")); @@ -89,7 +89,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { ScanFillVert *sf_verts[2]; BMVert **e_verts = &e->v1; - unsigned int i; + uint i; BMO_edge_flag_enable(bm, e, EDGE_MARK); @@ -115,7 +115,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) * Since we don't know winding, just accumulate */ ScanFillVert *sf_vert; struct SortNormal *nors; - unsigned int i; + uint i; bool is_degenerate = true; nors = MEM_mallocN(sizeof(*nors) * nors_tot, __func__); @@ -124,7 +124,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) BMVert *v = sf_vert->tmp.p; BMIter eiter; BMEdge *e_pair[2]; - unsigned int e_index = 0; + uint e_index = 0; nors[i].value = -1.0f; @@ -199,7 +199,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) int winding_votes = 0; for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { BMVert *v_tri[3] = {sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p}; - unsigned int i, i_prev; + uint i, i_prev; for (i = 0, i_prev = 2; i < 3; i_prev = i++) { e = BM_edge_exists(v_tri[i], v_tri[i_prev]); diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index 3e3a6547b75..f08f21a2c88 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -62,7 +62,7 @@ typedef struct EdRotState { #if 0 /* use BLI_ghashutil_inthash_v4 direct */ -static unsigned int erot_gsetutil_hash(const void *ptr) +static uint erot_gsetutil_hash(const void *ptr) { const EdRotState *e_state = (const EdRotState *)ptr; return BLI_ghashutil_inthash_v4(&e_state->v1); @@ -368,7 +368,7 @@ void BM_mesh_beautify_fill( TIMEIT_START(beautify_fill); #endif - eheap = BLI_heap_new_ex((unsigned int)edge_array_len); + eheap = BLI_heap_new_ex((uint)edge_array_len); eheap_table = MEM_mallocN(sizeof(HeapNode *) * (size_t)edge_array_len, __func__); /* build heap */ diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 05169a2a976..6673c5d25cf 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -205,6 +205,38 @@ static int bev_debug_flags = 0; #define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2) #define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4) +/* this flag values will get set on geom we want to return in 'out' slots for edges and verts */ +#define EDGE_OUT 4 +#define VERT_OUT 8 + +/* If we're called from the modifier, tool flags aren't available, but don't need output geometry */ +static void flag_out_edge(BMesh *bm, BMEdge *bme) +{ + if (bm->use_toolflags) + BMO_edge_flag_enable(bm, bme, EDGE_OUT); +} + +static void flag_out_vert(BMesh *bm, BMVert *bmv) +{ + if (bm->use_toolflags) + BMO_vert_flag_enable(bm, bmv, VERT_OUT); +} + +static void disable_flag_out_edge(BMesh *bm, BMEdge *bme) +{ + if (bm->use_toolflags) + BMO_edge_flag_disable(bm, bme, EDGE_OUT); +} + +/* Are d1 and d2 parallel or nearly so? */ +static bool nearly_parallel(const float d1[3], const float d2[3]) +{ + float ang; + + ang = angle_v3v3(d1, d2); + return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - M_PI) < BEVEL_EPSILON_ANG); +} + /* Make a new BoundVert of the given kind, insert it at the end of the circular linked * list with entry point bv->boundstart, and return it. */ static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3]) @@ -253,6 +285,7 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert NewVert *nv = mesh_vert(vm, i, j, k); nv->v = BM_vert_create(bm, nv->co, eg, BM_CREATE_NOP); BM_elem_flag_disable(nv->v, BM_ELEM_TAG); + flag_out_vert(bm, nv->v); } static void copy_mesh_vert( @@ -495,9 +528,12 @@ static BMFace *bev_create_ngon( } /* not essential for bevels own internal logic, - * this is done so the operator can select newly created faces */ + * this is done so the operator can select newly created geometry */ if (f) { BM_elem_flag_enable(f, BM_ELEM_TAG); + BM_ITER_ELEM(bme, &iter, f, BM_EDGES_OF_FACE) { + flag_out_edge(bm, bme); + } } if (mat_nr >= 0) @@ -916,8 +952,12 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc return false; } cross_v3_v3v3(fno, dir1, dir2); - if (dot_v3v3(fno, v->no) < 0.0f) + if (dot_v3v3(fno, v->no) < 0.0f) { ang = 2.0f * (float)M_PI - ang; /* angle is reflex */ + if (r_angle) + *r_angle = ang; + return false; + } if (r_angle) *r_angle = ang; @@ -1055,7 +1095,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) { EdgeHalf *e; Profile *pro; - float co1[3], co2[3], co3[3], d1[3], d2[3], l; + float co1[3], co2[3], co3[3], d1[3], d2[3]; bool do_linear_interp; copy_v3_v3(co1, bndv->nv.co); @@ -1093,8 +1133,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) normalize_v3(d1); normalize_v3(d2); cross_v3_v3v3(pro->plane_no, d1, d2); - l = normalize_v3(pro->plane_no); - if (l <= BEVEL_EPSILON_BIG) { + normalize_v3(pro->plane_no); + if (nearly_parallel(d1, d2)) { /* co1 - midco -co2 are collinear. * Should be case that beveled edge is coplanar with two boundary verts. * We want to move the profile to that common plane, if possible. @@ -1126,17 +1166,24 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) sub_v3_v3v3(d4, e->next->e->v1->co, e->next->e->v2->co); normalize_v3(d3); normalize_v3(d4); - add_v3_v3v3(co3, co1, d3); - add_v3_v3v3(co4, co2, d4); - isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2); - if (isect_kind != 0) { - copy_v3_v3(pro->midco, meetco); - } - else { + if (nearly_parallel(d3, d4)) { /* offset lines are collinear - want linear interpolation */ mid_v3_v3v3(pro->midco, co1, co2); do_linear_interp = true; } + else { + add_v3_v3v3(co3, co1, d3); + add_v3_v3v3(co4, co2, d4); + isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2); + if (isect_kind != 0) { + copy_v3_v3(pro->midco, meetco); + } + else { + /* offset lines don't intersect - want linear interpolation */ + mid_v3_v3v3(pro->midco, co1, co2); + do_linear_interp = true; + } + } } } copy_v3_v3(pro->cob, co2); @@ -1145,8 +1192,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv) sub_v3_v3v3(d2, pro->midco, co2); normalize_v3(d2); cross_v3_v3v3(pro->plane_no, d1, d2); - l = normalize_v3(pro->plane_no); - if (l <= BEVEL_EPSILON_BIG) { + normalize_v3(pro->plane_no); + if (nearly_parallel(d1, d2)) { /* whole profile is collinear with edge: just interpolate */ do_linear_interp = true; } @@ -2295,7 +2342,7 @@ static int interp_range(const float *frac, int n, const float f, float *r_rest) /* Interpolate given vmesh to make one with target nseg border vertices on the profiles */ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm0, int nseg) { - int n, ns0, nseg2, odd, i, j, k, j0, k0, k0prev; + int n, ns0, nseg2, odd, i, j, k, j0, k0, k0prev, j0inc, k0inc; float *prev_frac, *frac, *new_frac, *prev_new_frac; float f, restj, restk, restkprev; float quad[4][3], co[3], center[3]; @@ -2339,10 +2386,12 @@ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm0, int nseg) copy_v3_v3(co, mesh_vert_canon(vm0, i, j0, k0)->co); } else { + j0inc = (restj < BEVEL_EPSILON || j0 == ns0) ? 0 : 1; + k0inc = (restk < BEVEL_EPSILON || k0 == ns0) ? 0 : 1; copy_v3_v3(quad[0], mesh_vert_canon(vm0, i, j0, k0)->co); - copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + 1)->co); - copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + 1, k0 + 1)->co); - copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + 1, k0)->co); + copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + k0inc)->co); + copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + j0inc, k0 + k0inc)->co); + copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + j0inc, k0)->co); interp_bilinear_quad_v3(quad, restk, restj, co); } copy_v3_v3(mesh_vert(vm1, i, j, k)->co, co); @@ -3191,6 +3240,7 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv) BMFace *f_new; BLI_assert(v_fan == l_fan->v); f_new = BM_face_split(bm, f, l_fan, l_fan->next->next, &l_new, NULL, false); + flag_out_edge(bm, l_new->e); if (f_new->len > f->len) { f = f_new; @@ -3237,6 +3287,7 @@ static void bevel_build_quadstrip(BevelParams *bp, BMesh *bm, BevVert *bv) else { BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false); f = l_new->f; + flag_out_edge(bm, l_new->e); /* walk around the new face to get the next verts to split */ l_a = l_new->prev; @@ -3256,7 +3307,7 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv) { VMesh *vm = bv->vmesh; BMVert *v1, *v2; - BMEdge *e_eg; + BMEdge *e_eg, *bme; Profile *pro; float co[3]; BoundVert *bndv; @@ -3298,7 +3349,9 @@ static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv) v1 = mesh_vert(vm, 0, 0, k)->v; v2 = mesh_vert(vm, 0, 0, k + 1)->v; BLI_assert(v1 != NULL && v2 != NULL); - BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE); + bme = BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE); + if (bme) + flag_out_edge(bm, bme); } } } @@ -3879,7 +3932,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) /* Face f has at least one beveled vertex. Rebuild f */ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) { - BMIter liter; + BMIter liter, eiter, fiter; BMLoop *l, *lprev; BevVert *bv; BoundVert *v, *vstart, *vend; @@ -3887,10 +3940,10 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) VMesh *vm; int i, k, n; bool do_rebuild = false; - bool go_ccw, corner3special; + bool go_ccw, corner3special, keep; BMVert *bmv; BMEdge *bme, *bme_new, *bme_prev; - BMFace *f_new; + BMFace *f_new, *f_other; BMVert **vv = NULL; BMVert **vv_fix = NULL; BMEdge **ee = NULL; @@ -4028,9 +4081,21 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) } } - /* don't select newly created boundary faces... */ + /* don't select newly or return created boundary faces... */ if (f_new) { BM_elem_flag_disable(f_new, BM_ELEM_TAG); + /* Also don't want new edges that aren't part of a new bevel face */ + BM_ITER_ELEM(bme, &eiter, f_new, BM_EDGES_OF_FACE) { + keep = false; + BM_ITER_ELEM(f_other, &fiter, bme, BM_FACES_OF_EDGE) { + if (BM_elem_flag_test(f_other, BM_ELEM_TAG)) { + keep = true; + break; + } + } + if (!keep) + disable_flag_out_edge(bm, bme); + } } } @@ -4112,8 +4177,9 @@ static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v) } } } while ((bndv = bndv->next) != bv->vmesh->boundstart); - if (vclosest) + if (vclosest) { BM_edge_create(bm, vclosest, votherclosest, e, BM_CREATE_NO_DOUBLE); + } } } @@ -4517,9 +4583,9 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp) /** * - Currently only bevels BM_ELEM_TAG'd verts and edges. * - * - Newly created faces are BM_ELEM_TAG'd too, - * the caller needs to ensure this is cleared before calling - * if its going to use this face tag. + * - Newly created faces, edges, and verts are BM_ELEM_TAG'd too, + * the caller needs to ensure these are cleared before calling + * if its going to use this tag. * * - If limit_offset is set, adjusts offset down if necessary * to avoid geometry collisions. @@ -4611,6 +4677,20 @@ void BM_mesh_bevel( } } + /* When called from operator (as opposed to modifier), bm->use_toolflags + * will be set, and we to transfer the oflags to BM_ELEM_TAGs */ + if (bm->use_toolflags) { + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BMO_vert_flag_test(bm, v, VERT_OUT)) + BM_elem_flag_enable(v, BM_ELEM_TAG); + } + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BMO_edge_flag_test(bm, e, EDGE_OUT)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + } + } + /* primary free */ BLI_ghash_free(bp.vert_hash, NULL, NULL); BLI_memarena_free(bp.mem_arena); diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c index 828c50c39fd..676a8de94c8 100644 --- a/source/blender/bmesh/tools/bmesh_bisect_plane.c +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c @@ -74,7 +74,7 @@ static short plane_point_test_v3(const float plane[4], const float co[3], const #define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */ #define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */ #define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \ - (*((unsigned int *)(&(v)->no[2]))) + (*((uint *)(&(v)->no[2]))) /** * Hide flag access @@ -113,7 +113,7 @@ static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v) static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center, const short oflag_new) { /* unlikely more than 2 verts are needed */ - const unsigned int f_len_orig = (unsigned int)f->len; + const uint f_len_orig = (uint)f->len; BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig); STACK_DECLARE(vert_split_arr); BMLoop *l_iter, *l_first; @@ -171,7 +171,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con STACK_DECLARE(face_split_arr); float sort_dir[3]; - unsigned int i; + uint i; /* ---- */ @@ -246,7 +246,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con if (is_inside) { BMLoop *l_a, *l_b; bool found = false; - unsigned int j; + uint j; for (j = 0; j < STACK_SIZE(face_split_arr); j++) { /* would be nice to avoid loop lookup here, @@ -311,8 +311,8 @@ void BM_mesh_bisect_plane( const bool use_snap_center, const bool use_tag, const short oflag_center, const short oflag_new, const float eps) { - unsigned int einput_len; - unsigned int i; + uint einput_len; + uint i; BMEdge **edges_arr = MEM_mallocN(sizeof(*edges_arr) * (size_t)bm->totedge, __func__); BLI_LINKSTACK_DECLARE(face_stack, BMFace *); @@ -345,7 +345,7 @@ void BM_mesh_bisect_plane( } else { BMEdge *e; - einput_len = (unsigned int)bm->totedge; + einput_len = (uint)bm->totedge; BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { edge_is_cut_enable(e); edges_arr[i] = e; @@ -425,7 +425,7 @@ void BM_mesh_bisect_plane( else if (side[0] == 0 || side[1] == 0) { /* check if either edge verts are aligned, * if so - tag and push all faces that use it into the stack */ - unsigned int j; + uint j; BM_ITER_ELEM_INDEX (v, &iter, e, BM_VERTS_OF_EDGE, j) { if (side[j] == 0) { if (vert_is_center_test(v) == 0) { diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 372d341f223..c417131d588 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -180,7 +180,7 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_ { BMIter liter; BMLoop *l; - unsigned int i; + uint i; for (i = 0; i < 2; i++) { /* loop over both verts */ @@ -367,7 +367,7 @@ static void bm_decim_build_edge_cost( { BMIter iter; BMEdge *e; - unsigned int i; + uint i; BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { eheap_table[i] = NULL; /* keep sanity check happy */ @@ -418,12 +418,12 @@ static bool bm_edge_symmetry_check_cb(void *user_data, int index, const float UN return false; } -static int *bm_edge_symmetry_map(BMesh *bm, unsigned int symmetry_axis, float limit) +static int *bm_edge_symmetry_map(BMesh *bm, uint symmetry_axis, float limit) { struct KD_Symmetry_Data sym_data; BMIter iter; BMEdge *e, **etable; - unsigned int i; + uint i; int *edge_symmetry_map; const float limit_sq = SQUARE(limit); KDTree *tree; diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 92300ae66a2..f0ac6c673c9 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -43,10 +43,10 @@ static bool bm_vert_dissolve_fan_test(BMVert *v) BMVert *varr[4]; - unsigned int tot_edge = 0; - unsigned int tot_edge_boundary = 0; - unsigned int tot_edge_manifold = 0; - unsigned int tot_edge_wire = 0; + uint tot_edge = 0; + uint tot_edge_boundary = 0; + uint tot_edge_manifold = 0; + uint tot_edge_wire = 0; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { if (BM_edge_is_boundary(e)) { @@ -97,11 +97,11 @@ static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v) BMIter iter; BMEdge *e; - unsigned int tot_loop = 0; - unsigned int tot_edge = 0; - unsigned int tot_edge_boundary = 0; - unsigned int tot_edge_manifold = 0; - unsigned int tot_edge_wire = 0; + uint tot_loop = 0; + uint tot_edge = 0; + uint tot_edge_boundary = 0; + uint tot_edge_manifold = 0; + uint tot_edge_wire = 0; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { if (BM_edge_is_boundary(e)) { @@ -143,7 +143,7 @@ static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v) if (tot_loop) { BMLoop *f_loop[4]; - unsigned int i; + uint i; /* ensure there are exactly tot_loop loops */ BLI_assert(BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v, tot_loop) == NULL); @@ -192,8 +192,8 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool BMIter iter; - const unsigned int offset = 0; - const unsigned int nth = 2; + const uint offset = 0; + const uint nth = 2; int iter_step; @@ -229,8 +229,8 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool #ifdef USE_WALKER BMWalker walker; #else - unsigned int depth = 1; - unsigned int i; + uint depth = 1; + uint i; #endif BMVert *v_first = NULL; diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c index 2a1946df7ae..193a032b46e 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.c +++ b/source/blender/bmesh/tools/bmesh_edgenet.c @@ -100,13 +100,13 @@ static BMEdge *bm_edgenet_edge_get_next( * * This function returns half a loop, the caller needs to run twice to get both sides. */ -static unsigned int bm_edgenet_path_from_pass( +static uint bm_edgenet_path_from_pass( BMVert *v, LinkNode **v_ls, VertNetInfo *vnet_info, BLI_mempool *path_pool) { VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)]; const int pass = vn->pass; - unsigned int v_ls_tot = 0; + uint v_ls_tot = 0; do { BLI_linklist_prepend_pool(v_ls, v, path_pool); @@ -127,10 +127,10 @@ static bool bm_edgenet_path_check_overlap( VertNetInfo *vnet_info) { /* vert order doesn't matter */ - unsigned int v_ls_tot = 0; + uint v_ls_tot = 0; LinkNode *v_ls = NULL; BMVert *v_pair[2] = {v1, v2}; - unsigned int i; + uint i; for (i = 0; i < 2; i++) { BMVert *v = v_pair[i]; @@ -162,7 +162,7 @@ static bool bm_edgenet_path_check_overlap( * Create a face from the path. */ static BMFace *bm_edgenet_face_from_path( - BMesh *bm, LinkNode *path, const unsigned int path_len) + BMesh *bm, LinkNode *path, const uint path_len) { BMFace *f; LinkNode *v_lnk; @@ -205,8 +205,8 @@ static BMEdge *bm_edgenet_path_step( BMEdge *e; BMIter iter; - unsigned int tot; - unsigned int v_ls_tot; + uint tot; + uint v_ls_tot; begin: @@ -277,8 +277,8 @@ begin: * \return A linked list of verts. */ static LinkNode *bm_edgenet_path_calc( - BMEdge *e, const int pass_nr, const unsigned int path_cost_max, - unsigned int *r_path_len, unsigned int *r_path_cost, + BMEdge *e, const int pass_nr, const uint path_cost_max, + uint *r_path_len, uint *r_path_cost, VertNetInfo *vnet_info, BLI_mempool *path_pool) { VertNetInfo *vn_1, *vn_2; @@ -288,7 +288,7 @@ static LinkNode *bm_edgenet_path_calc( LinkNode *v_ls_prev = NULL; LinkNode *v_ls_next = NULL; - unsigned int path_cost_accum = 0; + uint path_cost_accum = 0; BLI_assert(bm_edge_step_ok(e)); @@ -331,7 +331,7 @@ static LinkNode *bm_edgenet_path_calc( if (e_found) { LinkNode *path = NULL; - unsigned int path_len; + uint path_len; BLI_linklist_free_pool(v_ls_next, NULL, path_pool); BLI_linklist_free_pool(v_ls_prev, NULL, path_pool); @@ -376,12 +376,12 @@ static LinkNode *bm_edgenet_path_calc( * _don't_ have a better option. */ static LinkNode *bm_edgenet_path_calc_best( - BMEdge *e, int *pass_nr, unsigned int path_cost_max, - unsigned int *r_path_len, unsigned int *r_path_cost, + BMEdge *e, int *pass_nr, uint path_cost_max, + uint *r_path_len, uint *r_path_cost, VertNetInfo *vnet_info, BLI_mempool *path_pool) { LinkNode *path; - unsigned int path_cost; + uint path_cost; path = bm_edgenet_path_calc(e, *pass_nr, path_cost_max, r_path_len, &path_cost, @@ -399,8 +399,8 @@ static LinkNode *bm_edgenet_path_calc_best( /* Check every edge to see if any can give a better path. * This avoids very strange/long paths from being created. */ - const unsigned int path_len = *r_path_len; - unsigned int i, i_prev; + const uint path_len = *r_path_len; + uint i, i_prev; BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len); LinkNode *v_lnk; @@ -413,8 +413,8 @@ static LinkNode *bm_edgenet_path_calc_best( BMEdge *e_other = BM_edge_exists(vert_arr[i], vert_arr[i_prev]); if (e_other != e) { LinkNode *path_test; - unsigned int path_len_test; - unsigned int path_cost_test; + uint path_len_test; + uint path_cost_test; path_test = bm_edgenet_path_calc(e_other, *pass_nr, path_cost, &path_len_test, &path_cost_test, @@ -471,8 +471,8 @@ void BM_mesh_edgenet( while (true) { LinkNode *path = NULL; - unsigned int path_len; - unsigned int path_cost; + uint path_len; + uint path_cost; e = bm_edgenet_edge_get_next(bm, &edge_queue, edge_queue_pool); if (e == NULL) { diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index a59a5c43c82..3a844a0b8d9 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -96,7 +96,7 @@ void BM_mesh_edgesplit( BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - unsigned int i; + uint i; for (i = 0; i < 2; i++) { BMVert *v = ((&e->v1)[i]); if (BM_elem_flag_test(v, BM_ELEM_TAG)) { diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index 2cb82d0fc02..b9408492cc1 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -152,7 +152,7 @@ struct ISectState { */ struct LinkBase { LinkNode *list; - unsigned int list_len; + uint list_len; }; static bool ghash_insert_link( @@ -193,7 +193,7 @@ struct vert_sort_t { static void edge_verts_sort(const float co[3], struct LinkBase *v_ls_base) { /* not optimal but list will be typically < 5 */ - unsigned int i; + uint i; struct vert_sort_t *vert_sort = BLI_array_alloca(vert_sort, v_ls_base->list_len); LinkNode *node; @@ -246,8 +246,8 @@ static void face_edges_split( bool use_island_connect, MemArena *mem_arena_edgenet) { - unsigned int i; - unsigned int edge_arr_len = e_ls_base->list_len; + uint i; + uint edge_arr_len = e_ls_base->list_len; BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len); LinkNode *node; BLI_assert(f->head.htype == BM_FACE); @@ -263,7 +263,7 @@ static void face_edges_split( #ifdef USE_NET_ISLAND_CONNECT if (use_island_connect) { - unsigned int edge_arr_holes_len; + uint edge_arr_holes_len; BMEdge **edge_arr_holes; if (BM_face_split_edgenet_connect_islands( bm, f, @@ -305,14 +305,14 @@ static enum ISectType intersect_line_tri( const struct ISectEpsilon *e) { float p_dir[3]; - unsigned int i_t0; + uint i_t0; float fac; sub_v3_v3v3(p_dir, p0, p1); normalize_v3(p_dir); for (i_t0 = 0; i_t0 < 3; i_t0++) { - const unsigned int i_t1 = (i_t0 + 1) % 3; + const uint i_t1 = (i_t0 + 1) % 3; float te_dir[3]; sub_v3_v3v3(te_dir, t_cos[i_t0], t_cos[i_t1]); @@ -375,7 +375,7 @@ static BMVert *bm_isect_edge_tri( { BMesh *bm = s->bm; int k_arr[IX_TOT][4]; - unsigned int i; + uint i; const int ti[3] = {UNPACK3_EX(BM_elem_index_get, t, )}; float ix[3]; @@ -470,7 +470,7 @@ static BMVert *bm_isect_edge_tri( } if ((*r_side >= IX_EDGE_TRI_EDGE0) && (*r_side <= IX_EDGE_TRI_EDGE2)) { - i = (unsigned int)(*r_side - IX_EDGE_TRI_EDGE0); + i = (uint)(*r_side - IX_EDGE_TRI_EDGE0); e = BM_edge_exists(t[i], t[(i + 1) % 3]); if (e) { edge_verts_add(s, e, iv, false); @@ -537,7 +537,7 @@ static void bm_isect_tri_tri( const float *f_b_cos[3] = {UNPACK3_EX(, fv_b, ->co)}; float f_a_nor[3]; float f_b_nor[3]; - unsigned int i; + uint i; /* should be enough but may need to bump */ @@ -578,9 +578,9 @@ static void bm_isect_tri_tri( /* first check in any verts are touching * (any case where we wont create new verts) */ - unsigned int i_a; + uint i_a; for (i_a = 0; i_a < 3; i_a++) { - unsigned int i_b; + uint i_b; for (i_b = 0; i_b < 3; i_b++) { if (len_squared_v3v3(fv_a[i_a]->co, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) { #ifdef USE_DUMP @@ -603,12 +603,12 @@ static void bm_isect_tri_tri( /* vert-edge * --------- */ { - unsigned int i_a; + uint i_a; for (i_a = 0; i_a < 3; i_a++) { if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT_A) == 0) { - unsigned int i_b_e0; + uint i_b_e0; for (i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) { - unsigned int i_b_e1 = (i_b_e0 + 1) % 3; + uint i_b_e1 = (i_b_e0 + 1) % 3; if (BM_ELEM_API_FLAG_TEST(fv_b[i_b_e0], VERT_VISIT_B) || BM_ELEM_API_FLAG_TEST(fv_b[i_b_e1], VERT_VISIT_B)) @@ -644,12 +644,12 @@ static void bm_isect_tri_tri( } { - unsigned int i_b; + uint i_b; for (i_b = 0; i_b < 3; i_b++) { if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT_B) == 0) { - unsigned int i_a_e0; + uint i_a_e0; for (i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) { - unsigned int i_a_e1 = (i_a_e0 + 1) % 3; + uint i_a_e1 = (i_a_e0 + 1) % 3; if (BM_ELEM_API_FLAG_TEST(fv_a[i_a_e0], VERT_VISIT_A) || BM_ELEM_API_FLAG_TEST(fv_a[i_a_e1], VERT_VISIT_A)) @@ -689,7 +689,7 @@ static void bm_isect_tri_tri( { float t_scale[3][3]; - unsigned int i_a; + uint i_a; copy_v3_v3(t_scale[0], fv_b[0]->co); copy_v3_v3(t_scale[1], fv_b[1]->co); @@ -717,7 +717,7 @@ static void bm_isect_tri_tri( { float t_scale[3][3]; - unsigned int i_b; + uint i_b; copy_v3_v3(t_scale[0], fv_a[0]->co); copy_v3_v3(t_scale[1], fv_a[1]->co); @@ -757,8 +757,8 @@ static void bm_isect_tri_tri( /* edge-tri & edge-edge * -------------------- */ { - for (unsigned int i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) { - unsigned int i_a_e1 = (i_a_e0 + 1) % 3; + for (uint i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) { + uint i_a_e1 = (i_a_e0 + 1) % 3; enum ISectType side; BMVert *iv; @@ -778,8 +778,8 @@ static void bm_isect_tri_tri( } } - for (unsigned int i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) { - unsigned int i_b_e1 = (i_b_e0 + 1) % 3; + for (uint i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) { + uint i_b_e1 = (i_b_e0 + 1) % 3; enum ISectType side; BMVert *iv; @@ -956,7 +956,7 @@ static int isect_bvhtree_point_v3( const float *depth_arr = z_buffer.data; float depth_last = depth_arr[0]; - for (unsigned int i = 1; i < z_buffer.count; i++) { + for (uint i = 1; i < z_buffer.count; i++) { if (depth_arr[i] - depth_last > eps) { depth_last = depth_arr[i]; num_isect++; @@ -1000,7 +1000,7 @@ bool BM_mesh_intersect( #ifdef USE_BVH BVHTree *tree_a, *tree_b; - unsigned int tree_overlap_tot; + uint tree_overlap_tot; BVHTreeOverlap *overlap; #else int i_a, i_b; @@ -1117,7 +1117,7 @@ bool BM_mesh_intersect( overlap = BLI_bvhtree_overlap(tree_b, tree_a, &tree_overlap_tot, NULL, NULL); if (overlap) { - unsigned int i; + uint i; for (i = 0; i < tree_overlap_tot; i++) { #ifdef USE_DUMP @@ -1390,7 +1390,7 @@ bool BM_mesh_intersect( GHASH_ITER (gh_iter, s.face_edges) { struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter); LinkNode **node_prev_p; - unsigned int i; + uint i; node_prev_p = &e_ls_base->list; for (i = 0, node = e_ls_base->list; node; i++, node = node->next) { @@ -1455,7 +1455,7 @@ bool BM_mesh_intersect( } { - unsigned int i; + uint i; for (i = 0; i < STACK_SIZE(splice_ls); i++) { if (!BLI_gset_haskey(verts_invalid, splice_ls[i][0]) && !BLI_gset_haskey(verts_invalid, splice_ls[i][1])) @@ -1610,7 +1610,7 @@ bool BM_mesh_intersect( #ifdef USE_BOOLEAN_RAYCAST_DRAW { - unsigned int colors[4] = {0x00000000, 0xffffffff, 0xff000000, 0x0000ff}; + uint colors[4] = {0x00000000, 0xffffffff, 0xff000000, 0x0000ff}; float co_other[3] = {UNPACK3(co)}; co_other[0] += 1000.0f; bl_debug_color_set(colors[(hits & 1) == 1]); diff --git a/source/blender/bmesh/tools/bmesh_path.h b/source/blender/bmesh/tools/bmesh_path.h index b6de5e0e4e0..fbdd2296121 100644 --- a/source/blender/bmesh/tools/bmesh_path.h +++ b/source/blender/bmesh/tools/bmesh_path.h @@ -28,8 +28,8 @@ */ struct BMCalcPathParams { - unsigned int use_topology_distance : 1; - unsigned int use_step_face : 1; + uint use_topology_distance : 1; + uint use_step_face : 1; }; struct LinkNode *BM_mesh_calc_path_vert( diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index a6860a6614a..2abf8f2c46e 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -114,7 +114,7 @@ typedef struct UUIDWalk { GHash *faces_from_uuid; /* UUID -> UUIDFaceStepItem */ UUID_Int *rehash_store; - unsigned int rehash_store_len; + uint rehash_store_len; } cache; } UUIDWalk; @@ -136,7 +136,7 @@ typedef struct UUIDFaceStepItem { uintptr_t uuid; LinkNode *list; - unsigned int list_len; + uint list_len; } UUIDFaceStepItem; BLI_INLINE bool bm_uuidwalk_face_test( @@ -178,10 +178,10 @@ BLI_INLINE bool bm_uuidwalk_face_lookup( } } -static unsigned int ghashutil_bmelem_indexhash(const void *key) +static uint ghashutil_bmelem_indexhash(const void *key) { const BMElem *ele = key; - return (unsigned int)BM_elem_index_get(ele); + return (uint)BM_elem_index_get(ele); } static bool ghashutil_bmelem_indexcmp(const void *a, const void *b) @@ -192,14 +192,14 @@ static bool ghashutil_bmelem_indexcmp(const void *a, const void *b) static GHash *ghash_bmelem_new_ex( const char *info, - const unsigned int nentries_reserve) + const uint nentries_reserve) { return BLI_ghash_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve); } static GSet *gset_bmelem_new_ex( const char *info, - const unsigned int nentries_reserve) + const uint nentries_reserve) { return BLI_gset_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve); } @@ -218,8 +218,8 @@ static GSet *gset_bmelem_new(const char *info) static void bm_uuidwalk_init( UUIDWalk *uuidwalk, - const unsigned int faces_src_region_len, - const unsigned int verts_src_region_len) + const uint faces_src_region_len, + const uint verts_src_region_len) { BLI_listbase_clear(&uuidwalk->faces_step); @@ -307,7 +307,7 @@ static UUID_Int bm_uuidwalk_calc_vert_uuid( /* vert -> other */ { - unsigned int tot = 0; + uint tot = 0; BMIter eiter; BMEdge *e; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { @@ -323,7 +323,7 @@ static UUID_Int bm_uuidwalk_calc_vert_uuid( /* faces */ { - unsigned int tot = 0; + uint tot = 0; BMIter iter; BMFace *f; @@ -357,7 +357,7 @@ static UUID_Int bm_uuidwalk_calc_face_uuid( UUID_Int uuid; - uuid = uuidwalk->pass * (unsigned int)f->len * PRIME_FACE_LARGE; + uuid = uuidwalk->pass * (uint)f->len * PRIME_FACE_LARGE; /* face-verts */ { @@ -399,7 +399,7 @@ static UUID_Int bm_uuidwalk_calc_face_uuid( } static void bm_uuidwalk_rehash_reserve( - UUIDWalk *uuidwalk, unsigned int rehash_store_len_new) + UUIDWalk *uuidwalk, uint rehash_store_len_new) { if (UNLIKELY(rehash_store_len_new > uuidwalk->cache.rehash_store_len)) { /* avoid re-allocs */ @@ -419,9 +419,9 @@ static void bm_uuidwalk_rehash( { GHashIterator gh_iter; UUID_Int *uuid_store; - unsigned int i; + uint i; - unsigned int rehash_store_len_new = MAX2(BLI_ghash_size(uuidwalk->verts_uuid), + uint rehash_store_len_new = MAX2(BLI_ghash_size(uuidwalk->verts_uuid), BLI_ghash_size(uuidwalk->faces_uuid)); bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new); @@ -454,12 +454,12 @@ static void bm_uuidwalk_rehash( static void bm_uuidwalk_rehash_facelinks( UUIDWalk *uuidwalk, - LinkNode *faces, const unsigned int faces_len, + LinkNode *faces, const uint faces_len, const bool is_init) { UUID_Int *uuid_store; LinkNode *f_link; - unsigned int i; + uint i; bm_uuidwalk_rehash_reserve(uuidwalk, faces_len); uuid_store = uuidwalk->cache.rehash_store; @@ -502,7 +502,7 @@ static bool bm_vert_is_uuid_connect( } static void bm_uuidwalk_pass_add( - UUIDWalk *uuidwalk, LinkNode *faces_pass, const unsigned int faces_pass_len) + UUIDWalk *uuidwalk, LinkNode *faces_pass, const uint faces_pass_len) { GHashIterator gh_iter; GHash *verts_uuid_pass; @@ -511,7 +511,7 @@ static void bm_uuidwalk_pass_add( UUIDFaceStep *fstep; - BLI_assert(faces_pass_len == (unsigned int)BLI_linklist_count(faces_pass)); + BLI_assert(faces_pass_len == (uint)BLI_linklist_count(faces_pass)); /* rehash faces now all their verts have been added */ bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, true); @@ -588,13 +588,13 @@ static int bm_face_len_cmp(const void *v1, const void *v2) else return 0; } -static unsigned int bm_uuidwalk_init_from_edge( +static uint bm_uuidwalk_init_from_edge( UUIDWalk *uuidwalk, BMEdge *e) { BMLoop *l_iter = e->l; - unsigned int f_arr_len = (unsigned int)BM_edge_face_count(e); + uint f_arr_len = (uint)BM_edge_face_count(e); BMFace **f_arr = BLI_array_alloca(f_arr, f_arr_len); - unsigned int fstep_num = 0, i = 0; + uint fstep_num = 0, i = 0; do { BMFace *f = l_iter->f; @@ -619,7 +619,7 @@ static unsigned int bm_uuidwalk_init_from_edge( * elsewhere using LinkNode's makes more sense */ for (i = 0; i < f_arr_len; ) { LinkNode *faces_pass = NULL; - const unsigned int i_init = i; + const uint i_init = i; const int f_len = f_arr[i]->len; do { @@ -750,9 +750,9 @@ static BMFace **bm_mesh_region_match_pair( UUIDWalk *w_src, UUIDWalk *w_dst, #endif BMEdge *e_src, BMEdge *e_dst, - const unsigned int faces_src_region_len, - const unsigned int verts_src_region_len, - unsigned int *r_faces_result_len) + const uint faces_src_region_len, + const uint verts_src_region_len, + uint *r_faces_result_len) { #ifndef USE_WALKER_REUSE UUIDWalk w_src_, w_dst_; @@ -877,8 +877,8 @@ static BMFace **bm_mesh_region_match_pair( if (found) { GHashIterator gh_iter; - const unsigned int faces_result_len = BLI_ghash_size(w_dst->faces_uuid); - unsigned int i; + const uint faces_result_len = BLI_ghash_size(w_dst->faces_uuid); + uint i; faces_result = MEM_mallocN(sizeof(*faces_result) * (faces_result_len + 1), __func__); GHASH_ITER_INDEX (gh_iter, w_dst->faces_uuid, i) { @@ -909,12 +909,12 @@ finally: * Tag as visited, avoid re-use. */ static void bm_face_array_visit( - BMFace **faces, const unsigned int faces_len, - unsigned int *r_verts_len, + BMFace **faces, const uint faces_len, + uint *r_verts_len, bool visit_faces) { - unsigned int verts_len = 0; - unsigned int i; + uint verts_len = 0; + uint i; for (i = 0; i < faces_len; i++) { BMFace *f = faces[i]; BMLoop *l_iter, *l_first; @@ -1081,9 +1081,9 @@ static SUID_Int bm_face_region_vert_pass_id(GHash *gh, BMVert *v) * This is only called once on the source region (no need to be highly optimized). */ static BMEdge *bm_face_region_pivot_edge_find( - BMFace **faces_region, unsigned int faces_region_len, - unsigned int verts_region_len, - unsigned int *r_depth) + BMFace **faces_region, uint faces_region_len, + uint verts_region_len, + uint *r_depth) { /* note, keep deterministic where possible (geometry order independent) * this function assumed all visit faces & edges are tagged */ @@ -1092,7 +1092,7 @@ static BMEdge *bm_face_region_pivot_edge_find( BLI_LINKSTACK_DECLARE(vert_queue_next, BMVert *); GHash *gh = BLI_ghash_ptr_new(__func__); - unsigned int i; + uint i; BMEdge *e_pivot = NULL; /* pick any non-boundary edge (not ideal) */ @@ -1101,7 +1101,7 @@ static BMEdge *bm_face_region_pivot_edge_find( SUID_Int pass = 0; /* total verts in 'gs' we have visited - aka - not v_init_none */ - unsigned int vert_queue_used = 0; + uint vert_queue_used = 0; BLI_LINKSTACK_INIT(vert_queue_prev); BLI_LINKSTACK_INIT(vert_queue_next); @@ -1115,7 +1115,7 @@ static BMEdge *bm_face_region_pivot_edge_find( do { BMEdge *e = l_iter->e; if (bm_edge_is_region_boundary(e)) { - unsigned int j; + uint j; for (j = 0; j < 2; j++) { void **val_p; if (!BLI_ghash_ensure_p(gh, (&e->v1)[j], &val_p)) { @@ -1251,7 +1251,7 @@ static BMEdge *bm_face_region_pivot_edge_find( pass = 0; } - *r_depth = (unsigned int)pass; + *r_depth = (uint)pass; return e_pivot; } @@ -1286,7 +1286,7 @@ static UUIDFashMatch bm_vert_fasthash_single(BMVert *v) e_num += 1; do { f_num += 1; - l_num += (unsigned int)l_iter->f->len; + l_num += (uint)l_iter->f->len; } while ((l_iter = l_iter->radial_next) != e->l); } } @@ -1301,16 +1301,16 @@ static UUIDFashMatch bm_vert_fasthash_single(BMVert *v) } static UUIDFashMatch *bm_vert_fasthash_create( - BMesh *bm, const unsigned int depth) + BMesh *bm, const uint depth) { UUIDFashMatch *id_prev; UUIDFashMatch *id_curr; - unsigned int pass, i; + uint pass, i; BMVert *v; BMIter iter; - id_prev = MEM_mallocN(sizeof(*id_prev) * (unsigned int)bm->totvert, __func__); - id_curr = MEM_mallocN(sizeof(*id_curr) * (unsigned int)bm->totvert, __func__); + id_prev = MEM_mallocN(sizeof(*id_prev) * (uint)bm->totvert, __func__); + id_curr = MEM_mallocN(sizeof(*id_curr) * (uint)bm->totvert, __func__); BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { id_prev[i] = bm_vert_fasthash_single(v); @@ -1319,7 +1319,7 @@ static UUIDFashMatch *bm_vert_fasthash_create( for (pass = 0; pass < depth; pass++) { BMEdge *e; - memcpy(id_curr, id_prev, sizeof(*id_prev) * (unsigned int)bm->totvert); + memcpy(id_curr, id_prev, sizeof(*id_prev) * (uint)bm->totvert); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_edge_is_wire(e) == false) { @@ -1379,16 +1379,16 @@ static void bm_vert_fasthash_destroy( */ int BM_mesh_region_match( BMesh *bm, - BMFace **faces_region, unsigned int faces_region_len, + BMFace **faces_region, uint faces_region_len, ListBase *r_face_regions) { BMEdge *e_src; BMEdge *e_dst; BMIter iter; - unsigned int verts_region_len = 0; - unsigned int faces_result_len = 0; + uint verts_region_len = 0; + uint faces_result_len = 0; /* number of steps from e_src to a boundary vert */ - unsigned int depth; + uint depth; #ifdef USE_WALKER_REUSE @@ -1457,7 +1457,7 @@ int BM_mesh_region_match( BM_ITER_MESH (e_dst, &iter, bm, BM_EDGES_OF_MESH) { BMFace **faces_result; - unsigned int faces_result_len_out; + uint faces_result_len_out; if (BM_elem_flag_test(e_dst, BM_ELEM_TAG) || BM_edge_is_wire(e_dst)) { continue; diff --git a/source/blender/bmesh/tools/bmesh_region_match.h b/source/blender/bmesh/tools/bmesh_region_match.h index edf8369b070..8ef138629b8 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.h +++ b/source/blender/bmesh/tools/bmesh_region_match.h @@ -27,7 +27,7 @@ int BM_mesh_region_match( BMesh *bm, - BMFace **faces_region, unsigned int faces_region_len, + BMFace **faces_region, uint faces_region_len, ListBase *r_face_regions); #endif /* __BMESH_REGION_MATCH_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_separate.c b/source/blender/bmesh/tools/bmesh_separate.c index ff28ed4c156..287b4125330 100644 --- a/source/blender/bmesh/tools/bmesh_separate.c +++ b/source/blender/bmesh/tools/bmesh_separate.c @@ -58,8 +58,8 @@ void BM_mesh_separate_faces( BMFace *f; BMIter iter; - unsigned int faces_a_len = 0; - unsigned int faces_b_len = 0; + uint faces_a_len = 0; + uint faces_b_len = 0; { int i_a = 0; int i_b = bm->totface; @@ -77,7 +77,7 @@ void BM_mesh_separate_faces( BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false); /* Disable vert tag on faces_b */ - for (unsigned int i = 0; i < faces_b_len; i++) { + for (uint i = 0; i < faces_b_len; i++) { BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]); do { @@ -89,7 +89,7 @@ void BM_mesh_separate_faces( BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128); /* Check shared verts ('faces_a' tag and disable) */ - for (unsigned int i = 0; i < faces_a_len; i++) { + for (uint i = 0; i < faces_a_len; i++) { BMLoop *l_iter, *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]); do { diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index 3bff20e846b..b3d512204be 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -530,7 +530,7 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_ addSampler(sampler); - std::string target = translate_id(bone_name) + "/transform"; + std::string target = get_joint_id(bone, ob_arm) + "/transform"; addChannel(COLLADABU::URI(empty, sampler_id), target); closeAnimation(); diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 9348f3b3285..d2495a8cb9f 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -116,7 +116,10 @@ bool ArmatureExporter::add_instance_controller(Object *ob) write_bone_URLs(ins, ob_arm, bone); } - InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + InstanceWriter::add_material_bindings(ins.getBindMaterial(), + ob, + this->export_settings->active_uv_only, + this->export_settings->export_texture_type); ins.add(); return true; diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 1c2642e8313..5cd5e6d271a 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -98,7 +98,10 @@ bool ControllerExporter::add_instance_controller(Object *ob) write_bone_URLs(ins, ob_arm, bone); } - InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + InstanceWriter::add_material_bindings(ins.getBindMaterial(), + ob, + this->export_settings->active_uv_only, + this->export_settings->export_texture_type); ins.add(); return true; diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index bd32e989ae3..634071bc90f 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -138,7 +138,8 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype); char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n) { int layer_index = CustomData_get_layer_index(data, type); - if (layer_index < 0) return NULL; + if (layer_index < 0) + return NULL; return data->layers[layer_index + n].name; } @@ -147,9 +148,10 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type) { /* get the layer index of the active layer of type */ int layer_index = CustomData_get_active_layer_index(data, type); - if (layer_index < 0) return NULL; + if (layer_index < 1) + return NULL; - return data->layers[layer_index].name; + return bc_CustomData_get_layer_name(data, type, layer_index-1); } DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) { diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 226f319cefd..435eaa0208a 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -388,9 +388,7 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera Camera *cam = uid_camera_map[cam_uid]; Camera *old_cam = (Camera *)ob->data; ob->data = cam; - id_us_min(&old_cam->id); - if (old_cam->id.us == 0) - BKE_libblock_free(G.main, old_cam); + BKE_libblock_free_us(G.main, old_cam); return ob; } @@ -406,9 +404,7 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce Lamp *la = uid_lamp_map[lamp_uid]; Lamp *old_lamp = (Lamp *)ob->data; ob->data = la; - id_us_min(&old_lamp->id); - if (old_lamp->id.us == 0) - BKE_libblock_free(G.main, old_lamp); + BKE_libblock_free_us(G.main, old_lamp); return ob; } diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 76b51148509..2bf0859b0f0 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -27,7 +27,6 @@ #include <map> -#include <set> #include "COLLADASWEffectProfile.h" #include "COLLADAFWColorOrTexture.h" @@ -49,21 +48,10 @@ extern "C" { #include "BKE_material.h" } -// OB_MESH is assumed -static std::string getActiveUVLayerName(Object *ob) -{ - Mesh *me = (Mesh *)ob->data; - - int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); - if (num_layers) - return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE)); - - return ""; -} - EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) { } + bool EffectsExporter::hasEffects(Scene *sce) { Base *base = (Base *)sce->base.first; @@ -86,13 +74,49 @@ bool EffectsExporter::hasEffects(Scene *sce) void EffectsExporter::exportEffects(Scene *sce) { - if (hasEffects(sce)) { - this->scene = sce; - openLibrary(); - MaterialFunctor mf; - mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set); - - closeLibrary(); + this->scene = sce; + + if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) { + if (hasEffects(sce)) { + MaterialFunctor mf; + openLibrary(); + mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set); + closeLibrary(); + } + } + else { + std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only); + std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only); + if (uv_images.size() > 0) { + openLibrary(); + std::set<Image *>::iterator uv_images_iter; + for (uv_images_iter = uv_images.begin(); + uv_images_iter != uv_images.end(); + uv_images_iter++) { + + Image *ima = *uv_images_iter; + std::string key(id_name(ima)); + key = translate_id(key); + COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D, + key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, + key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); + sampler.setImageId(key); + + openEffect(key + "-effect"); + COLLADASW::EffectProfile ep(mSW); + ep.setProfileType(COLLADASW::EffectProfile::COMMON); + ep.setShaderType(COLLADASW::EffectProfile::PHONG); + ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse"); + COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f); + ep.setSpecular(cot, false, "specular"); + ep.openProfile(); + ep.addProfileElements(); + ep.addExtraTechniques(mSW); + ep.closeProfile(); + closeEffect(); + } + closeLibrary(); + } } } @@ -176,8 +200,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob) { // create a list of indices to textures of type TEX_IMAGE std::vector<int> tex_indices; - if (this->export_settings->include_material_textures) - createTextureIndices(ma, tex_indices); + createTextureIndices(ma, tex_indices); openEffect(translate_id(id_name(ma)) + "-effect"); @@ -311,61 +334,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob) } } - int active_uv_layer = -1; - std::set<Image *> uv_textures; - if (ob->type == OB_MESH && ob->totcol && this->export_settings->include_uv_textures) { - bool active_uv_only = this->export_settings->active_uv_only; - Mesh *me = (Mesh *) ob->data; - active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); - - BKE_mesh_tessface_ensure(me); - for (int i = 0; i < me->pdata.totlayer; i++) { - if (!active_uv_only || active_uv_layer == i) - { - if (me->pdata.layers[i].type == CD_MTEXPOLY) { - MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; - MPoly *mpoly = me->mpoly; - for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { - - Material *mat = give_current_material(ob, mpoly->mat_nr + 1); - if (mat != ma) - continue; - - Image *ima = txface->tpage; - if (ima == NULL) - continue; - - - bool not_in_list = uv_textures.find(ima)==uv_textures.end(); - if (not_in_list) { - std::string name = id_name(ima); - std::string key(name); - key = translate_id(key); - - // create only one <sampler>/<surface> pair for each unique image - if (im_samp_map.find(key) == im_samp_map.end()) { - //<newparam> <sampler> <source> - COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D, - key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, - key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); - sampler.setImageId(key); - samplers[a] = sampler; - samp_surf[b] = &samplers[a]; - im_samp_map[key] = b; - b++; - a++; - uv_textures.insert(ima); - } - } - } - } - } - } - } - // used as fallback when MTex->uvname is "" (this is pretty common) // it is indeed the correct value to use in that case - std::string active_uv(getActiveUVLayerName(ob)); + std::string active_uv(bc_get_active_uvlayer_name(ob)); // write textures // XXX very slow @@ -385,19 +356,6 @@ void EffectsExporter::operator()(Material *ma, Object *ob) writeTextures(ep, key, sampler, t, ima, uvname); } - std::set<Image *>::iterator uv_t_iter; - int idx; - for (idx = 0, uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++, idx++ ) { - if (active_uv_layer>-1 && idx==active_uv_layer) { - Image *ima = *uv_t_iter; - std::string key(id_name(ima)); - key = translate_id(key); - int i = im_samp_map[key]; - COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i]; - ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse"); - } - } - // performs the actual writing ep.addProfileElements(); bool twoSided = false; diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h index d20cbfdfe0b..7d45a085777 100644 --- a/source/blender/collada/EffectExporter.h +++ b/source/blender/collada/EffectExporter.h @@ -48,7 +48,6 @@ class EffectsExporter: COLLADASW::LibraryEffects public: EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); void exportEffects(Scene *sce); - void operator()(Material *ma, Object *ob); COLLADASW::ColorOrTexture createTexture(Image *ima, diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp index 98aa85f8a9b..32aa5636e08 100644 --- a/source/blender/collada/ErrorHandler.cpp +++ b/source/blender/collada/ErrorHandler.cpp @@ -49,7 +49,7 @@ ErrorHandler::~ErrorHandler() //-------------------------------------------------------------------- bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) { - bool isError = true; + bool isError = false; if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) { COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error; @@ -81,10 +81,7 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) * Accept non critical errors as warnings (i.e. texture not found) * This makes the importer more graceful, so it now imports what makes sense. */ - if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) { - isError = false; - } - + isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL); std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl; } else { @@ -93,5 +90,5 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) mError |= isError; - return false; // let OpenCollada decide when to abort + return isError; // let OpenCollada decide when to abort } diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index de91f68a492..6d90edd2f67 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -28,7 +28,6 @@ #define __EXPORTSETTINGS_H__ #include "collada.h" -#include "collada.h" struct ExportSettings { public: @@ -42,8 +41,7 @@ public: bool deform_bones_only; bool active_uv_only; - bool include_uv_textures; - bool include_material_textures; + BC_export_texture_type export_texture_type; bool use_texture_copies; bool triangulate; diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 7c7c57f3305..b8b1ff7fd95 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -52,6 +52,7 @@ extern "C" { #include "collada_internal.h" #include "collada_utils.h" + // TODO: optimize UV sets by making indexed list with duplicates removed GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings) { @@ -134,13 +135,22 @@ void GeometryExporter::operator()(Object *ob) // Only create Polylists if number of faces > 0 if (me->totface > 0) { // XXX slow - if (ob->totcol) { - for (int a = 0; a < ob->totcol; a++) { - createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); + std::set<Image *> uv_images = bc_getUVImages(ob, !this->export_settings->active_uv_only); + if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT || uv_images.size() == 0) { + if (ob->totcol) { + for (int a = 0; a < ob->totcol; a++) { + createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); + } + } + else { + int i = 0; + createPolylist(i, has_uvs, has_color, ob, me, geom_id, norind); } } else { - createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind); + bool all_uv_layers = !this->export_settings->active_uv_only; + std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers); + createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind); } } @@ -220,13 +230,15 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb) //createLooseEdgeList(ob, me, geom_id, norind); // XXX slow - if (ob->totcol) { + if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) { for (int a = 0; a < ob->totcol; a++) { createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); } } else { - createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind); + bool all_uv_layers = !this->export_settings->active_uv_only; + std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers); + createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind); } closeMesh(); @@ -295,7 +307,44 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char return result; } -// powerful because it handles both cases when there is material and when there's not +static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase *facelist, std::vector<unsigned long> &vcount_list) +{ + // performs the actual writing + if (is_triangulated) { + ((COLLADASW::Triangles *)facelist)->prepareToAppendValues(); + } + else { + // sets <vcount> + facelist->setVCountList(vcount_list); + ((COLLADASW::Polylist *)facelist)-> prepareToAppendValues(); + } +} + +static void finishList(bool is_triangulated, COLLADASW::PrimitivesBase *facelist) +{ + if (is_triangulated) { + ((COLLADASW::Triangles *)facelist)->finish(); + } + else { + ((COLLADASW::Polylist *)facelist)->finish(); + } +} + +COLLADASW::PrimitivesBase *getFacelist(bool is_triangulated, COLLADASW::StreamWriter *mSW) +{ + COLLADASW::PrimitivesBase *facelist; + + if (is_triangulated) + { + facelist = new COLLADASW::Triangles(mSW); + } + else { + facelist = new COLLADASW::Polylist(mSW); + } + return facelist; +} + +// Export meshes with Materials void GeometryExporter::createPolylist(short material_index, bool has_uvs, bool has_color, @@ -313,7 +362,7 @@ void GeometryExporter::createPolylist(short material_index, int i; int faces_in_polylist = 0; std::vector<unsigned long> vcount_list; - + bool is_triangulated = true; // count faces with this material for (i = 0; i < totpolys; i++) { MPoly *p = &mpolys[i]; @@ -321,6 +370,9 @@ void GeometryExporter::createPolylist(short material_index, if (p->mat_nr == material_index) { faces_in_polylist++; vcount_list.push_back(p->totloop); + if (p->totloop != 3) { + is_triangulated = false; + } } } @@ -331,20 +383,21 @@ void GeometryExporter::createPolylist(short material_index, } Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL; - COLLADASW::Polylist polylist(mSW); + COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW); + // sets count attribute in <polylist> - polylist.setCount(faces_in_polylist); + facelist->setCount(faces_in_polylist); // sets material name if (ma) { std::string material_id = get_material_id(ma); std::ostringstream ostr; ostr << translate_id(material_id); - polylist.setMaterial(ostr.str()); + facelist->setMaterial(ostr.str()); } - COLLADASW::InputList &til = polylist.getInputList(); + COLLADASW::InputList &til = facelist->getInputList(); // creates <input> in <polylist> for vertices COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0); @@ -360,13 +413,21 @@ void GeometryExporter::createPolylist(short material_index, int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1; for (i = 0; i < num_layers; i++) { if (!this->export_settings->active_uv_only || i == active_uv_index) { - - // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i); + + std::string uv_name(bc_get_uvlayer_name(me, i)); + std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name; + std::string layer_id = makeTexcoordSourceId( + effective_id, + i, this->export_settings->active_uv_only); + + /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements + For now this is always 2 (This may change sometime/maybe) + */ COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD, - makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)), - 2, // this is only until we have optimized UV sets - (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set - ); + makeUrl(layer_id), + 2, // this is only until we have optimized UV sets + (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set + ); til.push_back(input3); } } @@ -387,12 +448,10 @@ void GeometryExporter::createPolylist(short material_index, } } - // sets <vcount> - polylist.setVCountList(vcount_list); // performs the actual writing - polylist.prepareToAppendValues(); - + prepareToAppendValues(is_triangulated, facelist, vcount_list); + // <p> int texindex = 0; for (i = 0; i < totpolys; i++) { @@ -404,22 +463,202 @@ void GeometryExporter::createPolylist(short material_index, BCPolygonNormalsIndices normal_indices = norind[i]; for (int j = 0; j < loop_count; j++) { - polylist.appendValues(l[j].v); - polylist.appendValues(normal_indices[j]); + facelist->appendValues(l[j].v); + facelist->appendValues(normal_indices[j]); if (has_uvs) - polylist.appendValues(texindex + j); + facelist->appendValues(texindex + j); if (has_color) - polylist.appendValues(texindex + j); + facelist->appendValues(texindex + j); } } texindex += loop_count; } - - polylist.finish(); + + finishList(is_triangulated, facelist); + delete facelist; +} + +void GeometryExporter::createPolylists(std::set<Image *> uv_images, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind) +{ + std::set<Image *>::iterator uv_images_iter; + for (uv_images_iter = uv_images.begin(); + uv_images_iter != uv_images.end(); + uv_images_iter++) { + + Image *ima = *uv_images_iter; + std::string imageid(id_name(ima)); + createPolylist(imageid, has_uvs, + has_color, + ob, + me, + geom_id, + norind); + } + + /* We msut add an additional collector for the case when + * some parts of the object are not textured at all. + * The next call creates a polylist for all untextured polygons + */ + + createPolylist("", has_uvs, + has_color, + ob, + me, + geom_id, + norind); + } +/* =========================================================================== + * Export Meshes with UV Textures (export as materials, see also in + * effectExporter and MaterialExporter) + * + * If imageid is the empty string, then collect only untextured polygons + * =========================================================================== */ +void GeometryExporter::createPolylist(std::string imageid, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind) +{ + + MPoly *mpolys = me->mpoly; + MLoop *mloops = me->mloop; + MTexPoly *mtpolys = me->mtpoly; + + int totpolys = me->totpoly; + + // <vcount> + int i; + int faces_in_polylist = 0; + std::vector<unsigned long> vcount_list; + bool is_triangulated = true; + // count faces with this material + for (i = 0; i < totpolys; i++) { + MTexPoly *tp = &mtpolys[i]; + MPoly *p = &mpolys[i]; + + std::string tpageid = (tp->tpage) ? id_name(tp->tpage):""; + if (tpageid == imageid) { + faces_in_polylist++; + vcount_list.push_back(p->totloop); + if (p->totloop != 3) { + is_triangulated = false; + } + } + } + + // no faces using this imageid + if (faces_in_polylist == 0) { + if (imageid != "") + fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid.c_str()); + return; + } + + COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW); + + // sets count attribute in <polylist> + facelist->setCount(faces_in_polylist); + + if (imageid != "") { + // sets material name + std::string material_id = get_material_id_from_id(imageid); + std::ostringstream ostr; + ostr << translate_id(material_id); + facelist->setMaterial(ostr.str()); + } + COLLADASW::InputList &til = facelist->getInputList(); + + // creates <input> in <polylist> for vertices + COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0); + + // creates <input> in <polylist> for normals + COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1); + + til.push_back(input1); + til.push_back(input2); + + // if mesh has uv coords writes <input> for TEXCOORD + int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1; + for (i = 0; i < num_layers; i++) { + if (!this->export_settings->active_uv_only || i == active_uv_index) { + + std::string uv_name(bc_get_uvlayer_name(me, i)); + std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name; + std::string layer_id = makeTexcoordSourceId( + effective_id, + i, this->export_settings->active_uv_only); + + /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements + For now this is always 2 (This may change sometime/maybe) + */ + COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD, + makeUrl(layer_id), + 2, // this is only until we have optimized UV sets + (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set + ); + til.push_back(input3); + } + } + + int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + if (totlayer_mcol > 0) { + int map_index = 0; + + for (int a = 0; a < totlayer_mcol; a++) { + char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a); + COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR, + makeUrl(makeVertexColorSourceId(geom_id, layer_name)), + (has_uvs) ? 3 : 2, // all color layers have same index order + map_index // set number equals color map index + ); + til.push_back(input4); + map_index++; + } + } + + // performs the actual writing + prepareToAppendValues(is_triangulated, facelist, vcount_list); + + // <p> + int texindex = 0; + for (i = 0; i < totpolys; i++) { + MTexPoly *tp = &mtpolys[i]; + MPoly *p = &mpolys[i]; + int loop_count = p->totloop; + std::string tpageid = (tp->tpage) ? id_name(tp->tpage) : ""; + if (tpageid == imageid) { + MLoop *l = &mloops[p->loopstart]; + BCPolygonNormalsIndices normal_indices = norind[i]; + + for (int j = 0; j < loop_count; j++) { + facelist->appendValues(l[j].v); + facelist->appendValues(normal_indices[j]); + if (has_uvs) + facelist->appendValues(texindex + j); + + if (has_color) + facelist->appendValues(texindex + j); + } + } + + texindex += loop_count; + } + + finishList(is_triangulated, facelist); + delete facelist; +} // creates <source> for positions void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) @@ -537,7 +776,13 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a); COLLADASW::FloatSourceF source(mSW); - std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only); + std::string active_uv_name(bc_get_active_uvlayer_name(me)); + std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name; + std::string layer_id = makeTexcoordSourceId( + effective_id, + a, + this->export_settings->active_uv_only ); + source.setId(layer_id); source.setArrayId(layer_id + ARRAY_ID_SUFFIX); diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 69d1067e6f4..890304f4568 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -85,15 +85,33 @@ public: Mesh *me, std::string& geom_id); - // powerful because it handles both cases when there is material and when there's not + // Create polylists for meshes with Materials void createPolylist(short material_index, - bool has_uvs, - bool has_color, - Object *ob, - Mesh *me, - std::string& geom_id, - std::vector<BCPolygonNormalsIndices>& norind); - + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind); + + // Create polylists for meshes with UV Textures + void createPolylists(std::set<Image *> uv_images, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind); + + // Create polylists for meshes with UV Textures + void createPolylist(std::string imageid, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind); + // creates <source> for positions void createVertsSource(std::string geom_id, Mesh *me); diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index aac41e2e93c..93be7de6236 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -55,9 +55,9 @@ ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings void ImagesExporter::export_UV_Image(Image *image, bool use_copies) { - std::string name(id_name(image)); - std::string translated_name(translate_id(name)); - bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end(); + std::string id(id_name(image)); + std::string translated_id(translate_id(id)); + bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end(); if (not_yet_exported) { @@ -88,7 +88,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) // make absolute destination path - BLI_strncpy(export_file, name.c_str(), sizeof(export_file)); + BLI_strncpy(export_file, id.c_str(), sizeof(export_file)); BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat); BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file); @@ -143,10 +143,11 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) } } - COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */ + /* set name also to mNameNC. This helps other viewers import files exported from Blender better */ + COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id); img.add(mSW); fprintf(stdout, "Collada export: Added image: %s\n", export_file); - mImages.push_back(translated_name); + mImages.push_back(translated_id); BKE_image_release_ibuf(image, imbuf, NULL); } @@ -161,7 +162,7 @@ void ImagesExporter::export_UV_Images() for (node = this->export_settings->export_set; node; node = node->next) { Object *ob = (Object *)node->link; - if (ob->type == OB_MESH && ob->totcol) { + if (ob->type == OB_MESH) { Mesh *me = (Mesh *) ob->data; BKE_mesh_tessface_ensure(me); int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); @@ -189,7 +190,13 @@ void ImagesExporter::export_UV_Images() } } - +/* ============================================================ + * Check if there are any images to be exported + * Returns true as soon as an object is detected that + * either has an UV Texture assigned, or has a material + * assigned that uses an Image Texture. + * ============================================================ + */ bool ImagesExporter::hasImages(Scene *sce) { LinkNode *node; @@ -232,11 +239,10 @@ void ImagesExporter::exportImages(Scene *sce) openLibrary(); MaterialFunctor mf; - if (this->export_settings->include_material_textures) { + if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) { mf.forEachMaterialInExportSet<ImagesExporter>(sce, *this, this->export_settings->export_set); } - - if (this->export_settings->include_uv_textures) { + else { export_UV_Images(); } diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp index 71371d280df..de1a4075462 100644 --- a/source/blender/collada/InstanceWriter.cpp +++ b/source/blender/collada/InstanceWriter.cpp @@ -32,43 +32,76 @@ #include "COLLADASWInstanceMaterial.h" extern "C" { - #include "BKE_customdata.h" - #include "BKE_material.h" - #include "DNA_mesh_types.h" +#include "BKE_customdata.h" +#include "BKE_material.h" +#include "DNA_mesh_types.h" } #include "InstanceWriter.h" #include "collada_internal.h" #include "collada_utils.h" -void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only) +void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type) { - for (int a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a + 1); - - COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList(); + bool all_uv_layers = !active_uv_only; + COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList(); - if (ma) { - std::string matid(get_material_id(ma)); - matid = translate_id(matid); + if (export_texture_type == BC_TEXTURE_TYPE_UV) + { + std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers); + std::set<Image *>::iterator uv_images_iter; + for (uv_images_iter = uv_images.begin(); + uv_images_iter != uv_images.end(); + uv_images_iter++) { + Image *ima = *uv_images_iter; + std::string matid(id_name(ima)); + matid = get_material_id_from_id(matid); std::ostringstream ostr; ostr << matid; COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid)); - + // create <bind_vertex_input> for each uv map Mesh *me = (Mesh *)ob->data; int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE); - + int map_index = 0; - int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) -1; + int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1; for (int b = 0; b < totlayer; b++) { if (!active_uv_only || b == active_uv_index) { char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b); im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++)); } } - + iml.push_back(im); } } + + else { + for (int a = 0; a < ob->totcol; a++) { + Material *ma = give_current_material(ob, a + 1); + if (ma) { + std::string matid(get_material_id(ma)); + matid = translate_id(matid); + std::ostringstream ostr; + ostr << matid; + COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid)); + + // create <bind_vertex_input> for each uv map + Mesh *me = (Mesh *)ob->data; + int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + + int map_index = 0; + int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1; + for (int b = 0; b < totlayer; b++) { + if (!active_uv_only || b == active_uv_index) { + char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b); + im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++)); + } + } + + iml.push_back(im); + } + } + } } diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h index 49ddf091b1c..a46027325a2 100644 --- a/source/blender/collada/InstanceWriter.h +++ b/source/blender/collada/InstanceWriter.h @@ -31,11 +31,12 @@ #include "COLLADASWBindMaterial.h" #include "DNA_object_types.h" +#include "collada.h" class InstanceWriter { protected: - void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only); + void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type); }; #endif diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp index 4aece997f72..6e6cc24be20 100644 --- a/source/blender/collada/MaterialExporter.cpp +++ b/source/blender/collada/MaterialExporter.cpp @@ -38,14 +38,39 @@ MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSe void MaterialsExporter::exportMaterials(Scene *sce) { - if (hasMaterials(sce)) { - openLibrary(); + if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) + { + if (hasMaterials(sce)) { + openLibrary(); - MaterialFunctor mf; - mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set); + MaterialFunctor mf; + mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set); - closeLibrary(); + closeLibrary(); + } } + + else { + std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only); + if (uv_images.size() > 0) { + openLibrary(); + std::set<Image *>::iterator uv_images_iter; + for (uv_images_iter = uv_images.begin(); + uv_images_iter != uv_images.end(); + uv_images_iter++) { + + Image *ima = *uv_images_iter; + std::string matid(id_name(ima)); + + openMaterial(get_material_id_from_id(matid), translate_id(matid)); + std::string efid = translate_id(matid) + "-effect"; + addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid)); + closeMaterial(); + } + closeLibrary(); + } + } + } bool MaterialsExporter::hasMaterials(Scene *sce) diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 8f3bf88af65..6ca53c64299 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -27,7 +27,7 @@ #include <algorithm> -#if !defined(WIN32) || defined(FREE_WINDOWS) +#if !defined(WIN32) #include <iostream> #endif @@ -1173,8 +1173,9 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta BKE_mesh_assign_object(ob, new_mesh); BKE_mesh_calc_normals(new_mesh); - if (old_mesh->id.us == 0) BKE_libblock_free(G.main, old_mesh); - + id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */ + BKE_libblock_free_us(G.main, old_mesh); + char layername[100]; layername[0] = '\0'; MTFace *texture_face = NULL; diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 30cd6ddf197..73945539931 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -151,7 +151,10 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) COLLADASW::InstanceGeometry instGeom(mSW); instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation))); instGeom.setName(translate_id(id_name(ob))); - InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only); + InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), + ob, + this->export_settings->active_uv_only, + this->export_settings->export_texture_type); instGeom.add(); } diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp index 71875d6274a..c48c060dc95 100644 --- a/source/blender/collada/SkinInfo.cpp +++ b/source/blender/collada/SkinInfo.cpp @@ -27,7 +27,7 @@ #include <algorithm> -#if !defined(WIN32) || defined(FREE_WINDOWS) +#if !defined(WIN32) #include <stdint.h> #endif diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index bfe3180909b..024bc4a4a5c 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -80,8 +80,7 @@ int collada_export(Scene *sce, int deform_bones_only, int active_uv_only, - int include_uv_textures, - int include_material_textures, + BC_export_texture_type export_texture_type, int use_texture_copies, int triangulate, @@ -106,8 +105,7 @@ int collada_export(Scene *sce, export_settings.deform_bones_only = deform_bones_only != 0; export_settings.active_uv_only = active_uv_only != 0; - export_settings.include_uv_textures = include_uv_textures != 0; - export_settings.include_material_textures= include_material_textures != 0; + export_settings.export_texture_type = export_texture_type; export_settings.use_texture_copies = use_texture_copies != 0; export_settings.triangulate = triangulate != 0; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index 8035af59c8b..d31f5a8ba62 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -46,6 +46,11 @@ typedef enum BC_export_transformation_type { BC_TRANSFORMATION_TYPE_TRANSROTLOC } BC_export_transformation_type; +typedef enum BC_export_texture_type { + BC_TEXTURE_TYPE_MAT, + BC_TEXTURE_TYPE_UV +} BC_export_texture_type; + struct bContext; struct Scene; @@ -74,8 +79,7 @@ int collada_export(struct Scene *sce, int deform_bones_only, int active_uv_only, - int include_uv_textures, - int include_material_textures, + BC_export_texture_type export_texture_type, int use_texture_copies, int triangulate, @@ -84,9 +88,9 @@ int collada_export(struct Scene *sce, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim, - int limit_precision, - int keep_bind_info); + int open_sim, + int limit_precision, + int keep_bind_info); #ifdef __cplusplus } diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp index 6ebde6bd773..8974acb3460 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -344,7 +344,13 @@ std::string get_camera_id(Object *ob) std::string get_material_id(Material *mat) { - return translate_id(id_name(mat)) + "-material"; + std::string id = id_name(mat); + return get_material_id_from_id(id); +} + +std::string get_material_id_from_id(std::string id) +{ + return translate_id(id) + "-material"; } std::string get_morph_id(Object *ob) diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index 1c7aa160f57..5f3fa34edc1 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -103,6 +103,7 @@ extern std::string get_joint_sid(Bone *bone, Object *ob_arm); extern std::string get_camera_id(Object *ob); extern std::string get_material_id(Material *mat); +extern std::string get_material_id_from_id(std::string id); extern std::string get_morph_id(Object *ob); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index ac4395e1430..b09732f9102 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -32,6 +32,8 @@ #include "COLLADAFWMeshPrimitive.h" #include "COLLADAFWMeshVertexData.h" +#include <set> + extern "C" { #include "DNA_modifier_types.h" #include "DNA_customdata_types.h" @@ -831,4 +833,160 @@ void bc_sanitize_mat(float mat[4][4], int precision) for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) mat[i][j] = double_round(mat[i][j], precision); +} + +/* +* Returns name of Active UV Layer or empty String if no active UV Layer defined. +* Assuming the Object is of type MESH +*/ +std::string bc_get_active_uvlayer_name(Object *ob) +{ + Mesh *me = (Mesh *)ob->data; + return bc_get_active_uvlayer_name(me); +} + +/* + * Returns name of Active UV Layer or empty String if no active UV Layer defined + */ +std::string bc_get_active_uvlayer_name(Mesh *me) +{ + int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + if (num_layers) { + return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE)); + } + return ""; +} + +/* + * Returns UV Layer name or empty string if layer index is out of range + */ +std::string bc_get_uvlayer_name(Mesh *me, int layer) +{ + int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + if (num_layers && layer < num_layers) { + return std::string(bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer)); + } + return ""; +} + +/********************************************************************** +* +* Return the list of Mesh objects with assigned UVtextures and Images +* Note: We need to create artificaial materials for each of them +* +***********************************************************************/ +std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers) +{ + std::set <Object *> UVObjects; + Base *base = (Base *)sce->base.first; + + while (base) { + Object *ob = base->object; + bool has_uvimage = false; + if (ob->type == OB_MESH) { + Mesh *me = (Mesh *)ob->data; + int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); + + for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) { + if (all_uv_layers || active_uv_layer == i) + { + if (me->pdata.layers[i].type == CD_MTEXPOLY) { + MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; + MPoly *mpoly = me->mpoly; + for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { + + Image *ima = txface->tpage; + if (ima != NULL) { + has_uvimage = true; + break; + } + } + } + } + } + + if (has_uvimage) { + UVObjects.insert(ob); + } + } + base = base->next; + } + return UVObjects; +} + +/********************************************************************** +* +* Return the list of UV Texture images from all exported Mesh Items +* Note: We need to create one artificial material for each Image. +* +***********************************************************************/ +std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers) +{ + std::set <Image *> UVImages; + Base *base = (Base *)sce->base.first; + + while (base) { + Object *ob = base->object; + bool has_uvimage = false; + if (ob->type == OB_MESH) { + Mesh *me = (Mesh *)ob->data; + int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); + + for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) { + if (all_uv_layers || active_uv_layer == i) + { + if (me->pdata.layers[i].type == CD_MTEXPOLY) { + MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; + MPoly *mpoly = me->mpoly; + for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { + + Image *ima = txface->tpage; + if (ima != NULL) { + if (UVImages.find(ima) == UVImages.end()) + UVImages.insert(ima); + } + } + } + } + } + } + base = base->next; + } + return UVImages; +} + +/********************************************************************** +* +* Return the list of UV Texture images for the given Object +* Note: We need to create one artificial material for each Image. +* +***********************************************************************/ +std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers) +{ + std::set <Image *> UVImages; + + bool has_uvimage = false; + if (ob->type == OB_MESH) { + Mesh *me = (Mesh *)ob->data; + int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); + + for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) { + if (all_uv_layers || active_uv_layer == i) + { + if (me->pdata.layers[i].type == CD_MTEXPOLY) { + MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; + MPoly *mpoly = me->mpoly; + for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { + + Image *ima = txface->tpage; + if (ima != NULL) { + if (UVImages.find(ima) == UVImages.end()) + UVImages.insert(ima); + } + } + } + } + } + } + return UVImages; }
\ No newline at end of file diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 38c0bd5096a..5447c39e902 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -34,6 +34,7 @@ #include <vector> #include <map> +#include <set> #include <algorithm> extern "C" { @@ -80,6 +81,7 @@ extern void bc_set_mark(Object *ob); extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n); extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type); +extern char *bc_CustomData_get_layer_name(const CustomData *data, int layer_index, int type); extern void bc_bubble_sort_by_Object_name(LinkNode *export_set); extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only); @@ -109,6 +111,14 @@ extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]) extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space); +extern std::string bc_get_active_uvlayer_name(Object *ob); +extern std::string bc_get_active_uvlayer_name(Mesh *me); +extern std::string bc_get_uvlayer_name(Mesh *me, int layer); + +extern std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers); +extern std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers); +extern std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers); + class BCPolygonNormalsIndices { std::vector<unsigned int> normal_indices; diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 3180e7e4154..3e1dd83112a 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -551,8 +551,4 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -if(WITH_CYCLES AND WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) -endif() - blender_add_lib(bf_compositor "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h index a5d7704a708..3b24f9c69a2 100644 --- a/source/blender/compositor/COM_compositor.h +++ b/source/blender/compositor/COM_compositor.h @@ -331,19 +331,6 @@ void COM_deinitialize(void); */ // void COM_clearCaches(void); // NOT YET WRITTEN -/** - * @brief Return a list of highlighted bnodes pointers. - * @return - */ -void COM_startReadHighlights(void); - -/** - * @brief check if a bnode is highlighted - * @param bnode - * @return - */ -int COM_isHighlightedbNode(bNode *bnode); - #ifdef __cplusplus } #endif diff --git a/source/blender/compositor/intern/COM_WorkScheduler.cpp b/source/blender/compositor/intern/COM_WorkScheduler.cpp index 39147f3ab84..68f934008a4 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.cpp +++ b/source/blender/compositor/intern/COM_WorkScheduler.cpp @@ -75,82 +75,6 @@ static bool g_openclInitialized = false; #endif #endif -#define MAX_HIGHLIGHT 8 -static bool g_highlightInitialized = false; -extern "C" { -static int g_highlightIndex; -static void **g_highlightedNodes; -static void **g_highlightedNodesRead; - -/* XXX highlighting disabled for now - * This requires pointers back to DNA data (bNodeTree/bNode) in operations, which is bad! - * Instead IF we want to keep this feature it should use a weak reference such as bNodeInstanceKey - */ -#if 0 -#if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE -#define HIGHLIGHT(wp) \ -{ \ - ExecutionGroup *group = wp->getExecutionGroup(); \ - if (group->isComplex()) { \ - NodeOperation *operation = group->getOutputOperation(); \ - if (operation->isWriteBufferOperation()) { \ - WriteBufferOperation *writeOperation = (WriteBufferOperation *)operation; \ - NodeOperation *complexOperation = writeOperation->getInput(); \ - bNode *node = complexOperation->getbNode(); \ - if (node) { \ - if (node->original) { \ - node = node->original; \ - } \ - if (g_highlightInitialized && g_highlightedNodes) { \ - if (g_highlightIndex < MAX_HIGHLIGHT) { \ - g_highlightedNodes[g_highlightIndex++] = node; \ - } \ - } \ - } \ - } \ - } \ -} -#endif /* COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE */ -#else -# if COM_CURRENT_THREADING_MODEL != COM_TM_NOTHREAD -#define HIGHLIGHT(wp) {} -# endif -#endif - -void COM_startReadHighlights() -{ - if (!g_highlightInitialized) { - return; - } - - if (g_highlightedNodesRead) { - MEM_freeN(g_highlightedNodesRead); - } - - g_highlightedNodesRead = g_highlightedNodes; - g_highlightedNodes = (void **)MEM_callocN(sizeof(void *) * MAX_HIGHLIGHT, __func__); - g_highlightIndex = 0; -} - -int COM_isHighlightedbNode(bNode *bnode) -{ - if (!g_highlightInitialized) { - return false; - } - - if (!g_highlightedNodesRead) { - return false; - } - - for (int i = 0; i < MAX_HIGHLIGHT; i++) { - void *p = g_highlightedNodesRead[i]; - if (!p) return false; - if (p == bnode) return true; - } - return false; -} -} // end extern "C" - #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE void *WorkScheduler::thread_execute_cpu(void *data) { @@ -158,7 +82,6 @@ void *WorkScheduler::thread_execute_cpu(void *data) WorkPackage *work; BLI_thread_local_set(g_thread_device, device); while ((work = (WorkPackage *)BLI_thread_queue_pop(g_cpuqueue))) { - HIGHLIGHT(work); device->execute(work); delete work; } @@ -172,7 +95,6 @@ void *WorkScheduler::thread_execute_gpu(void *data) WorkPackage *work; while ((work = (WorkPackage *)BLI_thread_queue_pop(g_gpuqueue))) { - HIGHLIGHT(work); device->execute(work); delete work; } @@ -289,19 +211,6 @@ static void CL_CALLBACK clContextError(const char *errinfo, void WorkScheduler::initialize(bool use_opencl, int num_cpu_threads) { - /* initialize highlighting */ - if (!g_highlightInitialized) { - if (g_highlightedNodesRead) MEM_freeN(g_highlightedNodesRead); - if (g_highlightedNodes) MEM_freeN(g_highlightedNodes); - - g_highlightedNodesRead = NULL; - g_highlightedNodes = NULL; - - COM_startReadHighlights(); - - g_highlightInitialized = true; - } - #if COM_CURRENT_THREADING_MODEL == COM_TM_QUEUE /* deinitialize if number of threads doesn't match */ if (g_cpudevices.size() != num_cpu_threads) { @@ -439,20 +348,6 @@ void WorkScheduler::deinitialize() } #endif #endif - - /* deinitialize highlighting */ - if (g_highlightInitialized) { - g_highlightInitialized = false; - if (g_highlightedNodes) { - MEM_freeN(g_highlightedNodes); - g_highlightedNodes = NULL; - } - - if (g_highlightedNodesRead) { - MEM_freeN(g_highlightedNodesRead); - g_highlightedNodesRead = NULL; - } - } } int WorkScheduler::current_thread_id() diff --git a/source/blender/compositor/nodes/COM_BrightnessNode.cpp b/source/blender/compositor/nodes/COM_BrightnessNode.cpp index 053f286c66e..6729571fac0 100644 --- a/source/blender/compositor/nodes/COM_BrightnessNode.cpp +++ b/source/blender/compositor/nodes/COM_BrightnessNode.cpp @@ -31,7 +31,9 @@ BrightnessNode::BrightnessNode(bNode *editorNode) : Node(editorNode) void BrightnessNode::convertToOperations(NodeConverter &converter, const CompositorContext &/*context*/) const { + bNode *bnode = this->getbNode(); BrightnessOperation *operation = new BrightnessOperation(); + operation->setUsePremultiply((bnode->custom1 & 1) != 0); converter.addOperation(operation); converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0)); diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index facd422c217..81891d853d2 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -95,17 +95,14 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo NodeOperation *operation = NULL; socket = this->getOutputSocket(index); bNodeSocket *bnodeSocket = socket->getbNodeSocket(); - RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, bnodeSocket->identifier, offsetof(RenderPass, internal_name)); + NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage; + RenderPass *rpass = (RenderPass *)BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name)); int view = 0; - /* Passes in the file can differ from passes stored in sockets (#36755). - * Look up the correct file pass using the socket identifier instead. - */ -#if 0 - NodeImageLayer *storage = (NodeImageLayer *)bnodeSocket->storage;*/ - int passindex = storage->pass_index;*/ - RenderPass *rpass = (RenderPass *)BLI_findlink(&rl->passes, passindex); -#endif + if (STREQ(storage->pass_name, RE_PASSNAME_COMBINED) && STREQ(bnodeSocket->name, "Alpha")) { + /* Alpha output is already handled with the associated combined output. */ + continue; + } /* returns the image view to use for the current active view */ if (BLI_listbase_count_ex(&image->rr->views, 2) > 1) { @@ -147,17 +144,25 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo if (index == 0 && operation) { converter.addPreview(operation->getOutputSocket()); } - if (rpass->passtype == SCE_PASS_COMBINED) { - BLI_assert(operation != NULL); - BLI_assert(index < numberOfOutputs - 1); - NodeOutput *outputSocket = this->getOutputSocket(index + 1); - SeparateChannelOperation *separate_operation; - separate_operation = new SeparateChannelOperation(); - separate_operation->setChannel(3); - converter.addOperation(separate_operation); - converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0)); - converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket()); - index++; + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { + for (int alphaIndex = 0; alphaIndex < numberOfOutputs; alphaIndex++) { + NodeOutput *alphaSocket = this->getOutputSocket(alphaIndex); + bNodeSocket *bnodeAlphaSocket = alphaSocket->getbNodeSocket(); + if (!STREQ(bnodeAlphaSocket->name, "Alpha")) { + continue; + } + NodeImageLayer *alphaStorage = (NodeImageLayer *)bnodeSocket->storage; + if (!STREQ(alphaStorage->pass_name, RE_PASSNAME_COMBINED)) { + continue; + } + SeparateChannelOperation *separate_operation; + separate_operation = new SeparateChannelOperation(); + separate_operation->setChannel(3); + converter.addOperation(separate_operation); + converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0)); + converter.mapOutputSocket(alphaSocket, separate_operation->getOutputSocket()); + break; + } } } diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp index 842edcf35c9..75128de2d84 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp @@ -27,76 +27,61 @@ #include "COM_ScaleOperation.h" #include "COM_SetValueOperation.h" -#ifdef WITH_CYCLES_DEBUG -# include "RE_pipeline.h" -#endif - RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode) { /* pass */ } void RenderLayersNode::testSocketLink(NodeConverter &converter, const CompositorContext &context, - int outputSocketNumber, RenderLayersBaseProg *operation) const + NodeOutput *output, RenderLayersProg *operation, + Scene *scene, int layerId, bool is_preview) const { - NodeOutput *outputSocket = this->getOutputSocket(outputSocketNumber); - Scene *scene = (Scene *)this->getbNode()->id; - short layerId = this->getbNode()->custom1; - operation->setScene(scene); operation->setLayerId(layerId); operation->setRenderData(context.getRenderData()); operation->setViewName(context.getViewName()); - converter.mapOutputSocket(outputSocket, operation->getOutputSocket()); + converter.mapOutputSocket(output, operation->getOutputSocket()); converter.addOperation(operation); - if (outputSocketNumber == 0) /* only for image socket */ + if (is_preview) /* only for image socket */ converter.addPreview(operation->getOutputSocket()); } void RenderLayersNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const { - testSocketLink(converter, context, 0, new RenderLayersColorProg()); - testSocketLink(converter, context, 1, new RenderLayersAlphaProg()); - testSocketLink(converter, context, 2, new RenderLayersDepthProg()); - testSocketLink(converter, context, 3, new RenderLayersNormalOperation()); - testSocketLink(converter, context, 4, new RenderLayersUVOperation()); - testSocketLink(converter, context, 5, new RenderLayersSpeedOperation()); - testSocketLink(converter, context, 6, new RenderLayersColorOperation()); - testSocketLink(converter, context, 7, new RenderLayersDiffuseOperation()); - testSocketLink(converter, context, 8, new RenderLayersSpecularOperation()); - testSocketLink(converter, context, 9, new RenderLayersShadowOperation()); - testSocketLink(converter, context, 10, new RenderLayersAOOperation()); - testSocketLink(converter, context, 11, new RenderLayersReflectionOperation()); - testSocketLink(converter, context, 12, new RenderLayersRefractionOperation()); - testSocketLink(converter, context, 13, new RenderLayersIndirectOperation()); - testSocketLink(converter, context, 14, new RenderLayersObjectIndexOperation()); - testSocketLink(converter, context, 15, new RenderLayersMaterialIndexOperation()); - testSocketLink(converter, context, 16, new RenderLayersMistOperation()); - testSocketLink(converter, context, 17, new RenderLayersEmitOperation()); - testSocketLink(converter, context, 18, new RenderLayersEnvironmentOperation()); + Scene *scene = (Scene *)this->getbNode()->id; + short layerId = this->getbNode()->custom1; + Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL; + int numberOfOutputs = this->getNumberOfOutputSockets(); - // cycles passes - testSocketLink(converter, context, 19, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_DIRECT)); - testSocketLink(converter, context, 20, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_INDIRECT)); - testSocketLink(converter, context, 21, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_COLOR)); - testSocketLink(converter, context, 22, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_DIRECT)); - testSocketLink(converter, context, 23, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_INDIRECT)); - testSocketLink(converter, context, 24, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_COLOR)); - testSocketLink(converter, context, 25, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_DIRECT)); - testSocketLink(converter, context, 26, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_INDIRECT)); - testSocketLink(converter, context, 27, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_COLOR)); - testSocketLink(converter, context, 28, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_DIRECT)); - testSocketLink(converter, context, 29, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_INDIRECT)); - testSocketLink(converter, context, 30, new RenderLayersCyclesOperation(SCE_PASS_SUBSURFACE_COLOR)); - -#ifdef WITH_CYCLES_DEBUG - { - Scene *scene = (Scene *)this->getbNode()->id; - Render *re = RE_GetRender(scene->id.name); - int debug_pass_type = ((re != NULL) ? RE_debug_pass_type_get(re) : scene->r.debug_pass_type); - testSocketLink(converter, context, 31, new RenderLayersCyclesDebugOperation(SCE_PASS_DEBUG, debug_pass_type)); + if (re) { + RenderResult *rr = RE_AcquireResultRead(re); + if (rr) { + SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, layerId); + if (srl) { + RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); + if (rl) { + for (int i = 0; i < numberOfOutputs; i++) { + NodeOutput *output = this->getOutputSocket(i); + NodeImageLayer *storage = (NodeImageLayer*) output->getbNodeSocket()->storage; + RenderPass *rpass = (RenderPass*) BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name)); + if (rpass) { + if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && STREQ(output->getbNodeSocket()->name, "Alpha")) { + testSocketLink(converter, context, output, new RenderLayersAlphaProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false); + } + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { + testSocketLink(converter, context, output, new RenderLayersDepthProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false); + } + else { + DataType type = ((rpass->channels == 4)? COM_DT_COLOR : ((rpass->channels == 3)? COM_DT_VECTOR : COM_DT_VALUE)); + testSocketLink(converter, context, output, new RenderLayersProg(rpass->name, type, rpass->channels), scene, layerId, STREQ(output->getbNodeSocket()->name, "Image")); + } + } + } + } + } + } + RE_ReleaseResult(re); } -#endif } diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.h b/source/blender/compositor/nodes/COM_RenderLayersNode.h index 5863cbb390c..1f733a9f4bb 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.h +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.h @@ -33,5 +33,11 @@ public: RenderLayersNode(bNode *editorNode); void convertToOperations(NodeConverter &converter, const CompositorContext &context) const; private: - void testSocketLink(NodeConverter &converter, const CompositorContext &context, int outputSocketNumber, RenderLayersBaseProg *operation) const; + void testSocketLink(NodeConverter &converter, + const CompositorContext &context, + NodeOutput *output, + RenderLayersProg *operation, + Scene *scene, + int layerId, + bool is_preview) const; }; diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.cpp b/source/blender/compositor/operations/COM_BrightnessOperation.cpp index 33e35c3fe3b..c7ba86b66bc 100644 --- a/source/blender/compositor/operations/COM_BrightnessOperation.cpp +++ b/source/blender/compositor/operations/COM_BrightnessOperation.cpp @@ -29,7 +29,14 @@ BrightnessOperation::BrightnessOperation() : NodeOperation() this->addInputSocket(COM_DT_VALUE); this->addOutputSocket(COM_DT_COLOR); this->m_inputProgram = NULL; + this->m_use_premultiply = false; } + +void BrightnessOperation::setUsePremultiply(bool use_premultiply) +{ + this->m_use_premultiply = use_premultiply; +} + void BrightnessOperation::initExecution() { this->m_inputProgram = this->getInputSocketReader(0); @@ -64,11 +71,16 @@ void BrightnessOperation::executePixelSampled(float output[4], float x, float y, delta *= -1; b = a * (brightness + delta); } - + if (this->m_use_premultiply) { + premul_to_straight_v4(inputValue); + } output[0] = a * inputValue[0] + b; output[1] = a * inputValue[1] + b; output[2] = a * inputValue[2] + b; output[3] = inputValue[3]; + if (this->m_use_premultiply) { + straight_to_premul_v4(output); + } } void BrightnessOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_BrightnessOperation.h b/source/blender/compositor/operations/COM_BrightnessOperation.h index 22086ae11e8..ff492f2b102 100644 --- a/source/blender/compositor/operations/COM_BrightnessOperation.h +++ b/source/blender/compositor/operations/COM_BrightnessOperation.h @@ -34,6 +34,8 @@ private: SocketReader *m_inputBrightnessProgram; SocketReader *m_inputContrastProgram; + bool m_use_premultiply; + public: BrightnessOperation(); @@ -52,5 +54,6 @@ public: */ void deinitExecution(); + void setUsePremultiply(bool use_premultiply); }; #endif diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp index 325ef83a529..aa58c0571cf 100644 --- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.cpp @@ -65,11 +65,11 @@ void DifferenceMatteOperation::executePixelSampled(float output[4], float x, flo difference = difference / 3.0f; /* make 100% transparent */ - if (difference < tolerance) { + if (difference <= tolerance) { output[0] = 0.0f; } /*in the falloff region, make partially transparent */ - else if (difference < falloff + tolerance) { + else if (difference <= falloff + tolerance) { difference = difference - tolerance; alpha = difference / falloff; /*only change if more transparent than before */ diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp index 57aa3a1bac2..94f407dad86 100644 --- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp @@ -65,10 +65,10 @@ void GlareSimpleStarOperation::generateGlare(float *data, MemoryBuffer *inputTil } } // // B - for (y = tbuf1->getHeight() - 1 && (!breaked); y >= 0; y--) { + for (y = this->getHeight() - 1; y >= 0 && (!breaked); y--) { ym = y - i; yp = y + i; - for (x = tbuf1->getWidth() - 1; x >= 0; x--) { + for (x = this->getWidth() - 1; x >= 0; x--) { xm = x - i; xp = x + i; tbuf1->read(c, x, y); diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp index fb8730c9fa0..d6affa6eee9 100644 --- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp @@ -29,8 +29,6 @@ #include "BLI_math_color.h" extern "C" { -# include "BLI_jitter.h" - # include "BKE_node.h" } diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp index a56aa0cbaa6..070b7562b2d 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp @@ -29,8 +29,6 @@ #include "BLI_math_color.h" extern "C" { -# include "BLI_jitter.h" - # include "BKE_movieclip.h" # include "BKE_node.h" # include "BKE_tracking.h" diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index 099208ce600..f2f1b211a97 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -34,17 +34,18 @@ extern "C" { /* ******** Render Layers Base Prog ******** */ -RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : NodeOperation() +RenderLayersProg::RenderLayersProg(const char *passName, DataType type, int elementsize) : NodeOperation(), m_passName(passName) { - this->m_renderpass = renderpass; this->setScene(NULL); this->m_inputBuffer = NULL; this->m_elementsize = elementsize; this->m_rd = NULL; + + this->addOutputSocket(type); } -void RenderLayersBaseProg::initExecution() +void RenderLayersProg::initExecution() { Scene *scene = this->getScene(); Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL; @@ -59,10 +60,7 @@ void RenderLayersBaseProg::initExecution() RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); if (rl) { - this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass, this->m_viewName); - if (this->m_inputBuffer == NULL && this->m_renderpass == SCE_PASS_COMBINED) { - this->m_inputBuffer = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, this->m_viewName); - } + this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_passName.c_str(), this->m_viewName); } } } @@ -72,7 +70,7 @@ void RenderLayersBaseProg::initExecution() } } -void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) +void RenderLayersProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) { unsigned int offset; int width = this->getWidth(), height = this->getHeight(); @@ -111,7 +109,7 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi } } -void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void RenderLayersProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { #if 0 const RenderData *rd = this->m_rd; @@ -173,12 +171,12 @@ void RenderLayersBaseProg::executePixelSampled(float output[4], float x, float y } } -void RenderLayersBaseProg::deinitExecution() +void RenderLayersProg::deinitExecution() { this->m_inputBuffer = NULL; } -void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) +void RenderLayersProg::determineResolution(unsigned int resolution[2], unsigned int /*preferredResolution*/[2]) { Scene *sce = this->getScene(); Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL; @@ -207,13 +205,6 @@ void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsig } /* ******** Render Layers AO Operation ******** */ - -RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PASS_AO, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} - - void RenderLayersAOOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { float *inputBuffer = this->getInputBuffer(); @@ -227,12 +218,6 @@ void RenderLayersAOOperation::executePixelSampled(float output[4], float x, floa } /* ******** Render Layers Alpha Operation ******** */ - -RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4) -{ - this->addOutputSocket(COM_DT_VALUE); -} - void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { float *inputBuffer = this->getInputBuffer(); @@ -247,27 +232,7 @@ void RenderLayersAlphaProg::executePixelSampled(float output[4], float x, float } } -/* ******** Render Layers Color Operation ******** */ - -RenderLayersColorOperation::RenderLayersColorOperation() : RenderLayersBaseProg(SCE_PASS_RGBA, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} - -/* ******** Render Layers Cycles Operation ******** */ - -RenderLayersCyclesOperation::RenderLayersCyclesOperation(int pass) : RenderLayersBaseProg(pass, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - /* ******** Render Layers Depth Operation ******** */ - -RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float y, PixelSampler /*sampler*/) { int ix = x; @@ -281,135 +246,4 @@ void RenderLayersDepthProg::executePixelSampled(float output[4], float x, float unsigned int offset = (iy * this->getWidth() + ix); output[0] = inputBuffer[offset]; } -} - -/* ******** Render Layers Diffuse Operation ******** */ - -RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Emit Operation ******** */ - -RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Environment Operation ******** */ - -RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Image Operation ******** */ - -RenderLayersColorProg::RenderLayersColorProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} - -/* ******** Render Layers Indirect Operation ******** */ - -RenderLayersIndirectOperation::RenderLayersIndirectOperation() : RenderLayersBaseProg(SCE_PASS_INDIRECT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Material Index Operation ******** */ - -RenderLayersMaterialIndexOperation::RenderLayersMaterialIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXMA, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - -/* ******** Render Layers Mist Operation ******** */ - -RenderLayersMistOperation::RenderLayersMistOperation() : RenderLayersBaseProg(SCE_PASS_MIST, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - -/* ******** Render Layers Normal Operation ******** */ - -RenderLayersNormalOperation::RenderLayersNormalOperation() : RenderLayersBaseProg(SCE_PASS_NORMAL, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Object Index Operation ******** */ - -RenderLayersObjectIndexOperation::RenderLayersObjectIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXOB, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - -/* ******** Render Layers Reflection Operation ******** */ - -RenderLayersReflectionOperation::RenderLayersReflectionOperation() : RenderLayersBaseProg(SCE_PASS_REFLECT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Refraction Operation ******** */ - -RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Shadow Operation ******** */ - -RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Specular Operation ******** */ - -RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Render Layers Speed Operation ******** */ - -RenderLayersSpeedOperation::RenderLayersSpeedOperation() : RenderLayersBaseProg(SCE_PASS_VECTOR, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} - -/* ******** Render Layers UV Operation ******** */ - -RenderLayersUVOperation::RenderLayersUVOperation() : RenderLayersBaseProg(SCE_PASS_UV, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} - -/* ******** Debug Render Layers Cycles Operation ******** */ - -#ifdef WITH_CYCLES_DEBUG - -RenderLayersCyclesDebugOperation::RenderLayersCyclesDebugOperation( - int pass, - int debug_pass_type) - : RenderLayersBaseProg(pass, RE_debug_pass_num_channels_get(debug_pass_type)) -{ - switch (m_elementsize) { - case 1: - this->addOutputSocket(COM_DT_VALUE); - break; - case 3: - this->addOutputSocket(COM_DT_VECTOR); - break; - case 4: - this->addOutputSocket(COM_DT_COLOR); - break; - default: - BLI_assert(!"Unkown debug pass type element size."); - } -} - -#endif +}
\ No newline at end of file diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h index 89eb2a6954d..1be15906770 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersProg.h @@ -40,7 +40,7 @@ extern "C" { * * @todo: rename to operation. */ -class RenderLayersBaseProg : public NodeOperation { +class RenderLayersProg : public NodeOperation { protected: /** * Reference to the scene object. @@ -65,7 +65,7 @@ protected: /** * renderpass where this operation needs to get its data from */ - int m_renderpass; + std::string m_passName; int m_elementsize; @@ -73,11 +73,6 @@ protected: * @brief render data used for active rendering */ const RenderData *m_rd; - - /** - * Constructor - */ - RenderLayersBaseProg(int renderpass, int elementsize); /** * Determine the output resolution. The resolution is retrieved from the Renderer @@ -92,6 +87,10 @@ protected: void doInterpolation(float output[4], float x, float y, PixelSampler sampler); public: /** + * Constructor + */ + RenderLayersProg(const char *passName, DataType type, int elementsize); + /** * setter for the scene field. Will be called from * @see RenderLayerNode to set the actual scene where * the data will be retrieved from. @@ -108,116 +107,25 @@ public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class RenderLayersAOOperation : public RenderLayersBaseProg { +class RenderLayersAOOperation : public RenderLayersProg { public: - RenderLayersAOOperation(); + RenderLayersAOOperation(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) {} void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class RenderLayersAlphaProg : public RenderLayersBaseProg { +class RenderLayersAlphaProg : public RenderLayersProg { public: - RenderLayersAlphaProg(); + RenderLayersAlphaProg(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) {} void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class RenderLayersColorOperation : public RenderLayersBaseProg { -public: - RenderLayersColorOperation(); -}; - -class RenderLayersCyclesOperation : public RenderLayersBaseProg { -public: - RenderLayersCyclesOperation(int pass); -}; - -class RenderLayersDepthProg : public RenderLayersBaseProg { +class RenderLayersDepthProg : public RenderLayersProg { public: - RenderLayersDepthProg(); + RenderLayersDepthProg(const char *passName, DataType type, int elementsize) + : RenderLayersProg(passName, type, elementsize) {} void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); }; -class RenderLayersDiffuseOperation : public RenderLayersBaseProg { -public: - RenderLayersDiffuseOperation(); -}; - -class RenderLayersEmitOperation : public RenderLayersBaseProg { -public: - RenderLayersEmitOperation(); -}; - -class RenderLayersEnvironmentOperation : public RenderLayersBaseProg { -public: - RenderLayersEnvironmentOperation(); -}; - -/// @todo rename to image operation -class RenderLayersColorProg : public RenderLayersBaseProg { -public: - RenderLayersColorProg(); -}; - -class RenderLayersIndirectOperation : public RenderLayersBaseProg { -public: - RenderLayersIndirectOperation(); -}; - -class RenderLayersMaterialIndexOperation : public RenderLayersBaseProg { -public: - RenderLayersMaterialIndexOperation(); -}; - -class RenderLayersMistOperation : public RenderLayersBaseProg { -public: - RenderLayersMistOperation(); -}; - -class RenderLayersNormalOperation : public RenderLayersBaseProg { -public: - RenderLayersNormalOperation(); -}; - -class RenderLayersObjectIndexOperation : public RenderLayersBaseProg { -public: - RenderLayersObjectIndexOperation(); -}; - -class RenderLayersReflectionOperation : public RenderLayersBaseProg { -public: - RenderLayersReflectionOperation(); -}; - -class RenderLayersRefractionOperation : public RenderLayersBaseProg { -public: - RenderLayersRefractionOperation(); -}; - -class RenderLayersShadowOperation : public RenderLayersBaseProg { -public: - RenderLayersShadowOperation(); -}; - -class RenderLayersSpecularOperation : public RenderLayersBaseProg { -public: - RenderLayersSpecularOperation(); -}; - -class RenderLayersSpeedOperation : public RenderLayersBaseProg { -public: - RenderLayersSpeedOperation(); -}; - -class RenderLayersUVOperation : public RenderLayersBaseProg { -public: - RenderLayersUVOperation(); -}; - -#ifdef WITH_CYCLES_DEBUG -class RenderLayersCyclesDebugOperation : public RenderLayersBaseProg { -public: - RenderLayersCyclesDebugOperation(int pass, - int debug_pass_type); -}; -#endif - #endif diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 6bfd8ae3888..d0c72935b16 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -41,6 +41,7 @@ TextureBaseOperation::TextureBaseOperation() : NodeOperation() this->m_rd = NULL; this->m_pool = NULL; this->m_sceneColorManage = false; + setComplex(true); } TextureOperation::TextureOperation() : TextureBaseOperation() { @@ -155,31 +156,3 @@ void TextureBaseOperation::executePixelSampled(float output[4], float x, float y output[0] = output[1] = output[2] = output[3]; } } - -MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti * /*rect2*/) -{ - int height = getHeight(); - int width = getWidth(); - DataType datatype = this->getOutputSocket()->getDataType(); - int add = 4; - if (datatype == COM_DT_VALUE) { - add = 1; - } - - rcti rect; - rect.xmin = 0; - rect.ymin = 0; - rect.xmax = width; - rect.ymax = height; - MemoryBuffer *result = new MemoryBuffer(datatype, &rect); - - float *data = result->getBuffer(); - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++, data += add) { - this->executePixelSampled(data, x, y, COM_PS_NEAREST); - } - } - - return result; -} diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index 4cc203b54a2..59ff58a7289 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -59,8 +59,6 @@ protected: * Constructor */ TextureBaseOperation(); - - MemoryBuffer *createMemoryBuffer(rcti *rect2); public: void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index 1ec52571be8..9ff0bf9ce12 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -286,9 +286,9 @@ void InverseSearchRadiusOperation::initExecution() this->m_inputRadius = this->getInputSocketReader(0); } -voi *InverseSearchRadiusOperation::initializeTileData(rcti *rect) +void *InverseSearchRadiusOperation::initializeTileData(rcti *rect) { - MemoryBuffer * data = new MemoryBuffer(NULL, rect); + MemoryBuffer * data = new MemoryBuffer(COM_DT_COLOR, rect); float *buffer = data->getBuffer(); int x, y; int width = this->m_inputRadius->getWidth(); @@ -343,7 +343,7 @@ voi *InverseSearchRadiusOperation::initializeTileData(rcti *rect) void InverseSearchRadiusOperation::executePixelChunk(float output[4], int x, int y, void *data) { MemoryBuffer *buffer = (MemoryBuffer *)data; - buffer->readNoCheck(color, x, y); + buffer->readNoCheck(output, x, y); } void InverseSearchRadiusOperation::deinitializeTileData(rcti *rect, void *data) diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index e635256cda6..33a7628c68d 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -87,8 +87,8 @@ set(SRC intern/depsgraph_intern.h intern/depsgraph_types.h + util/deg_util_foreach.h util/deg_util_function.h - util/deg_util_hash.h ) if(WITH_CXX11) diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index fdc86540171..b65d921cfd1 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -153,7 +153,8 @@ void DEG_add_object_cache_relation(struct DepsNodeHandle *handle, eDepsObjectComponentType component, const char *description); -/* TODO(sergey): Remove once all geometry update is granular. */ + +struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *handle); void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag); /* Utility functions for physics modifiers */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index 7f62eb122db..086fd0c1144 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -30,15 +30,13 @@ #include "intern/builder/deg_builder.h" -// TODO(sergey): Use own wrapper over STD. -#include <stack> - #include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_ID.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" +#include "BLI_stack.h" #include "intern/depsgraph.h" #include "intern/depsgraph_types.h" @@ -71,50 +69,52 @@ static bool check_object_needs_evaluation(Object *object) void deg_graph_build_flush_layers(Depsgraph *graph) { - std::stack<OperationDepsNode *> stack; + BLI_Stack *stack = BLI_stack_new(sizeof(OperationDepsNode*), + "DEG flush layers stack"); foreach (OperationDepsNode *node, graph->operations) { IDDepsNode *id_node = node->owner->owner; node->done = 0; node->num_links_pending = 0; foreach (DepsRelation *rel, node->outlinks) { - if ((rel->from->type == DEPSNODE_TYPE_OPERATION) && + if ((rel->from->type == DEG_NODE_TYPE_OPERATION) && (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { ++node->num_links_pending; } } if (node->num_links_pending == 0) { - stack.push(node); + BLI_stack_push(stack, &node); node->done = 1; } node->owner->layers = id_node->layers; id_node->id->tag |= LIB_TAG_DOIT; } - while (!stack.empty()) { - OperationDepsNode *node = stack.top(); - stack.pop(); + while (!BLI_stack_is_empty(stack)) { + OperationDepsNode *node; + BLI_stack_pop(stack, &node); /* Flush layers to parents. */ foreach (DepsRelation *rel, node->inlinks) { - if (rel->from->type == DEPSNODE_TYPE_OPERATION) { + if (rel->from->type == DEG_NODE_TYPE_OPERATION) { OperationDepsNode *from = (OperationDepsNode *)rel->from; from->owner->layers |= node->owner->layers; } } /* Schedule parent nodes. */ foreach (DepsRelation *rel, node->inlinks) { - if (rel->from->type == DEPSNODE_TYPE_OPERATION) { + if (rel->from->type == DEG_NODE_TYPE_OPERATION) { OperationDepsNode *from = (OperationDepsNode *)rel->from; if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { BLI_assert(from->num_links_pending > 0); --from->num_links_pending; } if (from->num_links_pending == 0 && from->done == 0) { - stack.push(from); + BLI_stack_push(stack, &from); from->done = 1; } } } } + BLI_stack_free(stack); } void deg_graph_build_finalize(Depsgraph *graph) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc index 9b37aaa12ff..3eed0697b5e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc @@ -32,11 +32,9 @@ // TOO(sergey): Use some wrappers over those? #include <cstdio> #include <cstdlib> -#include <stack> -extern "C" { #include "BLI_utildefines.h" -} +#include "BLI_stack.h" #include "util/deg_util_foreach.h" @@ -48,12 +46,6 @@ extern "C" { namespace DEG { -struct StackEntry { - OperationDepsNode *node; - StackEntry *from; - DepsRelation *via_relation; -}; - void deg_graph_detect_cycles(Depsgraph *graph) { enum { @@ -65,11 +57,19 @@ void deg_graph_detect_cycles(Depsgraph *graph) NODE_IN_STACK = 2, }; - std::stack<StackEntry> traversal_stack; + struct StackEntry { + OperationDepsNode *node; + StackEntry *from; + DepsRelation *via_relation; + }; + + BLI_Stack *traversal_stack = BLI_stack_new(sizeof(StackEntry), + "DEG detect cycles stack"); + foreach (OperationDepsNode *node, graph->operations) { bool has_inlinks = false; foreach (DepsRelation *rel, node->inlinks) { - if (rel->from->type == DEPSNODE_TYPE_OPERATION) { + if (rel->from->type == DEG_NODE_TYPE_OPERATION) { has_inlinks = true; } } @@ -78,7 +78,7 @@ void deg_graph_detect_cycles(Depsgraph *graph) entry.node = node; entry.from = NULL; entry.via_relation = NULL; - traversal_stack.push(entry); + BLI_stack_push(traversal_stack, &entry); node->tag = NODE_IN_STACK; } else { @@ -87,13 +87,13 @@ void deg_graph_detect_cycles(Depsgraph *graph) node->done = 0; } - while (!traversal_stack.empty()) { - StackEntry& entry = traversal_stack.top(); - OperationDepsNode *node = entry.node; + while (!BLI_stack_is_empty(traversal_stack)) { + StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack); + OperationDepsNode *node = entry->node; bool all_child_traversed = true; for (int i = node->done; i < node->outlinks.size(); ++i) { DepsRelation *rel = node->outlinks[i]; - if (rel->to->type == DEPSNODE_TYPE_OPERATION) { + if (rel->to->type == DEG_NODE_TYPE_OPERATION) { OperationDepsNode *to = (OperationDepsNode *)rel->to; if (to->tag == NODE_IN_STACK) { printf("Dependency cycle detected:\n"); @@ -102,7 +102,7 @@ void deg_graph_detect_cycles(Depsgraph *graph) node->full_identifier().c_str(), rel->name); - StackEntry *current = &entry; + StackEntry *current = entry; while (current->node != to) { BLI_assert(current != NULL); printf(" '%s' depends on '%s' through '%s'\n", @@ -117,9 +117,9 @@ void deg_graph_detect_cycles(Depsgraph *graph) else if (to->tag == NODE_NOT_VISITED) { StackEntry new_entry; new_entry.node = to; - new_entry.from = &entry; + new_entry.from = entry; new_entry.via_relation = rel; - traversal_stack.push(new_entry); + BLI_stack_push(traversal_stack, &new_entry); to->tag = NODE_IN_STACK; all_child_traversed = false; node->done = i; @@ -129,9 +129,11 @@ void deg_graph_detect_cycles(Depsgraph *graph) } if (all_child_traversed) { node->tag = NODE_VISITED; - traversal_stack.pop(); + BLI_stack_discard(traversal_stack); } } + + BLI_stack_free(traversal_stack); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 7bcaee61fe0..a90f8ff02b6 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -37,11 +37,11 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_blenlib.h" #include "BLI_string.h" #include "BLI_utildefines.h" +extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -94,13 +94,13 @@ extern "C" { #include "BKE_tracking.h" #include "BKE_world.h" -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" - #include "RNA_access.h" #include "RNA_types.h" } /* extern "C" */ +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "intern/builder/deg_builder.h" #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" @@ -160,55 +160,14 @@ DepsgraphNodeBuilder::~DepsgraphNodeBuilder() { } -RootDepsNode *DepsgraphNodeBuilder::add_root_node() -{ - return m_graph->add_root_node(); -} - IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id) { return m_graph->add_id_node(id, id->name); } -TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source(ID *id) +TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source() { - /* determine which node to attach timesource to */ - if (id) { -#if 0 /* XXX TODO */ - /* get ID node */ - IDDepsNode id_node = m_graph->find_id_node(id); - - /* depends on what this is... */ - switch (GS(id->name)) { - case ID_SCE: /* Scene - Usually sequencer strip causing time remapping... */ - { - // TODO... - } - break; - - case ID_GR: /* Group */ - { - // TODO... - } - break; - - // XXX: time source... - - default: /* Unhandled */ - printf("%s(): Unhandled ID - %s \n", __func__, id->name); - break; - } -#endif - } - else { - /* root-node */ - RootDepsNode *root_node = m_graph->root_node; - if (root_node) { - return root_node->add_time_source("Time Source"); - } - } - - return NULL; + return m_graph->add_time_source(); } ComponentDepsNode *DepsgraphNodeBuilder::add_component_node( @@ -224,8 +183,7 @@ ComponentDepsNode *DepsgraphNodeBuilder::add_component_node( OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( ComponentDepsNode *comp_node, - eDepsOperation_Type optype, - DepsEvalOperationCb op, + const DepsEvalOperationCb& op, eDepsOperation_Code opcode, const char *name, int name_tag) @@ -234,7 +192,7 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( name, name_tag); if (op_node == NULL) { - op_node = comp_node->add_operation(optype, op, opcode, name, name_tag); + op_node = comp_node->add_operation(op, opcode, name, name_tag); m_graph->operations.push_back(op_node); } else { @@ -252,21 +210,19 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( ID *id, eDepsNode_Type comp_type, const char *comp_name, - eDepsOperation_Type optype, - DepsEvalOperationCb op, + const DepsEvalOperationCb& op, eDepsOperation_Code opcode, const char *name, int name_tag) { ComponentDepsNode *comp_node = add_component_node(id, comp_type, comp_name); - return add_operation_node(comp_node, optype, op, opcode, name, name_tag); + return add_operation_node(comp_node, op, opcode, name, name_tag); } OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( ID *id, eDepsNode_Type comp_type, - eDepsOperation_Type optype, - DepsEvalOperationCb op, + const DepsEvalOperationCb& op, eDepsOperation_Code opcode, const char *name, int name_tag) @@ -274,7 +230,6 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( return add_operation_node(id, comp_type, "", - optype, op, opcode, name, @@ -352,41 +307,6 @@ void DepsgraphNodeBuilder::build_group(Scene *scene, } } -SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group) -{ - /* sanity checks */ - if (!group) - return NULL; - - /* create new subgraph's data */ - Depsgraph *subgraph = reinterpret_cast<Depsgraph *>(DEG_graph_new()); - - DepsgraphNodeBuilder subgraph_builder(m_bmain, subgraph); - - /* add group objects */ - LINKLIST_FOREACH (GroupObject *, go, &group->gobject) { - /*Object *ob = go->ob;*/ - - /* Each "group object" is effectively a separate instance of the - * underlying object data. When the group is evaluated, the transform - * results and/or some other attributes end up getting overridden by - * the group. - */ - } - - /* Create a node for representing subgraph. */ - SubgraphDepsNode *subgraph_node = m_graph->add_subgraph_node(&group->id); - subgraph_node->graph = subgraph; - - /* Make a copy of the data this node will need? */ - /* XXX: do we do this now, or later? */ - /* TODO: need API function which queries graph's ID's hash, and duplicates - * those blocks thoroughly with all outside links removed. - */ - - return subgraph_node; -} - void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) { const bool has_object = (ob->id.tag & LIB_TAG_DOIT); @@ -427,7 +347,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) BuilderWalkUserData data; data.builder = this; data.scene = scene; - modifiers_foreachObjectLink(ob, modifier_walk, &data); BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data); } @@ -513,15 +432,18 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob) { + OperationDepsNode *op_node; + /* local transforms (from transform channels - loc/rot/scale + deltas) */ - add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, - DEPSOP_TYPE_INIT, function_bind(BKE_object_eval_local_transform, _1, scene, ob), - DEG_OPCODE_TRANSFORM_LOCAL); + op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_local_transform, _1, scene, ob), + DEG_OPCODE_TRANSFORM_LOCAL); + op_node->set_as_entry(); /* object parent */ if (ob->parent) { - add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, - DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_parent, _1, scene, ob), + add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_parent, _1, scene, ob), DEG_OPCODE_TRANSFORM_PARENT); } @@ -537,14 +459,15 @@ void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob) * * TODO(sergey): Get rid of this node. */ - add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, - DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_uber_transform, _1, scene, ob), + add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_uber_transform, _1, scene, ob), DEG_OPCODE_OBJECT_UBEREVAL); /* object transform is done */ - add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, - DEPSOP_TYPE_POST, function_bind(BKE_object_eval_done, _1, ob), - DEG_OPCODE_TRANSFORM_FINAL); + op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_done, _1, ob), + DEG_OPCODE_TRANSFORM_FINAL); + op_node->set_as_exit(); } /** @@ -567,8 +490,8 @@ void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob) void DepsgraphNodeBuilder::build_object_constraints(Scene *scene, Object *ob) { /* create node for constraint stack */ - add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, - DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_constraints, _1, scene, ob), + add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_object_eval_constraints, _1, scene, ob), DEG_OPCODE_TRANSFORM_CONSTRAINTS); } @@ -590,8 +513,8 @@ void DepsgraphNodeBuilder::build_animdata(ID *id) /* actions and NLA - as a single unit for now, as it gets complicated to schedule otherwise */ if ((adt->action) || (adt->nla_tracks.first)) { /* create the node */ - add_operation_node(id, DEPSNODE_TYPE_ANIMATION, - DEPSOP_TYPE_EXEC, function_bind(BKE_animsys_eval_animdata, _1, id), + add_operation_node(id, DEG_NODE_TYPE_ANIMATION, + function_bind(BKE_animsys_eval_animdata, _1, id), DEG_OPCODE_ANIMATION, id->name); // TODO: for each channel affected, we might also want to add some support for running RNA update callbacks on them @@ -621,18 +544,17 @@ OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu) * and use some tagging magic instead. */ OperationDepsNode *driver_op = find_operation_node(id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, - fcu->rna_path, + fcu->rna_path ? fcu->rna_path : "", fcu->array_index); if (driver_op == NULL) { driver_op = add_operation_node(id, - DEPSNODE_TYPE_PARAMETERS, - DEPSOP_TYPE_EXEC, + DEG_NODE_TYPE_PARAMETERS, function_bind(BKE_animsys_eval_driver, _1, id, fcu), DEG_OPCODE_DRIVER, - fcu->rna_path, + fcu->rna_path ? fcu->rna_path : "", fcu->array_index); } @@ -653,12 +575,13 @@ void DepsgraphNodeBuilder::build_world(World *world) return; } - /* world itself */ - add_id_node(world_id); /* world shading/params? */ - build_animdata(world_id); - /* TODO: other settings? */ + /* world itself */ + add_component_node(world_id, DEG_NODE_TYPE_PARAMETERS); + + add_operation_node(world_id, DEG_NODE_TYPE_PARAMETERS, NULL, + DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); /* textures */ build_texture_stack(world->mtex); @@ -693,14 +616,14 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) /* XXX: is this the right component, or do we want to use another one instead? */ /* init/rebuild operation */ - /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM, - DEPSOP_TYPE_REBUILD, function_bind(BKE_rigidbody_rebuild_sim, _1, scene), + /*OperationDepsNode *init_node =*/ add_operation_node(&scene->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_rigidbody_rebuild_sim, _1, scene), DEG_OPCODE_RIGIDBODY_REBUILD); /* do-sim operation */ // XXX: what happens if we need to split into several groups? - OperationDepsNode *sim_node = add_operation_node(&scene->id, DEPSNODE_TYPE_TRANSFORM, - DEPSOP_TYPE_SIM, function_bind(BKE_rigidbody_eval_simulation, _1, scene), + OperationDepsNode *sim_node = add_operation_node(&scene->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_rigidbody_eval_simulation, _1, scene), DEG_OPCODE_RIGIDBODY_SIM); /* XXX: For now, the sim node is the only one that really matters here. If any other @@ -720,8 +643,8 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) /* 2) create operation for flushing results */ /* object's transform component - where the rigidbody operation lives */ - add_operation_node(&ob->id, DEPSNODE_TYPE_TRANSFORM, - DEPSOP_TYPE_EXEC, function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob), + add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM, + function_bind(BKE_rigidbody_object_sync_transforms, _1, scene, ob), DEG_OPCODE_TRANSFORM_RIGIDBODY); } } @@ -746,7 +669,14 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob) /* component for all particle systems */ ComponentDepsNode *psys_comp = - add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES); + add_component_node(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES); + + add_operation_node(psys_comp, + function_bind(BKE_particle_system_eval_init, + _1, + scene, + ob), + DEG_OPCODE_PSYS_EVAL_INIT); /* particle systems */ LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) { @@ -759,12 +689,7 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob) /* this particle system */ // TODO: for now, this will just be a placeholder "ubereval" node add_operation_node(psys_comp, - DEPSOP_TYPE_EXEC, - function_bind(BKE_particle_system_eval, - _1, - scene, - ob, - psys), + NULL, DEG_OPCODE_PSYS_EVAL, psys->name); } @@ -776,9 +701,8 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob) void DepsgraphNodeBuilder::build_cloth(Scene *scene, Object *object) { ComponentDepsNode *cache_comp = add_component_node(&object->id, - DEPSNODE_TYPE_CACHE); + DEG_NODE_TYPE_CACHE); add_operation_node(cache_comp, - DEPSOP_TYPE_EXEC, function_bind(BKE_object_eval_cloth, _1, scene, @@ -792,7 +716,7 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key) { build_animdata(&key->id); - add_operation_node(&key->id, DEPSNODE_TYPE_GEOMETRY, DEPSOP_TYPE_EXEC, NULL, + add_operation_node(&key->id, DEG_NODE_TYPE_GEOMETRY, NULL, DEG_OPCODE_PLACEHOLDER, "Shapekey Eval"); } @@ -801,18 +725,19 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key) void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) { ID *obdata = (ID *)ob->data; + OperationDepsNode *op_node; /* TODO(sergey): This way using this object's properties as driver target * works fine. * * Does this depend on other nodes? */ - add_operation_node(&ob->id, - DEPSNODE_TYPE_PARAMETERS, - DEPSOP_TYPE_POST, - NULL, - DEG_OPCODE_PLACEHOLDER, - "Parameters Eval"); + op_node = add_operation_node(&ob->id, + DEG_NODE_TYPE_PARAMETERS, + NULL, + DEG_OPCODE_PLACEHOLDER, + "Parameters Eval"); + op_node->set_as_exit(); /* Temporary uber-update node, which does everything. * It is for the being we're porting old dependencies into the new system. @@ -821,51 +746,34 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) * * TODO(sergey): Get rid of this node. */ - add_operation_node(&ob->id, - DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_POST, - function_bind(BKE_object_eval_uber_data, _1, scene, ob), - DEG_OPCODE_GEOMETRY_UBEREVAL); - - add_operation_node(&ob->id, - DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_INIT, - NULL, - DEG_OPCODE_PLACEHOLDER, - "Eval Init"); + op_node = add_operation_node(&ob->id, + DEG_NODE_TYPE_GEOMETRY, + function_bind(BKE_object_eval_uber_data, _1, scene, ob), + DEG_OPCODE_GEOMETRY_UBEREVAL); + op_node->set_as_exit(); + + op_node = add_operation_node(&ob->id, + DEG_NODE_TYPE_GEOMETRY, + NULL, + DEG_OPCODE_PLACEHOLDER, + "Eval Init"); + op_node->set_as_entry(); // TODO: "Done" operation - /* Modifiers */ + /* Cloyth modifier. */ LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) { - add_operation_node(&ob->id, - DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_EXEC, - function_bind(BKE_object_eval_modifier, - _1, - scene, - ob, - md), - DEG_OPCODE_GEOMETRY_MODIFIER, - md->name); if (md->type == eModifierType_Cloth) { build_cloth(scene, ob); } } /* materials */ - if (ob->totcol != 0) { - for (int a = 1; a <= ob->totcol; a++) { - Material *ma = give_current_material(ob, a); - if (ma != NULL) { - build_material(ma); - } + for (int a = 1; a <= ob->totcol; a++) { + Material *ma = give_current_material(ob, a); + if (ma != NULL) { + build_material(ma); } - add_operation_node(&ob->id, - DEPSNODE_TYPE_SHADING, - DEPSOP_TYPE_EXEC, - NULL, - DEG_OPCODE_PLACEHOLDER, "Material Update"); } /* geometry collision */ @@ -894,14 +802,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) //Mesh *me = (Mesh *)ob->data; /* evaluation operations */ - add_operation_node(obdata, - DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_INIT, - function_bind(BKE_mesh_eval_geometry, - _1, - (Mesh *)obdata), - DEG_OPCODE_PLACEHOLDER, - "Geometry Eval"); + op_node = add_operation_node(obdata, + DEG_NODE_TYPE_GEOMETRY, + function_bind(BKE_mesh_eval_geometry, + _1, + (Mesh *)obdata), + DEG_OPCODE_PLACEHOLDER, + "Geometry Eval"); + op_node->set_as_entry(); break; } @@ -913,14 +821,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) if (mom == ob) { /* metaball evaluation operations */ /* NOTE: only the motherball gets evaluated! */ - add_operation_node(obdata, - DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_INIT, - function_bind(BKE_mball_eval_geometry, - _1, - (MetaBall *)obdata), - DEG_OPCODE_PLACEHOLDER, - "Geometry Eval"); + op_node = add_operation_node(obdata, + DEG_NODE_TYPE_GEOMETRY, + function_bind(BKE_mball_eval_geometry, + _1, + (MetaBall *)obdata), + DEG_OPCODE_PLACEHOLDER, + "Geometry Eval"); + op_node->set_as_entry(); } break; } @@ -931,20 +839,19 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) { /* Curve/nurms evaluation operations. */ /* - calculate curve geometry (including path) */ - add_operation_node(obdata, - DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_INIT, - function_bind(BKE_curve_eval_geometry, - _1, - (Curve *)obdata), - DEG_OPCODE_PLACEHOLDER, - "Geometry Eval"); + op_node = add_operation_node(obdata, + DEG_NODE_TYPE_GEOMETRY, + function_bind(BKE_curve_eval_geometry, + _1, + (Curve *)obdata), + DEG_OPCODE_PLACEHOLDER, + "Geometry Eval"); + op_node->set_as_entry(); /* Calculate curve path - this is used by constraints, etc. */ if (ELEM(ob->type, OB_CURVE, OB_FONT)) { add_operation_node(obdata, - DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_EXEC, + DEG_NODE_TYPE_GEOMETRY, function_bind(BKE_curve_eval_path, _1, (Curve *)obdata), @@ -971,24 +878,24 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob) case OB_LATTICE: { /* Lattice evaluation operations. */ - add_operation_node(obdata, - DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_INIT, - function_bind(BKE_lattice_eval_geometry, - _1, - (Lattice *)obdata), - DEG_OPCODE_PLACEHOLDER, - "Geometry Eval"); + op_node = add_operation_node(obdata, + DEG_NODE_TYPE_GEOMETRY, + function_bind(BKE_lattice_eval_geometry, + _1, + (Lattice *)obdata), + DEG_OPCODE_PLACEHOLDER, + "Geometry Eval"); + op_node->set_as_entry(); break; } } - add_operation_node(obdata, DEPSNODE_TYPE_GEOMETRY, - DEPSOP_TYPE_POST, NULL, - DEG_OPCODE_PLACEHOLDER, "Eval Done"); + op_node = add_operation_node(obdata, DEG_NODE_TYPE_GEOMETRY, NULL, + DEG_OPCODE_PLACEHOLDER, "Eval Done"); + op_node->set_as_exit(); /* Parameters for driver sources. */ - add_operation_node(obdata, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL, + add_operation_node(obdata, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); } @@ -1004,15 +911,13 @@ void DepsgraphNodeBuilder::build_camera(Object *ob) build_animdata(&cam->id); - add_operation_node(camera_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL, + add_operation_node(camera_id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); if (cam->dof_ob != NULL) { /* TODO(sergey): For now parametrs are on object level. */ - add_operation_node(&ob->id, DEPSNODE_TYPE_PARAMETERS, - DEPSOP_TYPE_EXEC, NULL, - DEG_OPCODE_PLACEHOLDER, - "Camera DOF"); + add_operation_node(&ob->id, DEG_NODE_TYPE_PARAMETERS, NULL, + DEG_OPCODE_PLACEHOLDER, "Camera DOF"); } } @@ -1028,10 +933,10 @@ void DepsgraphNodeBuilder::build_lamp(Object *ob) build_animdata(&la->id); /* node for obdata */ - add_component_node(lamp_id, DEPSNODE_TYPE_PARAMETERS); + add_component_node(lamp_id, DEG_NODE_TYPE_PARAMETERS); /* TODO(sergey): Is it really how we're supposed to work with drivers? */ - add_operation_node(lamp_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_EXEC, NULL, + add_operation_node(lamp_id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); /* lamp's nodetree */ @@ -1050,12 +955,14 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) /* nodetree itself */ ID *ntree_id = &ntree->id; + OperationDepsNode *op_node; build_animdata(ntree_id); /* Parameters for drivers. */ - add_operation_node(ntree_id, DEPSNODE_TYPE_PARAMETERS, DEPSOP_TYPE_POST, NULL, - DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); + op_node = add_operation_node(ntree_id, DEG_NODE_TYPE_PARAMETERS, NULL, + DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); + op_node->set_as_exit(); /* nodetree's nodes... */ LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) { @@ -1094,8 +1001,7 @@ void DepsgraphNodeBuilder::build_material(Material *ma) /* material itself */ add_id_node(ma_id); - add_operation_node(ma_id, DEPSNODE_TYPE_SHADING, - DEPSOP_TYPE_EXEC, NULL, + add_operation_node(ma_id, DEG_NODE_TYPE_SHADING, NULL, DEG_OPCODE_PLACEHOLDER, "Material Update"); /* material animation */ @@ -1151,8 +1057,7 @@ void DepsgraphNodeBuilder::build_image(Image *image) { add_id_node(image_id); /* Placeholder so we can add relations and tag ID node for update. */ add_operation_node(image_id, - DEPSNODE_TYPE_PARAMETERS, - DEPSOP_TYPE_EXEC, + DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, "Image Eval"); @@ -1163,10 +1068,10 @@ void DepsgraphNodeBuilder::build_compositor(Scene *scene) /* For now, just a plain wrapper? */ // TODO: create compositing component? // XXX: component type undefined! - //graph->get_node(&scene->id, NULL, DEPSNODE_TYPE_COMPOSITING, NULL); + //graph->get_node(&scene->id, NULL, DEG_NODE_TYPE_COMPOSITING, NULL); /* for now, nodetrees are just parameters; compositing occurs in internals of renderer... */ - add_component_node(&scene->id, DEPSNODE_TYPE_PARAMETERS); + add_component_node(&scene->id, DEG_NODE_TYPE_PARAMETERS); build_nodetree(scene->nodetree); } @@ -1188,9 +1093,8 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file) { ID *cache_file_id = &cache_file->id; - add_component_node(cache_file_id, DEPSNODE_TYPE_CACHE); - add_operation_node(cache_file_id, DEPSNODE_TYPE_CACHE, - DEPSOP_TYPE_EXEC, NULL, + add_component_node(cache_file_id, DEG_NODE_TYPE_CACHE); + add_operation_node(cache_file_id, DEG_NODE_TYPE_CACHE, NULL, DEG_OPCODE_PLACEHOLDER, "Cache File Update"); add_id_node(cache_file_id); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 10b586342dd..a54b1c76c77 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -61,8 +61,6 @@ namespace DEG { struct Depsgraph; struct DepsNode; -struct RootDepsNode; -struct SubgraphDepsNode; struct IDDepsNode; struct TimeSourceDepsNode; struct ComponentDepsNode; @@ -74,32 +72,28 @@ struct DepsgraphNodeBuilder { void begin_build(Main *bmain); - RootDepsNode *add_root_node(); IDDepsNode *add_id_node(ID *id); - TimeSourceDepsNode *add_time_source(ID *id); + TimeSourceDepsNode *add_time_source(); ComponentDepsNode *add_component_node(ID *id, eDepsNode_Type comp_type, const char *comp_name = ""); OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node, - eDepsOperation_Type optype, - DepsEvalOperationCb op, + const DepsEvalOperationCb& op, eDepsOperation_Code opcode, const char *name = "", int name_tag = -1); OperationDepsNode *add_operation_node(ID *id, eDepsNode_Type comp_type, const char *comp_name, - eDepsOperation_Type optype, - DepsEvalOperationCb op, + const DepsEvalOperationCb& op, eDepsOperation_Code opcode, const char *name = "", int name_tag = -1); OperationDepsNode *add_operation_node(ID *id, eDepsNode_Type comp_type, - eDepsOperation_Type optype, - DepsEvalOperationCb op, + const DepsEvalOperationCb& op, eDepsOperation_Code opcode, const char *name = "", int name_tag = -1); @@ -125,12 +119,11 @@ struct DepsgraphNodeBuilder { int name_tag = -1); void build_scene(Main *bmain, Scene *scene); - SubgraphDepsNode *build_subgraph(Group *group); void build_group(Scene *scene, Base *base, Group *group); void build_object(Scene *scene, Base *base, Object *ob); void build_object_transform(Scene *scene, Object *ob); void build_object_constraints(Scene *scene, Object *ob); - void build_pose_constraints(Object *ob, bPoseChannel *pchan); + void build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan); void build_rigidbody(Scene *scene); void build_particles(Scene *scene, Object *ob); void build_cloth(Scene *scene, Object *object); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index f2437ce1fac..fe7ccaa7fc0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -37,11 +37,11 @@ #include "MEM_guardedalloc.h" -extern "C" { +#include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_string.h" -#include "BLI_utildefines.h" +extern "C" { #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -49,10 +49,10 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" +} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" -} /* extern "C" */ #include "intern/builder/deg_builder.h" #include "intern/nodes/deg_node.h" @@ -64,11 +64,11 @@ extern "C" { namespace DEG { -void DepsgraphNodeBuilder::build_pose_constraints(Object *ob, bPoseChannel *pchan) +void DepsgraphNodeBuilder::build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan) { /* create node for constraint stack */ - add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_EXEC, function_bind(BKE_pose_constraints_evaluate, _1, ob, pchan), + add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + function_bind(BKE_pose_constraints_evaluate, _1, scene, ob, pchan), DEG_OPCODE_BONE_CONSTRAINTS); } @@ -80,15 +80,15 @@ void DepsgraphNodeBuilder::build_ik_pose(Scene *scene, Object *ob, bPoseChannel /* Find the chain's root. */ bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data); - if (has_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, + if (has_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER)) { return; } /* Operation node for evaluating/running IK Solver. */ - add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, - DEPSOP_TYPE_SIM, function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan), + add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, + function_bind(BKE_pose_iktree_evaluate, _1, scene, ob, rootchan), DEG_OPCODE_POSE_IK_SOLVER); } @@ -103,8 +103,8 @@ void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseCh /* Operation node for evaluating/running Spline IK Solver. * Store the "root bone" of this chain in the solver, so it knows where to start. */ - add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, - DEPSOP_TYPE_SIM, function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan), + add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, + function_bind(BKE_pose_splineik_evaluate, _1, scene, ob, rootchan), DEG_OPCODE_POSE_SPLINE_IK_SOLVER); } @@ -112,6 +112,7 @@ void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene, Object *ob, bPoseCh void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob) { bArmature *arm = (bArmature *)ob->data; + OperationDepsNode *op_node; /* animation and/or drivers linking posebones to base-armature used to define them * NOTE: AnimData here is really used to control animated deform properties, @@ -124,8 +125,7 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob) /* Make sure pose is up-to-date with armature updates. */ add_operation_node(&arm->id, - DEPSNODE_TYPE_PARAMETERS, - DEPSOP_TYPE_EXEC, + DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, "Armature Eval"); @@ -174,34 +174,41 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob) */ /* pose eval context */ - add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, - DEPSOP_TYPE_INIT, function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_INIT); - - add_operation_node(&ob->id, DEPSNODE_TYPE_EVAL_POSE, - DEPSOP_TYPE_POST, function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), DEG_OPCODE_POSE_DONE); + op_node = add_operation_node(&ob->id, + DEG_NODE_TYPE_EVAL_POSE, + function_bind(BKE_pose_eval_init, _1, scene, ob, ob->pose), + DEG_OPCODE_POSE_INIT); + op_node->set_as_entry(); + + op_node = add_operation_node(&ob->id, + DEG_NODE_TYPE_EVAL_POSE, + function_bind(BKE_pose_eval_flush, _1, scene, ob, ob->pose), + DEG_OPCODE_POSE_DONE); + op_node->set_as_exit(); /* bones */ LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { /* node for bone eval */ - add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_INIT, NULL, // XXX: BKE_pose_eval_bone_local - DEG_OPCODE_BONE_LOCAL); + op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, + DEG_OPCODE_BONE_LOCAL); + op_node->set_as_entry(); - add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_EXEC, function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), // XXX: BKE_pose_eval_bone_pose + add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + function_bind(BKE_pose_eval_bone, _1, scene, ob, pchan), DEG_OPCODE_BONE_POSE_PARENT); - add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_OUT, NULL, /* NOTE: dedicated noop for easier relationship construction */ + add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + NULL, /* NOTE: dedicated noop for easier relationship construction */ DEG_OPCODE_BONE_READY); - add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_POST, function_bind(BKE_pose_bone_done, _1, pchan), - DEG_OPCODE_BONE_DONE); + op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + function_bind(BKE_pose_bone_done, _1, pchan), + DEG_OPCODE_BONE_DONE); + op_node->set_as_exit(); /* constraints */ if (pchan->constraints.first != NULL) { - build_pose_constraints(ob, pchan); + build_pose_constraints(scene, ob, pchan); } /** @@ -235,6 +242,8 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob) void DepsgraphNodeBuilder::build_proxy_rig(Object *ob) { ID *obdata = (ID *)ob->data; + OperationDepsNode *op_node; + build_animdata(obdata); BLI_assert(ob->pose != NULL); @@ -245,31 +254,28 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *ob) BKE_pose_update_constraint_flags(ob->pose); } - add_operation_node(&ob->id, - DEPSNODE_TYPE_EVAL_POSE, - DEPSOP_TYPE_INIT, - function_bind(BKE_pose_eval_proxy_copy, _1, ob), - DEG_OPCODE_POSE_INIT); + op_node = add_operation_node(&ob->id, + DEG_NODE_TYPE_EVAL_POSE, + function_bind(BKE_pose_eval_proxy_copy, _1, ob), + DEG_OPCODE_POSE_INIT); + op_node->set_as_entry(); LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { - add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_INIT, NULL, - DEG_OPCODE_BONE_LOCAL); + op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + NULL, DEG_OPCODE_BONE_LOCAL); + op_node->set_as_entry(); - add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_EXEC, NULL, - DEG_OPCODE_BONE_READY); + add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + NULL, DEG_OPCODE_BONE_READY); - add_operation_node(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, - DEPSOP_TYPE_POST, NULL, - DEG_OPCODE_BONE_DONE); + op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, + NULL, DEG_OPCODE_BONE_DONE); + op_node->set_as_exit(); } - add_operation_node(&ob->id, - DEPSNODE_TYPE_EVAL_POSE, - DEPSOP_TYPE_POST, - NULL, - DEG_OPCODE_POSE_DONE); + op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, + NULL, DEG_OPCODE_POSE_DONE); + op_node->set_as_exit(); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc index 7dd694cb570..3249867e416 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc @@ -37,21 +37,21 @@ #include "MEM_guardedalloc.h" -extern "C" { +#include "BLI_utildefines.h" #include "BLI_blenlib.h" #include "BLI_string.h" -#include "BLI_utildefines.h" +extern "C" { #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "BKE_main.h" #include "BKE_node.h" +} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" -} /* extern "C" */ #include "intern/builder/deg_builder.h" #include "intern/nodes/deg_node.h" @@ -69,7 +69,7 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene) add_id_node(&scene->id); /* timesource */ - add_time_source(NULL); + add_time_source(); /* build subgraph for set, and link this in... */ // XXX: depending on how this goes, that scene itself could probably store its diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc index f870a33fb68..59eb7ed8cf1 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc @@ -33,10 +33,8 @@ #include <stdio.h> #include <string.h> -extern "C" { #include "BLI_utildefines.h" #include "BLI_ghash.h" -} namespace DEG { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 7f2c6d8d9a1..a1abcb96411 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -38,10 +38,10 @@ #include "MEM_guardedalloc.h" -extern "C" { -#include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_blenlib.h" +extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -92,13 +92,13 @@ extern "C" { #include "BKE_tracking.h" #include "BKE_world.h" -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" - #include "RNA_access.h" #include "RNA_types.h" } /* extern "C" */ +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_pchanmap.h" @@ -113,6 +113,41 @@ extern "C" { namespace DEG { +namespace { + +struct BuilderWalkUserData { + DepsgraphRelationBuilder *builder; + Main *bmain; + Scene *scene; +}; + +static void modifier_walk(void *user_data, + struct Object * /*ob*/, + struct Object **obpoin, + int /*cb_flag*/) +{ + BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; + if (*obpoin) { + data->builder->build_object(data->bmain, data->scene, *obpoin); + } +} + +void constraint_walk(bConstraint * /*con*/, + ID **idpoin, + bool /*is_reference*/, + void *user_data) +{ + BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; + if (*idpoin) { + ID *id = *idpoin; + if (GS(id->name) == ID_OB) { + data->builder->build_object(data->bmain, data->scene, (Object *)id); + } + } +} + +} /* namespace */ + /* ***************** */ /* Relations Builder */ @@ -163,13 +198,6 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Depsgraph *graph) : { } -RootDepsNode *DepsgraphRelationBuilder::find_node(const RootKey &key) const -{ - (void)key; - BLI_assert(!"Doesn't seem to be correct"); - return m_graph->root_node; -} - TimeSourceDepsNode *DepsgraphRelationBuilder::find_node( const TimeSourceKey &key) const { @@ -178,7 +206,7 @@ TimeSourceDepsNode *DepsgraphRelationBuilder::find_node( return NULL; } else { - return m_graph->root_node->time_source; + return m_graph->time_source; } } @@ -247,7 +275,7 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc, const char *description) { if (timesrc && node_to) { - m_graph->add_new_relation(timesrc, node_to, DEPSREL_TYPE_TIME, description); + m_graph->add_new_relation(timesrc, node_to, description); } else { DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n", @@ -260,17 +288,16 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc, void DepsgraphRelationBuilder::add_operation_relation( OperationDepsNode *node_from, OperationDepsNode *node_to, - eDepsRelation_Type type, const char *description) { if (node_from && node_to) { - m_graph->add_new_relation(node_from, node_to, type, description); + m_graph->add_new_relation(node_from, node_to, description); } else { - DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %d, %s) Failed\n", + DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %s) Failed\n", node_from, (node_from) ? node_from->identifier().c_str() : "<None>", node_to, (node_to) ? node_to->identifier().c_str() : "<None>", - type, description); + description); } } @@ -283,11 +310,11 @@ void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, { Object *ob1 = collobjs[i]; - ComponentKey trf_key(&ob1->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, name); + ComponentKey trf_key(&ob1->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(trf_key, key, name); - ComponentKey coll_key(&ob1->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(coll_key, key, DEPSREL_TYPE_STANDARD, name); + ComponentKey coll_key(&ob1->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(coll_key, key, name); } if (collobjs) @@ -301,31 +328,31 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, if (effectors) { for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) { if (eff->ob != ob) { - ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name); + ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(eff_key, key, name); } if (eff->psys) { if (eff->ob != ob) { - ComponentKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES); - add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name); + ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES); + add_relation(eff_key, key, name); /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */ - ComponentKey mod_key(&eff->ob->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(mod_key, key, DEPSREL_TYPE_STANDARD, name); + ComponentKey mod_key(&eff->ob->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(mod_key, key, name); } else if (eff->psys != psys) { - OperationKey eff_key(&eff->ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, eff->psys->name); - add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, name); + OperationKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, eff->psys->name); + add_relation(eff_key, key, name); } } if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) { - ComponentKey trf_key(&eff->pd->f_source->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain"); + ComponentKey trf_key(&eff->pd->f_source->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(trf_key, key, "Smoke Force Domain"); - ComponentKey eff_key(&eff->pd->f_source->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain"); + ComponentKey eff_key(&eff->pd->f_source->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(eff_key, key, "Smoke Force Domain"); } if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { @@ -337,6 +364,11 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, pdEndEffectors(&effectors); } +Depsgraph *DepsgraphRelationBuilder::getGraph() +{ + return m_graph; +} + /* **** Functions to build relations between entities **** */ void DepsgraphRelationBuilder::begin_build(Main *bmain) @@ -363,17 +395,14 @@ void DepsgraphRelationBuilder::build_group(Main *bmain, ID *group_id = &group->id; bool group_done = (group_id->tag & LIB_TAG_DOIT) != 0; OperationKey object_local_transform_key(&object->id, - DEPSNODE_TYPE_TRANSFORM, + DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); LINKLIST_FOREACH (GroupObject *, go, &group->gobject) { if (!group_done) { build_object(bmain, scene, go->ob); } - ComponentKey dupli_transform_key(&go->ob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(dupli_transform_key, - object_local_transform_key, - DEPSREL_TYPE_TRANSFORM, - "Dupligroup"); + ComponentKey dupli_transform_key(&go->ob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup"); } group_id->tag |= LIB_TAG_DOIT; } @@ -387,13 +416,13 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o /* Object Transforms */ eDepsOperation_Code base_op = (ob->parent) ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL; - OperationKey base_op_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, base_op); + OperationKey base_op_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, base_op); - OperationKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); - OperationKey parent_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); - OperationKey final_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + OperationKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); + OperationKey parent_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); + OperationKey final_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); - OperationKey ob_ubereval_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL); + OperationKey ob_ubereval_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL); /* parenting */ if (ob->parent != NULL) { @@ -401,16 +430,28 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o build_object_parent(ob); /* local -> parent */ - add_relation(local_transform_key, - parent_transform_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "[ObLocal -> ObParent]"); + add_relation(local_transform_key, parent_transform_key, "[ObLocal -> ObParent]"); + } + + if (ob->modifiers.first != NULL) { + BuilderWalkUserData data; + data.builder = this; + data.bmain = bmain; + data.scene = scene; + modifiers_foreachObjectLink(ob, modifier_walk, &data); + } + if (ob->constraints.first != NULL) { + BuilderWalkUserData data; + data.builder = this; + data.bmain = bmain; + data.scene = scene; + BKE_constraints_id_loop(&ob->constraints, constraint_walk, &data); } /* object constraints */ if (ob->constraints.first != NULL) { OperationKey constraint_key(&ob->id, - DEPSNODE_TYPE_TRANSFORM, + DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS); /* constraint relations */ @@ -418,30 +459,18 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o // XXX: this is broken build_constraints(scene, &ob->id, - DEPSNODE_TYPE_TRANSFORM, + DEG_NODE_TYPE_TRANSFORM, "", &ob->constraints, NULL); /* operation order */ - add_relation(base_op_key, - constraint_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "[ObBase-> Constraint Stack]"); - add_relation(constraint_key, - final_transform_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "[ObConstraints -> Done]"); + add_relation(base_op_key, constraint_key, "[ObBase-> Constraint Stack]"); + add_relation(constraint_key, final_transform_key, "[ObConstraints -> Done]"); // XXX - add_relation(constraint_key, - ob_ubereval_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "Temp Ubereval"); - add_relation(ob_ubereval_key, - final_transform_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "Temp Ubereval"); + add_relation(constraint_key, ob_ubereval_key, "Temp Ubereval"); + add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval"); } else { /* NOTE: Keep an eye here, we skip some relations here to "streamline" @@ -452,31 +481,20 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o /* Rigid body will hook up another node inbetween, so skip * relation here to avoid transitive relation. */ - add_relation(base_op_key, - ob_ubereval_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "Temp Ubereval"); + add_relation(base_op_key, ob_ubereval_key, "Temp Ubereval"); } - add_relation(ob_ubereval_key, - final_transform_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "Temp Ubereval"); + add_relation(ob_ubereval_key, final_transform_key, "Temp Ubereval"); } - /* AnimData */ build_animdata(&ob->id); // XXX: This should be hooked up by the build_animdata code if (needs_animdata_node(&ob->id)) { - ComponentKey adt_key(&ob->id, DEPSNODE_TYPE_ANIMATION); - add_relation(adt_key, - local_transform_key, - DEPSREL_TYPE_OPERATION, - "Object Animation"); + ComponentKey adt_key(&ob->id, DEG_NODE_TYPE_ANIMATION); + add_relation(adt_key, local_transform_key, "Object Animation"); } - /* object data */ if (ob->data) { ID *obdata_id = (ID *)ob->data; @@ -517,12 +535,9 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o Key *key = BKE_key_from_object(ob); if (key != NULL) { - ComponentKey geometry_key((ID *)ob->data, DEPSNODE_TYPE_GEOMETRY); - ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(key_key, - geometry_key, - DEPSREL_TYPE_GEOMETRY_EVAL, - "Shapekeys"); + ComponentKey geometry_key((ID *)ob->data, DEG_NODE_TYPE_GEOMETRY); + ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(key_key, geometry_key, "Shapekeys"); } } @@ -543,9 +558,9 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o /* TODO(sergey): This is an inverted relation, matches old depsgraph * behavior and need to be investigated if it still need to be inverted. */ - ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); - ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE); - add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy"); + ComponentKey ob_pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE); + ComponentKey proxy_pose_key(&ob->proxy->id, DEG_NODE_TYPE_EVAL_POSE); + add_relation(ob_pose_key, proxy_pose_key, "Proxy"); } /* Object dupligroup. */ @@ -561,23 +576,23 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) */ // XXX: @sergey - it would be good if we got that backwards flushing working // when tagging for updates. - //OperationKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); - ComponentKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM); + //OperationKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT); + ComponentKey ob_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); /* type-specific links */ switch (ob->partype) { case PARSKEL: /* Armature Deform (Virtual Modifier) */ { - ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Armature Deform Parent"); + ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(parent_key, ob_key, "Armature Deform Parent"); break; } case PARVERT1: /* Vertex Parent */ case PARVERT3: { - ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(parent_key, ob_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Vertex Parent"); + ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(parent_key, ob_key, "Vertex Parent"); /* XXX not sure what this is for or how you could be done properly - lukas */ OperationDepsNode *parent_node = find_operation_node(parent_key); @@ -585,27 +600,21 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) parent_node->customdata_mask |= CD_MASK_ORIGINDEX; } - ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Vertex Parent TFM"); + ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(transform_key, ob_key, "Vertex Parent TFM"); break; } case PARBONE: /* Bone Parent */ { ComponentKey parent_bone_key(&ob->parent->id, - DEPSNODE_TYPE_BONE, + DEG_NODE_TYPE_BONE, ob->parsubstr); OperationKey parent_transform_key(&ob->parent->id, - DEPSNODE_TYPE_TRANSFORM, + DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); - add_relation(parent_bone_key, - ob_key, - DEPSREL_TYPE_TRANSFORM, - "Bone Parent"); - add_relation(parent_transform_key, - ob_key, - DEPSREL_TYPE_TRANSFORM, - "Armature Parent"); + add_relation(parent_bone_key, ob_key, "Bone Parent"); + add_relation(parent_transform_key, ob_key, "Armature Parent"); break; } @@ -614,33 +623,33 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob) if (ob->parent->type == OB_LATTICE) { /* Lattice Deform Parent - Virtual Modifier */ // XXX: no virtual modifiers should be left! - ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); - ComponentKey geom_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY); + ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey geom_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY); - add_relation(parent_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent"); - add_relation(geom_key, ob_key, DEPSREL_TYPE_STANDARD, "Lattice Deform Parent Geom"); + add_relation(parent_key, ob_key, "Lattice Deform Parent"); + add_relation(geom_key, ob_key, "Lattice Deform Parent Geom"); } else if (ob->parent->type == OB_CURVE) { Curve *cu = (Curve *)ob->parent->data; if (cu->flag & CU_PATH) { /* Follow Path */ - ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow Parent"); + ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(parent_key, ob_key, "Curve Follow Parent"); - ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Follow TFM"); + ComponentKey transform_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(transform_key, ob_key, "Curve Follow TFM"); } else { /* Standard Parent */ - ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Curve Parent"); + ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(parent_key, ob_key, "Curve Parent"); } } else { /* Standard Parent */ - ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(parent_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Parent"); + ComponentKey parent_key(&ob->parent->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(parent_key, ob_key, "Parent"); } break; } @@ -656,7 +665,7 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode ListBase *constraints, RootPChanMap *root_map) { OperationKey constraint_op_key(id, component_type, component_subdata, - (component_type == DEPSNODE_TYPE_BONE) ? DEG_OPCODE_BONE_CONSTRAINTS : DEG_OPCODE_TRANSFORM_CONSTRAINTS); + (component_type == DEG_NODE_TYPE_BONE) ? DEG_OPCODE_BONE_CONSTRAINTS : DEG_OPCODE_TRANSFORM_CONSTRAINTS); /* add dependencies for each constraint in turn */ for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) { @@ -679,8 +688,8 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode if (data->depth_ob) { // DAG_RL_DATA_OB | DAG_RL_OB_OB - ComponentKey depth_key(&data->depth_ob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(depth_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + ComponentKey depth_key(&data->depth_ob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(depth_key, constraint_op_key, cti->name); } } else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) { @@ -689,24 +698,24 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode if (depends_on_camera && scene->camera) { // DAG_RL_DATA_OB | DAG_RL_OB_OB - ComponentKey camera_key(&scene->camera->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(camera_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + ComponentKey camera_key(&scene->camera->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(camera_key, constraint_op_key, cti->name); } /* TODO(sergey): This is more a TimeSource -> MovieClip -> Constraint dependency chain. */ TimeSourceKey time_src_key; - add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]"); + add_relation(time_src_key, constraint_op_key, "[TimeSrc -> Animation]"); } else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) { /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint dependency chain. */ TimeSourceKey time_src_key; - add_relation(time_src_key, constraint_op_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]"); + add_relation(time_src_key, constraint_op_key, "[TimeSrc -> Animation]"); bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data; if (data->cache_file) { - ComponentKey cache_key(&data->cache_file->id, DEPSNODE_TYPE_CACHE); - add_relation(cache_key, constraint_op_key, DEPSREL_TYPE_CACHE, cti->name); + ComponentKey cache_key(&data->cache_file->id, DEG_NODE_TYPE_CACHE); + add_relation(cache_key, constraint_op_key, cti->name); } } else if (cti->get_constraint_targets) { @@ -723,8 +732,8 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode } else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) { /* these constraints require path geometry data... */ - ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name); // XXX: type = geom_transform + ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(target_key, constraint_op_key, cti->name); // XXX: type = geom_transform // TODO: path dependency } else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) { @@ -743,20 +752,20 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode target_key_opcode = DEG_OPCODE_BONE_DONE; } - OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, target_key_opcode); - add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_BONE, ct->subtarget, target_key_opcode); + add_relation(target_key, constraint_op_key, cti->name); } else { /* different armature - we can safely use the result of that */ - OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_BONE, ct->subtarget, DEG_OPCODE_BONE_DONE); - add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_BONE, ct->subtarget, DEG_OPCODE_BONE_DONE); + add_relation(target_key, constraint_op_key, cti->name); } } else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { /* vertex group */ /* NOTE: for now, we don't need to represent vertex groups separately... */ - ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name); + ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(target_key, constraint_op_key, cti->name); if (ct->tar->type == OB_MESH) { OperationDepsNode *node2 = find_operation_node(target_key); @@ -767,12 +776,12 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode } else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) { /* Constraints which requires the target object surface. */ - ComponentKey target_key(&ct->tar->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + ComponentKey target_key(&ct->tar->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(target_key, constraint_op_key, cti->name); /* NOTE: obdata eval now doesn't necessarily depend on the object's transform... */ - ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + ComponentKey target_transform_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(target_transform_key, constraint_op_key, cti->name); } else { /* standard object relation */ @@ -784,19 +793,19 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode * - If however it is a real self targetting case, just make it depend on the * previous constraint (or the pre-constraint state)... */ - if ((ct->tar->type == OB_ARMATURE) && (component_type == DEPSNODE_TYPE_BONE)) { - OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); - add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + if ((ct->tar->type == OB_ARMATURE) && (component_type == DEG_NODE_TYPE_BONE)) { + OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + add_relation(target_key, constraint_op_key, cti->name); } else { - OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); - add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); + add_relation(target_key, constraint_op_key, cti->name); } } else { /* normal object dependency */ - OperationKey target_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); - add_relation(target_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + OperationKey target_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + add_relation(target_key, constraint_op_key, cti->name); } } @@ -810,8 +819,8 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode CONSTRAINT_TYPE_TRANSLIKE)) { /* TODO(sergey): Add used space check. */ - ComponentKey target_transform_key(&ct->tar->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(target_transform_key, constraint_op_key, DEPSREL_TYPE_TRANSFORM, cti->name); + ComponentKey target_transform_key(&ct->tar->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(target_transform_key, constraint_op_key, cti->name); } } @@ -829,13 +838,13 @@ void DepsgraphRelationBuilder::build_animdata(ID *id) if (adt == NULL) return; - ComponentKey adt_key(id, DEPSNODE_TYPE_ANIMATION); + ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION); /* animation */ if (adt->action || adt->nla_tracks.first) { /* wire up dependency to time source */ TimeSourceKey time_src_key; - add_relation(time_src_key, adt_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Animation]"); + add_relation(time_src_key, adt_key, "[TimeSrc -> Animation]"); // XXX: Hook up specific update callbacks for special properties which may need it... @@ -845,9 +854,9 @@ void DepsgraphRelationBuilder::build_animdata(ID *id) /* drivers */ LINKLIST_FOREACH (FCurve *, fcu, &adt->drivers) { OperationKey driver_key(id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, - fcu->rna_path, + fcu->rna_path ? fcu->rna_path : "", fcu->array_index); /* create the driver's relations to targets */ @@ -869,7 +878,8 @@ void DepsgraphRelationBuilder::build_animdata(ID *id) FCurve *fcu_prev = NULL; LINKLIST_FOREACH (FCurve *, fcu_candidate, &adt->drivers) { /* Writing to different RNA paths is */ - if (!STREQ(fcu_candidate->rna_path, fcu->rna_path)) { + const char *rna_path = fcu->rna_path ? fcu->rna_path : ""; + if (!STREQ(fcu_candidate->rna_path, rna_path)) { continue; } /* We only do relation from previous fcurve to previous one. */ @@ -885,26 +895,22 @@ void DepsgraphRelationBuilder::build_animdata(ID *id) } if (fcu_prev != NULL) { OperationKey prev_driver_key(id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, - fcu_prev->rna_path, + fcu_prev->rna_path ? fcu_prev->rna_path : "", fcu_prev->array_index); OperationKey driver_key(id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, - fcu->rna_path, + fcu->rna_path ? fcu->rna_path : "", fcu->array_index); - add_relation(prev_driver_key, - driver_key, - DEPSREL_TYPE_OPERATION, - "[Driver Order]"); + add_relation(prev_driver_key, driver_key, "[Driver Order]"); } } /* prevent driver from occurring before own animation... */ if (adt->action || adt->nla_tracks.first) { - add_relation(adt_key, driver_key, DEPSREL_TYPE_OPERATION, - "[AnimData Before Drivers]"); + add_relation(adt_key, driver_key, "[AnimData Before Drivers]"); } } } @@ -913,26 +919,28 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) { ChannelDriver *driver = fcu->driver; OperationKey driver_key(id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, - fcu->rna_path, + fcu->rna_path ? fcu->rna_path : "", fcu->array_index); bPoseChannel *pchan = NULL; + const char *rna_path = fcu->rna_path ? fcu->rna_path : ""; + /* create dependency between driver and data affected by it */ /* - direct property relationship... */ //RNAPathKey affected_key(id, fcu->rna_path); - //add_relation(driver_key, affected_key, DEPSREL_TYPE_DRIVER, "[Driver -> Data] DepsRel"); + //add_relation(driver_key, affected_key, "[Driver -> Data] DepsRel"); /* driver -> data components (for interleaved evaluation - bones/constraints/modifiers) */ // XXX: this probably should probably be moved out into a separate function - if (strstr(fcu->rna_path, "pose.bones[") != NULL) { + if (strstr(rna_path, "pose.bones[") != NULL) { /* interleaved drivers during bone eval */ // TODO: ideally, if this is for a constraint, it goes to said constraint Object *ob = (Object *)id; char *bone_name; - bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); + bone_name = BLI_str_quoted_substrN(rna_path, "pose.bones["); pchan = BKE_pose_channel_find_name(ob->pose, bone_name); if (bone_name) { @@ -941,21 +949,21 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) } if (pchan) { - OperationKey bone_key(id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); - add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Driver -> Bone]"); + OperationKey bone_key(id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + add_relation(driver_key, bone_key, "[Driver -> Bone]"); } else { fprintf(stderr, "Couldn't find bone name for driver path - '%s'\n", - fcu->rna_path); + rna_path); } } - else if (GS(id->name) == ID_AR && strstr(fcu->rna_path, "bones[")) { + else if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) { /* drivers on armature-level bone settings (i.e. bbone stuff), * which will affect the evaluation of corresponding pose bones */ IDDepsNode *arm_node = m_graph->find_id_node(id); - char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "bones["); + char *bone_name = BLI_str_quoted_substrN(rna_path, "bones["); if (arm_node && bone_name) { /* find objects which use this, and make their eval callbacks depend on this */ @@ -968,8 +976,8 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); // NOTE: ob->pose may be NULL if (pchan) { - OperationKey bone_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); - add_relation(driver_key, bone_key, DEPSREL_TYPE_DRIVER, "[Arm Bone -> Driver -> Bone]"); + OperationKey bone_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + add_relation(driver_key, bone_key, "[Arm Bone -> Driver -> Bone]"); } } } @@ -981,48 +989,39 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) else { fprintf(stderr, "Couldn't find armature bone name for driver path - '%s'\n", - fcu->rna_path); + rna_path); } } - else if (GS(id->name) == ID_OB && strstr(fcu->rna_path, "modifiers[")) { - /* modifier driver - connect directly to the modifier */ - char *modifier_name = BLI_str_quoted_substrN(fcu->rna_path, "modifiers["); - if (modifier_name) { - OperationKey modifier_key(id, - DEPSNODE_TYPE_GEOMETRY, - DEG_OPCODE_GEOMETRY_MODIFIER, - modifier_name); - if (has_node(modifier_key)) { - add_relation(driver_key, modifier_key, DEPSREL_TYPE_DRIVER, "[Driver -> Modifier]"); - } - else { - printf("Unexisting driver RNA path: %s\n", fcu->rna_path); - } - - MEM_freeN(modifier_name); + else if (GS(id->name) == ID_OB && strstr(rna_path, "modifiers[")) { + OperationKey modifier_key(id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); + if (has_node(modifier_key)) { + add_relation(driver_key, modifier_key, "[Driver -> Modifier]"); + } + else { + printf("Unexisting driver RNA path: %s\n", rna_path); } } - else if (GS(id->name) == ID_KE && strstr(fcu->rna_path, "key_blocks[")) { + else if (GS(id->name) == ID_KE && strstr(rna_path, "key_blocks[")) { /* shape key driver - hook into the base geometry operation */ // XXX: double check where this points Key *shape_key = (Key *)id; - ComponentKey geometry_key(shape_key->from, DEPSNODE_TYPE_GEOMETRY); - add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]"); + ComponentKey geometry_key(shape_key->from, DEG_NODE_TYPE_GEOMETRY); + add_relation(driver_key, geometry_key, "[Driver -> ShapeKey Geom]"); } - else if (strstr(fcu->rna_path, "key_blocks[")) { - ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY); - add_relation(driver_key, geometry_key, DEPSREL_TYPE_DRIVER, "[Driver -> ShapeKey Geom]"); + else if (strstr(rna_path, "key_blocks[")) { + ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY); + add_relation(driver_key, geometry_key, "[Driver -> ShapeKey Geom]"); } else { if (GS(id->name) == ID_OB) { /* assume that driver affects a transform... */ - OperationKey local_transform_key(id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); - add_relation(driver_key, local_transform_key, DEPSREL_TYPE_OPERATION, "[Driver -> Transform]"); + OperationKey local_transform_key(id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); + add_relation(driver_key, local_transform_key, "[Driver -> Transform]"); } else if (GS(id->name) == ID_KE) { - ComponentKey geometry_key(id, DEPSNODE_TYPE_GEOMETRY); - add_relation(driver_key, geometry_key, DEPSREL_TYPE_GEOMETRY_EVAL, "[Driver -> Shapekey Geometry]"); + ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY); + add_relation(driver_key, geometry_key, "[Driver -> Shapekey Geometry]"); } } @@ -1055,14 +1054,14 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) { continue; } - OperationKey target_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_DONE); - add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Bone Target -> Driver]"); + OperationKey target_key(dtar->id, DEG_NODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_DONE); + add_relation(target_key, driver_key, "[Bone Target -> Driver]"); } } else if (dtar->flag & DTAR_FLAG_STRUCT_REF) { /* get node associated with the object's transforms */ - OperationKey target_key(dtar->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); - add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[Target -> Driver]"); + OperationKey target_key(dtar->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_FINAL); + add_relation(target_key, driver_key, "[Target -> Driver]"); } else if (dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) { /* workaround for ensuring that local bone transforms don't end up @@ -1082,8 +1081,8 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) { continue; } - OperationKey bone_key(dtar->id, DEPSNODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_LOCAL); - add_relation(bone_key, driver_key, DEPSREL_TYPE_DRIVER, "[RNA Bone -> Driver]"); + OperationKey bone_key(dtar->id, DEG_NODE_TYPE_BONE, target_pchan->name, DEG_OPCODE_BONE_LOCAL); + add_relation(bone_key, driver_key, "[RNA Bone -> Driver]"); } } else { @@ -1095,7 +1094,7 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) } /* resolve path to get node */ RNAPathKey target_key(dtar->id, dtar->rna_path ? dtar->rna_path : ""); - add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[RNA Target -> Driver]"); + add_relation(target_key, driver_key, "[RNA Target -> Driver]"); } } DRIVER_TARGETS_LOOPER_END @@ -1109,7 +1108,7 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) python_driver_depends_on_time(driver)) { TimeSourceKey time_src_key; - add_relation(time_src_key, driver_key, DEPSREL_TYPE_TIME, "[TimeSrc -> Driver]"); + add_relation(time_src_key, driver_key, "[TimeSrc -> Driver]"); } } @@ -1129,27 +1128,29 @@ void DepsgraphRelationBuilder::build_world(World *world) build_texture_stack(world->mtex); /* world's nodetree */ - build_nodetree(world->nodetree); + if (world->nodetree != NULL) { + build_nodetree(world->nodetree); + ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_PARAMETERS); + ComponentKey world_key(world_id, DEG_NODE_TYPE_PARAMETERS); + add_relation(ntree_key, world_key, "NTree->World Parameters"); + } } void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) { RigidBodyWorld *rbw = scene->rigidbody_world; - OperationKey init_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_REBUILD); - OperationKey sim_key(&scene->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_SIM); + OperationKey init_key(&scene->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_REBUILD); + OperationKey sim_key(&scene->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_RIGIDBODY_SIM); /* rel between the two sim-nodes */ - add_relation(init_key, sim_key, DEPSREL_TYPE_OPERATION, "Rigidbody [Init -> SimStep]"); + add_relation(init_key, sim_key, "Rigidbody [Init -> SimStep]"); /* set up dependencies between these operations and other builtin nodes --------------- */ /* time dependency */ TimeSourceKey time_src_key; - add_relation(time_src_key, - init_key, - DEPSREL_TYPE_TIME, - "TimeSrc -> Rigidbody Reset/Rebuild (Optional)"); + add_relation(time_src_key, init_key, "TimeSrc -> Rigidbody Reset/Rebuild (Optional)"); /* objects - simulation participants */ if (rbw->group) { @@ -1167,12 +1168,12 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) * XXX: there's probably a difference between passive and active * - passive don't change, so may need to know full transform... */ - OperationKey rbo_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); + OperationKey rbo_key(&ob->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); eDepsOperation_Code trans_opcode = ob->parent ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL; - OperationKey trans_op(&ob->id, DEPSNODE_TYPE_TRANSFORM, trans_opcode); + OperationKey trans_op(&ob->id, DEG_NODE_TYPE_TRANSFORM, trans_opcode); - add_relation(sim_key, rbo_key, DEPSREL_TYPE_COMPONENT_ORDER, "Rigidbody Sim Eval -> RBO Sync"); + add_relation(sim_key, rbo_key, "Rigidbody Sim Eval -> RBO Sync"); /* if constraints exist, those depend on the result of the rigidbody sim * - This allows constraints to modify the result of the sim (i.e. clamping) @@ -1184,12 +1185,9 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) */ if (ob->constraints.first) { OperationKey constraint_key(&ob->id, - DEPSNODE_TYPE_TRANSFORM, + DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS); - add_relation(rbo_key, - constraint_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "RBO Sync -> Ob Constraints"); + add_relation(rbo_key, constraint_key, "RBO Sync -> Ob Constraints"); } else { /* Final object transform depends on rigidbody. @@ -1198,19 +1196,13 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) * If it is gone we'll need to reconsider relation here. */ OperationKey uber_key(&ob->id, - DEPSNODE_TYPE_TRANSFORM, + DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL); - add_relation(rbo_key, - uber_key, - DEPSREL_TYPE_COMPONENT_ORDER, - "RBO Sync -> Uber (Temp)"); + add_relation(rbo_key, uber_key, "RBO Sync -> Uber (Temp)"); } /* Needed to get correct base values. */ - add_relation(trans_op, - sim_key, - DEPSREL_TYPE_OPERATION, - "Base Ob Transform -> Rigidbody Sim Eval"); + add_relation(trans_op, sim_key, "Base Ob Transform -> Rigidbody Sim Eval"); } } @@ -1227,16 +1219,16 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* final result of the constraint object's transform controls how the * constraint affects the physics sim for these objects */ - ComponentKey trans_key(&ob->id, DEPSNODE_TYPE_TRANSFORM); - OperationKey ob1_key(&rbc->ob1->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); - OperationKey ob2_key(&rbc->ob2->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); + ComponentKey trans_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); + OperationKey ob1_key(&rbc->ob1->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); + OperationKey ob2_key(&rbc->ob2->id, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_RIGIDBODY); /* - constrained-objects sync depends on the constraint-holder */ - add_relation(trans_key, ob1_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_1"); - add_relation(trans_key, ob2_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint -> RBC.Object_2"); + add_relation(trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1"); + add_relation(trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2"); /* - ensure that sim depends on this constraint's transform */ - add_relation(trans_key, sim_key, DEPSREL_TYPE_TRANSFORM, "RigidBodyConstraint Transform -> RB Simulation"); + add_relation(trans_key, sim_key, "RigidBodyConstraint Transform -> RB Simulation"); } } } @@ -1245,8 +1237,15 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob) { TimeSourceKey time_src_key; OperationKey obdata_ubereval_key(&ob->id, - DEPSNODE_TYPE_GEOMETRY, + DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); + OperationKey eval_init_key(&ob->id, + DEG_NODE_TYPE_EVAL_PARTICLES, + DEG_OPCODE_PSYS_EVAL_INIT); + /* TODO(sergey): Are all particle systems depends on time? + * Hair without dynamics i.e. + */ + add_relation(time_src_key, eval_init_key, "TimeSrc -> PSys"); /* particle systems */ LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) { @@ -1256,55 +1255,19 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob) build_animdata(&part->id); /* this particle system */ - OperationKey psys_key(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name); + OperationKey psys_key(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PSYS_EVAL, psys->name); /* XXX: if particle system is later re-enabled, we must do full rebuild? */ if (!psys_check_enabled(ob, psys, G.is_rendering)) continue; - /* TODO(sergey): Are all particle systems depends on time? - * Hair without dynamics i.e. - */ - add_relation(time_src_key, psys_key, - DEPSREL_TYPE_TIME, - "TimeSrc -> PSys"); + add_relation(eval_init_key, psys_key, "Init -> PSys"); /* TODO(sergey): Currently particle update is just a placeholder, * hook it to the ubereval node so particle system is getting updated * on playback. */ - add_relation(psys_key, - obdata_ubereval_key, - DEPSREL_TYPE_OPERATION, - "PSys -> UberEval"); - -#if 0 - if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) { - LINKLIST_FOREACH (ParticleTarget *, pt, &psys->targets) { - if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) { - node2 = dag_get_node(dag, pt->ob); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets"); - } - } - } - - if (part->ren_as == PART_DRAW_OB && part->dup_ob) { - node2 = dag_get_node(dag, part->dup_ob); - /* note that this relation actually runs in the wrong direction, the problem - * is that dupli system all have this (due to parenting), and the render - * engine instancing assumes particular ordering of objects in list */ - dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization"); - if (part->dup_ob->type == OB_MBALL) - dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization"); - } - - if (part->ren_as == PART_DRAW_GR && part->dup_group) { - LINKLIST_FOREACH (GroupObject *, go, &part->dup_group->gobject) { - node2 = dag_get_node(dag, go->ob); - dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization"); - } - } -#endif + add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval"); /* collisions */ if (part->type != PART_HAIR) { @@ -1328,19 +1291,16 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob) ruleob = ((BoidRuleFollowLeader *)rule)->ob; if (ruleob) { - ComponentKey ruleob_key(&ruleob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(ruleob_key, psys_key, DEPSREL_TYPE_TRANSFORM, "Boid Rule"); + ComponentKey ruleob_key(&ruleob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(ruleob_key, psys_key, "Boid Rule"); } } } } if (part->ren_as == PART_DRAW_OB && part->dup_ob) { - ComponentKey dup_ob_key(&part->dup_ob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(dup_ob_key, - psys_key, - DEPSREL_TYPE_TRANSFORM, - "Particle Object Visualization"); + ComponentKey dup_ob_key(&part->dup_ob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(dup_ob_key, psys_key, "Particle Object Visualization"); } } @@ -1350,11 +1310,8 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob) * TODO(sergey): This relation should be altered once real granular update * is implemented. */ - ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(transform_key, - obdata_ubereval_key, - DEPSREL_TYPE_GEOMETRY_EVAL, - "Partcile Eval"); + ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(transform_key, obdata_ubereval_key, "Partcile Eval"); /* pointcache */ // TODO... @@ -1362,27 +1319,23 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob) void DepsgraphRelationBuilder::build_cloth(Scene * /*scene*/, Object *object, - ModifierData *md) + ModifierData * /*md*/) { OperationKey cache_key(&object->id, - DEPSNODE_TYPE_CACHE, + DEG_NODE_TYPE_CACHE, DEG_OPCODE_PLACEHOLDER, "Cloth Modifier"); /* Cache component affects on modifier. */ OperationKey modifier_key(&object->id, - DEPSNODE_TYPE_GEOMETRY, - DEG_OPCODE_GEOMETRY_MODIFIER, - md->name); - add_relation(cache_key, - modifier_key, - DEPSREL_TYPE_TIME, - "Cloth Cache -> Cloth"); + DEG_NODE_TYPE_GEOMETRY, + DEG_OPCODE_GEOMETRY_UBEREVAL); + add_relation(cache_key, modifier_key, "Cloth Cache -> Cloth"); } /* Shapekeys */ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key) { - ComponentKey obdata_key(obdata, DEPSNODE_TYPE_GEOMETRY); + ComponentKey obdata_key(obdata, DEG_NODE_TYPE_GEOMETRY); /* attach animdata to geometry */ build_animdata(&key->id); @@ -1390,8 +1343,8 @@ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key) if (key->adt) { // TODO: this should really be handled in build_animdata, since many of these cases will need it if (key->adt->action || key->adt->nla_tracks.first) { - ComponentKey adt_key(&key->id, DEPSNODE_TYPE_ANIMATION); - add_relation(adt_key, obdata_key, DEPSREL_TYPE_OPERATION, "Animation"); + ComponentKey adt_key(&key->id, DEG_NODE_TYPE_ANIMATION); + add_relation(adt_key, obdata_key, "Animation"); } /* NOTE: individual shapekey drivers are handled above already */ @@ -1399,8 +1352,8 @@ void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key) /* attach to geometry */ // XXX: aren't shapekeys now done as a pseudo-modifier on object? - //ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY); // FIXME: this doesn't exist - //add_relation(key_key, obdata_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Shapekeys"); + //ComponentKey key_key(&key->id, DEG_NODE_TYPE_GEOMETRY); // FIXME: this doesn't exist + //add_relation(key_key, obdata_key, "Shapekeys"); } /** @@ -1428,34 +1381,26 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje ID *obdata = (ID *)ob->data; /* Init operation of object-level geometry evaluation. */ - OperationKey geom_init_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init"); + OperationKey geom_init_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Init"); /* get nodes for result of obdata's evaluation, and geometry evaluation on object */ - ComponentKey obdata_geom_key(obdata, DEPSNODE_TYPE_GEOMETRY); - ComponentKey geom_key(&ob->id, DEPSNODE_TYPE_GEOMETRY); + ComponentKey obdata_geom_key(obdata, DEG_NODE_TYPE_GEOMETRY); + ComponentKey geom_key(&ob->id, DEG_NODE_TYPE_GEOMETRY); /* link components to each other */ - add_relation(obdata_geom_key, geom_key, DEPSREL_TYPE_DATABLOCK, "Object Geometry Base Data"); + add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data"); /* Modifiers */ - if (ob->modifiers.first) { - OperationKey prev_mod_key; + if (ob->modifiers.first != NULL) { + OperationKey obdata_ubereval_key(&ob->id, + DEG_NODE_TYPE_GEOMETRY, + DEG_OPCODE_GEOMETRY_UBEREVAL); LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) { const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type); - OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name); - - if (md->prev) { - /* Stack relation: modifier depends on previous modifier in the stack */ - add_relation(prev_mod_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack"); - } - else { - /* Stack relation: first modifier depends on the geometry. */ - add_relation(geom_init_key, mod_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Modifier Stack"); - } if (mti->updateDepsgraph) { - DepsNodeHandle handle = create_node_handle(mod_key); + DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); mti->updateDepsgraph( md, bmain, @@ -1466,7 +1411,7 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje if (BKE_object_modifier_use_time(ob, md)) { TimeSourceKey time_src_key; - add_relation(time_src_key, mod_key, DEPSREL_TYPE_TIME, "Time Source"); + add_relation(time_src_key, obdata_ubereval_key, "Time Source"); /* Hacky fix for T45633 (Animated modifiers aren't updated) * @@ -1475,32 +1420,23 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje */ /* XXX: Remove this hack when these links are added as part of build_animdata() instead */ if (modifier_dependsOnTime(md) == false && needs_animdata_node(&ob->id)) { - ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION); - add_relation(animation_key, mod_key, DEPSREL_TYPE_OPERATION, "Modifier Animation"); + ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION); + add_relation(animation_key, obdata_ubereval_key, "Modifier Animation"); } } if (md->type == eModifierType_Cloth) { build_cloth(scene, ob, md); } - - prev_mod_key = mod_key; } } /* materials */ - if (ob->totcol != 0) { - ComponentKey object_shading_key(&ob->id, DEPSNODE_TYPE_SHADING); + if (ob->totcol) { for (int a = 1; a <= ob->totcol; a++) { Material *ma = give_current_material(ob, a); if (ma != NULL) { build_material(ma); - ComponentKey material_shading_key(&ma->id, - DEPSNODE_TYPE_SHADING); - add_relation(material_shading_key, - object_shading_key, - DEPSREL_TYPE_UPDATE, - "Object Shading"); } } } @@ -1516,15 +1452,8 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje */ if (ob->type != OB_ARMATURE) { /* Armatures does no longer require uber node. */ - OperationKey obdata_ubereval_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); - if (ob->modifiers.last) { - ModifierData *md = (ModifierData *)ob->modifiers.last; - OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name); - add_relation(mod_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval"); - } - else { - add_relation(geom_init_key, obdata_ubereval_key, DEPSREL_TYPE_OPERATION, "Object Geometry UberEval"); - } + OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); + add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval"); } if (obdata->tag & LIB_TAG_DOIT) { @@ -1533,13 +1462,26 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje obdata->tag |= LIB_TAG_DOIT; /* Link object data evaluation node to exit operation. */ - OperationKey obdata_geom_eval_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); - OperationKey obdata_geom_done_key(obdata, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Done"); - add_relation(obdata_geom_eval_key, obdata_geom_done_key, DEPSREL_TYPE_DATABLOCK, "ObData Geom Eval Done"); + OperationKey obdata_geom_eval_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); + OperationKey obdata_geom_done_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Eval Done"); + add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done"); /* type-specific node/links */ switch (ob->type) { case OB_MESH: + /* NOTE: This is compatibility code to support particle systems + * + * for viewport being properly rendered in final render mode. + * This relation is similar to what dag_object_time_update_flags() + * was doing for mesh objects with particle system/ + * + * Ideally we need to get rid of this relation. + */ + if (ob->particlesystem.first != NULL) { + TimeSourceKey time_key; + OperationKey obdata_ubereval_key(&ob->id, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_UBEREVAL); + add_relation(time_key, obdata_ubereval_key, "Legacy particle time"); + } break; case OB_MBALL: @@ -1549,10 +1491,10 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje /* motherball - mom depends on children! */ if (mom != ob) { /* non-motherball -> cannot be directly evaluated! */ - ComponentKey mom_key(&mom->id, DEPSNODE_TYPE_GEOMETRY); - ComponentKey transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(geom_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball"); - add_relation(transform_key, mom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Metaball Motherball"); + ComponentKey mom_key(&mom->id, DEG_NODE_TYPE_GEOMETRY); + ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(geom_key, mom_key, "Metaball Motherball"); + add_relation(transform_key, mom_key, "Metaball Motherball"); } break; } @@ -1565,20 +1507,20 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje /* curve's dependencies */ // XXX: these needs geom data, but where is geom stored? if (cu->bevobj) { - ComponentKey bevob_key(&cu->bevobj->id, DEPSNODE_TYPE_GEOMETRY); + ComponentKey bevob_key(&cu->bevobj->id, DEG_NODE_TYPE_GEOMETRY); build_object(bmain, scene, cu->bevobj); - add_relation(bevob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Bevel"); + add_relation(bevob_key, geom_key, "Curve Bevel"); } if (cu->taperobj) { - ComponentKey taperob_key(&cu->taperobj->id, DEPSNODE_TYPE_GEOMETRY); + ComponentKey taperob_key(&cu->taperobj->id, DEG_NODE_TYPE_GEOMETRY); build_object(bmain, scene, cu->taperobj); - add_relation(taperob_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Curve Taper"); + add_relation(taperob_key, geom_key, "Curve Taper"); } if (ob->type == OB_FONT) { if (cu->textoncurve) { - ComponentKey textoncurve_key(&cu->textoncurve->id, DEPSNODE_TYPE_GEOMETRY); + ComponentKey textoncurve_key(&cu->textoncurve->id, DEG_NODE_TYPE_GEOMETRY); build_object(bmain, scene, cu->textoncurve); - add_relation(textoncurve_key, geom_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Text on Curve"); + add_relation(textoncurve_key, geom_key, "Text on Curve"); } } break; @@ -1602,14 +1544,13 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje } if (needs_animdata_node(obdata)) { - ComponentKey animation_key(obdata, DEPSNODE_TYPE_ANIMATION); - ComponentKey parameters_key(obdata, DEPSNODE_TYPE_PARAMETERS); - add_relation(animation_key, parameters_key, - DEPSREL_TYPE_COMPONENT_ORDER, "Geom Parameters"); + ComponentKey animation_key(obdata, DEG_NODE_TYPE_ANIMATION); + ComponentKey parameters_key(obdata, DEG_NODE_TYPE_PARAMETERS); + add_relation(animation_key, parameters_key, "Geom Parameters"); /* Evaluation usually depends on animation. * TODO(sergey): Need to re-hook it after granular update is implemented.. */ - add_relation(animation_key, obdata_geom_eval_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Animation"); + add_relation(animation_key, obdata_geom_eval_key, "Animation"); } } @@ -1624,19 +1565,18 @@ void DepsgraphRelationBuilder::build_camera(Object *ob) } camera_id->tag |= LIB_TAG_DOIT; - ComponentKey parameters_key(camera_id, DEPSNODE_TYPE_PARAMETERS); + ComponentKey parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS); if (needs_animdata_node(camera_id)) { - ComponentKey animation_key(camera_id, DEPSNODE_TYPE_ANIMATION); - add_relation(animation_key, parameters_key, - DEPSREL_TYPE_COMPONENT_ORDER, "Camera Parameters"); + ComponentKey animation_key(camera_id, DEG_NODE_TYPE_ANIMATION); + add_relation(animation_key, parameters_key, "Camera Parameters"); } /* DOF */ if (cam->dof_ob) { - ComponentKey ob_param_key(&ob->id, DEPSNODE_TYPE_PARAMETERS); - ComponentKey dof_ob_key(&cam->dof_ob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(dof_ob_key, ob_param_key, DEPSREL_TYPE_TRANSFORM, "Camera DOF"); + ComponentKey ob_param_key(&ob->id, DEG_NODE_TYPE_PARAMETERS); + ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(dof_ob_key, ob_param_key, "Camera DOF"); } } @@ -1650,20 +1590,18 @@ void DepsgraphRelationBuilder::build_lamp(Object *ob) } lamp_id->tag |= LIB_TAG_DOIT; - ComponentKey parameters_key(lamp_id, DEPSNODE_TYPE_PARAMETERS); + ComponentKey parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS); if (needs_animdata_node(lamp_id)) { - ComponentKey animation_key(lamp_id, DEPSNODE_TYPE_ANIMATION); - add_relation(animation_key, parameters_key, - DEPSREL_TYPE_COMPONENT_ORDER, "Lamp Parameters"); + ComponentKey animation_key(lamp_id, DEG_NODE_TYPE_ANIMATION); + add_relation(animation_key, parameters_key, "Lamp Parameters"); } /* lamp's nodetree */ if (la->nodetree) { build_nodetree(la->nodetree); - ComponentKey nodetree_key(&la->nodetree->id, DEPSNODE_TYPE_PARAMETERS); - add_relation(nodetree_key, parameters_key, - DEPSREL_TYPE_COMPONENT_ORDER, "NTree->Lamp Parameters"); + ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_PARAMETERS); + add_relation(nodetree_key, parameters_key, "NTree->Lamp Parameters"); } /* textures */ @@ -1680,7 +1618,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) build_animdata(ntree_id); OperationKey parameters_key(ntree_id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); @@ -1700,19 +1638,17 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) group_ntree->id.tag |= LIB_TAG_DOIT; } OperationKey group_parameters_key(&group_ntree->id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); - add_relation(group_parameters_key, parameters_key, - DEPSREL_TYPE_COMPONENT_ORDER, "Group Node"); + add_relation(group_parameters_key, parameters_key, "Group Node"); } } } if (needs_animdata_node(ntree_id)) { - ComponentKey animation_key(ntree_id, DEPSNODE_TYPE_ANIMATION); - add_relation(animation_key, parameters_key, - DEPSREL_TYPE_COMPONENT_ORDER, "NTree Parameters"); + ComponentKey animation_key(ntree_id, DEG_NODE_TYPE_ANIMATION); + add_relation(animation_key, parameters_key, "NTree Parameters"); } } @@ -1735,15 +1671,14 @@ void DepsgraphRelationBuilder::build_material(Material *ma) if (ma->nodetree != NULL) { build_nodetree(ma->nodetree); OperationKey ntree_key(&ma->nodetree->id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); OperationKey material_key(&ma->id, - DEPSNODE_TYPE_SHADING, + DEG_NODE_TYPE_SHADING, DEG_OPCODE_PLACEHOLDER, "Material Update"); - add_relation(ntree_key, material_key, - DEPSREL_TYPE_UPDATE, "Material's NTree"); + add_relation(ntree_key, material_key, "Material's NTree"); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 4ca95bebe3f..02f8fc69070 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -78,17 +78,12 @@ struct Depsgraph; struct DepsNode; struct DepsNodeHandle; struct RootDepsNode; -struct SubgraphDepsNode; struct IDDepsNode; struct TimeSourceDepsNode; struct ComponentDepsNode; struct OperationDepsNode; struct RootPChanMap; -struct RootKey { - RootKey(); -}; - struct TimeSourceKey { TimeSourceKey(); @@ -177,19 +172,16 @@ struct DepsgraphRelationBuilder template <typename KeyFrom, typename KeyTo> void add_relation(const KeyFrom& key_from, const KeyTo& key_to, - eDepsRelation_Type type, const char *description); template <typename KeyTo> void add_relation(const TimeSourceKey& key_from, const KeyTo& key_to, - eDepsRelation_Type type, const char *description); template <typename KeyType> void add_node_handle_relation(const KeyType& key_from, const DepsNodeHandle *handle, - eDepsRelation_Type type, const char *description); void build_scene(Main *bmain, Scene *scene); @@ -237,8 +229,9 @@ struct DepsgraphRelationBuilder template <typename KeyType> OperationDepsNode *find_operation_node(const KeyType &key); + Depsgraph *getGraph(); + protected: - RootDepsNode *find_node(const RootKey &key) const; TimeSourceDepsNode *find_node(const TimeSourceKey &key) const; ComponentDepsNode *find_node(const ComponentKey &key) const; OperationDepsNode *find_node(const OperationKey &key) const; @@ -250,7 +243,6 @@ protected: const char *description); void add_operation_relation(OperationDepsNode *node_from, OperationDepsNode *node_to, - eDepsRelation_Type type, const char *description); template <typename KeyType> @@ -290,7 +282,6 @@ OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& template <typename KeyFrom, typename KeyTo> void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, const KeyTo &key_to, - eDepsRelation_Type type, const char *description) { DepsNode *node_from = find_node(key_from); @@ -298,27 +289,27 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; if (op_from && op_to) { - add_operation_relation(op_from, op_to, type, description); + add_operation_relation(op_from, op_to, description); } else { if (!op_from) { /* XXX TODO handle as error or report if needed */ node_from = find_node(key_from); - fprintf(stderr, "add_relation(%d, %s) - Could not find op_from (%s)\n", - type, description, key_from.identifier().c_str()); + fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n", + description, key_from.identifier().c_str()); } else { - fprintf(stderr, "add_relation(%d, %s) - Failed, but op_from (%s) was ok\n", - type, description, key_from.identifier().c_str()); + fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n", + description, key_from.identifier().c_str()); } if (!op_to) { /* XXX TODO handle as error or report if needed */ - fprintf(stderr, "add_relation(%d, %s) - Could not find op_to (%s)\n", - type, description, key_to.identifier().c_str()); + fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n", + description, key_to.identifier().c_str()); } else { - fprintf(stderr, "add_relation(%d, %s) - Failed, but op_to (%s) was ok\n", - type, description, key_to.identifier().c_str()); + fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n", + description, key_to.identifier().c_str()); } } } @@ -326,11 +317,8 @@ void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from, template <typename KeyTo> void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from, const KeyTo &key_to, - eDepsRelation_Type type, const char *description) { - (void)type; /* Ignored in release builds. */ - BLI_assert(type == DEPSREL_TYPE_TIME); TimeSourceDepsNode *time_from = find_node(key_from); DepsNode *node_to = find_node(key_to); OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL; @@ -345,23 +333,22 @@ template <typename KeyType> void DepsgraphRelationBuilder::add_node_handle_relation( const KeyType &key_from, const DepsNodeHandle *handle, - eDepsRelation_Type type, const char *description) { DepsNode *node_from = find_node(key_from); OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL; OperationDepsNode *op_to = handle->node->get_entry_operation(); if (op_from && op_to) { - add_operation_relation(op_from, op_to, type, description); + add_operation_relation(op_from, op_to, description); } else { if (!op_from) { - fprintf(stderr, "add_node_handle_relation(%d, %s) - Could not find op_from (%s)\n", - type, description, key_from.identifier().c_str()); + fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n", + description, key_from.identifier().c_str()); } if (!op_to) { - fprintf(stderr, "add_node_handle_relation(%d, %s) - Could not find op_to (%s)\n", - type, description, key_from.identifier().c_str()); + fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n", + description, key_from.identifier().c_str()); } } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc index feae8bca303..9d6ab3358a7 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc @@ -35,13 +35,6 @@ namespace DEG { ///////////////////////////////////////// -// Root. - -RootKey::RootKey() -{ -} - -///////////////////////////////////////// // Time source. TimeSourceKey::TimeSourceKey() @@ -64,7 +57,7 @@ string TimeSourceKey::identifier() const ComponentKey::ComponentKey() : id(NULL), - type(DEPSNODE_TYPE_UNDEFINED), + type(DEG_NODE_TYPE_UNDEFINED), name("") { } @@ -90,7 +83,7 @@ string ComponentKey::identifier() const OperationKey::OperationKey() : id(NULL), - component_type(DEPSNODE_TYPE_UNDEFINED), + component_type(DEG_NODE_TYPE_UNDEFINED), component_name(""), opcode(DEG_OPCODE_OPERATION), name(""), diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index 2b4c000f483..be666165a0b 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -38,10 +38,10 @@ #include "MEM_guardedalloc.h" -extern "C" { -#include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_blenlib.h" +extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -51,10 +51,10 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" +} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" -} /* extern "C" */ #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_pchanmap.h" @@ -83,7 +83,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, * - see notes on direction of rel below... */ bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data); - OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER); + OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER); /* IK target */ // XXX: this should get handled as part of the constraint code @@ -96,25 +96,25 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, * testing IK solver. */ // FIXME: geometry targets... - ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); + ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE); if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) { /* TODO(sergey): This is only for until granular update stores intermediate result. */ if (data->tar != ob) { /* different armature - can just read the results */ - ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget); - add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name); + ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_BONE, data->subtarget); + add_relation(target_key, pose_key, con->name); } else { /* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */ - OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE); - add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name); + OperationKey target_key(&data->tar->id, DEG_NODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE); + add_relation(target_key, solver_key, con->name); } } else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) { /* vertex group target */ /* NOTE: for now, we don't need to represent vertex groups separately... */ - ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name); + ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(target_key, solver_key, con->name); if (data->tar->type == OB_MESH) { OperationDepsNode *node2 = find_operation_node(target_key); @@ -125,8 +125,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, } else { /* Standard Object Target */ - ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name); + ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(target_key, pose_key, con->name); } if ((data->tar == ob) && (data->subtarget[0])) { @@ -142,14 +142,14 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, if (data->poletar != NULL) { if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) { // XXX: same armature issues - ready vs done? - ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->polesubtarget); - add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name); + ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_BONE, data->polesubtarget); + add_relation(target_key, solver_key, con->name); } else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->polesubtarget[0])) { /* vertex group target */ /* NOTE: for now, we don't need to represent vertex groups separately... */ - ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY); - add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name); + ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(target_key, solver_key, con->name); if (data->poletar->type == OB_MESH) { OperationDepsNode *node2 = find_operation_node(target_key); @@ -159,8 +159,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, } } else { - ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name); + ComponentKey target_key(&data->poletar->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(target_key, solver_key, con->name); } } @@ -170,19 +170,17 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, bPoseChannel *parchan = pchan; /* exclude tip from chain? */ if (!(data->flag & CONSTRAINT_IK_TIP)) { - OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, + OperationKey tip_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_LOCAL); - add_relation(solver_key, tip_transforms_key, - DEPSREL_TYPE_TRANSFORM, "IK Solver Result"); + add_relation(solver_key, tip_transforms_key, "IK Solver Result"); parchan = pchan->parent; } root_map->add_bone(parchan->name, rootchan->name); - OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, + OperationKey parchan_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); - add_relation(parchan_transforms_key, solver_key, - DEPSREL_TYPE_TRANSFORM, "IK Solver Owner"); + add_relation(parchan_transforms_key, solver_key, "IK Solver Owner"); /* Walk to the chain's root */ //size_t segcount = 0; @@ -196,15 +194,15 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, * grab the result with IK solver results... */ if (parchan != pchan) { - OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); - add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent"); + OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); + add_relation(parent_key, solver_key, "IK Chain Parent"); - OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); - add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result"); + OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, done_key, "IK Chain Result"); } else { - OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); - add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result"); + OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, final_transforms_key, "IK Solver Result"); } parchan->flag |= POSE_DONE; @@ -219,8 +217,8 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob, parchan = parchan->parent; } - OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); - add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link"); + OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + add_relation(solver_key, flush_key, "PoseEval Result-Bone Link"); } /* Spline IK Eval Steps */ @@ -231,14 +229,14 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, { bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data); - OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); - OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER); + OperationKey transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey solver_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER); /* attach owner to IK Solver too * - assume that owner is always part of chain * - see notes on direction of rel below... */ - add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner"); + add_relation(transforms_key, solver_key, "Spline IK Solver Owner"); /* attach path dependency to solver */ if (data->tar) { @@ -247,14 +245,14 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, * See IK pose for a bit more information. */ // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry... - ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY); - ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); - add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel"); + ComponentKey target_key(&data->tar->id, DEG_NODE_TYPE_GEOMETRY); + ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE); + add_relation(target_key, pose_key, "[Curve.Path -> Spline IK] DepsRel"); } pchan->flag |= POSE_DONE; - OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); - add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result"); + OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, final_transforms_key, "Spline IK Result"); root_map->add_bone(pchan->name, rootchan->name); @@ -270,16 +268,16 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, * grab the result with IK solver results... */ if (parchan != pchan) { - OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); - add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update"); + OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY); + add_relation(parent_key, solver_key, "Spline IK Solver Update"); - OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); - add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result"); + OperationKey done_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, done_key, "IK Chain Result"); } parchan->flag |= POSE_DONE; - OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); - add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result"); + OperationKey final_transforms_key(&ob->id, DEG_NODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE); + add_relation(solver_key, final_transforms_key, "Spline IK Solver Result"); root_map->add_bone(parchan->name, rootchan->name); @@ -288,8 +286,8 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *ob, if ((segcount == data->chainlen) || (segcount > 255)) break; /* 255 is weak */ } - OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); - add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link"); + OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + add_relation(solver_key, flush_key, "PoseEval Result-Bone Link"); } /* Pose/Armature Bones Graph */ @@ -301,21 +299,21 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob) // TODO: selection status? /* attach links between pose operations */ - OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); - OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + OperationKey init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); + OperationKey flush_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); - add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]"); + add_relation(init_key, flush_key, "[Pose Init -> Pose Cleanup]"); /* Make sure pose is up-to-date with armature updates. */ OperationKey armature_key(&arm->id, - DEPSNODE_TYPE_PARAMETERS, + DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_PLACEHOLDER, "Armature Eval"); - add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency"); + add_relation(armature_key, init_key, "Data dependency"); if (needs_animdata_node(&ob->id)) { - ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION); - add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation"); + ComponentKey animation_key(&ob->id, DEG_NODE_TYPE_ANIMATION); + add_relation(animation_key, init_key, "Rig Animation"); } /* IK Solvers... @@ -370,26 +368,25 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob) /* TODO(sergey): Once partial updates are possible use relation between * object transform and solver itself in it's build function. */ - ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE); - ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM); - add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms"); + ComponentKey pose_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE); + ComponentKey local_transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(local_transform_key, pose_key, "Local Transforms"); } - /* links between operations for each bone */ LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { - OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); - OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT); - OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); - OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + OperationKey bone_pose_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT); + OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); pchan->flag &= ~POSE_DONE; /* pose init to bone local */ - add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link"); + add_relation(init_key, bone_local_key, "PoseEval Source-Bone Link"); /* local to pose parenting operation */ - add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link"); + add_relation(bone_local_key, bone_pose_key, "Bone Local - PoseSpace Link"); /* parent relation */ if (pchan->parent != NULL) { @@ -403,26 +400,26 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob) parent_key_opcode = DEG_OPCODE_BONE_DONE; } - OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode); - add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]"); + OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode); + add_relation(parent_key, bone_pose_key, "[Parent Bone -> Child Bone]"); } /* constraints */ if (pchan->constraints.first != NULL) { /* constraints stack and constraint dependencies */ - build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map); + build_constraints(scene, &ob->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map); /* pose -> constraints */ - OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS); - add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack"); + OperationKey constraints_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS); + add_relation(bone_pose_key, constraints_key, "Constraints Stack"); /* constraints -> ready */ // TODO: when constraint stack is exploded, this step should occur before the first IK solver - add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready"); + add_relation(constraints_key, bone_ready_key, "Constraints -> Ready"); } else { /* pose -> ready */ - add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready"); + add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready"); } /* bone ready -> done @@ -430,25 +427,25 @@ void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob) * For IK chains however, an additional rel is created from IK to done, * with transitive reduction removing this one... */ - add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done"); + add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); /* assume that all bones must be done for the pose to be ready (for deformers) */ - add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link"); + add_relation(bone_done_key, flush_key, "PoseEval Result-Bone Link"); } } void DepsgraphRelationBuilder::build_proxy_rig(Object *ob) { - OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); - OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); + OperationKey pose_init_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); + OperationKey pose_done_key(&ob->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); LINKLIST_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { - OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); - OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); - OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); - add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local"); - add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready"); - add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done"); - add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done"); + OperationKey bone_local_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); + OperationKey bone_ready_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); + OperationKey bone_done_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local"); + add_relation(bone_local_key, bone_ready_key, "Local -> Ready"); + add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); + add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done"); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc index 3bf435c37e0..6a9568e7e8d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc @@ -38,20 +38,20 @@ #include "MEM_guardedalloc.h" -extern "C" { -#include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_blenlib.h" +extern "C" { #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "BKE_main.h" #include "BKE_node.h" +} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" -} /* extern "C" */ #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_pchanmap.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc index da71db09f3d..b12af21fc8d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc @@ -30,9 +30,7 @@ #include "intern/builder/deg_builder_transitive.h" -extern "C" { #include "MEM_guardedalloc.h" -} #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" @@ -105,7 +103,7 @@ void deg_graph_transitive_reduction(Depsgraph *graph) /* Increment in advance, so we can safely remove the relation. */ ++it_rel; - if (rel->from->type == DEPSNODE_TYPE_TIMESOURCE) { + if (rel->from->type == DEG_NODE_TYPE_TIMESOURCE) { /* HACK: time source nodes don't get "done" flag set/cleared. */ /* TODO: there will be other types in future, so iterators above * need modifying. diff --git a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc index 0d56ce71c7d..51d4ed91419 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc @@ -35,10 +35,10 @@ extern "C" { #include "DNA_listBase.h" +} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" -} /* extern "C" */ #include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" @@ -77,20 +77,18 @@ static const char *deg_debug_colors_light[] = { #ifdef COLOR_SCHEME_NODE_TYPE static const int deg_debug_node_type_color_map[][2] = { - {DEPSNODE_TYPE_ROOT, 0}, - {DEPSNODE_TYPE_TIMESOURCE, 1}, - {DEPSNODE_TYPE_ID_REF, 2}, - {DEPSNODE_TYPE_SUBGRAPH, 3}, + {DEG_NODE_TYPE_TIMESOURCE, 0}, + {DEG_NODE_TYPE_ID_REF, 2}, /* Outer Types */ - {DEPSNODE_TYPE_PARAMETERS, 4}, - {DEPSNODE_TYPE_PROXY, 5}, - {DEPSNODE_TYPE_ANIMATION, 6}, - {DEPSNODE_TYPE_TRANSFORM, 7}, - {DEPSNODE_TYPE_GEOMETRY, 8}, - {DEPSNODE_TYPE_SEQUENCER, 9}, - {DEPSNODE_TYPE_SHADING, 10}, - {DEPSNODE_TYPE_CACHE, 11}, + {DEG_NODE_TYPE_PARAMETERS, 2}, + {DEG_NODE_TYPE_PROXY, 3}, + {DEG_NODE_TYPE_ANIMATION, 4}, + {DEG_NODE_TYPE_TRANSFORM, 5}, + {DEG_NODE_TYPE_GEOMETRY, 6}, + {DEG_NODE_TYPE_SEQUENCER, 7}, + {DEG_NODE_TYPE_SHADING, 8}, + {DEG_NODE_TYPE_CACHE, 9}, {-1, 0} }; #endif @@ -100,9 +98,9 @@ static int deg_debug_node_color_index(const DepsNode *node) #ifdef COLOR_SCHEME_NODE_CLASS /* Some special types. */ switch (node->type) { - case DEPSNODE_TYPE_ID_REF: + case DEG_NODE_TYPE_ID_REF: return 5; - case DEPSNODE_TYPE_OPERATION: + case DEG_NODE_TYPE_OPERATION: { OperationDepsNode *op_node = (OperationDepsNode *)node; if (op_node->is_noop()) @@ -115,9 +113,9 @@ static int deg_debug_node_color_index(const DepsNode *node) } /* Do others based on class. */ switch (node->tclass) { - case DEPSNODE_CLASS_OPERATION: + case DEG_NODE_CLASS_OPERATION: return 4; - case DEPSNODE_CLASS_COMPONENT: + case DEG_NODE_CLASS_COMPONENT: return 1; default: return 9; @@ -201,7 +199,7 @@ static void deg_debug_graphviz_node_color(const DebugContext &ctx, const char *color_update = "dodgerblue3"; const char *color = color_default; if (ctx.show_tags) { - if (node->tclass == DEPSNODE_CLASS_OPERATION) { + if (node->tclass == DEG_NODE_CLASS_OPERATION) { OperationDepsNode *op_node = (OperationDepsNode *)node; if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) { color = color_modified; @@ -222,7 +220,7 @@ static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx, float penwidth_update = 4.0f; float penwidth = penwidth_default; if (ctx.show_tags) { - if (node->tclass == DEPSNODE_CLASS_OPERATION) { + if (node->tclass == DEG_NODE_CLASS_OPERATION) { OperationDepsNode *op_node = (OperationDepsNode *)node; if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) { penwidth = penwidth_modified; @@ -260,7 +258,7 @@ static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNod { const char *base_style = "filled"; /* default style */ if (ctx.show_tags) { - if (node->tclass == DEPSNODE_CLASS_OPERATION) { + if (node->tclass == DEG_NODE_CLASS_OPERATION) { OperationDepsNode *op_node = (OperationDepsNode *)node; if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) { base_style = "striped"; @@ -268,13 +266,13 @@ static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNod } } switch (node->tclass) { - case DEPSNODE_CLASS_GENERIC: + case DEG_NODE_CLASS_GENERIC: deg_debug_fprintf(ctx, "\"%s\"", base_style); break; - case DEPSNODE_CLASS_COMPONENT: + case DEG_NODE_CLASS_COMPONENT: deg_debug_fprintf(ctx, "\"%s\"", base_style); break; - case DEPSNODE_CLASS_OPERATION: + case DEG_NODE_CLASS_OPERATION: deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style); break; } @@ -286,13 +284,13 @@ static void deg_debug_graphviz_node_single(const DebugContext &ctx, const char *shape = "box"; string name = node->identifier(); float priority = -1.0f; - if (node->type == DEPSNODE_TYPE_ID_REF) { + if (node->type == DEG_NODE_TYPE_ID_REF) { IDDepsNode *id_node = (IDDepsNode *)node; char buf[256]; BLI_snprintf(buf, sizeof(buf), " (Layers: %u)", id_node->layers); name += buf; } - if (ctx.show_eval_priority && node->tclass == DEPSNODE_CLASS_OPERATION) { + if (ctx.show_eval_priority && node->tclass == DEG_NODE_CLASS_OPERATION) { priority = ((OperationDepsNode *)node)->eval_priority; } deg_debug_fprintf(ctx, "// %s\n", name.c_str()); @@ -322,7 +320,7 @@ static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx, const DepsNode *node) { string name = node->identifier(); - if (node->type == DEPSNODE_TYPE_ID_REF) { + if (node->type == DEG_NODE_TYPE_ID_REF) { IDDepsNode *id_node = (IDDepsNode *)node; char buf[256]; BLI_snprintf(buf, sizeof(buf), " (Layers: %u)", id_node->layers); @@ -363,7 +361,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, const DepsNode *node) { switch (node->type) { - case DEPSNODE_TYPE_ID_REF: + case DEG_NODE_TYPE_ID_REF: { const IDDepsNode *id_node = (const IDDepsNode *)node; if (BLI_ghash_size(id_node->components) == 0) { @@ -380,30 +378,17 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, } break; } - case DEPSNODE_TYPE_SUBGRAPH: - { - SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node; - if (sub_node->graph) { - deg_debug_graphviz_node_cluster_begin(ctx, node); - deg_debug_graphviz_graph_nodes(ctx, sub_node->graph); - deg_debug_graphviz_node_cluster_end(ctx); - } - else { - deg_debug_graphviz_node_single(ctx, node); - } - break; - } - case DEPSNODE_TYPE_PARAMETERS: - case DEPSNODE_TYPE_ANIMATION: - case DEPSNODE_TYPE_TRANSFORM: - case DEPSNODE_TYPE_PROXY: - case DEPSNODE_TYPE_GEOMETRY: - case DEPSNODE_TYPE_SEQUENCER: - case DEPSNODE_TYPE_EVAL_POSE: - case DEPSNODE_TYPE_BONE: - case DEPSNODE_TYPE_SHADING: - case DEPSNODE_TYPE_CACHE: - case DEPSNODE_TYPE_EVAL_PARTICLES: + case DEG_NODE_TYPE_PARAMETERS: + case DEG_NODE_TYPE_ANIMATION: + case DEG_NODE_TYPE_TRANSFORM: + case DEG_NODE_TYPE_PROXY: + case DEG_NODE_TYPE_GEOMETRY: + case DEG_NODE_TYPE_SEQUENCER: + case DEG_NODE_TYPE_EVAL_POSE: + case DEG_NODE_TYPE_BONE: + case DEG_NODE_TYPE_SHADING: + case DEG_NODE_TYPE_CACHE: + case DEG_NODE_TYPE_EVAL_PARTICLES: { ComponentDepsNode *comp_node = (ComponentDepsNode *)node; if (!comp_node->operations.empty()) { @@ -427,24 +412,19 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, static bool deg_debug_graphviz_is_cluster(const DepsNode *node) { switch (node->type) { - case DEPSNODE_TYPE_ID_REF: + case DEG_NODE_TYPE_ID_REF: { const IDDepsNode *id_node = (const IDDepsNode *)node; return BLI_ghash_size(id_node->components) > 0; } - case DEPSNODE_TYPE_SUBGRAPH: - { - SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node; - return sub_node->graph != NULL; - } - case DEPSNODE_TYPE_PARAMETERS: - case DEPSNODE_TYPE_ANIMATION: - case DEPSNODE_TYPE_TRANSFORM: - case DEPSNODE_TYPE_PROXY: - case DEPSNODE_TYPE_GEOMETRY: - case DEPSNODE_TYPE_SEQUENCER: - case DEPSNODE_TYPE_EVAL_POSE: - case DEPSNODE_TYPE_BONE: + case DEG_NODE_TYPE_PARAMETERS: + case DEG_NODE_TYPE_ANIMATION: + case DEG_NODE_TYPE_TRANSFORM: + case DEG_NODE_TYPE_PROXY: + case DEG_NODE_TYPE_GEOMETRY: + case DEG_NODE_TYPE_SEQUENCER: + case DEG_NODE_TYPE_EVAL_POSE: + case DEG_NODE_TYPE_BONE: { ComponentDepsNode *comp_node = (ComponentDepsNode *)node; return !comp_node->operations.empty(); @@ -458,14 +438,14 @@ static bool deg_debug_graphviz_is_owner(const DepsNode *node, const DepsNode *other) { switch (node->tclass) { - case DEPSNODE_CLASS_COMPONENT: + case DEG_NODE_CLASS_COMPONENT: { ComponentDepsNode *comp_node = (ComponentDepsNode *)node; if (comp_node->owner == other) return true; break; } - case DEPSNODE_CLASS_OPERATION: + case DEG_NODE_CLASS_OPERATION: { OperationDepsNode *op_node = (OperationDepsNode *)node; if (op_node->owner == other) @@ -517,15 +497,12 @@ static void deg_debug_graphviz_node_relations(const DebugContext &ctx, static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, const Depsgraph *graph) { - if (graph->root_node) { - deg_debug_graphviz_node(ctx, graph->root_node); - } GHASH_FOREACH_BEGIN (DepsNode *, node, graph->id_hash) { deg_debug_graphviz_node(ctx, node); } GHASH_FOREACH_END(); - TimeSourceDepsNode *time_source = graph->find_time_source(NULL); + TimeSourceDepsNode *time_source = graph->find_time_source(); if (time_source != NULL) { deg_debug_graphviz_node(ctx, time_source); } @@ -546,7 +523,7 @@ static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, } GHASH_FOREACH_END(); - TimeSourceDepsNode *time_source = graph->find_time_source(NULL); + TimeSourceDepsNode *time_source = graph->find_time_source(); if (time_source != NULL) { deg_debug_graphviz_node_relations(ctx, time_source); } diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 5604044e123..aa21f0995be 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -69,26 +69,22 @@ static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL; static DEG_EditorUpdateScenePreCb deg_editor_update_scene_pre_cb = NULL; Depsgraph::Depsgraph() - : root_node(NULL), + : time_source(NULL), need_update(false), layers(0) { BLI_spin_init(&lock); id_hash = BLI_ghash_ptr_new("Depsgraph id hash"); - subgraphs = BLI_gset_ptr_new("Depsgraph subgraphs"); entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags"); } Depsgraph::~Depsgraph() { - /* Free root node - it won't have been freed yet... */ clear_id_nodes(); - clear_subgraph_nodes(); BLI_ghash_free(id_hash, NULL, NULL); - BLI_gset_free(subgraphs, NULL); BLI_gset_free(entry_tags, NULL); - if (this->root_node != NULL) { - OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode); + if (time_source != NULL) { + OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode); } BLI_spin_end(&lock); } @@ -131,7 +127,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, bPoseChannel *pchan = (bPoseChannel *)ptr->data; /* Bone - generally, we just want the bone component... */ - *type = DEPSNODE_TYPE_BONE; + *type = DEG_NODE_TYPE_BONE; *subdata = pchan->name; return true; @@ -141,7 +137,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, /* armature-level bone, but it ends up going to bone component anyway */ // TODO: the ID in thise case will end up being bArmature, not Object as needed! - *type = DEPSNODE_TYPE_BONE; + *type = DEG_NODE_TYPE_BONE; *subdata = bone->name; //*id = ... @@ -155,7 +151,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, if (BLI_findindex(&ob->constraints, con) != -1) { /* object transform */ // XXX: for now, we can't address the specific constraint or the constraint stack... - *type = DEPSNODE_TYPE_TRANSFORM; + *type = DEG_NODE_TYPE_TRANSFORM; return true; } else if (ob->pose) { @@ -163,7 +159,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (BLI_findindex(&pchan->constraints, con) != -1) { /* bone transforms */ - *type = DEPSNODE_TYPE_BONE; + *type = DEG_NODE_TYPE_BONE; *subdata = pchan->name; return true; } @@ -178,7 +174,7 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, * so although we have unique ops for modifiers, * we can't lump them together */ - *type = DEPSNODE_TYPE_BONE; + *type = DEG_NODE_TYPE_BONE; //*subdata = md->name; return true; @@ -195,14 +191,14 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, strstr(prop_identifier, "scale") || strstr(prop_identifier, "matrix_")) { - *type = DEPSNODE_TYPE_TRANSFORM; + *type = DEG_NODE_TYPE_TRANSFORM; return true; } else if (strstr(prop_identifier, "data")) { /* We access object.data, most likely a geometry. * Might be a bone tho.. */ - *type = DEPSNODE_TYPE_GEOMETRY; + *type = DEG_NODE_TYPE_GEOMETRY; return true; } } @@ -212,21 +208,21 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr, /* ShapeKeys are currently handled as geometry on the geometry that owns it */ *id = key->from; // XXX - *type = DEPSNODE_TYPE_PARAMETERS; + *type = DEG_NODE_TYPE_PARAMETERS; return true; } else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) { Sequence *seq = (Sequence *)ptr->data; /* Sequencer strip */ - *type = DEPSNODE_TYPE_SEQUENCER; + *type = DEG_NODE_TYPE_SEQUENCER; *subdata = seq->name; // xxx? return true; } if (prop) { /* All unknown data effectively falls under "parameter evaluation" */ - *type = DEPSNODE_TYPE_PARAMETERS; + *type = DEG_NODE_TYPE_PARAMETERS; return true; } @@ -263,72 +259,18 @@ static void id_node_deleter(void *value) OBJECT_GUARDED_DELETE(id_node, IDDepsNode); } -RootDepsNode *Depsgraph::add_root_node() +TimeSourceDepsNode *Depsgraph::add_time_source() { - if (!root_node) { - DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_ROOT); - root_node = (RootDepsNode *)factory->create_node(NULL, "", "Root (Scene)"); + if (time_source == NULL) { + DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_TIMESOURCE); + time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", "Time Source"); } - return root_node; + return time_source; } -TimeSourceDepsNode *Depsgraph::find_time_source(const ID *id) const +TimeSourceDepsNode *Depsgraph::find_time_source() const { - /* Search for one attached to a particular ID? */ - if (id) { - /* Check if it was added as a component - * (as may be done for subgraphs needing timeoffset). - */ - IDDepsNode *id_node = find_id_node(id); - if (id_node) { - // XXX: review this -// return id_node->find_component(DEPSNODE_TYPE_TIMESOURCE); - } - BLI_assert(!"Not implemented yet"); - } - else { - /* Use "official" timesource. */ - return root_node->time_source; - } - return NULL; -} - -SubgraphDepsNode *Depsgraph::add_subgraph_node(const ID *id) -{ - DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_SUBGRAPH); - SubgraphDepsNode *subgraph_node = - (SubgraphDepsNode *)factory->create_node(id, "", id->name + 2); - - /* Add to subnodes list. */ - BLI_gset_insert(subgraphs, subgraph_node); - - /* if there's an ID associated, add to ID-nodes lookup too */ - if (id) { -#if 0 - /* XXX subgraph node is NOT a true IDDepsNode - what is this supposed to do? */ - // TODO: what to do if subgraph's ID has already been added? - BLI_assert(!graph->find_id_node(id)); - graph->id_hash[id] = this; -#endif - } - - return subgraph_node; -} - -void Depsgraph::remove_subgraph_node(SubgraphDepsNode *subgraph_node) -{ - BLI_gset_remove(subgraphs, subgraph_node, NULL); - OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode); -} - -void Depsgraph::clear_subgraph_nodes() -{ - GSET_FOREACH_BEGIN(SubgraphDepsNode *, subgraph_node, subgraphs) - { - OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode); - } - GSET_FOREACH_END(); - BLI_gset_clear(subgraphs, NULL); + return time_source; } IDDepsNode *Depsgraph::find_id_node(const ID *id) const @@ -340,7 +282,7 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name) { IDDepsNode *id_node = find_id_node(id); if (!id_node) { - DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_ID_REF); + DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_ID_REF); id_node = (IDDepsNode *)factory->create_node(id, "", name); id->tag |= LIB_TAG_DOIT; /* register */ @@ -349,16 +291,6 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name) return id_node; } -void Depsgraph::remove_id_node(const ID *id) -{ - IDDepsNode *id_node = find_id_node(id); - if (id_node) { - /* unregister */ - BLI_ghash_remove(id_hash, id, NULL, NULL); - OBJECT_GUARDED_DELETE(id_node, IDDepsNode); - } -} - void Depsgraph::clear_id_nodes() { BLI_ghash_clear(id_hash, NULL, id_node_deleter); @@ -367,15 +299,14 @@ void Depsgraph::clear_id_nodes() /* Add new relationship between two nodes. */ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from, OperationDepsNode *to, - eDepsRelation_Type type, const char *description) { /* Create new relation, and add it to the graph. */ - DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description); + DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description); /* TODO(sergey): Find a better place for this. */ #ifdef WITH_OPENSUBDIV ComponentDepsNode *comp_node = from->owner; - if (comp_node->type == DEPSNODE_TYPE_GEOMETRY) { + if (comp_node->type == DEG_NODE_TYPE_GEOMETRY) { IDDepsNode *id_to = to->owner->owner; IDDepsNode *id_from = from->owner->owner; if (id_to != id_from && (id_to->id->tag & LIB_TAG_ID_RECALC_ALL)) { @@ -391,11 +322,10 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from, /* Add new relation between two nodes */ DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to, - eDepsRelation_Type type, const char *description) { /* Create new relation, and add it to the graph. */ - DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, type, description); + DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description); return rel; } @@ -404,12 +334,10 @@ DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to, DepsRelation::DepsRelation(DepsNode *from, DepsNode *to, - eDepsRelation_Type type, const char *description) : from(from), to(to), name(description), - type(type), flag(0) { #ifndef NDEBUG @@ -472,11 +400,10 @@ void Depsgraph::add_entry_tag(OperationDepsNode *node) void Depsgraph::clear_all_nodes() { clear_id_nodes(); - clear_subgraph_nodes(); BLI_ghash_clear(id_hash, NULL, NULL); - if (this->root_node) { - OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode); - root_node = NULL; + if (time_source != NULL) { + OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode); + time_source = NULL; } } diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index e668facd645..f72f8dd9311 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -49,10 +49,8 @@ struct PropertyRNA; namespace DEG { struct DepsNode; -struct RootDepsNode; struct TimeSourceDepsNode; struct IDDepsNode; -struct SubgraphDepsNode; struct ComponentDepsNode; struct OperationDepsNode; @@ -79,12 +77,10 @@ struct DepsRelation { /* relationship attributes */ const char *name; /* label for debugging */ - eDepsRelation_Type type; /* type */ int flag; /* (eDepsRelation_Flag) */ DepsRelation(DepsNode *from, DepsNode *to, - eDepsRelation_Type type, const char *description); ~DepsRelation(); @@ -111,28 +107,20 @@ struct Depsgraph { */ DepsNode *find_node_from_pointer(const PointerRNA *ptr, const PropertyRNA *prop) const; - RootDepsNode *add_root_node(); - - TimeSourceDepsNode *find_time_source(const ID *id = NULL) const; - - SubgraphDepsNode *add_subgraph_node(const ID *id); - void remove_subgraph_node(SubgraphDepsNode *subgraph_node); - void clear_subgraph_nodes(); + TimeSourceDepsNode *add_time_source(); + TimeSourceDepsNode *find_time_source() const; IDDepsNode *find_id_node(const ID *id) const; IDDepsNode *add_id_node(ID *id, const char *name = ""); - void remove_id_node(const ID *id); void clear_id_nodes(); /* Add new relationship between two nodes. */ DepsRelation *add_new_relation(OperationDepsNode *from, OperationDepsNode *to, - eDepsRelation_Type type, const char *description); DepsRelation *add_new_relation(DepsNode *from, DepsNode *to, - eDepsRelation_Type type, const char *description); /* Tag a specific node as needing updates. */ @@ -147,11 +135,8 @@ struct Depsgraph { * (for quick lookups). */ GHash *id_hash; - /* "root" node - the one where all evaluation enters from. */ - RootDepsNode *root_node; - - /* Subgraphs referenced in tree. */ - GSet *subgraphs; + /* Top-level time source node. */ + TimeSourceDepsNode *time_source; /* Indicates whether relations needs to be updated. */ bool need_update; diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index 3a69469053c..47bf5e7ecbb 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -34,12 +34,6 @@ // #define DEBUG_TIME -extern "C" { -#include "DNA_cachefile_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_object_force.h" - #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -48,17 +42,22 @@ extern "C" { # include "PIL_time_utildefines.h" #endif +extern "C" { +#include "DNA_cachefile_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_force.h" + #include "BKE_main.h" #include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_modifier.h" +} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" #include "DEG_depsgraph_build.h" -} /* extern "C" */ - #include "builder/deg_builder.h" #include "builder/deg_builder_cycle.h" #include "builder/deg_builder_nodes.h" @@ -81,29 +80,29 @@ static DEG::eDepsNode_Type deg_build_scene_component_type( eDepsSceneComponentType component) { switch (component) { - case DEG_SCENE_COMP_PARAMETERS: return DEG::DEPSNODE_TYPE_PARAMETERS; - case DEG_SCENE_COMP_ANIMATION: return DEG::DEPSNODE_TYPE_ANIMATION; - case DEG_SCENE_COMP_SEQUENCER: return DEG::DEPSNODE_TYPE_SEQUENCER; + case DEG_SCENE_COMP_PARAMETERS: return DEG::DEG_NODE_TYPE_PARAMETERS; + case DEG_SCENE_COMP_ANIMATION: return DEG::DEG_NODE_TYPE_ANIMATION; + case DEG_SCENE_COMP_SEQUENCER: return DEG::DEG_NODE_TYPE_SEQUENCER; } - return DEG::DEPSNODE_TYPE_UNDEFINED; + return DEG::DEG_NODE_TYPE_UNDEFINED; } static DEG::eDepsNode_Type deg_build_object_component_type( eDepsObjectComponentType component) { switch (component) { - case DEG_OB_COMP_PARAMETERS: return DEG::DEPSNODE_TYPE_PARAMETERS; - case DEG_OB_COMP_PROXY: return DEG::DEPSNODE_TYPE_PROXY; - case DEG_OB_COMP_ANIMATION: return DEG::DEPSNODE_TYPE_ANIMATION; - case DEG_OB_COMP_TRANSFORM: return DEG::DEPSNODE_TYPE_TRANSFORM; - case DEG_OB_COMP_GEOMETRY: return DEG::DEPSNODE_TYPE_GEOMETRY; - case DEG_OB_COMP_EVAL_POSE: return DEG::DEPSNODE_TYPE_EVAL_POSE; - case DEG_OB_COMP_BONE: return DEG::DEPSNODE_TYPE_BONE; - case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEPSNODE_TYPE_EVAL_PARTICLES; - case DEG_OB_COMP_SHADING: return DEG::DEPSNODE_TYPE_SHADING; - case DEG_OB_COMP_CACHE: return DEG::DEPSNODE_TYPE_CACHE; + case DEG_OB_COMP_PARAMETERS: return DEG::DEG_NODE_TYPE_PARAMETERS; + case DEG_OB_COMP_PROXY: return DEG::DEG_NODE_TYPE_PROXY; + case DEG_OB_COMP_ANIMATION: return DEG::DEG_NODE_TYPE_ANIMATION; + case DEG_OB_COMP_TRANSFORM: return DEG::DEG_NODE_TYPE_TRANSFORM; + case DEG_OB_COMP_GEOMETRY: return DEG::DEG_NODE_TYPE_GEOMETRY; + case DEG_OB_COMP_EVAL_POSE: return DEG::DEG_NODE_TYPE_EVAL_POSE; + case DEG_OB_COMP_BONE: return DEG::DEG_NODE_TYPE_BONE; + case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEG_NODE_TYPE_EVAL_PARTICLES; + case DEG_OB_COMP_SHADING: return DEG::DEG_NODE_TYPE_SHADING; + case DEG_OB_COMP_CACHE: return DEG::DEG_NODE_TYPE_CACHE; } - return DEG::DEPSNODE_TYPE_UNDEFINED; + return DEG::DEG_NODE_TYPE_UNDEFINED; } static DEG::DepsNodeHandle *get_handle(DepsNodeHandle *handle) @@ -121,7 +120,6 @@ void DEG_add_scene_relation(DepsNodeHandle *handle, DEG::DepsNodeHandle *deg_handle = get_handle(handle); deg_handle->builder->add_node_handle_relation(comp_key, deg_handle, - DEG::DEPSREL_TYPE_GEOMETRY_EVAL, description); } @@ -135,7 +133,6 @@ void DEG_add_object_relation(DepsNodeHandle *handle, DEG::DepsNodeHandle *deg_handle = get_handle(handle); deg_handle->builder->add_node_handle_relation(comp_key, deg_handle, - DEG::DEPSREL_TYPE_GEOMETRY_EVAL, description); } @@ -149,7 +146,6 @@ void DEG_add_object_cache_relation(DepsNodeHandle *handle, DEG::DepsNodeHandle *deg_handle = get_handle(handle); deg_handle->builder->add_node_handle_relation(comp_key, deg_handle, - DEG::DEPSREL_TYPE_CACHE, description); } @@ -167,10 +163,16 @@ void DEG_add_bone_relation(DepsNodeHandle *handle, */ deg_handle->builder->add_node_handle_relation(comp_key, deg_handle, - DEG::DEPSREL_TYPE_GEOMETRY_EVAL, description); } +struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *handle) +{ + DEG::DepsNodeHandle *deg_handle = get_handle(handle); + DEG::DepsgraphRelationBuilder *relation_builder = deg_handle->builder; + return reinterpret_cast<Depsgraph *>(relation_builder->getGraph()); +} + void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag) { DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph); @@ -205,30 +207,14 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene) /* 1) Generate all the nodes in the graph first */ DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph); - /* create root node for scene first - * - this way it should be the first in the graph, - * reflecting its role as the entrypoint - */ node_builder.begin_build(bmain); - node_builder.add_root_node(); node_builder.build_scene(bmain, scene); /* 2) Hook up relationships between operations - to determine evaluation * order. */ DEG::DepsgraphRelationBuilder relation_builder(deg_graph); - /* Hook scene up to the root node as entrypoint to graph. */ - /* XXX what does this relation actually mean? - * it doesnt add any operations anyway and is not clear what part of the - * scene is to be connected. - */ relation_builder.begin_build(bmain); -#if 0 - relation_builder.add_relation(RootKey(), - IDKey(scene), - DEPSREL_TYPE_ROOT_TO_ACTIVE, - "Root to Active Scene"); -#endif relation_builder.build_scene(bmain, scene); /* Detect and solve cycles. */ diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc index d3b48930779..388b692d742 100644 --- a/source/blender/depsgraph/intern/depsgraph_debug.cc +++ b/source/blender/depsgraph/intern/depsgraph_debug.cc @@ -35,11 +35,11 @@ extern "C" { #include "DNA_scene_types.h" +} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" #include "DEG_depsgraph_build.h" -} /* extern "C" */ #include "intern/eval/deg_eval_debug.h" #include "intern/depsgraph_intern.h" @@ -165,7 +165,7 @@ bool DEG_debug_consistency_check(Depsgraph *graph) return false; } foreach (DEG::DepsRelation *rel, node->outlinks) { - if (rel->to->type == DEG::DEPSNODE_TYPE_OPERATION) { + if (rel->to->type == DEG::DEG_NODE_TYPE_OPERATION) { DEG::OperationDepsNode *to = (DEG::OperationDepsNode *)rel->to; BLI_assert(to->num_links_pending < to->inlinks.size()); ++to->num_links_pending; @@ -177,7 +177,7 @@ bool DEG_debug_consistency_check(Depsgraph *graph) foreach (DEG::OperationDepsNode *node, deg_graph->operations) { int num_links_pending = 0; foreach (DEG::DepsRelation *rel, node->inlinks) { - if (rel->from->type == DEG::DEPSNODE_TYPE_OPERATION) { + if (rel->from->type == DEG::DEG_NODE_TYPE_OPERATION) { ++num_links_pending; } } @@ -232,7 +232,7 @@ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer, } GHASH_FOREACH_END(); - DEG::TimeSourceDepsNode *time_source = deg_graph->find_time_source(NULL); + DEG::TimeSourceDepsNode *time_source = deg_graph->find_time_source(); if (time_source != NULL) { tot_rels += time_source->inlinks.size(); } diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc index c41f28b07e8..85a0d336d28 100644 --- a/source/blender/depsgraph/intern/depsgraph_eval.cc +++ b/source/blender/depsgraph/intern/depsgraph_eval.cc @@ -32,17 +32,17 @@ #include "MEM_guardedalloc.h" -extern "C" { -#include "DNA_scene_types.h" - #include "BLI_utildefines.h" #include "BLI_ghash.h" +extern "C" { +#include "DNA_scene_types.h" + #include "BKE_depsgraph.h" #include "BKE_scene.h" +} /* extern "C" */ #include "DEG_depsgraph.h" -} /* extern "C" */ #include "intern/eval/deg_eval.h" #include "intern/eval/deg_eval_flush.h" diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 7f2f6a65f5e..e58a7a32407 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -35,9 +35,9 @@ extern "C" { #include "BKE_idcode.h" #include "BKE_main.h" +} /* extern "C" */ #include "DEG_depsgraph_query.h" -} /* extern "C" */ #include "intern/depsgraph_intern.h" diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index cfc9005a1e3..31b4bbc7950 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -34,15 +34,16 @@ #include <cstring> /* required for memset */ #include <queue> -extern "C" { #include "BLI_utildefines.h" +#include "BLI_task.h" +#include "BLI_listbase.h" +extern "C" { #include "DNA_object_types.h" #include "DNA_particle_types.h" #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" -#include "BLI_task.h" #include "BKE_idcode.h" #include "BKE_library.h" @@ -52,9 +53,9 @@ extern "C" { #define new new_ #include "BKE_screen.h" #undef new +} /* extern "C" */ #include "DEG_depsgraph.h" -} /* extern "C" */ #include "intern/builder/deg_builder.h" #include "intern/eval/deg_eval_flush.h" @@ -336,7 +337,7 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene) { id_node->tag_update(graph); DEG::ComponentDepsNode *anim_comp = - id_node->find_component(DEG::DEPSNODE_TYPE_ANIMATION); + id_node->find_component(DEG::DEG_NODE_TYPE_ANIMATION); if (anim_comp != NULL && object->recalc & OB_RECALC_TIME) { anim_comp->tag_update(graph); } @@ -356,6 +357,10 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene) Object *object = base->object; DEG::IDDepsNode *id_node = graph->find_id_node(&object->id); id_node->layers |= base->lay; + if (object == scene->camera) { + /* Camera should always be updated, it used directly by viewport. */ + id_node->layers |= (unsigned int)(-1); + } } DEG::deg_graph_build_flush_layers(graph); LINKLIST_FOREACH (Base *, base, &scene->base) { diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc index 39c189629f2..e5033affe2f 100644 --- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc +++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc @@ -32,12 +32,11 @@ #include <cstdlib> // for BLI_assert() -extern "C" { + #include "BLI_utildefines.h" #include "BLI_ghash.h" #include "DEG_depsgraph.h" -} /* extern "C" */ #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" @@ -98,23 +97,17 @@ static const char *stringify_opcode(eDepsOperation_Code opcode) #define STRINGIFY_OPCODE(name) case DEG_OPCODE_##name: return #name STRINGIFY_OPCODE(OPERATION); STRINGIFY_OPCODE(PLACEHOLDER); - STRINGIFY_OPCODE(NOOP); STRINGIFY_OPCODE(ANIMATION); STRINGIFY_OPCODE(DRIVER); - //STRINGIFY_OPCODE(PROXY); STRINGIFY_OPCODE(TRANSFORM_LOCAL); STRINGIFY_OPCODE(TRANSFORM_PARENT); STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS); - //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS_INIT); - //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINT); - //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS_DONE); STRINGIFY_OPCODE(RIGIDBODY_REBUILD); STRINGIFY_OPCODE(RIGIDBODY_SIM); STRINGIFY_OPCODE(TRANSFORM_RIGIDBODY); STRINGIFY_OPCODE(TRANSFORM_FINAL); STRINGIFY_OPCODE(OBJECT_UBEREVAL); STRINGIFY_OPCODE(GEOMETRY_UBEREVAL); - STRINGIFY_OPCODE(GEOMETRY_MODIFIER); STRINGIFY_OPCODE(GEOMETRY_PATH); STRINGIFY_OPCODE(POSE_INIT); STRINGIFY_OPCODE(POSE_DONE); @@ -123,12 +116,10 @@ static const char *stringify_opcode(eDepsOperation_Code opcode) STRINGIFY_OPCODE(BONE_LOCAL); STRINGIFY_OPCODE(BONE_POSE_PARENT); STRINGIFY_OPCODE(BONE_CONSTRAINTS); - //STRINGIFY_OPCODE(BONE_CONSTRAINTS_INIT); - //STRINGIFY_OPCODE(BONE_CONSTRAINT); - //STRINGIFY_OPCODE(BONE_CONSTRAINTS_DONE); STRINGIFY_OPCODE(BONE_READY); STRINGIFY_OPCODE(BONE_DONE); STRINGIFY_OPCODE(PSYS_EVAL); + STRINGIFY_OPCODE(PSYS_EVAL_INIT); case DEG_NUM_OPCODES: return "SpecialCase"; #undef STRINGIFY_OPCODE diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h index c9c4329769d..f05f82caa3d 100644 --- a/source/blender/depsgraph/intern/depsgraph_types.h +++ b/source/blender/depsgraph/intern/depsgraph_types.h @@ -67,74 +67,66 @@ typedef enum eDepsNode_Class { /* Types generally unassociated with user-visible entities, * but needed for graph functioning. */ - DEPSNODE_CLASS_GENERIC = 0, + DEG_NODE_CLASS_GENERIC = 0, /* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring * certain types of evaluation behavior. */ - DEPSNODE_CLASS_COMPONENT = 1, + DEG_NODE_CLASS_COMPONENT = 1, /* [Inner Node] A glorified function-pointer/callback for scheduling up * evaluation operations for components, subject to relationship * requirements. */ - DEPSNODE_CLASS_OPERATION = 2, + DEG_NODE_CLASS_OPERATION = 2, } eDepsNode_Class; /* Types of Nodes */ typedef enum eDepsNode_Type { /* Fallback type for invalid return value */ - DEPSNODE_TYPE_UNDEFINED = -1, + DEG_NODE_TYPE_UNDEFINED = -1, /* Inner Node (Operation) */ - DEPSNODE_TYPE_OPERATION = 0, + DEG_NODE_TYPE_OPERATION = 0, /* **** Generic Types **** */ - /* "Current Scene" - basically whatever kicks off the evaluation process. */ - DEPSNODE_TYPE_ROOT, /* Time-Source */ - DEPSNODE_TYPE_TIMESOURCE, + DEG_NODE_TYPE_TIMESOURCE, /* ID-Block reference - used as landmarks/collection point for components, * but not usually part of main graph. */ - DEPSNODE_TYPE_ID_REF, - /* Isolated sub-graph - used for keeping instanced data separate from - * instances using them. - */ - DEPSNODE_TYPE_SUBGRAPH, + DEG_NODE_TYPE_ID_REF, /* **** Outer Types **** */ /* Parameters Component - Default when nothing else fits * (i.e. just SDNA property setting). */ - DEPSNODE_TYPE_PARAMETERS, - /* Generic "Proxy-Inherit" Component - * XXX: Also for instancing of subgraphs? - */ - DEPSNODE_TYPE_PROXY, + DEG_NODE_TYPE_PARAMETERS, + /* Generic "Proxy-Inherit" Component. */ + DEG_NODE_TYPE_PROXY, /* Animation Component * * XXX: merge in with parameters? */ - DEPSNODE_TYPE_ANIMATION, + DEG_NODE_TYPE_ANIMATION, /* Transform Component (Parenting/Constraints) */ - DEPSNODE_TYPE_TRANSFORM, + DEG_NODE_TYPE_TRANSFORM, /* Geometry Component (DerivedMesh/Displist) */ - DEPSNODE_TYPE_GEOMETRY, + DEG_NODE_TYPE_GEOMETRY, /* Sequencer Component (Scene Only) */ - DEPSNODE_TYPE_SEQUENCER, + DEG_NODE_TYPE_SEQUENCER, /* **** Evaluation-Related Outer Types (with Subdata) **** */ /* Pose Component - Owner/Container of Bones Eval */ - DEPSNODE_TYPE_EVAL_POSE, + DEG_NODE_TYPE_EVAL_POSE, /* Bone Component - Child/Subcomponent of Pose */ - DEPSNODE_TYPE_BONE, + DEG_NODE_TYPE_BONE, /* Particle Systems Component */ - DEPSNODE_TYPE_EVAL_PARTICLES, + DEG_NODE_TYPE_EVAL_PARTICLES, /* Material Shading Component */ - DEPSNODE_TYPE_SHADING, + DEG_NODE_TYPE_SHADING, /* Cache Component */ - DEPSNODE_TYPE_CACHE, + DEG_NODE_TYPE_CACHE, } eDepsNode_Type; /* Identifiers for common operations (as an enum). */ @@ -147,8 +139,6 @@ typedef enum eDepsOperation_Code { // XXX: Placeholder while porting depsgraph code DEG_OPCODE_PLACEHOLDER, - DEG_OPCODE_NOOP, - /* Animation, Drivers, etc. ------------------------ */ /* NLA + Action */ @@ -157,9 +147,6 @@ typedef enum eDepsOperation_Code { /* Driver */ DEG_OPCODE_DRIVER, - /* Proxy Inherit? */ - //DEG_OPCODE_PROXY, - /* Transform --------------------------------------- */ /* Transform entry point - local transforms only */ @@ -170,9 +157,6 @@ typedef enum eDepsOperation_Code { /* Constraints */ DEG_OPCODE_TRANSFORM_CONSTRAINTS, - //DEG_OPCODE_TRANSFORM_CONSTRAINTS_INIT, - //DEG_OPCODE_TRANSFORM_CONSTRAINT, - //DEG_OPCODE_TRANSFORM_CONSTRAINTS_DONE, /* Rigidbody Sim - Perform Sim */ DEG_OPCODE_RIGIDBODY_REBUILD, @@ -192,9 +176,6 @@ typedef enum eDepsOperation_Code { /* XXX: Placeholder - UberEval */ DEG_OPCODE_GEOMETRY_UBEREVAL, - /* Modifier */ - DEG_OPCODE_GEOMETRY_MODIFIER, - /* Curve Objects - Path Calculation (used for path-following tools, */ DEG_OPCODE_GEOMETRY_PATH, @@ -220,9 +201,6 @@ typedef enum eDepsOperation_Code { /* Constraints */ DEG_OPCODE_BONE_CONSTRAINTS, - //DEG_OPCODE_BONE_CONSTRAINTS_INIT, - //DEG_OPCODE_BONE_CONSTRAINT, - //DEG_OPCODE_BONE_CONSTRAINTS_DONE, /* Bone transforms are ready * @@ -241,6 +219,7 @@ typedef enum eDepsOperation_Code { /* Particles --------------------------------------- */ /* XXX: placeholder - Particle System eval */ + DEG_OPCODE_PSYS_EVAL_INIT, DEG_OPCODE_PSYS_EVAL, DEG_NUM_OPCODES, @@ -258,83 +237,4 @@ protected: /* String defines for these opcodes, defined in depsgraph_type_defines.cpp */ extern DepsOperationStringifier DEG_OPNAMES; -/* Type of operation */ -typedef enum eDepsOperation_Type { - /* **** Primary operation types **** */ - - /* Initialise evaluation data */ - DEPSOP_TYPE_INIT = 0, - /* Standard evaluation step */ - DEPSOP_TYPE_EXEC = 1, - /* Cleanup evaluation data + flush results */ - DEPSOP_TYPE_POST = 2, - - /* **** Additional operation types **** */ - /* Indicator for outputting a temporary result that other components - * can use. // XXX? - */ - DEPSOP_TYPE_OUT = 3, - /* Indicator for things like IK Solvers and Rigidbody Sim steps which - * modify final results of separate entities at once. - */ - DEPSOP_TYPE_SIM = 4, - /* Rebuild internal evaluation data - used for Rigidbody Reset and - * Armature Rebuild-On-Load. - */ - DEPSOP_TYPE_REBUILD = 5, -} eDepsOperation_Type; - -/* Types of relationships between nodes - * - * This is used to provide additional hints to use when filtering - * the graph, so that we can go without doing more extensive - * data-level checks... - */ -typedef enum eDepsRelation_Type { - /* relationship type unknown/irrelevant */ - DEPSREL_TYPE_STANDARD = 0, - - /* root -> active scene or entity (screen, image, etc.) */ - DEPSREL_TYPE_ROOT_TO_ACTIVE, - - /* general datablock dependency */ - DEPSREL_TYPE_DATABLOCK, - - /* time dependency */ - DEPSREL_TYPE_TIME, - - /* component depends on results of another */ - DEPSREL_TYPE_COMPONENT_ORDER, - - /* relationship is just used to enforce ordering of operations - * (e.g. "init()" callback done before "exec() and "cleanup()") - */ - DEPSREL_TYPE_OPERATION, - - /* relationship results from a property driver affecting property */ - DEPSREL_TYPE_DRIVER, - - /* relationship is something driver depends on */ - DEPSREL_TYPE_DRIVER_TARGET, - - /* relationship is used for transform stack - * (e.g. parenting, user transforms, constraints) - */ - DEPSREL_TYPE_TRANSFORM, - - /* relationship is used for geometry evaluation - * (e.g. metaball "motherball" or modifiers) - */ - DEPSREL_TYPE_GEOMETRY_EVAL, - - /* relationship is used to trigger a post-change validity updates */ - DEPSREL_TYPE_UPDATE, - - /* relationship is used to trigger editor/screen updates */ - DEPSREL_TYPE_UPDATE_UI, - - /* cache dependency */ - DEPSREL_TYPE_CACHE, -} eDepsRelation_Type; - } // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index e739bc9dbb5..98b10718404 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -34,16 +34,16 @@ #include "PIL_time.h" -extern "C" { #include "BLI_utildefines.h" #include "BLI_task.h" #include "BLI_ghash.h" +extern "C" { #include "BKE_depsgraph.h" #include "BKE_global.h" +} /* extern "C" */ #include "DEG_depsgraph.h" -} /* extern "C" */ #include "atomic_ops.h" @@ -126,7 +126,9 @@ static void deg_task_run_func(TaskPool *pool, #endif } + BLI_task_pool_delayed_push_begin(pool, thread_id); schedule_children(pool, state->graph, node, state->layers, thread_id); + BLI_task_pool_delayed_push_end(pool, thread_id); } typedef struct CalculatePengindData { @@ -150,7 +152,7 @@ static void calculate_pending_func(void *data_v, int i) (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0) { foreach (DepsRelation *rel, node->inlinks) { - if (rel->from->type == DEPSNODE_TYPE_OPERATION && + if (rel->from->type == DEG_NODE_TYPE_OPERATION && (rel->flag & DEPSREL_FLAG_CYCLIC) == 0) { OperationDepsNode *from = (OperationDepsNode *)rel->from; @@ -195,7 +197,7 @@ static void calculate_eval_priority(OperationDepsNode *node) foreach (DepsRelation *rel, node->outlinks) { OperationDepsNode *to = (OperationDepsNode *)rel->to; - BLI_assert(to->type == DEPSNODE_TYPE_OPERATION); + BLI_assert(to->type == DEG_NODE_TYPE_OPERATION); calculate_eval_priority(to); node->eval_priority += to->eval_priority; } @@ -263,7 +265,7 @@ static void schedule_children(TaskPool *pool, { foreach (DepsRelation *rel, node->outlinks) { OperationDepsNode *child = (OperationDepsNode *)rel->to; - BLI_assert(child->type == DEPSNODE_TYPE_OPERATION); + BLI_assert(child->type == DEG_NODE_TYPE_OPERATION); if (child->scheduled) { /* Happens when having cyclic dependencies. */ continue; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_debug.cc b/source/blender/depsgraph/intern/eval/deg_eval_debug.cc index 060544a4407..23f4adbaacd 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_debug.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_debug.cc @@ -34,16 +34,16 @@ #include <cstring> /* required for STREQ later on. */ -extern "C" { #include "BLI_listbase.h" #include "BLI_ghash.h" -#include "DEG_depsgraph_debug.h" - +extern "C" { #include "WM_api.h" #include "WM_types.h" } /* extern "C" */ +#include "DEG_depsgraph_debug.h" + #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index e10f86f6e95..c230ab4c8fd 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -35,16 +35,16 @@ // TODO(sergey): Use some sort of wrapper. #include <deque> -extern "C" { -#include "DNA_object_types.h" - #include "BLI_utildefines.h" #include "BLI_task.h" #include "BLI_ghash.h" -#include "DEG_depsgraph.h" +extern "C" { +#include "DNA_object_types.h" } /* extern "C" */ +#include "DEG_depsgraph.h" + #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" @@ -139,18 +139,18 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) IDDepsNode *id_node = comp_node->owner; ID *id = id_node->id; - if(id_node->done == 0) { + if (id_node->done == 0) { deg_editors_id_update(bmain, id); lib_id_recalc_tag(bmain, id); /* TODO(sergey): For until we've got proper data nodes in the graph. */ lib_id_recalc_data_tag(bmain, id); } - if(comp_node->done == 0) { + if (comp_node->done == 0) { Object *object = NULL; if (GS(id->name) == ID_OB) { object = (Object *)id; - if(id_node->done == 0) { + if (id_node->done == 0) { ++num_flushed_objects; } } @@ -164,14 +164,30 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) * Plus it ensures visibility changes and relations and * layers visibility update has proper flags to work with. */ - if (comp_node->type == DEPSNODE_TYPE_ANIMATION) { - object->recalc |= OB_RECALC_TIME; - } - else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) { - object->recalc |= OB_RECALC_OB; - } - else { - object->recalc |= OB_RECALC_DATA; + switch (comp_node->type) { + case DEG_NODE_TYPE_UNDEFINED: + case DEG_NODE_TYPE_OPERATION: + case DEG_NODE_TYPE_TIMESOURCE: + case DEG_NODE_TYPE_ID_REF: + case DEG_NODE_TYPE_PARAMETERS: + case DEG_NODE_TYPE_SEQUENCER: + /* Ignore, does not translate to object component. */ + break; + case DEG_NODE_TYPE_ANIMATION: + object->recalc |= OB_RECALC_TIME; + break; + case DEG_NODE_TYPE_TRANSFORM: + object->recalc |= OB_RECALC_OB; + break; + case DEG_NODE_TYPE_GEOMETRY: + case DEG_NODE_TYPE_EVAL_POSE: + case DEG_NODE_TYPE_BONE: + case DEG_NODE_TYPE_EVAL_PARTICLES: + case DEG_NODE_TYPE_SHADING: + case DEG_NODE_TYPE_CACHE: + case DEG_NODE_TYPE_PROXY: + object->recalc |= OB_RECALC_DATA; + break; } } } diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc index 57b25c10670..a15317586c1 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node.cc @@ -41,15 +41,14 @@ extern "C" { #include "DNA_anim_types.h" #include "BKE_animsys.h" +} #include "DEG_depsgraph.h" -} #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" #include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" -#include "util/deg_util_hash.h" namespace DEG { @@ -61,12 +60,12 @@ namespace DEG { DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname) { this->type = type; - if (type == DEPSNODE_TYPE_OPERATION) - this->tclass = DEPSNODE_CLASS_OPERATION; - else if (type < DEPSNODE_TYPE_PARAMETERS) - this->tclass = DEPSNODE_CLASS_GENERIC; + if (type == DEG_NODE_TYPE_OPERATION) + this->tclass = DEG_NODE_CLASS_OPERATION; + else if (type < DEG_NODE_TYPE_PARAMETERS) + this->tclass = DEG_NODE_CLASS_GENERIC; else - this->tclass = DEPSNODE_CLASS_COMPONENT; + this->tclass = DEG_NODE_CLASS_COMPONENT; this->tname = tname; } @@ -110,34 +109,9 @@ void TimeSourceDepsNode::tag_update(Depsgraph *graph) } } - -/* Root Node ============================================== */ - -RootDepsNode::RootDepsNode() : scene(NULL), time_source(NULL) -{ -} - -RootDepsNode::~RootDepsNode() -{ - OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode); -} - -TimeSourceDepsNode *RootDepsNode::add_time_source(const char *name) -{ - if (!time_source) { - DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_TIMESOURCE); - time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", name); - /*time_source->owner = this;*/ // XXX - } - return time_source; -} - -DEG_DEPSNODE_DEFINE(RootDepsNode, DEPSNODE_TYPE_ROOT, "Root DepsNode"); -static DepsNodeFactoryImpl<RootDepsNode> DNTI_ROOT; - /* Time Source Node ======================================= */ -DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEPSNODE_TYPE_TIMESOURCE, "Time Source"); +DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEG_NODE_TYPE_TIMESOURCE, "Time Source"); static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE; /* ID Node ================================================ */ @@ -158,8 +132,8 @@ static unsigned int id_deps_node_hash_key(const void *key_v) { const IDDepsNode::ComponentIDKey *key = reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v); - return hash_combine(BLI_ghashutil_uinthash(key->type), - BLI_ghashutil_strhash_p(key->name)); + return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->type), + BLI_ghashutil_strhash_p(key->name)); } static bool id_deps_node_hash_key_cmp(const void *a, const void *b) @@ -211,8 +185,9 @@ void IDDepsNode::init(const ID *id, const char *UNUSED(subdata)) /* Free 'id' node. */ IDDepsNode::~IDDepsNode() { - clear_components(); - BLI_ghash_free(components, id_deps_node_hash_key_free, NULL); + BLI_ghash_free(components, + id_deps_node_hash_key_free, + id_deps_node_hash_value_free); } ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type, @@ -238,33 +213,13 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type, return comp_node; } -void IDDepsNode::remove_component(eDepsNode_Type type, const char *name) -{ - ComponentDepsNode *comp_node = find_component(type, name); - if (comp_node) { - /* Unregister. */ - ComponentIDKey key(type, name); - BLI_ghash_remove(components, - &key, - id_deps_node_hash_key_free, - id_deps_node_hash_value_free); - } -} - -void IDDepsNode::clear_components() -{ - BLI_ghash_clear(components, - id_deps_node_hash_key_free, - id_deps_node_hash_value_free); -} - void IDDepsNode::tag_update(Depsgraph *graph) { GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components) { /* TODO(sergey): What about drievrs? */ - bool do_component_tag = comp_node->type != DEPSNODE_TYPE_ANIMATION; - if (comp_node->type == DEPSNODE_TYPE_ANIMATION) { + bool do_component_tag = comp_node->type != DEG_NODE_TYPE_ANIMATION; + if (comp_node->type == DEG_NODE_TYPE_ANIMATION) { AnimData *adt = BKE_animdata_from_id(id); /* Animation data might be null if relations are tagged for update. */ if (adt != NULL && (adt->recalc & ADT_RECALC_ANIM)) { @@ -287,46 +242,13 @@ void IDDepsNode::finalize_build() GHASH_FOREACH_END(); } -DEG_DEPSNODE_DEFINE(IDDepsNode, DEPSNODE_TYPE_ID_REF, "ID Node"); +DEG_DEPSNODE_DEFINE(IDDepsNode, DEG_NODE_TYPE_ID_REF, "ID Node"); static DepsNodeFactoryImpl<IDDepsNode> DNTI_ID_REF; -/* Subgraph Node ========================================== */ - -/* Initialize 'subgraph' node - from pointer data given. */ -void SubgraphDepsNode::init(const ID *id, const char *UNUSED(subdata)) -{ - /* Store ID-ref if provided. */ - this->root_id = (ID *)id; - - /* NOTE: graph will need to be added manually, - * as we don't have any way of passing this down. - */ -} - -/* Free 'subgraph' node */ -SubgraphDepsNode::~SubgraphDepsNode() -{ - /* Only free if graph not shared, of if this node is the first - * reference to it... - */ - // XXX: prune these flags a bit... - if ((this->flag & SUBGRAPH_FLAG_FIRSTREF) || !(this->flag & SUBGRAPH_FLAG_SHARED)) { - /* Free the referenced graph. */ - DEG_graph_free(reinterpret_cast< ::Depsgraph* >(graph)); - graph = NULL; - } -} - -DEG_DEPSNODE_DEFINE(SubgraphDepsNode, DEPSNODE_TYPE_SUBGRAPH, "Subgraph Node"); -static DepsNodeFactoryImpl<SubgraphDepsNode> DNTI_SUBGRAPH; - void deg_register_base_depsnodes() { - deg_register_node_typeinfo(&DNTI_ROOT); deg_register_node_typeinfo(&DNTI_TIMESOURCE); - deg_register_node_typeinfo(&DNTI_ID_REF); - deg_register_node_typeinfo(&DNTI_SUBGRAPH); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/nodes/deg_node.h b/source/blender/depsgraph/intern/nodes/deg_node.h index 7c2f53840b6..9f1b61faf24 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node.h +++ b/source/blender/depsgraph/intern/nodes/deg_node.h @@ -127,22 +127,6 @@ struct TimeSourceDepsNode : public DepsNode { DEG_DEPSNODE_DECLARE; }; -/* Root Node. */ -struct RootDepsNode : public DepsNode { - RootDepsNode(); - ~RootDepsNode(); - - TimeSourceDepsNode *add_time_source(const char *name = ""); - - /* scene that this corresponds to */ - Scene *scene; - - /* Entrypoint node for time-changed. */ - TimeSourceDepsNode *time_source; - - DEG_DEPSNODE_DECLARE; -}; - /* ID-Block Reference */ struct IDDepsNode : public DepsNode { struct ComponentIDKey { @@ -160,8 +144,6 @@ struct IDDepsNode : public DepsNode { const char *name = "") const; ComponentDepsNode *add_component(eDepsNode_Type type, const char *name = ""); - void remove_component(eDepsNode_Type type, const char *name = ""); - void clear_components(); void tag_update(Depsgraph *graph); @@ -185,41 +167,6 @@ struct IDDepsNode : public DepsNode { DEG_DEPSNODE_DECLARE; }; -/* Subgraph Reference. */ -struct SubgraphDepsNode : public DepsNode { - void init(const ID *id, const char *subdata); - ~SubgraphDepsNode(); - - /* Instanced graph. */ - Depsgraph *graph; - - /* ID-block at root of subgraph (if applicable). */ - ID *root_id; - - /* Number of nodes which use/reference this subgraph - if just 1, it may be - * possible to merge into main, - */ - size_t num_users; - - /* (eSubgraphRef_Flag) assorted settings for subgraph node. */ - int flag; - - DEG_DEPSNODE_DECLARE; -}; - -/* Flags for subgraph node */ -typedef enum eSubgraphRef_Flag { - /* Subgraph referenced is shared with another reference, so shouldn't - * free on exit. - */ - SUBGRAPH_FLAG_SHARED = (1 << 0), - - /* Node is first reference to subgraph, so it can be freed when we are - * removed. - */ - SUBGRAPH_FLAG_FIRSTREF = (1 << 1), -} eSubgraphRef_Flag; - void deg_register_base_depsnodes(); } // namespace DEG diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc index 06f91ac7fdc..e87c87813e3 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc @@ -33,9 +33,10 @@ #include <stdio.h> #include <cstring> /* required for STREQ later on. */ -extern "C" { #include "BLI_utildefines.h" +#include "BLI_ghash.h" +extern "C" { #include "DNA_object_types.h" #include "BKE_action.h" @@ -44,7 +45,6 @@ extern "C" { #include "intern/nodes/deg_node_operation.h" #include "intern/depsgraph_intern.h" #include "util/deg_util_foreach.h" -#include "util/deg_util_hash.h" namespace DEG { @@ -95,8 +95,8 @@ static unsigned int comp_node_hash_key(const void *key_v) { const ComponentDepsNode::OperationIDKey *key = reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v); - return hash_combine(BLI_ghashutil_uinthash(key->opcode), - BLI_ghashutil_strhash_p(key->name)); + return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->opcode), + BLI_ghashutil_strhash_p(key->name)); } static bool comp_node_hash_key_cmp(const void *a, const void *b) @@ -198,32 +198,20 @@ OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode, return has_operation(key); } -OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype, - DepsEvalOperationCb op, +OperationDepsNode *ComponentDepsNode::add_operation(const DepsEvalOperationCb& op, eDepsOperation_Code opcode, const char *name, int name_tag) { OperationDepsNode *op_node = has_operation(opcode, name, name_tag); if (!op_node) { - DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_OPERATION); + DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_OPERATION); op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name); /* register opnode in this component's operation set */ OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag); BLI_ghash_insert(operations_map, key, op_node); - /* set as entry/exit node of component (if appropriate) */ - if (optype == DEPSOP_TYPE_INIT) { - BLI_assert(this->entry_operation == NULL); - this->entry_operation = op_node; - } - else if (optype == DEPSOP_TYPE_POST) { - // XXX: review whether DEPSOP_TYPE_OUT is better than DEPSOP_TYPE_POST, or maybe have both? - BLI_assert(this->exit_operation == NULL); - this->exit_operation = op_node; - } - /* set backlink */ op_node->owner = this; } @@ -235,13 +223,24 @@ OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype, /* attach extra data */ op_node->evaluate = op; - op_node->optype = optype; op_node->opcode = opcode; op_node->name = name; return op_node; } +void ComponentDepsNode::set_entry_operation(OperationDepsNode *op_node) +{ + BLI_assert(entry_operation == NULL); + entry_operation = op_node; +} + +void ComponentDepsNode::set_exit_operation(OperationDepsNode *op_node) +{ + BLI_assert(exit_operation == NULL); + exit_operation = op_node; +} + void ComponentDepsNode::clear_operations() { if (operations_map != NULL) { @@ -336,37 +335,37 @@ void ComponentDepsNode::finalize_build() /* Parameter Component Defines ============================ */ -DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEPSNODE_TYPE_PARAMETERS, "Parameters Component"); +DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEG_NODE_TYPE_PARAMETERS, "Parameters Component"); static DepsNodeFactoryImpl<ParametersComponentDepsNode> DNTI_PARAMETERS; /* Animation Component Defines ============================ */ -DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEPSNODE_TYPE_ANIMATION, "Animation Component"); +DEG_DEPSNODE_DEFINE(AnimationComponentDepsNode, DEG_NODE_TYPE_ANIMATION, "Animation Component"); static DepsNodeFactoryImpl<AnimationComponentDepsNode> DNTI_ANIMATION; /* Transform Component Defines ============================ */ -DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEPSNODE_TYPE_TRANSFORM, "Transform Component"); +DEG_DEPSNODE_DEFINE(TransformComponentDepsNode, DEG_NODE_TYPE_TRANSFORM, "Transform Component"); static DepsNodeFactoryImpl<TransformComponentDepsNode> DNTI_TRANSFORM; /* Proxy Component Defines ================================ */ -DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEPSNODE_TYPE_PROXY, "Proxy Component"); +DEG_DEPSNODE_DEFINE(ProxyComponentDepsNode, DEG_NODE_TYPE_PROXY, "Proxy Component"); static DepsNodeFactoryImpl<ProxyComponentDepsNode> DNTI_PROXY; /* Geometry Component Defines ============================= */ -DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEPSNODE_TYPE_GEOMETRY, "Geometry Component"); +DEG_DEPSNODE_DEFINE(GeometryComponentDepsNode, DEG_NODE_TYPE_GEOMETRY, "Geometry Component"); static DepsNodeFactoryImpl<GeometryComponentDepsNode> DNTI_GEOMETRY; /* Sequencer Component Defines ============================ */ -DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEPSNODE_TYPE_SEQUENCER, "Sequencer Component"); +DEG_DEPSNODE_DEFINE(SequencerComponentDepsNode, DEG_NODE_TYPE_SEQUENCER, "Sequencer Component"); static DepsNodeFactoryImpl<SequencerComponentDepsNode> DNTI_SEQUENCER; /* Pose Component ========================================= */ -DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEPSNODE_TYPE_EVAL_POSE, "Pose Eval Component"); +DEG_DEPSNODE_DEFINE(PoseComponentDepsNode, DEG_NODE_TYPE_EVAL_POSE, "Pose Eval Component"); static DepsNodeFactoryImpl<PoseComponentDepsNode> DNTI_EVAL_POSE; /* Bone Component ========================================= */ @@ -388,22 +387,22 @@ void BoneComponentDepsNode::init(const ID *id, const char *subdata) this->pchan = BKE_pose_channel_find_name(ob->pose, subdata); } -DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEPSNODE_TYPE_BONE, "Bone Component"); +DEG_DEPSNODE_DEFINE(BoneComponentDepsNode, DEG_NODE_TYPE_BONE, "Bone Component"); static DepsNodeFactoryImpl<BoneComponentDepsNode> DNTI_BONE; /* Particles Component Defines ============================ */ -DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEPSNODE_TYPE_EVAL_PARTICLES, "Particles Component"); +DEG_DEPSNODE_DEFINE(ParticlesComponentDepsNode, DEG_NODE_TYPE_EVAL_PARTICLES, "Particles Component"); static DepsNodeFactoryImpl<ParticlesComponentDepsNode> DNTI_EVAL_PARTICLES; /* Shading Component Defines ============================ */ -DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEPSNODE_TYPE_SHADING, "Shading Component"); +DEG_DEPSNODE_DEFINE(ShadingComponentDepsNode, DEG_NODE_TYPE_SHADING, "Shading Component"); static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING; /* Cache Component Defines ============================ */ -DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEPSNODE_TYPE_CACHE, "Cache Component"); +DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEG_NODE_TYPE_CACHE, "Cache Component"); static DepsNodeFactoryImpl<CacheComponentDepsNode> DNTI_CACHE; diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h index 969771a29c9..4ef7dad3ac6 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_component.h +++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h @@ -99,12 +99,18 @@ struct ComponentDepsNode : public DepsNode { * \param op: The operation to perform * \param name: Identifier for operation - used to find/locate it again */ - OperationDepsNode *add_operation(eDepsOperation_Type optype, - DepsEvalOperationCb op, + OperationDepsNode *add_operation(const DepsEvalOperationCb& op, eDepsOperation_Code opcode, const char *name, int name_tag); + /* Entry/exit operations management. + * + * Use those instead of direct set since this will perform sanity checks. + */ + void set_entry_operation(OperationDepsNode *op_node); + void set_exit_operation(OperationDepsNode *op_node); + void clear_operations(); void tag_update(Depsgraph *graph); diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc index 9eed4dfe8d8..7467264f612 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc @@ -32,13 +32,11 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_utildefines.h" -} /* extern "C" */ +#include "BLI_ghash.h" #include "intern/depsgraph.h" #include "intern/depsgraph_intern.h" -#include "util/deg_util_hash.h" namespace DEG { @@ -67,7 +65,7 @@ string OperationDepsNode::identifier() const string OperationDepsNode::full_identifier() const { string owner_str = ""; - if (owner->type == DEPSNODE_TYPE_BONE) { + if (owner->type == DEG_NODE_TYPE_BONE) { owner_str = string(owner->owner->name) + "." + owner->name; } else { @@ -86,7 +84,19 @@ void OperationDepsNode::tag_update(Depsgraph *graph) graph->add_entry_tag(this); } -DEG_DEPSNODE_DEFINE(OperationDepsNode, DEPSNODE_TYPE_OPERATION, "Operation"); +void OperationDepsNode::set_as_entry() +{ + BLI_assert(owner != NULL); + owner->set_entry_operation(this); +} + +void OperationDepsNode::set_as_exit() +{ + BLI_assert(owner != NULL); + owner->set_exit_operation(this); +} + +DEG_DEPSNODE_DEFINE(OperationDepsNode, DEG_NODE_TYPE_OPERATION, "Operation"); static DepsNodeFactoryImpl<OperationDepsNode> DNTI_OPERATION; void deg_register_operation_depsnodes() diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.h b/source/blender/depsgraph/intern/nodes/deg_node_operation.h index 598393054db..1e5c3832d03 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node_operation.h +++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.h @@ -44,9 +44,6 @@ typedef enum eDepsOperation_Flag { DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0), /* node was directly modified, causing need for update */ - /* XXX: intention is to make it easier to tell when we just need to - * take subgraphs. - */ DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1), /* Operation is evaluated using CPython; has GIL and security @@ -57,8 +54,6 @@ typedef enum eDepsOperation_Flag { /* Atomic Operation - Base type for all operations */ struct OperationDepsNode : public DepsNode { - - OperationDepsNode(); ~OperationDepsNode(); @@ -72,21 +67,21 @@ struct OperationDepsNode : public DepsNode { OperationDepsNode *get_entry_operation() { return this; } OperationDepsNode *get_exit_operation() { return this; } + /* Set this operation as compoonent's entry/exit operation. */ + void set_as_entry(); + void set_as_exit(); + /* Component that contains the operation. */ ComponentDepsNode *owner; /* Callback for operation. */ DepsEvalOperationCb evaluate; - /* How many inlinks are we still waiting on before we can be evaluated. */ uint32_t num_links_pending; float eval_priority; bool scheduled; - /* Stage of evaluation */ - eDepsOperation_Type optype; - /* Identifier for the operation being performed. */ eDepsOperation_Code opcode; diff --git a/source/blender/depsgraph/util/deg_util_foreach.h b/source/blender/depsgraph/util/deg_util_foreach.h index 87d37168d51..cb7361fc708 100644 --- a/source/blender/depsgraph/util/deg_util_foreach.h +++ b/source/blender/depsgraph/util/deg_util_foreach.h @@ -46,28 +46,3 @@ # define foreach(x, y) for (x; false; (void)y) #endif - -#define GHASH_FOREACH_BEGIN(type, var, what) \ - do { \ - GHashIterator gh_iter##var; \ - GHASH_ITER(gh_iter##var, what) { \ - type var = reinterpret_cast<type>(BLI_ghashIterator_getValue(&gh_iter##var)); \ - -#define GHASH_FOREACH_END() \ - } \ - } while(0) - -#define GSET_FOREACH_BEGIN(type, var, what) \ - do { \ - GSetIterator gh_iter##var; \ - GSET_ITER(gh_iter##var, what) { \ - type var = reinterpret_cast<type>(BLI_gsetIterator_getKey(&gh_iter##var)); \ - -#define GSET_FOREACH_END() \ - } \ - } while(0) - -#define LINKLIST_FOREACH(type, var, list) \ - for (type var = (type)((list)->first); \ - var != NULL; \ - var = (type)(((Link*)(var))->next)) diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 98900812bb2..a6febdb575e 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -579,6 +579,7 @@ void ANIM_center_frame(struct bContext *C, int smooth_viewtx) break; } /* else drop through, keep range instead */ + ATTR_FALLTHROUGH; case ZOOM_FRAME_MODE_KEEP_RANGE: default: diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 823cde75334..be01f8cbe69 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -888,13 +888,14 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even ed_marker_move_cancel(C, op); return OPERATOR_CANCELLED; } - /* else continue; <--- see if release event should be caught for tweak-end */ + /* else continue; <--- see if release event should be caught for tweak-end */ + ATTR_FALLTHROUGH; case RETKEY: case PADENTER: case LEFTMOUSE: case MIDDLEMOUSE: - if (WM_modal_tweak_exit(event, mm->event_type)) { + if (WM_event_is_modal_tweak_exit(event, mm->event_type)) { ed_marker_move_exit(C, op); WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index 4571df0f077..9d25fc9e1a3 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -452,7 +452,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac) ok |= KEYFRAME_OK_H2; \ } \ } (void)0 - + /* ------------------------ */ static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt) diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index c928508237d..db4b642fe91 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -311,8 +311,8 @@ typedef struct BoneFlipNameData { * This way if we are flipping related bones (e.g., Bone.L, Bone.R) at the same time * all the bones are safely renamed, without conflicting with each other. * - * \param arm Armature the bones belong to - * \param bones ListBase of BoneConflict elems, populated via ED_armature_bones_flip_names_add + * \param arm: Armature the bones belong to + * \param bones_names: List of BoneConflict elems. */ void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names) { diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index e3c64b523b1..25f1b282f14 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -328,7 +328,7 @@ static int poselib_sanitize_exec(bContext *C, wmOperator *op) /* add pose to poselib */ marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker"); - BLI_strncpy(marker->name, "Pose", sizeof(marker->name)); + BLI_snprintf(marker->name, sizeof(marker->name), "F%d Pose", (int)ak->cfra); marker->frame = (int)ak->cfra; marker->flag = -1; diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 21cb405c32b..8dfcd5acab8 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -885,6 +885,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) break; } default: + { if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) { float value; @@ -972,6 +973,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) /* allow to pass through */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } + } } diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c index 661a8e1de9f..2bcf3099104 100644 --- a/source/blender/editors/armature/reeb.c +++ b/source/blender/editors/armature/reeb.c @@ -2240,9 +2240,9 @@ static void glueByMergeSort(ReebGraph *rg, ReebArc *a0, ReebArc *a1, ReebEdge *e else { a1 = nextArcMappedToEdge(a1, e1); } + } } } -} static void mergePaths(ReebGraph *rg, ReebEdge *e0, ReebEdge *e1, ReebEdge *e2) { diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 037c85e19dc..4580b0f667b 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -4161,7 +4161,7 @@ static int make_segment_exec(bContext *C, wmOperator *op) */ bp = nu->bp; - if (bp[nu->pntsu - 1].f1 & SELECT) { + if (bp[nu->pntsu - 1].f1 & SELECT) { if (nu2 == NULL) { nu2 = nu; } @@ -5851,6 +5851,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) BLI_assert(points_stride + dims == points + (points_len * dims)); float tan_l[3], tan_r[3], error_sq_dummy; + unsigned int error_index_dummy; sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]); normalize_v3(tan_l); @@ -5861,7 +5862,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) points, points_len, NULL, dims, FLT_EPSILON, tan_l, tan_r, bezt_prev->vec[2], bezt_next->vec[0], - &error_sq_dummy); + &error_sq_dummy, &error_index_dummy); if (!ELEM(bezt_prev->h2, HD_FREE, HD_ALIGN)) { bezt_prev->h2 = (bezt_prev->h2 == HD_VECT) ? HD_FREE : HD_ALIGN; @@ -6048,6 +6049,9 @@ int join_curve_exec(bContext *C, wmOperator *op) cu = ob->data; BLI_movelisttolist(&cu->nurb, &tempbase); + /* Account for mixed 2D/3D curves when joining */ + BKE_curve_curve_dimension_update(cu); + DAG_relations_tag_update(bmain); // because we removed object(s), call before editmode! DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index f091609da49..ecab37c729f 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -528,15 +528,15 @@ static void gp_draw_stroke_fill( } else { /* As an initial implementation, we use the OpenGL filled polygon drawing - * here since it's the easiest option to implement for this case. It does - * come with limitations (notably for concave shapes), though it shouldn't - * be much of an issue in most cases. - * - * We keep this legacy implementation around despite now having the high quality - * fills, as this is necessary for keeping everything working nicely for files - * created using old versions of Blender which may have depended on the artifacts - * the old fills created. - */ + * here since it's the easiest option to implement for this case. It does + * come with limitations (notably for concave shapes), though it shouldn't + * be much of an issue in most cases. + * + * We keep this legacy implementation around despite now having the high quality + * fills, as this is necessary for keeping everything working nicely for files + * created using old versions of Blender which may have depended on the artifacts + * the old fills created. + */ bGPDspoint *pt; glBegin(GL_POLYGON); diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index ec5a42c23a5..e5fb162a96c 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -297,9 +297,9 @@ static bool gp_brush_strength_apply( float inf; /* Compute strength of effect - * - We divide the strength by 10, so that users can set "sane" values. - * Otherwise, good default values are in the range of 0.093 - */ + * - We divide the strength by 10, so that users can set "sane" values. + * Otherwise, good default values are in the range of 0.093 + */ inf = gp_brush_influence_calc(gso, radius, co) / 10.0f; /* apply */ @@ -710,7 +710,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in } else { /* ERROR */ - BLI_assert("3D stroke being sculpted in non-3D view"); + BLI_assert(!"3D stroke being sculpted in non-3D view"); } } else { @@ -773,6 +773,9 @@ typedef struct tGPSB_CloneBrushData { /* for "stamp" mode, the currently pasted brushes */ bGPDstroke **new_strokes; + + /* mapping from colors referenced per stroke, to the new colours in the "pasted" strokes */ + GHash *new_colors; } tGPSB_CloneBrushData; /* Initialise "clone" brush data */ @@ -816,6 +819,11 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso) if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) { data->new_strokes = MEM_callocN(sizeof(bGPDstroke *) * data->totitems, "cloned strokes ptr array"); } + + /* Init colormap for mapping between the pasted stroke's source colour(names) + * and the final colours that will be used here instead... + */ + data->new_colors = gp_copybuf_validate_colormap(gso->gpd); } /* Free custom data used for "clone" brush */ @@ -829,6 +837,12 @@ static void gp_brush_clone_free(tGP_BrushEditData *gso) data->new_strokes = NULL; } + /* free copybuf colormap */ + if (data->new_colors) { + BLI_ghash_free(data->new_colors, NULL, NULL); + data->new_colors = NULL; + } + /* free the customdata itself */ MEM_freeN(data); gso->customdata = NULL; @@ -869,6 +883,13 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) new_stroke->next = new_stroke->prev = NULL; BLI_addtail(&gpf->strokes, new_stroke); + /* Fix color references */ + BLI_assert(new_stroke->colorname[0] != '\0'); + new_stroke->palcolor = BLI_ghash_lookup(data->new_colors, new_stroke->colorname); + + BLI_assert(new_stroke->palcolor != NULL); + BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname)); + /* Adjust all the stroke's points, so that the strokes * get pasted relative to where the cursor is now */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 601a86b97cb..fc6df49cf6c 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -38,8 +38,11 @@ #include "MEM_guardedalloc.h" -#include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_string_utils.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -335,11 +338,27 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot) /* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */ ListBase gp_strokes_copypastebuf = {NULL, NULL}; +/* Hash for hanging on to all the palette colors used by strokes in the buffer + * + * This is needed to prevent dangling and unsafe pointers when pasting across datablocks, + * or after a color used by a stroke in the buffer gets deleted (via user action or undo). + */ +GHash *gp_strokes_copypastebuf_colors = NULL; + /* Free copy/paste buffer data */ void ED_gpencil_strokes_copybuf_free(void) { bGPDstroke *gps, *gpsn; + /* Free the palettes buffer + * NOTE: This is done before the strokes so that the name ptrs (keys) are still safe + */ + if (gp_strokes_copypastebuf_colors) { + BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN); + gp_strokes_copypastebuf_colors = NULL; + } + + /* Free the stroke buffer */ for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) { gpsn = gps->next; @@ -352,6 +371,46 @@ void ED_gpencil_strokes_copybuf_free(void) gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL; } +/* Ensure that destination datablock has all the colours the pasted strokes need + * Helper function for copy-pasting strokes + */ +GHash *gp_copybuf_validate_colormap(bGPdata *gpd) +{ + GHash *new_colors = BLI_ghash_str_new("GPencil Paste Dst Colors"); + GHashIterator gh_iter; + + /* If there's no active palette yet (i.e. new datablock), add one */ + bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); + if (palette == NULL) { + palette = BKE_gpencil_palette_addnew(gpd, "Pasted Palette", true); + } + + /* For each color, figure out what to map to... */ + GHASH_ITER(gh_iter, gp_strokes_copypastebuf_colors) { + bGPDpalettecolor *palcolor; + char *name = BLI_ghashIterator_getKey(&gh_iter); + + /* Look for existing color to map to */ + /* XXX: What to do if same name but different color? Behaviour here should depend on a property? */ + palcolor = BKE_gpencil_palettecolor_getbyname(palette, name); + if (palcolor == NULL) { + /* Doesn't Exist - Create new matching color for this palette */ + /* XXX: This still doesn't fix the pasting across file boundaries problem... */ + bGPDpalettecolor *src_color = BLI_ghashIterator_getValue(&gh_iter); + + palcolor = MEM_dupallocN(src_color); + BLI_addtail(&palette->colors, palcolor); + + BLI_uniquename(&palette->colors, palcolor, DATA_("GP Color"), '.', offsetof(bGPDpalettecolor, info), sizeof(palcolor->info)); + } + + /* Store this mapping (for use later when pasting) */ + BLI_ghash_insert(new_colors, name, palcolor); + } + + return new_colors; +} + /* --------------------- */ /* Copy selected strokes */ @@ -413,7 +472,26 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) } CTX_DATA_END; - /* done - no updates needed */ + /* Build up hash of colors used in these strokes, making copies of these to protect against dangling pointers */ + if (gp_strokes_copypastebuf.first) { + gp_strokes_copypastebuf_colors = BLI_ghash_str_new("GPencil CopyBuf Colors"); + + for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { + if (ED_gpencil_stroke_can_use(C, gps)) { + if (BLI_ghash_haskey(gp_strokes_copypastebuf_colors, gps->colorname) == false) { + bGPDpalettecolor *color = MEM_dupallocN(gps->palcolor); + + BLI_ghash_insert(gp_strokes_copypastebuf_colors, gps->colorname, color); + gps->palcolor = color; + } + } + } + } + + /* updates (to ensure operator buttons are refreshed, when used via hotkeys) */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); // XXX? + + /* done */ return OPERATOR_FINISHED; } @@ -458,6 +536,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) bGPDframe *gpf; eGP_PasteMode type = RNA_enum_get(op->ptr, "type"); + GHash *new_colors; /* check for various error conditions */ if (gpd == NULL) { @@ -515,6 +594,10 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) } CTX_DATA_END; + /* Ensure that all the necessary colors exist */ + new_colors = gp_copybuf_validate_colormap(gpd); + + /* Copy over the strokes from the buffer (and adjust the colors) */ for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { /* Need to verify if layer exists */ @@ -533,6 +616,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) */ gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true); if (gpf) { + /* Create new stroke */ bGPDstroke *new_stroke = MEM_dupallocN(gps); new_stroke->tmp_layerinfo[0] = '\0'; @@ -543,10 +627,22 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) new_stroke->next = new_stroke->prev = NULL; BLI_addtail(&gpf->strokes, new_stroke); + + /* Fix color references */ + BLI_assert(new_stroke->colorname[0] != '\0'); + new_stroke->palcolor = BLI_ghash_lookup(new_colors, new_stroke->colorname); + + BLI_assert(new_stroke->palcolor != NULL); + BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname)); + + /*new_stroke->flag |= GP_STROKE_RECALC_COLOR; */ } } } + /* free temp data */ + BLI_ghash_free(new_colors, NULL, NULL); + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -748,10 +844,10 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) void GPENCIL_OT_blank_frame_add(wmOperatorType *ot) { /* identifiers */ - ot->name = "Add Blank Frame"; + ot->name = "Insert Blank Frame"; ot->idname = "GPENCIL_OT_blank_frame_add"; - ot->description = "Add a new frame with nothing in it on the current frame. " - "If there is already a frame, all existing frames are shifted one frame later"; + ot->description = "Insert a blank frame on the current frame " + "(all subsequently existing frames, if any, are shifted right by one frame)"; /* callbacks */ ot->exec = gp_blank_frame_add_exec; diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 5c7c9b84adb..a3734c56c59 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -40,6 +40,8 @@ struct bGPdata; struct bGPDstroke; struct bGPDspoint; +struct GHash; + struct ARegion; struct View2D; struct wmOperatorType; @@ -69,75 +71,23 @@ typedef struct GP_SpaceConversion { float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */ } GP_SpaceConversion; - -/** - * Check whether a given stroke segment is inside a circular brush - * - * \param mval The current screen-space coordinates (midpoint) of the brush - * \param mvalo The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED) - * \param rad The radius of the brush - * - * \param x0, y0 The screen-space x and y coordinates of the start of the stroke segment - * \param x1, y1 The screen-space x and y coordinates of the end of the stroke segment - */ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1); - -/** - * Init settings for stroke point space conversions - * - * \param[out] r_gsc The space conversion settings struct, populated with necessary params - */ void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc); -/** - * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D) - * - * \param[out] r_x The screen-space x-coordinate of the point - * \param[out] r_y The screen-space y-coordinate of the point - */ void gp_point_to_xy(GP_SpaceConversion *settings, struct bGPDstroke *gps, struct bGPDspoint *pt, int *r_x, int *r_y); -/** - * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D) - * - * Just like gp_point_to_xy(), except the resulting coordinates are floats not ints. - * Use this version to solve "stair-step" artifacts which may arise when roundtripping the calculations. - * - * \param[out] r_x The screen-space x-coordinate of the point - * \param[out] r_y The screen-space y-coordinate of the point - */ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, float *r_x, float *r_y); -/** - * Convert point to parent space - * - * \param pt Original point - * \param diff_mat Matrix with the difference between original parent matrix - * \param[out] r_pt Pointer to new point after apply matrix - */ void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt); -/** - * Change points position relative to parent object - */ + void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps); -/** - * Change point position relative to parent object - */ + void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt); -/** - * Convert a screenspace point to a 3D Grease Pencil coordinate. - * - * For use with editing tools where it is easier to perform the operations in 2D, - * and then later convert the transformed points back to 3D. - * - * \param screeN_co The screenspace 2D coordinates to convert to - * \param[out] r_out The resulting 3D coordinates of the input point - */ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, struct Scene *scene, const float screen_co[2], float r_out[3]); /* Poll Callbacks ------------------------------------ */ @@ -155,48 +105,18 @@ int gp_brush_crt_presets_poll(bContext *C); extern ListBase gp_strokes_copypastebuf; +/* Build a map for converting between old colornames and destination-color-refs */ +struct GHash *gp_copybuf_validate_colormap(bGPdata *gpd); + /* Stroke Editing ------------------------------------ */ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke *next_stroke, int tag_flags); -/** - * Apply smooth to stroke point - * \param gps Stroke to smooth - * \param i Point index - * \param inf Amount of smoothing to apply - * \param affect_pressure Apply smoothing to pressure values too? - */ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure); - -/** -* Apply smooth for strength to stroke point -* \param gps Stroke to smooth -* \param i Point index -* \param inf Amount of smoothing to apply -*/ bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf); - -/** -* Apply smooth for thickness to stroke point (use pressure) -* \param gps Stroke to smooth -* \param i Point index -* \param inf Amount of smoothing to apply -*/ bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf); - -/** - * Subdivide a stroke once, by adding points at the midpoint between each pair of points - * \param gps Stroke data - * \param new_totpoints Total number of points (after subdividing) - */ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints); - -/** -* Add randomness to stroke -* \param gps Stroke data -* \param brush Brush data -*/ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush); /* Layers Enums -------------------------------------- */ diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index d2360fea672..59b5b41f114 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -77,7 +77,6 @@ #include "ED_object.h" #include "ED_screen.h" #include "ED_view3d.h" -#include "ED_screen.h" #include "ED_space_api.h" #include "gpencil_intern.h" @@ -626,6 +625,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent break; } default: + { if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) { const float factor = tgpi->init_factor; float value; @@ -650,6 +650,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent /* unhandled event - allow to pass through */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } + } } /* still running... */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 5879306b06c..eb49060b629 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -162,6 +162,8 @@ typedef struct tGPsdata { bGPDbrush *brush; /* current drawing brush */ short straight[2]; /* 1: line horizontal, 2: line vertical, other: not defined, second element position */ int lock_axis; /* lock drawing to one axis */ + + short keymodifier; /* key used for invoking the operator */ } tGPsdata; /* ------ */ @@ -484,7 +486,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, bGPdata *gpd = p->gpd; bGPDbrush *brush = p->brush; tGPspoint *pt; - + ToolSettings *ts = p->scene->toolsettings; + /* check painting mode */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only - i.e. only store start and end point in buffer */ @@ -636,7 +639,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, View3D *v3d = p->sa->spacedata.first; view3d_region_operator_needs_opengl(p->win, p->ar); - ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1 : 0); + ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); } /* convert screen-coordinates to appropriate coordinates (and store them) */ @@ -756,7 +759,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) int i, totelem; /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */ - int depth_margin = (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 4 : 0; + int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0; /* get total number of points to allocate space for * - drawing straight-lines only requires the endpoints @@ -893,7 +896,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) copy_v2_v2_int(mval, &ptc->x); if ((ED_view3d_autodist_depth(p->ar, mval, depth_margin, depth_arr + i) == 0) && - (i && (ED_view3d_autodist_depth_seg(p->ar, mval, mval_prev, depth_margin + 1, depth_arr + i) == 0))) + (i && (ED_view3d_autodist_depth_seg(p->ar, mval, mval_prev, depth_margin + 1, depth_arr + i) == 0))) { interp_depth = true; } @@ -910,7 +913,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) depth_arr[i] = 0.9999f; } else { - if (p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) { + if (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) { /* remove all info between the valid endpoints */ int first_valid = 0; int last_valid = 0; @@ -1004,9 +1007,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname)); /* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke is added on listbase head - * because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist - * when drawing the background - */ + * because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist + * when drawing the background + */ if ((ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK) && (p->paintmode != GP_PAINTMODE_DRAW_POLY)) { BLI_addhead(&p->gpf->strokes, gps); } @@ -1794,6 +1797,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) /* finish off a stroke (clears buffer, but doesn't finish the paint operation) */ static void gp_paint_strokeend(tGPsdata *p) { + ToolSettings *ts = p->scene->toolsettings; /* for surface sketching, need to set the right OpenGL context stuff so that * the conversions will project the values correctly... */ @@ -1802,7 +1806,7 @@ static void gp_paint_strokeend(tGPsdata *p) /* need to restore the original projection settings before packing up */ view3d_region_operator_needs_opengl(p->win, p->ar); - ED_view3d_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1 : 0); + ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); } /* check if doing eraser or not */ @@ -1938,7 +1942,7 @@ static void gpencil_draw_cancel(bContext *C, wmOperator *op) /* ------------------------------- */ -static int gpencil_draw_init(bContext *C, wmOperator *op) +static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p; eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode"); @@ -1957,6 +1961,13 @@ static int gpencil_draw_init(bContext *C, wmOperator *op) gpencil_draw_exit(C, op); return 0; } + + if (event != NULL) { + p->keymodifier = event->keymodifier; + } + else { + p->keymodifier = -1; + } /* everything is now setup ok */ return 1; @@ -2198,7 +2209,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) /* printf("GPencil - Starting Re-Drawing\n"); */ /* try to initialize context data needed while drawing */ - if (!gpencil_draw_init(C, op)) { + if (!gpencil_draw_init(C, op, NULL)) { if (op->customdata) MEM_freeN(op->customdata); /* printf("\tGP - no valid data\n"); */ return OPERATOR_CANCELLED; @@ -2273,7 +2284,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event printf("GPencil - Starting Drawing\n"); /* try to initialize context data needed while drawing */ - if (!gpencil_draw_init(C, op)) { + if (!gpencil_draw_init(C, op, event)) { if (op->customdata) MEM_freeN(op->customdata); if (G.debug & G_DEBUG) @@ -2436,7 +2447,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * is essential for ensuring that they can quickly return to that view */ } - else if ((ELEM(event->type, DKEY)) && (event->val == KM_RELEASE)) { + else if ((ELEM(event->type, p->keymodifier)) && (event->val == KM_RELEASE)) { /* enable continuous if release D key in mid drawing */ p->scene->toolsettings->gpencil_flags |= GP_TOOL_FLAG_PAINTSESSIONS_ON; } diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 45dbde80284..2912a1ac4eb 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -1012,7 +1012,7 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op) } /* test if in lasso boundbox + within the lasso noose */ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&rect, x0, y0) && - BLI_lasso_is_point_inside(mcords, mcords_tot, x0, y0, INT_MAX)) + BLI_lasso_is_point_inside(mcords, mcords_tot, x0, y0, INT_MAX)) { if (select) { pt->flag |= GP_SPOINT_SELECT; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 76e85f20c36..ed05b8be9ca 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -391,7 +391,16 @@ EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, PointerRNA /* ******************************************************** */ /* Brush Tool Core */ -/* Check if part of stroke occurs within last segment drawn by eraser */ +/** + * Check whether a given stroke segment is inside a circular brush + * + * \param mval The current screen-space coordinates (midpoint) of the brush + * \param mvalo The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED) + * \param rad The radius of the brush + * + * \param x0, y0 The screen-space x and y coordinates of the start of the stroke segment + * \param x1, y1 The screen-space x and y coordinates of the end of the stroke segment + */ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1) { @@ -502,7 +511,11 @@ bGPDpalettecolor *ED_gpencil_stroke_getcolor(bGPdata *gpd, bGPDstroke *gps) /* ******************************************************** */ /* Space Conversion */ -/* Init handling for space-conversion function (from passed-in parameters) */ +/** + * Init settings for stroke point space conversions + * + * \param r_gsc: [out] The space conversion settings struct, populated with necessary params + */ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) { ScrArea *sa = CTX_wm_area(C); @@ -538,7 +551,13 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) } } -/* convert point to parent space */ +/** + * Convert point to parent space + * + * \param pt Original point + * \param diff_mat Matrix with the difference between original parent matrix + * \param[out] r_pt Pointer to new point after apply matrix + */ void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt) { float fpt[3]; @@ -547,7 +566,9 @@ void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint * copy_v3_v3(&r_pt->x, fpt); } -/* Change position relative to parent object */ +/** + * Change points position relative to parent object + */ void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps) { bGPDspoint *pt; @@ -568,7 +589,9 @@ void gp_apply_parent(bGPDlayer *gpl, bGPDstroke *gps) } } -/* Change point position relative to parent object */ +/** + * Change point position relative to parent object + */ void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt) { /* undo matrix */ @@ -583,8 +606,13 @@ void gp_apply_parent_point(bGPDlayer *gpl, bGPDspoint *pt) copy_v3_v3(&pt->x, fpt); } -/* Convert Grease Pencil points to screen-space values - * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn +/** + * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D) + * + * \param[out] r_x The screen-space x-coordinate of the point + * \param[out] r_y The screen-space y-coordinate of the point + * + * \warning This assumes that the caller has already checked whether the stroke in question can be drawn. */ void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, int *r_x, int *r_y) @@ -628,8 +656,16 @@ void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, } } -/* Convert Grease Pencil points to screen-space values (as floats) - * WARNING: This assumes that the caller has already checked whether the stroke in question can be drawn +/** + * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D) + * + * Just like gp_point_to_xy(), except the resulting coordinates are floats not ints. + * Use this version to solve "stair-step" artifacts which may arise when roundtripping the calculations. + * + * \param r_x: [out] The screen-space x-coordinate of the point + * \param r_y: [out] The screen-space y-coordinate of the point + * + * \warning This assumes that the caller has already checked whether the stroke in question can be drawn */ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, float *r_x, float *r_y) @@ -688,6 +724,12 @@ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, /** * Project screenspace coordinates to 3D-space * + * For use with editing tools where it is easier to perform the operations in 2D, + * and then later convert the transformed points back to 3D. + * + * \param screen_co: The screenspace 2D coordinates to convert to + * \param r_out: The resulting 3D coordinates of the input point + * * \note We include this as a utility function, since the standard method * involves quite a few steps, which are invariably always the same * for all GPencil operations. So, it's nicer to just centralize these. @@ -722,7 +764,7 @@ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen } /** - * Apply smooth to stroke point + * Apply smooth to stroke point * \param gps Stroke to smooth * \param i Point index * \param inf Amount of smoothing to apply @@ -830,8 +872,8 @@ bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf) ptc = &gps->points[after]; /* the optimal value is the corresponding to the interpolation of the strength - * at the distance of point b - */ + * at the distance of point b + */ const float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x); const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength; diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 5f8ebd87d19..91f8b39f7b9 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -63,7 +63,7 @@ int ED_space_clip_get_clip_frame_number(struct SpaceClip *sc); struct ImBuf *ED_space_clip_get_buffer(struct SpaceClip *sc); struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc, float loc[2], float *scale, float *angle); -bool ED_space_clip_color_sample(struct Scene *scene, struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]); +bool ED_space_clip_color_sample(struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]); void ED_clip_update_frame(const struct Main *mainp, int cfra); bool ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, bool fit); diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 283113f93d6..9de550a20ce 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -46,7 +46,7 @@ void ED_space_image_set(struct SpaceImage *sima, struct Scene *scene, s struct Mask *ED_space_image_get_mask(struct SpaceImage *sima); void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sima, struct Mask *mask); -bool ED_space_image_color_sample(struct Scene *scene, struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]); +bool ED_space_image_color_sample(struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]); struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock); void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock); bool ED_space_image_has_buffer(struct SpaceImage *sima); diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index f7b9d6b4f9e..e3c382382a9 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -107,7 +107,7 @@ void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree, void ED_operatormacros_node(void); /* node_view.c */ -bool ED_space_node_color_sample(struct Scene *scene, struct SpaceNode *snode, struct ARegion *ar, int mval[2], float r_col[3]); +bool ED_space_node_color_sample(struct SpaceNode *snode, struct ARegion *ar, int mval[2], float r_col[3]); #endif /* __ED_NODE_H__ */ diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h index 6eaae49912c..8066adf55ce 100644 --- a/source/blender/editors/include/ED_transform_snap_object_context.h +++ b/source/blender/editors/include/ED_transform_snap_object_context.h @@ -84,7 +84,6 @@ void ED_transform_snap_object_context_set_editmesh_callbacks( bool ED_transform_snap_object_project_ray_ex( struct SnapObjectContext *sctx, - const unsigned short snap_to, const struct SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float *ray_depth, /* return args */ @@ -98,7 +97,6 @@ bool ED_transform_snap_object_project_ray( bool ED_transform_snap_object_project_ray_all( SnapObjectContext *sctx, - const unsigned short snap_to, const struct SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float ray_depth, bool sort, diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 9ce71258573..d5c301d98d6 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -356,6 +356,9 @@ void ED_view3d_draw_offscreen( float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname, struct GPUFX *fx, struct GPUFXSettings *fx_settings, struct GPUOffScreen *ofs); +void ED_view3d_draw_setup_view( + struct wmWindow *win, struct Scene *scene, struct ARegion *ar, struct View3D *v3d, + float viewmat[4][4], float winmat[4][4], const struct rcti *rect); struct ImBuf *ED_view3d_draw_offscreen_imbuf( struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, @@ -370,7 +373,9 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple( struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip); -void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]); +void ED_view3d_update_viewmat( + struct Scene *scene, struct View3D *v3d, struct ARegion *ar, + float viewmat[4][4], float winmat[4][4], const struct rcti *rect); bool ED_view3d_quat_from_axis_view(const char view, float quat[4]); char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon); char ED_view3d_lock_view_from_index(int index); diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 8420591aa3e..0c83038b7a3 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -313,9 +313,9 @@ DEF_ICON(OUTLINER_OB_ARMATURE) DEF_ICON(OUTLINER_OB_FONT) DEF_ICON(OUTLINER_OB_SURFACE) DEF_ICON(OUTLINER_OB_SPEAKER) +DEF_ICON(OUTLINER_OB_FORCE_FIELD) +DEF_ICON(OUTLINER_OB_GROUP_INSTANCE) #ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK120) - DEF_ICON(BLANK121) DEF_ICON(BLANK122) DEF_ICON(BLANK123) DEF_ICON(BLANK124) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 2ce4f3e2790..7b4fac08a7b 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -217,7 +217,6 @@ enum { /* scale fixed button widths by this to account for DPI */ #define UI_DPI_FAC ((U.pixelsize * (float)U.dpi) / 72.0f) -#define UI_DPI_WINDOW_FAC (((float)U.dpi) / 72.0f) /* 16 to copy ICON_DEFAULT_HEIGHT */ #define UI_DPI_ICON_SIZE ((float)16 * UI_DPI_FAC) @@ -1083,7 +1082,7 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p); /* Float precision helpers */ -#define UI_PRECISION_FLOAT_MAX 7 +#define UI_PRECISION_FLOAT_MAX 6 /* For float buttons the 'step' (or a1), is scaled */ #define UI_PRECISION_FLOAT_SCALE 0.01f diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 7180e18ab92..2bf10c1c932 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1337,7 +1337,7 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u rctf rectf; ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect); - BLI_rcti_rctf_copy(rect, &rectf); + BLI_rcti_rctf_copy_round(rect, &rectf); BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin); } @@ -2146,9 +2146,14 @@ static float ui_get_but_step_unit(uiBut *but, float step_default) /** * \param float_precision For number buttons the precision to use or -1 to fallback to the button default. + * \param use_exp_float Use exponent representation of floats when out of reasonable range (outside of 1e3/1e-3). */ -void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) +void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision, const bool use_exp_float, bool *r_use_exp_float) { + if (r_use_exp_float) { + *r_use_exp_float = false; + } + if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { PropertyType type; const char *buf = NULL; @@ -2217,16 +2222,31 @@ void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int } else { const int prec = (float_precision == -1) ? ui_but_calc_float_precision(but, value) : float_precision; - BLI_snprintf(str, maxlen, "%.*f", prec, value); + if (use_exp_float) { + const int l10 = (int)log10(fabs(value)); + if (l10 < -6 || l10 > 12) { + BLI_snprintf(str, maxlen, "%.*g", prec, value); + if (r_use_exp_float) { + *r_use_exp_float = true; + } + } + else { + BLI_snprintf(str, maxlen, "%.*f", prec - l10 + (int)(l10 < 0), value); + } + } + else { + BLI_snprintf(str, maxlen, "%.*f", prec, value); + } } } - else + else { BLI_snprintf(str, maxlen, "%d", (int)value); + } } } void ui_but_string_get(uiBut *but, char *str, const size_t maxlen) { - ui_but_string_get_ex(but, str, maxlen, -1); + ui_but_string_get_ex(but, str, maxlen, -1, false, NULL); } /** @@ -2335,11 +2355,10 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double #else /* WITH_PYTHON */ - *value = atof(str); + *r_value = atof(str); ok = true; - (void)C; - (void)but; + UNUSED_VARS(C, but); #endif /* WITH_PYTHON */ @@ -3168,7 +3187,9 @@ static uiBut *ui_def_but( } if (block->flag & UI_BLOCK_RADIAL) { - but->drawflag |= (UI_BUT_TEXT_LEFT | UI_BUT_ICON_LEFT); + but->drawflag |= UI_BUT_TEXT_LEFT; + if (but->str && but->str[0]) + but->drawflag |= UI_BUT_ICON_LEFT; } else if ((block->flag & UI_BLOCK_LOOP) || ELEM(but->type, diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index f3859154dfb..eab609ebe84 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -225,7 +225,7 @@ static bool eyedropper_init(bContext *C, wmOperator *op) return false; } - if (RNA_property_subtype(eye->prop) == PROP_COLOR) { + if (RNA_property_subtype(eye->prop) != PROP_COLOR) { const char *display_device; float col[4]; @@ -235,7 +235,7 @@ static bool eyedropper_init(bContext *C, wmOperator *op) /* store inital color */ RNA_property_float_get_array(&eye->ptr, eye->prop, col); if (eye->display) { - IMB_colormanagement_scene_linear_to_display_v3(col, eye->display); + IMB_colormanagement_display_to_scene_linear_v3(col, eye->display); } copy_v3_v3(eye->init_col, col); } @@ -266,6 +266,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int /* we could use some clever */ wmWindow *win = CTX_wm_window(C); ScrArea *sa = BKE_screen_find_area_xy(win->screen, SPACE_TYPE_ANY, mx, my); + const char *display_device = CTX_data_scene(C)->display_settings.display_device; + struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); if (sa) { if (sa->spacetype == SPACE_IMAGE) { @@ -275,7 +277,7 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; - if (ED_space_image_color_sample(CTX_data_scene(C), sima, ar, mval, r_col)) { + if (ED_space_image_color_sample(sima, ar, mval, r_col)) { return; } } @@ -287,7 +289,7 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; - if (ED_space_node_color_sample(CTX_data_scene(C), snode, ar, mval, r_col)) { + if (ED_space_node_color_sample(snode, ar, mval, r_col)) { return; } } @@ -299,7 +301,7 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; - if (ED_space_clip_color_sample(CTX_data_scene(C), sc, ar, mval, r_col)) { + if (ED_space_clip_color_sample(sc, ar, mval, r_col)) { return; } } @@ -310,6 +312,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int glReadBuffer(GL_FRONT); glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col); glReadBuffer(GL_BACK); + + IMB_colormanagement_display_to_scene_linear_v3(r_col, display); } /* sets the sample color RGB, maintaining A */ @@ -320,10 +324,10 @@ static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3 /* to maintain alpha */ RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv); - /* convert from display space to linear rgb space */ + /* convert from linear rgb space to display space */ if (eye->display) { copy_v3_v3(col_conv, col); - IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display); + IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display); } else { copy_v3_v3(col_conv, col); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 2974c2e9304..bcfe4fe6bb4 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2319,7 +2319,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, /* Get many decimal places, then strip trailing zeros. * note: too high values start to give strange results */ char buf_copy[UI_MAX_DRAW_STR]; - ui_but_string_get_ex(but, buf_copy, sizeof(buf_copy), UI_PRECISION_FLOAT_MAX); + ui_but_string_get_ex(but, buf_copy, sizeof(buf_copy), UI_PRECISION_FLOAT_MAX, false, NULL); BLI_str_rstrip_float_zero(buf_copy, '\0'); WM_clipboard_text_set(buf_copy, 0); @@ -3060,6 +3060,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) wmWindow *win = CTX_wm_window(C); int len; const bool is_num_but = ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER); + bool no_zero_strip = false; if (data->str) { MEM_freeN(data->str); @@ -3092,14 +3093,16 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) data->maxlen = ui_but_string_get_max_length(but); if (data->maxlen != 0) { data->str = MEM_callocN(sizeof(char) * data->maxlen, "textedit str"); - ui_but_string_get(but, data->str, data->maxlen); + /* We do not want to truncate precision to default here, it's nice to show value, + * not to edit it - way too much precision is lost then. */ + ui_but_string_get_ex(but, data->str, data->maxlen, UI_PRECISION_FLOAT_MAX, true, &no_zero_strip); } else { data->is_str_dynamic = true; data->str = ui_but_string_get_dynamic(but, &data->maxlen); } - if (ui_but_is_float(but) && !ui_but_is_unit(but) && !ui_but_anim_expression_get(but, NULL, 0)) { + if (ui_but_is_float(but) && !ui_but_is_unit(but) && !ui_but_anim_expression_get(but, NULL, 0) && !no_zero_strip) { BLI_str_rstrip_float_zero(data->str, '\0'); } @@ -3378,7 +3381,7 @@ static void ui_do_but_textedit( if (event->type == WHEELDOWNMOUSE) { break; } - /* fall-through */ + ATTR_FALLTHROUGH; case ENDKEY: ui_textedit_move(but, data, STRCUR_DIR_NEXT, event->shift != 0, STRCUR_JUMP_ALL); @@ -3396,7 +3399,7 @@ static void ui_do_but_textedit( if (event->type == WHEELUPMOUSE) { break; } - /* fall-through */ + ATTR_FALLTHROUGH; case HOMEKEY: ui_textedit_move(but, data, STRCUR_DIR_PREV, event->shift != 0, STRCUR_JUMP_ALL); @@ -6757,6 +6760,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) { uiPopupMenu *pup; uiLayout *layout; + MenuType *mt = WM_menutype_find("WM_MT_button_context", true); bool is_array, is_array_component; uiStringInfo label = {BUT_GET_LABEL, NULL}; @@ -6788,6 +6792,12 @@ static bool ui_but_menu(bContext *C, uiBut *but) /*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */ bool is_set = RNA_property_is_set(ptr, prop); + /* set the prop and pointer data for python access to the hovered ui element; TODO, index could be supported as well*/ + PointerRNA temp_ptr; + RNA_pointer_create(NULL, &RNA_Property, but->rnaprop, &temp_ptr); + uiLayoutSetContextPointer(layout,"button_prop", &temp_ptr); + uiLayoutSetContextPointer(layout,"button_pointer", ptr); + /* second slower test, saved people finding keyframe items in menus when its not possible */ if (is_anim) is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop); @@ -7003,7 +7013,11 @@ static bool ui_but_menu(bContext *C, uiBut *but) 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); } - + + /* Set the operator pointer for python access */ + if (but->opptr) + uiLayoutSetContextPointer(layout,"button_operator", but->opptr); + uiItemS(layout); } @@ -7050,6 +7064,14 @@ static bool ui_but_menu(bContext *C, uiBut *but) } uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0); + mt = WM_menutype_find("WM_MT_button_context", false); + if (mt) { + Menu menu = {NULL}; + menu.layout = uiLayoutColumn(layout, false); + menu.type = mt; + mt->draw(C, &menu); + } + UI_popup_menu_end(C, pup); return true; @@ -8389,7 +8411,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) case MIDDLEMOUSE: case MOUSEPAN: UI_but_tooltip_timer_remove(C, but); - /* fall-through */ + ATTR_FALLTHROUGH; default: /* handle button type specific events */ retval = ui_do_button(C, block, but, event); @@ -9183,23 +9205,23 @@ static int ui_handle_menu_event( break; case ONEKEY: case PAD1: - act = 1; + act = 1; ATTR_FALLTHROUGH; case TWOKEY: case PAD2: - if (act == 0) act = 2; + if (act == 0) act = 2; ATTR_FALLTHROUGH; case THREEKEY: case PAD3: - if (act == 0) act = 3; + if (act == 0) act = 3; ATTR_FALLTHROUGH; case FOURKEY: case PAD4: - if (act == 0) act = 4; + if (act == 0) act = 4; ATTR_FALLTHROUGH; case FIVEKEY: case PAD5: - if (act == 0) act = 5; + if (act == 0) act = 5; ATTR_FALLTHROUGH; case SIXKEY: case PAD6: - if (act == 0) act = 6; + if (act == 0) act = 6; ATTR_FALLTHROUGH; case SEVENKEY: case PAD7: - if (act == 0) act = 7; + if (act == 0) act = 7; ATTR_FALLTHROUGH; case EIGHTKEY: case PAD8: - if (act == 0) act = 8; + if (act == 0) act = 8; ATTR_FALLTHROUGH; case NINEKEY: case PAD9: - if (act == 0) act = 9; + if (act == 0) act = 9; ATTR_FALLTHROUGH; case ZEROKEY: case PAD0: if (act == 0) act = 10; @@ -9794,13 +9816,13 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle case (ZEROKEY + n): case (PAD0 + n): \ { if (num_dir == UI_RADIAL_NONE) num_dir = d; } (void)0 - CASE_NUM_TO_DIR(1, UI_RADIAL_SW); - CASE_NUM_TO_DIR(2, UI_RADIAL_S); - CASE_NUM_TO_DIR(3, UI_RADIAL_SE); - CASE_NUM_TO_DIR(4, UI_RADIAL_W); - CASE_NUM_TO_DIR(6, UI_RADIAL_E); - CASE_NUM_TO_DIR(7, UI_RADIAL_NW); - CASE_NUM_TO_DIR(8, UI_RADIAL_N); + CASE_NUM_TO_DIR(1, UI_RADIAL_SW); ATTR_FALLTHROUGH; + CASE_NUM_TO_DIR(2, UI_RADIAL_S); ATTR_FALLTHROUGH; + CASE_NUM_TO_DIR(3, UI_RADIAL_SE); ATTR_FALLTHROUGH; + CASE_NUM_TO_DIR(4, UI_RADIAL_W); ATTR_FALLTHROUGH; + CASE_NUM_TO_DIR(6, UI_RADIAL_E); ATTR_FALLTHROUGH; + CASE_NUM_TO_DIR(7, UI_RADIAL_NW); ATTR_FALLTHROUGH; + CASE_NUM_TO_DIR(8, UI_RADIAL_N); ATTR_FALLTHROUGH; CASE_NUM_TO_DIR(9, UI_RADIAL_NE); { but = ui_block_pie_dir_activate(block, event, num_dir); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 067279777ba..ab760c40451 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -473,7 +473,9 @@ extern void ui_hsvcircle_pos_from_vals(struct uiBut *but, const rcti *rect, floa extern void ui_hsvcube_pos_from_vals(struct uiBut *but, const rcti *rect, float *hsv, float *xp, float *yp); bool ui_but_is_colorpicker_display_space(struct uiBut *but); -extern void ui_but_string_get_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) ATTR_NONNULL(); +extern void ui_but_string_get_ex( + uiBut *but, char *str, const size_t maxlen, + const int float_precision, const bool use_exp_float, bool *r_use_exp_float) ATTR_NONNULL(1, 2); extern void ui_but_string_get(uiBut *but, char *str, const size_t maxlen) ATTR_NONNULL(); extern char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size); extern void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen) ATTR_NONNULL(); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 9b6547cf8a1..da43a58bc74 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1274,7 +1274,8 @@ static void ui_item_rna_size( if (!w) { if (type == PROP_ENUM && icon_only) { w = ui_text_icon_width(layout, "", ICON_BLANK1, 0); - w += 0.6f * UI_UNIT_X; + if (index != RNA_ENUM_VALUE) + w += 0.6f * UI_UNIT_X; } else { w = ui_text_icon_width(layout, name, icon, 0); @@ -2395,8 +2396,10 @@ static void ui_litem_layout_radial(uiLayout *litem) /* add a little bit more here to include number */ bitem->but->rect.xmax += 1.5f * UI_UNIT_X; /* enable drawing as pie item if supported by widget */ - if (ui_item_is_radial_drawable(bitem)) + if (ui_item_is_radial_drawable(bitem)) { bitem->but->dt = UI_EMBOSS_RADIAL; + bitem->but->drawflag |= UI_BUT_ICON_LEFT; + } } ui_item_size(item, &itemw, &itemh); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 534bd4278ca..5ed94474726 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2099,9 +2099,11 @@ static void ui_update_color_picker_buts_rgb(uiBlock *block, ColorPicker *cpicker continue; if (bt->rnaprop) { - ui_but_v3_set(bt, rgb); + /* original button that created the color picker already does undo + * push, so disable it on RNA buttons in the color picker block */ + UI_but_flag_disable(bt, UI_BUT_UNDO); } else if (STREQ(bt->str, "Hex: ")) { float rgb_gamma[3]; diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 636b7e4e9ce..1927d7280f3 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -265,7 +265,7 @@ int UI_icon_from_report_type(int type) */ int UI_calc_float_precision(int prec, double value) { - static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7}; + static const double pow10_neg[UI_PRECISION_FLOAT_MAX + 1] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6}; static const double max_pow = 10000000.0; /* pow(10, UI_PRECISION_FLOAT_MAX) */ BLI_assert(prec <= UI_PRECISION_FLOAT_MAX); @@ -380,6 +380,17 @@ uiButStore *UI_butstore_create(uiBlock *block) void UI_butstore_free(uiBlock *block, uiButStore *bs_handle) { + /* Workaround for button store being moved into new block, + * which then can't use the previous buttons state ('ui_but_update_from_old_block' fails to find a match), + * keeping the active button in the old block holding a reference to the button-state in the new block: see T49034. + * + * Ideally we would manage moving the 'uiButStore', keeping a correct state. + * All things considered this is the most straightforward fix - Campbell. + */ + if (block != bs_handle->block && bs_handle->block != NULL) { + block = bs_handle->block; + } + BLI_freelistN(&bs_handle->items); BLI_remlink(&block->butstore, bs_handle); diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 3f9eb33e239..ca4ab30a08d 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -31,6 +31,9 @@ # include "BLI_winstuff.h" #endif +#include <string.h> +#include <errno.h> + #include "MEM_guardedalloc.h" #include "DNA_mesh_types.h" @@ -102,12 +105,12 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) char filename[FILE_MAX]; RNA_string_get(op->ptr, "filepath", filename); - const struct AlembicExportParams params = { + struct AlembicExportParams params = { .frame_start = RNA_int_get(op->ptr, "start"), .frame_end = RNA_int_get(op->ptr, "end"), - .frame_step_xform = 1.0 / (double)RNA_int_get(op->ptr, "xsamples"), - .frame_step_shape = 1.0 / (double)RNA_int_get(op->ptr, "gsamples"), + .frame_samples_xform = RNA_int_get(op->ptr, "xsamples"), + .frame_samples_shape = RNA_int_get(op->ptr, "gsamples"), .shutter_open = RNA_float_get(op->ptr, "sh_open"), .shutter_close = RNA_float_get(op->ptr, "sh_close"), @@ -122,6 +125,8 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"), .face_sets = RNA_boolean_get(op->ptr, "face_sets"), .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), + .export_hair = RNA_boolean_get(op->ptr, "export_hair"), + .export_particles = RNA_boolean_get(op->ptr, "export_particles"), .compression_type = RNA_enum_get(op->ptr, "compression_type"), .packuv = RNA_boolean_get(op->ptr, "packuv"), .triangulate = RNA_boolean_get(op->ptr, "triangulate"), @@ -131,15 +136,26 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .global_scale = RNA_float_get(op->ptr, "global_scale"), }; - ABC_export(CTX_data_scene(C), C, filename, ¶ms); + /* Take some defaults from the scene, if not specified explicitly. */ + Scene *scene = CTX_data_scene(C); + if (params.frame_start == INT_MIN) { + params.frame_start = SFRA; + } + if (params.frame_end == INT_MIN) { + params.frame_end = EFRA; + } + + const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job"); + bool ok = ABC_export(scene, C, filename, ¶ms, as_background_job); - return OPERATOR_FINISHED; + return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) { uiLayout *box; uiLayout *row; + uiLayout *col; #ifdef WITH_ALEMBIC_HDF5 box = uiLayoutBox(layout); @@ -231,6 +247,15 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); uiLayoutSetEnabled(row, triangulate); uiItemR(row, imfptr, "ngon_method", 0, NULL, ICON_NONE); + + /* Object Data */ + box = uiLayoutBox(layout); + row = uiLayoutRow(box, false); + uiItemL(row, IFACE_("Particle Systems:"), ICON_PARTICLE_DATA); + + col = uiLayoutColumn(box, true); + uiItemR(col, imfptr, "export_hair", 0, NULL, ICON_NONE); + uiItemR(col, imfptr, "export_particles", 0, NULL, ICON_NONE); } static void wm_alembic_export_draw(bContext *C, wmOperator *op) @@ -282,11 +307,17 @@ void WM_OT_alembic_export(wmOperatorType *ot) FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - RNA_def_int(ot->srna, "start", 1, INT_MIN, INT_MAX, - "Start Frame", "Start Frame", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "start", INT_MIN, INT_MIN, INT_MAX, + "Start Frame", + "Start frame of the export, use the default value to " + "take the start frame of the current scene", + INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "end", 1, INT_MIN, INT_MAX, - "End Frame", "End Frame", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "end", INT_MIN, INT_MIN, INT_MAX, + "End Frame", + "End frame of the export, use the default value to " + "take the end frame of the current scene", + INT_MIN, INT_MAX); RNA_def_int(ot->srna, "xsamples", 1, 1, 128, "Transform Samples", "Number of times per frame transformations are sampled", 1, 128); @@ -348,9 +379,15 @@ void WM_OT_alembic_export(wmOperatorType *ot) RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_quad_method_items, MOD_TRIANGULATE_NGON_BEAUTY, "Polygon Method", "Method for splitting the polygons into triangles"); + RNA_def_boolean(ot->srna, "export_hair", 1, "Export Hair", "Exports hair particle systems as animated curves"); + RNA_def_boolean(ot->srna, "export_particles", 1, "Export Particles", "Exports non-hair particle systems"); + + RNA_def_boolean(ot->srna, "as_background_job", true, "Run as Background Job", + "Enable this to run the import in the background, disable to block Blender while importing"); + /* This dummy prop is used to check whether we need to init the start and - * end frame values to that of the scene's, otherwise they are reset at - * every change, draw update. */ + * end frame values to that of the scene's, otherwise they are reset at + * every change, draw update. */ RNA_def_boolean(ot->srna, "init_scene_frame_range", false, "", ""); } @@ -383,9 +420,20 @@ static int get_sequence_len(char *filename, int *ofs) } char path[FILE_MAX]; + BLI_path_abs(filename, G.main->name); BLI_split_dir_part(filename, path, FILE_MAX); + if (path[0] == '\0') { + /* The filename had no path, so just use the blend file path. */ + BLI_split_dir_part(G.main->name, path, FILE_MAX); + } + DIR *dir = opendir(path); + if (dir == NULL) { + fprintf(stderr, "Error opening directory '%s': %s\n", + path, errno ? strerror(errno) : "unknown error"); + return -1; + } const char *ext = ".abc"; const char *basename = BLI_path_basename(filename); @@ -482,17 +530,24 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op) const bool is_sequence = RNA_boolean_get(op->ptr, "is_sequence"); const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range"); const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes"); + const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job"); int offset = 0; int sequence_len = 1; if (is_sequence) { sequence_len = get_sequence_len(filename, &offset); + if (sequence_len < 0) { + BKE_report(op->reports, RPT_ERROR, "Unable to determine ABC sequence length"); + return OPERATOR_CANCELLED; + } } - ABC_import(C, filename, scale, is_sequence, set_frame_range, sequence_len, offset, validate_meshes); + bool ok = ABC_import(C, filename, scale, is_sequence, set_frame_range, + sequence_len, offset, validate_meshes, + as_background_job); - return OPERATOR_FINISHED; + return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } void WM_OT_alembic_import(wmOperatorType *ot) @@ -523,6 +578,9 @@ void WM_OT_alembic_import(wmOperatorType *ot) RNA_def_boolean(ot->srna, "is_sequence", false, "Is Sequence", "Set to true if the cache is split into separate files"); + + RNA_def_boolean(ot->srna, "as_background_job", true, "Run as Background Job", + "Enable this to run the export in the background, disable to block Blender while exporting"); } #endif diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index ebe8898571d..a5e90ebbe7a 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -97,22 +97,24 @@ static int cachefile_open_exec(bContext *C, wmOperator *op) BLI_strncpy(cache_file->filepath, filename, FILE_MAX); BKE_cachefile_reload(bmain, cache_file); - /* hook into UI */ - PropertyPointerRNA *pprop = op->customdata; - - if (pprop->prop) { - /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ - id_us_min(&cache_file->id); - - PointerRNA idptr; - RNA_id_pointer_create(&cache_file->id, &idptr); - RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); - RNA_property_update(C, &pprop->ptr, pprop->prop); + /* Will be set when running invoke, not exec directly. */ + if (op->customdata != NULL) { + /* hook into UI */ + PropertyPointerRNA *pprop = op->customdata; + if (pprop->prop) { + /* when creating new ID blocks, use is already 1, but RNA + * pointer se also increases user, so this compensates it */ + id_us_min(&cache_file->id); + + PointerRNA idptr; + RNA_id_pointer_create(&cache_file->id, &idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); + RNA_property_update(C, &pprop->ptr, pprop->prop); + } + + MEM_freeN(op->customdata); } - MEM_freeN(op->customdata); - return OPERATOR_FINISHED; } @@ -143,7 +145,7 @@ static int cachefile_reload_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); - BLI_listbase_clear(&cache_file->object_paths); + BLI_freelistN(&cache_file->object_paths); BKE_cachefile_reload(bmain, cache_file); return OPERATOR_FINISHED; diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 139c9817437..cead08afd61 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -87,8 +87,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int include_shapekeys; int deform_bones_only; - int include_uv_textures; - int include_material_textures; + int export_texture_type; int use_texture_copies; int active_uv_only; @@ -139,8 +138,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys"); deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only"); - include_uv_textures = RNA_boolean_get(op->ptr, "include_uv_textures"); - include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures"); + export_texture_type = RNA_enum_get(op->ptr, "export_texture_type_selection"); use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies"); active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only"); @@ -169,8 +167,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) deform_bones_only, active_uv_only, - include_uv_textures, - include_material_textures, + export_texture_type, use_texture_copies, triangulate, @@ -241,10 +238,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "active_uv_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "include_uv_textures", 0, NULL, ICON_NONE); - - row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "include_material_textures", 0, NULL, ICON_NONE); + uiItemR(row, imfptr, "export_texture_type_selection", 0, "", ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "use_texture_copies", 1, NULL, ICON_NONE); @@ -321,9 +315,15 @@ void WM_OT_collada_export(wmOperatorType *ot) }; static EnumPropertyItem prop_bc_export_transformation_type[] = { - {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"}, - {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"}, - {0, NULL, 0, NULL, NULL} + { BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations" }, + { BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations" }, + { 0, NULL, 0, NULL, NULL } + }; + + static EnumPropertyItem prop_bc_export_texture_type[] = { + { BC_TEXTURE_TYPE_MAT, "mat", 0, "Materials", "Export Materials" }, + { BC_TEXTURE_TYPE_UV, "uv", 0, "UV Textures", "Export UV Textures (Face textures) as materials" }, + { 0, NULL, 0, NULL, NULL } }; ot->name = "Export COLLADA"; @@ -368,16 +368,9 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures"); - RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map", "Export only the selected UV Map"); - RNA_def_boolean(func, "include_uv_textures", 0, "Include UV Textures", - "Export textures assigned to the object UV Maps"); - - RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures", - "Export textures assigned to the object Materials"); - RNA_def_boolean(func, "use_texture_copies", 1, "Copy", "Copy textures to same folder where the .dae file is exported"); @@ -394,11 +387,20 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); + RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX, - "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); + "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0, - "Transform", "Transformation type for translation, scale and rotation"); + "Transform", "Transformation type for translation, scale and rotation"); + + + RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX, + "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX); + + RNA_def_enum(func, "export_texture_type_selection", prop_bc_export_texture_type, 0, + "Texture Type", "Type for exported Textures (UV or MAT)"); + RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds"); diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index f01af22cec9..69335195b96 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -770,14 +770,17 @@ static int create_primitive_from_points(bContext *C, wmOperator *op, const float new_spline = BKE_mask_spline_add(mask_layer); new_spline->flag = MASK_SPLINE_CYCLIC | SELECT; - new_spline->tot_point = num_points; new_spline->points = MEM_recallocN(new_spline->points, - sizeof(MaskSplinePoint) * new_spline->tot_point); + sizeof(MaskSplinePoint) * num_points); mask_layer->act_spline = new_spline; mask_layer->act_point = NULL; + const int spline_index = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline); + for (i = 0; i < num_points; i++) { + new_spline->tot_point = i + 1; + MaskSplinePoint *new_point = &new_spline->points[i]; BKE_mask_parent_init(&new_point->parent); @@ -788,6 +791,12 @@ static int create_primitive_from_points(bContext *C, wmOperator *op, const float new_point->bezt.h1 = handle_type; new_point->bezt.h2 = handle_type; BKE_mask_point_select_set(new_point, true); + + if (mask_layer->splines_shapes.first) { + BKE_mask_layer_shape_changed_add(mask_layer, + spline_index + i, + true, true); + } } WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 2b4f94a37ef..be7eb2bf9ed 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -834,13 +834,12 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */ glPushMatrix(); - + glTranslatef(x + xofs, y + yofs, 0); + glScalef(zoomx, zoomy, 0); if (stabmat) { glMultMatrixf(stabmat); } - - glTranslatef(x + xofs, y + yofs, 0); - glScalef(maxdim * zoomx, maxdim * zoomy, 0); + glScalef(maxdim, maxdim, 0); if (do_draw_cb) { ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index eef03852007..35de390274c 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -889,7 +889,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) data->is_accurate = (event->val == KM_PRESS); - /* fall-through */ /* update CV position */ + ATTR_FALLTHROUGH; /* update CV position */ case MOUSEMOVE: { ScrArea *sa = CTX_wm_area(C); @@ -1376,7 +1376,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve } - /* fall-through */ /* update CV position */ + ATTR_FALLTHROUGH; /* update CV position */ case MOUSEMOVE: { float B[2], mouse_coord[2], delta[2]; diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index c4e87614732..6c6c106b19a 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -306,31 +306,30 @@ void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags) bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) { - Mesh *me; - MPoly *mp; - MTexPoly *tf; - MLoop *ml; - MVert *mvert; + const Mesh *me; + const MPoly *mp; + const MLoop *ml; + const MVert *mvert; int a, b; bool ok = false; float vec[3], bmat[3][3]; me = BKE_mesh_from_object(ob); - if (!me || !me->mtpoly) return ok; + if (!me || !me->mloopuv) { + return ok; + } copy_m3_m4(bmat, ob->obmat); mvert = me->mvert; mp = me->mpoly; - tf = me->mtpoly; - for (a = me->totpoly; a > 0; a--, mp++, tf++) { + for (a = me->totpoly; a > 0; a--, mp++) { if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL)) continue; ml = me->mloop + mp->totloop; for (b = 0; b < mp->totloop; b++, ml++) { - copy_v3_v3(vec, (mvert[ml->v].co)); - mul_m3_v3(bmat, vec); + mul_v3_m3v3(vec, bmat, mvert[ml->v].co); add_v3_v3v3(vec, vec, ob->obmat[3]); minmax_v3v3_v3(r_min, r_max, vec); } @@ -798,25 +797,47 @@ void ED_mesh_mirrtopo_init(Mesh *me, DerivedMesh *dm, const int ob_mode, MirrTop qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort); - /* Since the loop starts at 2, we must define the last index where the hash's differ */ - last = ((totvert >= 2) && (topo_pairs[0].hash == topo_pairs[1].hash)) ? 0 : 1; + last = 0; /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2, * but you cant ever access the last 'a' index of MirrTopoPairs */ - for (a = 2; a <= totvert; a++) { - /* printf("I %d %ld %d\n", (a-last), MirrTopoPairs[a ].hash, MirrTopoPairs[a ].v_index ); */ - if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) { - if (a - last == 2) { - if (em) { - index_lookup[topo_pairs[a - 1].v_index] = (intptr_t)BM_vert_at_index(em->bm, topo_pairs[a - 2].v_index); - index_lookup[topo_pairs[a - 2].v_index] = (intptr_t)BM_vert_at_index(em->bm, topo_pairs[a - 1].v_index); + if (em) { + BMVert **vtable = em->bm->vtable; + for (a = 1; a <= totvert; a++) { + /* printf("I %d %ld %d\n", (a - last), MirrTopoPairs[a].hash, MirrTopoPairs[a].v_indexs); */ + if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) { + const int match_count = a - last; + if (match_count == 2) { + const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index; + index_lookup[j] = (intptr_t)vtable[k]; + index_lookup[k] = (intptr_t)vtable[j]; + } + else if (match_count == 1) { + /* Center vertex. */ + const int j = topo_pairs[a - 1].v_index; + index_lookup[j] = (intptr_t)vtable[j]; + } + last = a; + } + } + } + else { + /* same as above, for mesh */ + for (a = 1; a <= totvert; a++) { + if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) { + const int match_count = a - last; + if (match_count == 2) { + const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index; + index_lookup[j] = k; + index_lookup[k] = j; } - else { - index_lookup[topo_pairs[a - 1].v_index] = topo_pairs[a - 2].v_index; - index_lookup[topo_pairs[a - 2].v_index] = topo_pairs[a - 1].v_index; + else if (match_count == 1) { + /* Center vertex. */ + const int j = topo_pairs[a - 1].v_index; + index_lookup[j] = j; } + last = a; } - last = a; } } diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 3725590c188..07fedffaf80 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -384,7 +384,7 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot) /* props */ RNA_def_int(ot->srna, "vertices", 32, 3, MESH_ADD_VERTS_MAXI, "Vertices", "", 3, 500); RNA_def_float_distance(ot->srna, "radius1", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 1", "", 0.001, 100.00); - RNA_def_float_distance(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.001, 100.00); + RNA_def_float_distance(ot->srna, "radius2", 0.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius 2", "", 0.0, 100.00); RNA_def_float_distance(ot->srna, "depth", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Depth", "", 0.001, 100.00); RNA_def_enum(ot->srna, "end_fill_type", fill_type_items, 1, "Base Fill Type", ""); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index bf59693b856..5e44509e10a 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1472,7 +1472,7 @@ static void clip_to_ortho_planes(float v1[3], float v2[3], const float center[3] /* could be v1 or v2 */ sub_v3_v3(v1, center); - project_plane_v3_v3v3(closest, v1, dir); + project_plane_normalized_v3_v3v3(closest, v1, dir); add_v3_v3(closest, center); madd_v3_v3v3fl(v1, closest, dir, d); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index a6de1b284b7..68bd8ff27b1 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -446,6 +446,9 @@ BMVert *EDBM_vert_find_nearest_ex( unsigned int index; BMVert *eve; + /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ + ED_view3d_backbuf_validate(vc); + index = ED_view3d_backbuf_sample_rect( vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; @@ -630,7 +633,8 @@ BMEdge *EDBM_edge_find_nearest_ex( float dist_test = 0.0f; unsigned int index; BMEdge *eed; - + + /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ ED_view3d_backbuf_validate(vc); index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 65ee097e8e1..1f90b60a1f5 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -5235,8 +5235,10 @@ static int edbm_noise_exec(bContext *C, wmOperator *op) else { BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - float tin, dum; - externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL, false, false); + float tin = 0.0f, dum; + if (ma->mtex[ma->texact] != NULL) { + externtex(ma->mtex[ma->texact], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL, false, false); + } eve->co[2] += fac * tin; } } diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 743efb246ab..3f06ba2ced4 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -57,6 +57,7 @@ #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_material.h" +#include "BKE_object.h" #include "BKE_report.h" #include "BKE_editmesh.h" #include "BKE_multires.h" @@ -103,22 +104,26 @@ static void join_mesh_single( /* vertex groups */ MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT); + MDeformVert *dvert_src = CustomData_get(&me->vdata, 0, CD_MDEFORMVERT); - /* NB: vertex groups here are new version */ - if (dvert) { - for (a = 0; a < me->totvert; a++) { - for (b = 0; b < dvert[a].totweight; b++) { - /* Find the old vertex group */ - bDeformGroup *dg, *odg = BLI_findlink(&base_src->object->defbase, dvert[a].dw[b].def_nr); - int index; - if (odg) { - /* Search for a match in the new object, and set new index */ - for (dg = ob_dst->defbase.first, index = 0; dg; dg = dg->next, index++) { - if (STREQ(dg->name, odg->name)) { - dvert[a].dw[b].def_nr = index; - break; - } - } + /* Remap to correct new vgroup indices, if needed. */ + if (dvert_src) { + BLI_assert(dvert != NULL); + + /* Build src to merged mapping of vgroup indices. */ + bDeformGroup *dg_src; + int *vgroup_index_map = alloca(sizeof(*vgroup_index_map) * BLI_listbase_count(&base_src->object->defbase)); + bool is_vgroup_remap_needed = false; + + for (dg_src = base_src->object->defbase.first, b = 0; dg_src; dg_src = dg_src->next, b++) { + vgroup_index_map[b] = defgroup_name_index(ob_dst, dg_src->name); + is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[b] != b); + } + + if (is_vgroup_remap_needed) { + for (a = 0; a < me->totvert; a++) { + for (b = 0; b < dvert[a].totweight; b++) { + dvert[a].dw[b].def_nr = vgroup_index_map[dvert_src[a].dw[b].def_nr]; } } } @@ -596,6 +601,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_key_sort(key); } + /* Due to dependnecy cycle some other object might access old derived data. */ + BKE_object_free_derived_caches(ob); + DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 20523264cd9..4ed1e85fb48 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1154,7 +1154,21 @@ static int object_delete_exec(bContext *C, wmOperator *op) base->object->id.name + 2, scene->id.name + 2); continue; } + + /* This is sort of a quick hack to address T51243 - Proper thing to do here would be to nuke most of all this + * custom scene/object/base handling, and use generic lib remap/query for that. + * But this is for later (aka 2.8, once layers & co are settled and working). + */ + if (use_global && base->object->id.lib == NULL) { + /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */ + BKE_libblock_delete(bmain, &base->object->id); + changed = true; + continue; + } + /* remove from Grease Pencil parent */ + /* XXX This is likely not correct? Will also remove parent from grease pencil from other scenes, + * even when use_global is false... */ for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) { for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpl->parent != NULL) { @@ -1450,8 +1464,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, } if (ob_dst->parent) { - invert_m4_m4(ob_dst->parentinv, dob->mat); - /* note, this may be the parent of other objects, but it should * still work out ok */ BKE_object_apply_mat4(ob_dst, dob->mat, false, true); @@ -1472,7 +1484,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, ob_dst->partype = PAROBJECT; /* similer to the code above, see comments */ - invert_m4_m4(ob_dst->parentinv, dob->mat); BKE_object_apply_mat4(ob_dst, dob->mat, false, true); DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB); } @@ -1626,7 +1637,7 @@ static int convert_exec(bContext *C, wmOperator *op) MetaBall *mb; Mesh *me; const short target = RNA_enum_get(op->ptr, "target"); - const bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); + bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); int a, mballConverted = 0; /* don't forget multiple users! */ @@ -1664,6 +1675,19 @@ static int convert_exec(bContext *C, wmOperator *op) { for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) { Base *base = link->ptr.data; + ob = base->object; + + /* The way object type conversion works currently (enforcing conversion of *all* objetcs using converted + * obdata, even some un-selected/hidden/inother scene ones, sounds totally bad to me. + * However, changing this is more design than bugfix, not to mention convoluted code below, + * so that will be for later. + * But at the very least, do not do that with linked IDs! */ + if ((ID_IS_LINKED_DATABLOCK(ob) || (ob->data && ID_IS_LINKED_DATABLOCK(ob->data))) && !keep_original) { + keep_original = true; + BKE_reportf(op->reports, RPT_INFO, + "Converting some linked object/object data, enforcing 'Keep Original' option to True"); + } + DAG_id_tag_update(&base->object->id, OB_RECALC_DATA); } diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 968081818a2..ad43c48f0b9 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -51,6 +51,7 @@ #include "BKE_image.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_node.h" #include "BKE_report.h" #include "BKE_modifier.h" @@ -411,22 +412,18 @@ static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports) } } else { - if (ob->mat[i]) { - BKE_reportf(reports, RPT_ERROR, - "No active image found in material \"%s\" (%d) for object \"%s\"", - ob->mat[i]->id.name + 2, i, ob->id.name + 2); - } - else if (((Mesh *) ob->data)->mat[i]) { - BKE_reportf(reports, RPT_ERROR, + Material *mat = give_current_material(ob, i); + if (mat != NULL) { + BKE_reportf(reports, RPT_INFO, "No active image found in material \"%s\" (%d) for object \"%s\"", - ((Mesh *) ob->data)->mat[i]->id.name + 2, i, ob->id.name + 2); + mat->id.name + 2, i, ob->id.name + 2); } else { - BKE_reportf(reports, RPT_ERROR, - "No active image found in material (%d) for object \"%s\"", + BKE_reportf(reports, RPT_INFO, + "No active image found in material slot (%d) for object \"%s\"", i, ob->id.name + 2); } - return false; + continue; } image->id.tag |= LIB_TAG_DOIT; @@ -566,7 +563,11 @@ static void build_image_lookup(Main *bmain, Object *ob, BakeImages *bake_images) Image *image; ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); - if ((image->id.tag & LIB_TAG_DOIT)) { + /* Some materials have no image, we just ignore those cases. */ + if (image == NULL) { + bake_images->lookup[i] = -1; + } + else if (image->id.tag & LIB_TAG_DOIT) { for (j = 0; j < i; j++) { if (bake_images->data[j].image == image) { bake_images->lookup[i] = j; @@ -1172,6 +1173,9 @@ static int bake_exec(bContext *C, wmOperator *op) BakeAPIRender bkr = {NULL}; Scene *scene = CTX_data_scene(C); + G.is_break = false; + G.is_rendering = true; + bake_set_props(op, scene); bake_init_api_data(op, C, &bkr); @@ -1223,6 +1227,7 @@ static int bake_exec(bContext *C, wmOperator *op) finally: + G.is_rendering = false; BLI_freelistN(&bkr.selected_objects); return result; } diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 0fe43c44d7d..568778c0a86 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -528,8 +528,7 @@ static int group_unlink_exec(bContext *C, wmOperator *UNUSED(op)) if (!group) return OPERATOR_CANCELLED; - BKE_libblock_unlink(bmain, group, false, false); - BKE_libblock_free(bmain, group); + BKE_libblock_delete(bmain, group); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, NULL); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 06d306ded42..1aa1407797b 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -793,7 +793,7 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot) /* identifiers */ ot->name = "Add Modifier"; - ot->description = "Add a modifier to the active object"; + ot->description = "Add a procedural operation/effect to the active object"; ot->idname = "OBJECT_OT_modifier_add"; /* api callbacks */ diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index b5fbe4ba586..3284af2df69 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -72,6 +72,7 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_fcurve.h" +#include "BKE_idprop.h" #include "BKE_lamp.h" #include "BKE_lattice.h" #include "BKE_library.h" @@ -82,6 +83,7 @@ #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_sca.h" @@ -2101,30 +2103,52 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo single_tex_users_expand(bmain); } - BKE_main_id_clear_newpoins(bmain); - DAG_relations_tag_update(bmain); -} + /* Relink nodetrees' pointers that have been duplicated. */ + FOREACH_NODETREE(bmain, ntree, id) + { + /* This is a bit convoluted, we want to root ntree of copied IDs and only those, + * so we first check that old ID has been copied and that ntree is root tree of old ID, + * then get root tree of new ID and remap its pointers to new ID... */ + if (id->newid && (&ntree->id != id)) { + ntree = ntreeFromID(id->newid); + BKE_libblock_relink_to_newid(&ntree->id); + } + } FOREACH_NODETREE_END -/******************************* Make Local ***********************************/ + /* Relink datablock pointer properties */ + { + IDP_RelinkProperty(scene->id.properties); -/* helper for below, ma was checked to be not NULL */ -static void make_local_makelocalmaterial(Material *ma) -{ - AnimData *adt; - int b; + for (Base *base = scene->base.first; base; base = base->next) { + Object *ob = base->object; + if (!ID_IS_LINKED_DATABLOCK(ob)) { + IDP_RelinkProperty(ob->id.properties); + } + } - id_make_local(G.main, &ma->id, false, false); + if (scene->nodetree) { + IDP_RelinkProperty(scene->nodetree->id.properties); + for (bNode *node = scene->nodetree->nodes.first; node; node = node->next) { + IDP_RelinkProperty(node->prop); + } + } - for (b = 0; b < MAX_MTEX; b++) - if (ma->mtex[b] && ma->mtex[b]->tex) - id_make_local(G.main, &ma->mtex[b]->tex->id, false, false); + if (scene->gpd) { + IDP_RelinkProperty(scene->gpd->id.properties); + } - adt = BKE_animdata_from_id(&ma->id); - if (adt) BKE_animdata_make_local(adt); + IDP_RelinkProperty(scene->world->id.properties); - /* nodetree? XXX */ + if (scene->clip) { + IDP_RelinkProperty(scene->clip->id.properties); + } + } + BKE_main_id_clear_newpoins(bmain); + DAG_relations_tag_update(bmain); } +/******************************* Make Local ***********************************/ + enum { MAKE_LOCAL_SELECT_OB = 1, MAKE_LOCAL_SELECT_OBDATA = 2, @@ -2210,123 +2234,142 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene) return changed; } -static int make_local_exec(bContext *C, wmOperator *op) +static void make_local_animdata_tag_strips(ListBase *strips) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - AnimData *adt; - ParticleSystem *psys; - Material *ma, ***matarar; - Lamp *la; - ID *id; - const int mode = RNA_enum_get(op->ptr, "type"); - int a, b; - - if (mode == MAKE_LOCAL_ALL) { - /* de-select so the user can differentiate newly instanced from existing objects */ - BKE_scene_base_deselect_all(scene); + NlaStrip *strip; - if (make_local_all__instance_indirect_unused(bmain, scene)) { - BKE_report(op->reports, RPT_INFO, - "Orphan library objects added to the current scene to avoid loss"); + for (strip = strips->first; strip; strip = strip->next) { + if (strip->act) { + strip->act->id.tag &= ~LIB_TAG_PRE_EXISTING; + } + if (strip->remap && strip->remap->target) { + strip->remap->target->id.tag &= ~LIB_TAG_PRE_EXISTING; } - BKE_library_make_local(bmain, NULL, NULL, false, false); /* NULL is all libs */ - WM_event_add_notifier(C, NC_WINDOW, NULL); - return OPERATOR_FINISHED; + make_local_animdata_tag_strips(&strip->strips); } +} - tag_localizable_objects(C, mode); - - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) - { - if ((ob->id.tag & LIB_TAG_DOIT) == 0) { - continue; +/* Tag all actions used by given animdata to be made local. */ +static void make_local_animdata_tag(AnimData *adt) +{ + if (adt) { + /* Actions - Active and Temp */ + if (adt->action) { + adt->action->id.tag &= ~LIB_TAG_PRE_EXISTING; + } + if (adt->tmpact) { + adt->tmpact->id.tag &= ~LIB_TAG_PRE_EXISTING; + } + /* Remaps */ + if (adt->remap && adt->remap->target) { + adt->remap->target->id.tag &= ~LIB_TAG_PRE_EXISTING; } - if (ob->id.lib) - id_make_local(bmain, &ob->id, false, false); - } - CTX_DATA_END; + /* Drivers */ + /* TODO: need to handle the ID-targets too? */ - /* maybe object pointers */ - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) - { - if (ob->id.lib == NULL) { - ID_NEW_REMAP(ob->parent); + /* NLA Data */ + for (NlaTrack *nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + make_local_animdata_tag_strips(&nlt->strips); } } - CTX_DATA_END; - - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) - { - if ((ob->id.tag & LIB_TAG_DOIT) == 0) { - continue; - } +} - id = ob->data; +static void make_local_material_tag(Material *ma) +{ + if (ma) { + ma->id.tag &= ~LIB_TAG_PRE_EXISTING; + make_local_animdata_tag(BKE_animdata_from_id(&ma->id)); - if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) { - id_make_local(bmain, id, false, false); - adt = BKE_animdata_from_id(id); - if (adt) BKE_animdata_make_local(adt); + /* About nodetrees: root one is made local together with material, others we keep linked for now... */ - /* tag indirect data direct */ - matarar = give_matarar(ob); - if (matarar) { - for (a = 0; a < ob->totcol; a++) { - ma = (*matarar)[a]; - if (ma) - id_lib_extern(&ma->id); - } + for (int a = 0; a < MAX_MTEX; a++) { + if (ma->mtex[a] && ma->mtex[a]->tex) { + ma->mtex[a]->tex->id.tag &= ~LIB_TAG_PRE_EXISTING; } } + } +} - for (psys = ob->particlesystem.first; psys; psys = psys->next) - id_make_local(bmain, &psys->part->id, false, false); +static int make_local_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ParticleSystem *psys; + Material *ma, ***matarar; + Lamp *la; + const int mode = RNA_enum_get(op->ptr, "type"); + int a; + + /* Note: we (ab)use LIB_TAG_PRE_EXISTING to cherry pick which ID to make local... */ + if (mode == MAKE_LOCAL_ALL) { + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - adt = BKE_animdata_from_id(&ob->id); - if (adt) BKE_animdata_make_local(adt); + /* de-select so the user can differentiate newly instanced from existing objects */ + BKE_scene_base_deselect_all(scene); + + if (make_local_all__instance_indirect_unused(bmain, scene)) { + BKE_report(op->reports, RPT_INFO, "Orphan library objects added to the current scene to avoid loss"); + } } - CTX_DATA_END; + else { + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); + tag_localizable_objects(C, mode); - if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) { CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { if ((ob->id.tag & LIB_TAG_DOIT) == 0) { continue; } - if (ob->type == OB_LAMP) { - la = ob->data; - - for (b = 0; b < MAX_MTEX; b++) - if (la->mtex[b] && la->mtex[b]->tex) - id_make_local(bmain, &la->mtex[b]->tex->id, false, false); + ob->id.tag &= ~LIB_TAG_PRE_EXISTING; + make_local_animdata_tag(BKE_animdata_from_id(&ob->id)); + for (psys = ob->particlesystem.first; psys; psys = psys->next) { + psys->part->id.tag &= ~LIB_TAG_PRE_EXISTING; } - else { + + if (mode == MAKE_LOCAL_SELECT_OBDATA_MATERIAL) { for (a = 0; a < ob->totcol; a++) { ma = ob->mat[a]; - if (ma) - make_local_makelocalmaterial(ma); + if (ma) { + make_local_material_tag(ma); + } } matarar = (Material ***)give_matarar(ob); if (matarar) { for (a = 0; a < ob->totcol; a++) { ma = (*matarar)[a]; - if (ma) - make_local_makelocalmaterial(ma); + if (ma) { + make_local_material_tag(ma); + } + } + } + + if (ob->type == OB_LAMP) { + BLI_assert(ob->data != NULL); + la = ob->data; + for (a = 0; a < MAX_MTEX; a++) { + if (la->mtex[a] && la->mtex[a]->tex) { + la->id.tag &= ~LIB_TAG_PRE_EXISTING; + } } } } + + if (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL) && ob->data != NULL) { + ID *ob_data = ob->data; + ob_data->tag &= ~LIB_TAG_PRE_EXISTING; + make_local_animdata_tag(BKE_animdata_from_id(ob_data)); + } } CTX_DATA_END; } - BKE_main_id_clear_newpoins(bmain); - WM_event_add_notifier(C, NC_WINDOW, NULL); + BKE_library_make_local(bmain, NULL, NULL, true, false); /* NULL is all libs */ + WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 4d7d7df0d2f..47a3f79b0b4 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -923,8 +923,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) cent[2] = 0.0f; - cu->xof = cu->xof - (cent[0] / cu->fsize); - cu->yof = cu->yof - (cent[1] / cu->fsize); + cu->xof = cu->xof - cent[0]; + cu->yof = cu->yof - cent[1]; tot_change++; cu->id.tag |= LIB_TAG_DOIT; diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index 3d7a45843cc..edc3f6c784c 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -279,10 +279,10 @@ void DPAINT_OT_output_toggle(wmOperatorType *ot) /***************************** Image Sequence Baking ******************************/ typedef struct DynamicPaintBakeJob { - /* from wmJob */ - void *owner; - short *stop, *do_update; - float *progress; + /* from wmJob */ + void *owner; + short *stop, *do_update; + float *progress; struct Main *bmain; Scene *scene; @@ -297,13 +297,13 @@ typedef struct DynamicPaintBakeJob { static void dpaint_bake_free(void *customdata) { - DynamicPaintBakeJob *job = customdata; - MEM_freeN(job); + DynamicPaintBakeJob *job = customdata; + MEM_freeN(job); } static void dpaint_bake_endjob(void *customdata) { - DynamicPaintBakeJob *job = customdata; + DynamicPaintBakeJob *job = customdata; DynamicPaintCanvasSettings *canvas = job->canvas; canvas->flags &= ~MOD_DPAINT_BAKING; @@ -311,7 +311,7 @@ static void dpaint_bake_endjob(void *customdata) dynamicPaint_freeSurfaceData(job->surface); G.is_rendering = false; - BKE_spacedata_draw_locks(false); + BKE_spacedata_draw_locks(false); WM_set_locked_interface(G.main->wm.first, false); @@ -421,26 +421,26 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job) static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress) { - DynamicPaintBakeJob *job = customdata; + DynamicPaintBakeJob *job = customdata; - job->stop = stop; - job->do_update = do_update; - job->progress = progress; + job->stop = stop; + job->do_update = do_update; + job->progress = progress; job->start = PIL_check_seconds_timer(); job->success = 1; - G.is_break = false; /* reset BKE_blender_test_break*/ + G.is_break = false; /* reset BKE_blender_test_break*/ /* XXX annoying hack: needed to prevent data corruption when changing * scene frame in separate threads - */ - G.is_rendering = true; - BKE_spacedata_draw_locks(true); + */ + G.is_rendering = true; + BKE_spacedata_draw_locks(true); dynamicPaint_bakeImageSequence(job); - *do_update = true; - *stop = 0; + *do_update = true; + *stop = 0; } /* diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index e22a145b3a6..2541aaa4b11 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -4419,7 +4419,7 @@ void PE_undo_push(Scene *scene, const char *str) undo= undo->prev; } if (undo) { - while (edit->undo.first!=undo) { + while (edit->undo.first != undo) { PTCacheUndo *first= edit->undo.first; BLI_remlink(&edit->undo, first); free_PTCacheUndo(first); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index b5adf38527b..6460e83e2a0 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -631,71 +631,63 @@ static int fluid_validate_scene(ReportList *reports, Scene *scene, Object *fsDom #define FLUID_SUFFIX_CONFIG_TMP (FLUID_SUFFIX_CONFIG ".tmp") #define FLUID_SUFFIX_SURFACE "fluidsurface" -static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetFile, char *debugStrBuffer) +static bool fluid_init_filepaths( + ReportList *reports, FluidsimSettings *domainSettings, Object *fsDomain, + char *targetDir, char *targetFile) { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(fsDomain, eModifierType_Fluidsim); - FluidsimSettings *domainSettings= fluidmd->fss; - FILE *fileCfg; - int dirExist = 0; - char newSurfdataPath[FILE_MAX]; /* modified output settings */ const char *suffixConfigTmp = FLUID_SUFFIX_CONFIG_TMP; - int outStringsChanged = 0; /* prepare names... */ - const char *relbase= modifier_path_relbase(fsDomain); + const char *relbase = modifier_path_relbase(fsDomain); + + /* We do not accept empty paths, they can end in random places silently, see T51176. */ + if (domainSettings->surfdataPath[0] == '\0') { + modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath), + OB_FLUIDSIM_SURF_DIR_DEFAULT); + BKE_reportf(reports, RPT_WARNING, "Fluidsim: empty cache path, reset to default '%s'", + domainSettings->surfdataPath); + } BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); - BLI_strncpy(newSurfdataPath, domainSettings->surfdataPath, FILE_MAXDIR); /* if 0'd out below, this value is never used! */ - BLI_path_abs(targetDir, relbase); /* fixed #frame-no */ + BLI_path_abs(targetDir, relbase); /* .tmp: don't overwrite/delete original file */ BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp); - // make sure all directories exist - // as the bobjs use the same dir, this only needs to be checked - // for the cfg output - BLI_make_existing_file(targetFile); - - // check selected directory - // simply try to open cfg file for writing to test validity of settings - fileCfg = BLI_fopen(targetFile, "w"); - if (fileCfg) { - dirExist = 1; fclose(fileCfg); - // remove cfg dummy from directory test - BLI_delete(targetFile, false, false); - } - - if (targetDir[0] == '\0' || (!dirExist)) { - char blendFile[FILE_MAX]; - - // invalid dir, reset to current/previous - BLI_split_file_part(G.main->name, blendFile, sizeof(blendFile)); - BLI_replace_extension(blendFile, FILE_MAX, ""); /* strip .blend */ - BLI_snprintf(newSurfdataPath, FILE_MAX, "//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name); - - BLI_snprintf(debugStrBuffer, 256, "fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath); - elbeemDebugOut(debugStrBuffer); - outStringsChanged=1; - } - - /* check if modified output dir is ok */ -#if 0 - if (outStringsChanged) { - char dispmsg[FILE_MAX+256]; - int selection=0; - BLI_strncpy(dispmsg, "Output settings set to: '", sizeof(dispmsg)); - strcat(dispmsg, newSurfdataPath); - strcat(dispmsg, "'%t|Continue with changed settings %x1|Discard and abort %x0"); - - /* ask user if thats what he/she wants... */ - selection = pupmenu(dispmsg); - if (selection < 1) return 0; /* 0 from menu, or -1 aborted */ - BLI_strncpy(targetDir, newSurfdataPath, sizeof(targetDir)); - strncpy(domainSettings->surfdataPath, newSurfdataPath, FILE_MAXDIR); - BLI_path_abs(targetDir, G.main->name); /* fixed #frame-no */ + /* Ensure whole path exists and is wirtable. */ + const bool dir_exists = BLI_dir_create_recursive(targetDir); + const bool is_writable = BLI_file_is_writable(targetFile); + + /* We change path to some presumably valid default value, but do not allow bake process to continue, + * this gives user chance to set manually another path. */ + if (!dir_exists || !is_writable) { + modifier_path_init(domainSettings->surfdataPath, sizeof(domainSettings->surfdataPath), + OB_FLUIDSIM_SURF_DIR_DEFAULT); + + if (!dir_exists) { + BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not create cache directory '%s', reset to default '%s'", + targetDir, domainSettings->surfdataPath); + } + else { + BKE_reportf(reports, RPT_ERROR, "Fluidsim: cache directory '%s' is not writable, reset to default '%s'", + targetDir, domainSettings->surfdataPath); + } + + BLI_strncpy(targetDir, domainSettings->surfdataPath, FILE_MAXDIR); + BLI_path_abs(targetDir, relbase); + + /* .tmp: don't overwrite/delete original file */ + BLI_join_dirfile(targetFile, FILE_MAX, targetDir, suffixConfigTmp); + + /* Ensure whole path exists and is wirtable. */ + if (!BLI_dir_create_recursive(targetDir) || !BLI_file_is_writable(targetFile)) { + BKE_reportf(reports, RPT_ERROR, "Fluidsim: could not use default cache directory '%s', " + "please define a valid cache path manually", targetDir); + } + return false; } -#endif - return outStringsChanged; + + return true; } /* ******************************************************************************** */ @@ -857,7 +849,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor char targetDir[FILE_MAX]; // store & modify output settings char targetFile[FILE_MAX]; // temp. store filename from targetDir for access - int outStringsChanged = 0; // modified? copy back before baking float domainMat[4][4]; float invDomMat[4][4]; @@ -943,7 +934,11 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* ******** prepare output file paths ******** */ - outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer); + if (!fluid_init_filepaths(reports, domainSettings, fsDomain, targetDir, targetFile)) { + fluidbake_free_data(channels, fobjects, fsset, fb); + return false; + } + channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra) channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames; @@ -968,11 +963,6 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* ******** start writing / exporting ******** */ // use .tmp, don't overwrite/delete original file BLI_join_dirfile(targetFile, sizeof(targetFile), targetDir, suffixConfigTmp); - - // make sure these directories exist as well - if (outStringsChanged) { - BLI_make_existing_file(targetFile); - } /* ******** export domain to elbeem ******** */ elbeemResetSettings(fsset); diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index e81aa584586..f36ebb3715e 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -99,45 +99,45 @@ static int ptcache_job_break(void *customdata) static void ptcache_job_update(void *customdata, float progress, int *cancel) { - PointCacheJob *job = customdata; + PointCacheJob *job = customdata; - if (ptcache_job_break(job)) { - *cancel = 1; - } + if (ptcache_job_break(job)) { + *cancel = 1; + } - *(job->do_update) = true; - *(job->progress) = progress; + *(job->do_update) = true; + *(job->progress) = progress; } static void ptcache_job_startjob(void *customdata, short *stop, short *do_update, float *progress) { - PointCacheJob *job = customdata; + PointCacheJob *job = customdata; - job->stop = stop; - job->do_update = do_update; - job->progress = progress; + job->stop = stop; + job->do_update = do_update; + job->progress = progress; - G.is_break = false; + G.is_break = false; - /* XXX annoying hack: needed to prevent data corruption when changing - * scene frame in separate threads - */ - G.is_rendering = true; - BKE_spacedata_draw_locks(true); + /* XXX annoying hack: needed to prevent data corruption when changing + * scene frame in separate threads + */ + G.is_rendering = true; + BKE_spacedata_draw_locks(true); BKE_ptcache_bake(job->baker); - *do_update = true; - *stop = 0; + *do_update = true; + *stop = 0; } static void ptcache_job_endjob(void *customdata) { - PointCacheJob *job = customdata; + PointCacheJob *job = customdata; Scene *scene = job->baker->scene; - G.is_rendering = false; - BKE_spacedata_draw_locks(false); + G.is_rendering = false; + BKE_spacedata_draw_locks(false); WM_set_locked_interface(G.main->wm.first, false); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 8c5d25ad44d..9d98a3676ac 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -116,6 +116,7 @@ typedef struct RenderJob { ScrArea *sa; ColorManagedViewSettings view_settings; ColorManagedDisplaySettings display_settings; + bool supports_glsl_draw; bool interface_locked; } RenderJob; @@ -210,7 +211,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu } else { if (rr->renlay == NULL) return; - rectf = RE_RenderLayerGetPass(rr->renlay, SCE_PASS_COMBINED, viewname); + rectf = RE_RenderLayerGetPass(rr->renlay, RE_PASSNAME_COMBINED, viewname); } } if (rectf == NULL) return; @@ -569,6 +570,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec * operate with. */ if (rr->do_exr_tile || + !rj->supports_glsl_draw || ibuf->channels == 1 || U.image_draw_method != IMAGE_DRAW_METHOD_GLSL) { @@ -904,6 +906,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even rj->orig_layer = 0; rj->last_layer = 0; rj->sa = sa; + rj->supports_glsl_draw = IMB_colormanagement_support_glsl_draw(&scene->view_settings); BKE_color_managed_display_settings_copy(&rj->display_settings, &scene->display_settings); BKE_color_managed_view_settings_copy(&rj->view_settings, &scene->view_settings); @@ -1234,7 +1237,7 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda use_border = render_view3d_disprect(rp->scene, rp->ar, rp->v3d, rp->rv3d, &cliprct); - if ((update_flag & (PR_UPDATE_RENDERSIZE | PR_UPDATE_DATABASE)) || rstats->convertdone == 0) { + if ((update_flag & (PR_UPDATE_RENDERSIZE | PR_UPDATE_DATABASE | PR_UPDATE_VIEW)) || rstats->convertdone == 0) { RenderData rdata; /* no osa, blur, seq, layers, savebuffer etc for preview render */ diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 1d0f433ba38..01050eda70b 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -38,7 +38,6 @@ #include "BLI_math_color_blend.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLI_jitter.h" #include "BLI_threads.h" #include "BLI_task.h" @@ -257,10 +256,8 @@ static void screen_opengl_views_setup(OGLRender *oglrender) } } - BLI_lock_thread(LOCK_DRAW_IMAGE); if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd))) oglrender->iuser.flag &= ~IMA_SHOW_STEREO; - BLI_unlock_thread(LOCK_DRAW_IMAGE); /* will only work for non multiview correctly */ if (v3d) { @@ -874,7 +871,7 @@ static bool screen_opengl_render_anim_initialize(bContext *C, wmOperator *op) typedef struct WriteTaskData { RenderResult *rr; - int cfra; + Scene tmp_scene; } WriteTaskData; static void write_result_func(TaskPool * __restrict pool, @@ -883,10 +880,10 @@ static void write_result_func(TaskPool * __restrict pool, { OGLRender *oglrender = (OGLRender *) BLI_task_pool_userdata(pool); WriteTaskData *task_data = (WriteTaskData *) task_data_v; - Scene *scene = oglrender->scene; + Scene *scene = &task_data->tmp_scene; RenderResult *rr = task_data->rr; const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype); - const int cfra = task_data->cfra; + const int cfra = scene->r.cfra; bool ok; /* Don't attempt to write if we've got an error. */ if (!oglrender->pool_ok) { @@ -908,13 +905,11 @@ static void write_result_func(TaskPool * __restrict pool, * This is because underlying calls do not use r.cfra but use scene * for that. */ - Scene tmp_scene = *scene; - tmp_scene.r.cfra = cfra; if (is_movie) { ok = RE_WriteRenderViewsMovie(&reports, rr, - &tmp_scene, - &tmp_scene.r, + scene, + &scene->r, oglrender->mh, oglrender->movie_ctx_arr, oglrender->totvideos, @@ -934,8 +929,8 @@ static void write_result_func(TaskPool * __restrict pool, true, NULL); - BKE_render_result_stamp_info(&tmp_scene, tmp_scene.camera, rr, false); - ok = RE_WriteRenderViewsImage(NULL, rr, &tmp_scene, true, name); + BKE_render_result_stamp_info(scene, scene->camera, rr, false); + ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name); if (!ok) { BKE_reportf(&reports, RPT_ERROR, @@ -974,7 +969,7 @@ static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr) Scene *scene = oglrender->scene; WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data"); task_data->rr = rr; - task_data->cfra = scene->r.cfra; + task_data->tmp_scene = *scene; BLI_mutex_lock(&oglrender->task_mutex); oglrender->num_scheduled_frames++; if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) { @@ -1088,7 +1083,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent /* render frame? */ if (oglrender->timer == event->customdata) break; - /* fall-through */ + ATTR_FALLTHROUGH; default: /* nothing to do */ return OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index fa18b82507e..35d772afae7 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -1180,7 +1180,7 @@ void ED_preview_icon_render(Main *bmain, Scene *scene, ID *id, unsigned int *rec ip.bmain = bmain; ip.scene = scene; - ip.owner = id; + ip.owner = BKE_previewimg_id_ensure(id); ip.id = id; icon_preview_add_size(&ip, rect, sizex, sizey); diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 837573ad175..9bdb34f5384 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -611,7 +611,7 @@ void WORLD_OT_new(wmOperatorType *ot) /* identifiers */ ot->name = "New World"; ot->idname = "WORLD_OT_new"; - ot->description = "Add a new world"; + ot->description = "Create a new world Data-Block"; /* api callbacks */ ot->exec = new_world_exec; @@ -1818,7 +1818,7 @@ static void paste_mtex_copybuf(ID *id) mtex = &(((FreestyleLineStyle *)id)->mtex[(int)((FreestyleLineStyle *)id)->texact]); break; default: - BLI_assert("invalid id type"); + BLI_assert(!"invalid id type"); return; } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index f11a8177bf8..4e02ff77a31 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -189,8 +189,12 @@ void ED_render_engine_changed(Main *bmain) RE_FreePersistentData(); - for (scene = bmain->scene.first; scene; scene = scene->id.next) + for (scene = bmain->scene.first; scene; scene = scene->id.next) { ED_render_id_flush_update(bmain, &scene->id); + if (scene->nodetree) { + ntreeCompositUpdateRLayers(scene->nodetree); + } + } } /***************************** Updates *********************************** diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index 65f0fec50bc..c4a9af79ec2 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -44,6 +44,7 @@ #include "WM_types.h" #include "ED_screen.h" +#include "UI_interface.h" #include "wm_window.h" @@ -128,8 +129,8 @@ static ScrArea *find_area_image_empty(bContext *C) /* new window uses x,y to set position */ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) { - wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); + wmWindow *win = NULL; ScrArea *sa = NULL; SpaceImage *sima; bool area_was_image = false; @@ -138,25 +139,15 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports) return NULL; if (scene->r.displaymode == R_OUTPUT_WINDOW) { - rcti rect; - int sizex, sizey; - - sizex = 10 + (scene->r.xsch * scene->r.size) / 100; - sizey = 40 + (scene->r.ysch * scene->r.size) / 100; + int sizex = 30 * UI_DPI_FAC + (scene->r.xsch * scene->r.size) / 100; + int sizey = 60 * UI_DPI_FAC + (scene->r.ysch * scene->r.size) / 100; /* arbitrary... miniature image window views don't make much sense */ if (sizex < 320) sizex = 320; if (sizey < 256) sizey = 256; - /* some magic to calculate postition */ - /* pixelsize: mouse coords are in U.pixelsize units :/ */ - rect.xmin = (mx / U.pixelsize) + win->posx - sizex / 2; - rect.ymin = (my / U.pixelsize) + win->posy - sizey / 2; - rect.xmax = rect.xmin + sizex; - rect.ymax = rect.ymin + sizey; - /* changes context! */ - if (WM_window_open_temp(C, &rect, WM_WINDOW_RENDER) == NULL) { + if (WM_window_open_temp(C, mx, my, sizex, sizey, WM_WINDOW_RENDER) == NULL) { BKE_report(reports, RPT_ERROR, "Failed to open window!"); return NULL; } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 93bac3f6660..216cbe9d7f4 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -566,7 +566,7 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo float rast_x = x + off_x * xzoom; float rast_y = y + off_y * yzoom; - GLfloat scissor[4]; + GLfloat viewport[4]; int draw_w, draw_h; /* Determine the smallest number of pixels we need to draw @@ -581,9 +581,9 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo * fails if we zoom in on one really huge pixel so that it * covers the entire screen). */ - glGetFloatv(GL_SCISSOR_BOX, scissor); - draw_w = min_ii(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom)); - draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom)); + glGetFloatv(GL_VIEWPORT, viewport); + draw_w = min_ii(img_w - off_x, ceil((viewport[2] - rast_x) / xzoom)); + draw_h = min_ii(img_h - off_y, ceil((viewport[3] - rast_y) / yzoom)); if (draw_w > 0 && draw_h > 0) { diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 5cd0d33c365..f469686b0b2 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -766,7 +766,9 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y) /* lower edge */ const int yval = sa->v2->vec.y - headery_init; se = screen_findedge(sc, sa->v4, sa->v1); - select_connected_scredge(sc, se); + if (se != NULL) { + select_connected_scredge(sc, se); + } for (sv = sc->vertbase.first; sv; sv = sv->next) { if (sv != sa->v2 && sv != sa->v3) { if (sv->flag) { @@ -779,7 +781,9 @@ static void screen_test_scale(bScreen *sc, int winsize_x, int winsize_y) /* upper edge */ const int yval = sa->v1->vec.y + headery_init; se = screen_findedge(sc, sa->v2, sa->v3); - select_connected_scredge(sc, se); + if (se != NULL) { + select_connected_scredge(sc, se); + } for (sv = sc->vertbase.first; sv; sv = sv->next) { if (sv != sa->v1 && sv != sa->v4) { if (sv->flag) { @@ -1224,6 +1228,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) winrct.ymax = winsize_y - 1; /* header size depends on DPI, let's verify */ + WM_window_set_dpi(win); screen_refresh_headersizes(); screen_test_scale(win->screen, winsize_x, winsize_y); @@ -1758,7 +1763,7 @@ bool ED_screen_delete_scene(bContext *C, Scene *scene) BKE_libblock_remap(bmain, scene, newscene, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE); - BKE_libblock_free(bmain, scene); + BKE_libblock_free_us(bmain, scene); return true; } @@ -1922,7 +1927,6 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s ED_screen_set(C, sc); - BKE_screen_free(oldscreen); BKE_libblock_free(CTX_data_main(C), oldscreen); /* After we've restored back to SCREENNORMAL, we have to wait with @@ -2166,10 +2170,11 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute)) /* update animated texture nodes */ { Tex *tex; - for (tex = bmain->tex.first; tex; tex = tex->id.next) + for (tex = bmain->tex.first; tex; tex = tex->id.next) { if (tex->use_nodes && tex->nodetree) { ntreeTexTagAnimated(tex->nodetree); } + } } } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index c2e094fc161..27e19ca1fc3 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2260,25 +2260,28 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) BLI_dlrbTree_linkedlist_sync(&keys); /* find matching keyframe in the right direction */ - do { - if (next) - ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra); - else - ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra); - - if (ak) { - if (CFRA != (int)ak->cfra) { - /* this changes the frame, so set the frame and we're done */ - CFRA = (int)ak->cfra; - done = true; + if (next) + ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra); + else + ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra); + + while ((ak != NULL) && (done == false)) { + if (CFRA != (int)ak->cfra) { + /* this changes the frame, so set the frame and we're done */ + CFRA = (int)ak->cfra; + done = true; + } + else { + /* take another step... */ + if (next) { + ak = ak->next; } else { - /* make this the new starting point for the search */ - cfra = ak->cfra; + ak = ak->prev; } } - } while ((ak != NULL) && (done == false)); - + } + /* free temp stuff */ BLI_dlrbTree_free(&keys); @@ -3756,7 +3759,7 @@ static int screen_animation_cancel_exec(bContext *C, wmOperator *op) bScreen *screen = ED_screen_animation_playing(CTX_wm_manager(C)); if (screen) { - if (RNA_boolean_get(op->ptr, "restore_frame")) { + if (RNA_boolean_get(op->ptr, "restore_frame") && screen->animtimer) { ScreenAnimData *sad = screen->animtimer->customdata; Scene *scene = CTX_data_scene(C); @@ -3883,22 +3886,11 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot) static int userpref_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - rcti rect; - int sizex, sizey; - - sizex = 800 * UI_DPI_WINDOW_FAC; - sizey = 480 * UI_DPI_WINDOW_FAC; - - /* some magic to calculate postition */ - /* pixelsize: mouse coords are in U.pixelsize units :/ */ - rect.xmin = (event->x / U.pixelsize) + win->posx - sizex / 2; - rect.ymin = (event->y / U.pixelsize) + win->posy - sizey / 2; - rect.xmax = rect.xmin + sizex; - rect.ymax = rect.ymin + sizey; + int sizex = 800 * UI_DPI_FAC; + int sizey = 480 * UI_DPI_FAC; /* changes context! */ - if (WM_window_open_temp(C, &rect, WM_WINDOW_USERPREFS) != NULL) { + if (WM_window_open_temp(C, event->x, event->y, sizex, sizey, WM_WINDOW_USERPREFS) != NULL) { return OPERATOR_FINISHED; } else { diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 4f93c12385d..09b0847b306 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -797,6 +797,7 @@ static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus float map_alpha = (rgb[3] == 0.0f) ? rrgbf[3] : rrgbf[3] / rgb[3]; mul_v3_v3fl(rrgbf, rgb, map_alpha); + rrgbf[3] = rgb[3]; } else { unsigned char straight[4]; @@ -806,6 +807,7 @@ static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const bool is_torus rrgb[0] = straight[0]; rrgb[1] = straight[1]; rrgb[2] = straight[2]; + rrgb[3] = straight[3]; } } @@ -995,7 +997,7 @@ static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos, short tile) IMB_rectblend(ibufb, ibufb, ibuf, NULL, NULL, NULL, 0, region[a].destx, region[a].desty, region[a].destx, region[a].desty, region[a].srcx, region[a].srcy, - region[a].width, region[a].height, IMB_BLEND_COPY_RGB, false); + region[a].width, region[a].height, IMB_BLEND_COPY, false); } static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos) @@ -1096,6 +1098,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign /* lift from canvas */ if (s->tool == PAINT_TOOL_SOFTEN) { paint_2d_lift_soften(s, s->canvas, ibufb, bpos, tile); + blend = IMB_BLEND_INTERPOLATE; } else if (s->tool == PAINT_TOOL_SMEAR) { if (lastpos[0] == pos[0] && lastpos[1] == pos[1]) @@ -1103,6 +1106,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign paint_2d_convert_brushco(ibufb, lastpos, blastpos); paint_2d_lift_smear(s->canvas, ibufb, blastpos, tile); + blend = IMB_BLEND_INTERPOLATE; } else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) { liftpos[0] = pos[0] - offset[0] * s->canvas->x; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d0f1cc99b8d..8586eb42bec 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -3712,8 +3712,12 @@ static void project_paint_prepare_all_faces( } /* don't allow using the same inage for painting and stencilling */ - if (slot->ima == ps->stencil_ima) + if (slot->ima == ps->stencil_ima) { + /* While this shouldn't be used, face-winding reads all polys. + * It's less trouble to set all faces to valid UV's, avoiding NULL checks all over. */ + ps->dm_mloopuv[lt->poly] = mloopuv_base; continue; + } tpage = slot->ima; } @@ -4291,7 +4295,7 @@ static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, f return; } else { - blend_color_interpolate_float(rgba, rgba, projPixel->pixel.f_pt, mask); + blend_color_interpolate_float(rgba, projPixel->pixel.f_pt, rgba, mask); } BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); @@ -4750,6 +4754,9 @@ static void *do_projectpaint_thread(void *ph_v) copy_v3_v3(texrgb, texrgba); mask *= texrgba[3]; } + else { + zero_v3(texrgb); + } /* extra mask for normal, layer stencil, .. */ mask *= ((float)projPixel->mask) * (1.0f / 65535.0f); diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 31c471c3517..10628d8cccb 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -426,7 +426,7 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr Scene *scene = CTX_data_scene(C); Paint *paint = BKE_paint_get_active_from_context(C); Palette *palette = BKE_paint_palette(paint); - PaletteColor *color; + PaletteColor *color = NULL; Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C)); unsigned int col; const unsigned char *cp; diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index c2c52f58181..e273d3a40f0 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -670,7 +670,7 @@ static void SOUND_OT_mixdown(wmOperatorType *ot) /* identifiers */ ot->name = "Mixdown"; - ot->description = "Mixes the scene's audio to a sound file"; + ot->description = "Mix the scene's audio to a sound file"; ot->idname = "SOUND_OT_mixdown"; /* api callbacks */ diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 72de7e5c81c..1d67ac620b0 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -470,7 +470,7 @@ void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts) } else { /* set one user as active based on active index */ - if (ct->index == BLI_listbase_count_ex(&ct->users, ct->index + 1)) + if (ct->index >= BLI_listbase_count_ex(&ct->users, ct->index + 1)) ct->index = 0; ct->user = BLI_findlink(&ct->users, ct->index); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 14d0f909d23..59dd755173f 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -259,11 +259,9 @@ ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale return NULL; } -/* Returns color in the display space, matching ED_space_image_color_sample(). */ -bool ED_space_clip_color_sample(Scene *scene, SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3]) +/* Returns color in linear space, matching ED_space_image_color_sample(). */ +bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3]) { - const char *display_device = scene->display_settings.display_device; - struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); ImBuf *ibuf; float fx, fy, co[2]; bool ret = false; @@ -299,11 +297,7 @@ bool ED_space_clip_color_sample(Scene *scene, SpaceClip *sc, ARegion *ar, int mv ret = true; } } - - if (ret) { - IMB_colormanagement_scene_linear_to_display_v3(r_col, display); - } - + IMB_freeImBuf(ibuf); return ret; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 05e69968e35..237082f948b 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -337,7 +337,7 @@ static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) switch (wmn->data) { case ND_FRAME: clip_scopes_tag_refresh(sa); - /* fall-through */ + ATTR_FALLTHROUGH; case ND_FRAME_RANGE: ED_area_tag_redraw(sa); diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 169eb76399b..56c240c3d20 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -875,8 +875,7 @@ static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event) if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) { data->accurate = event->val == KM_PRESS; } - - /* fall-through */ + ATTR_FALLTHROUGH; case MOUSEMOVE: mdelta[0] = event->mval[0] - data->mval[0]; mdelta[1] = event->mval[1] - data->mval[1]; diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c index 4332f3ea765..aa8518befaa 100644 --- a/source/blender/editors/space_clip/tracking_ops_plane.c +++ b/source/blender/editors/space_clip/tracking_ops_plane.c @@ -301,8 +301,7 @@ static int slide_plane_marker_modal(bContext *C, if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) { data->accurate = event->val == KM_PRESS; } - - /* fall-through */ + ATTR_FALLTHROUGH; case MOUSEMOVE: mdelta[0] = event->mval[0] - data->previous_mval[0]; mdelta[1] = event->mval[1] - data->previous_mval[1]; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 83469a48165..d94aad640b7 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -277,9 +277,10 @@ typedef struct FileListFilter { /* FileListFilter.flags */ enum { - FLF_HIDE_DOT = 1 << 0, - FLF_HIDE_PARENT = 1 << 1, - FLF_HIDE_LIB_DIR = 1 << 2, + FLF_DO_FILTER = 1 << 0, + FLF_HIDE_DOT = 1 << 1, + FLF_HIDE_PARENT = 1 << 2, + FLF_HIDE_LIB_DIR = 1 << 3, }; typedef struct FileList { @@ -594,24 +595,27 @@ static bool is_filtered_file(FileListInternEntry *file, const char *UNUSED(root) { bool is_filtered = !is_hidden_file(file->relpath, filter); - if (is_filtered && filter->filter && !FILENAME_IS_CURRPAR(file->relpath)) { - if (file->typeflag & FILE_TYPE_DIR) { - if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { - if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { - is_filtered = false; + if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) { + /* We only check for types if some type are enabled in filtering. */ + if (filter->filter) { + if (file->typeflag & FILE_TYPE_DIR) { + if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { + if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { + is_filtered = false; + } + } + else { + if (!(filter->filter & FILE_TYPE_FOLDER)) { + is_filtered = false; + } } } else { - if (!(filter->filter & FILE_TYPE_FOLDER)) { + if (!(file->typeflag & filter->filter)) { is_filtered = false; } } } - else { - if (!(file->typeflag & filter->filter)) { - is_filtered = false; - } - } if (is_filtered && (filter->filter_search[0] != '\0')) { if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) { is_filtered = false; @@ -631,28 +635,31 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis if (BLO_library_path_explode(path, dir, &group, &name)) { is_filtered = !is_hidden_file(file->relpath, filter); - if (is_filtered && filter->filter && !FILENAME_IS_CURRPAR(file->relpath)) { - if (file->typeflag & FILE_TYPE_DIR) { - if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { - if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { - is_filtered = false; + if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) { + /* We only check for types if some type are enabled in filtering. */ + if (filter->filter || filter->filter_id) { + if (file->typeflag & FILE_TYPE_DIR) { + if (file->typeflag & (FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) { + if (!(filter->filter & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP))) { + is_filtered = false; + } } - } - else { - if (!(filter->filter & FILE_TYPE_FOLDER)) { - is_filtered = false; + else { + if (!(filter->filter & FILE_TYPE_FOLDER)) { + is_filtered = false; + } } } - } - if (is_filtered && group) { - if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) { - is_filtered = false; - } - else { - unsigned int filter_id = groupname_to_filter_id(group); - if (!(filter_id & filter->filter_id)) { + if (is_filtered && group) { + if (!name && (filter->flags & FLF_HIDE_LIB_DIR)) { is_filtered = false; } + else { + unsigned int filter_id = groupname_to_filter_id(group); + if (!(filter_id & filter->filter_id)) { + is_filtered = false; + } + } } } if (is_filtered && (filter->filter_search[0] != '\0')) { @@ -729,12 +736,17 @@ void filelist_filter(FileList *filelist) MEM_freeN(filtered_tmp); } -void filelist_setfilter_options(FileList *filelist, const bool hide_dot, const bool hide_parent, +void filelist_setfilter_options(FileList *filelist, const bool do_filter, + const bool hide_dot, const bool hide_parent, const unsigned int filter, const unsigned int filter_id, const char *filter_glob, const char *filter_search) { bool update = false; + if (((filelist->filter_data.flags & FLF_DO_FILTER) != 0) != (do_filter != 0)) { + filelist->filter_data.flags ^= FLF_DO_FILTER; + update = true; + } if (((filelist->filter_data.flags & FLF_HIDE_DOT) != 0) != (hide_dot != 0)) { filelist->filter_data.flags ^= FLF_HIDE_DOT; update = true; @@ -1104,7 +1116,10 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source); IMB_thumb_path_unlock(preview->path); - preview->flags = 0; /* Used to tell free func to not free anything! */ + /* Used to tell free func to not free anything. + * Note that we do not care about cas result here, + * we only want value attribution itself to be atomic (and memory barier).*/ + atomic_cas_uint32(&preview->flags, preview->flags, 0); BLI_thread_queue_push(cache->previews_done, preview); // printf("%s: End (%d)...\n", __func__, threadid); @@ -1964,7 +1979,7 @@ int ED_path_extension_type(const char *path) else if (BLI_testextensie(path, ".py")) { return FILE_TYPE_PYSCRIPT; } - else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", NULL)) { + else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) { return FILE_TYPE_TEXT; } else if (BLI_testextensie_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) { diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index f4304681780..4e9c1e0dd1d 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -68,7 +68,8 @@ int folderlist_clear_next(struct SpaceFile *sfile); void filelist_setsorting(struct FileList *filelist, const short sort); void filelist_sort(struct FileList *filelist); -void filelist_setfilter_options(struct FileList *filelist, const bool hide_dot, const bool hide_parent, +void filelist_setfilter_options(struct FileList *filelist, const bool do_filter, + const bool hide_dot, const bool hide_parent, const unsigned int filter, const unsigned int filter_id, const char *filter_glob, const char *filter_search); void filelist_filter(struct FileList *filelist); diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 71d49e0dc2e..ee0ec3fda39 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -48,9 +48,6 @@ #ifdef WIN32 # include <windows.h> /* need to include windows.h so _WIN32_IE is defined */ -# ifndef _WIN32_IE -# define _WIN32_IE 0x0400 /* minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already */ -# endif # include <shlobj.h> /* for SHGetSpecialFolderPath, has to be done before BLI_winstuff * because 'near' is disabled through BLI_windstuff */ # include "BLI_winstuff.h" diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 374db92297d..287b98fa589 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -223,9 +223,10 @@ static void file_refresh(const bContext *C, ScrArea *sa) filelist_setdir(sfile->files, params->dir); filelist_setrecursion(sfile->files, params->recursion_level); filelist_setsorting(sfile->files, params->sort); - filelist_setfilter_options(sfile->files, (params->flag & FILE_HIDE_DOT) != 0, + filelist_setfilter_options(sfile->files, (params->flag & FILE_FILTER) != 0, + (params->flag & FILE_HIDE_DOT) != 0, false, /* TODO hide_parent, should be controllable? */ - (params->flag & FILE_FILTER) ? params->filter : 0, + params->filter, params->filter_id, params->filter_glob, params->filter_search); diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index b9d98dfe794..8037c2deb5b 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -428,7 +428,6 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * RenderPass *rpass; const char *fake_name; int nr; - int passflag = 0; /* may have been freed since drawing */ rr = BKE_image_acquire_renderresult(scene, image); @@ -450,30 +449,31 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void * fake_name = ui_imageuser_pass_fake_name(rl); if (fake_name) { - BLI_strncpy(rpass_fake.internal_name, fake_name, sizeof(rpass_fake.internal_name)); + BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name)); nr += 1; } + ListBase added_passes; + BLI_listbase_clear(&added_passes); + /* rendered results don't have a Combined pass */ /* multiview: the ordering must be ascending, so the left-most pass is always the one picked */ for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) { - /* just show one pass of each kind */ - if (passflag & rpass->passtype) + if (BLI_findstring_ptr(&added_passes, rpass->name, offsetof(LinkData, data))) { continue; + } + BLI_addtail(&added_passes, BLI_genericNodeN(rpass->name)); - passflag |= rpass->passtype; - -final: - uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0, + uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->name), 0, 0, UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, ""); } + BLI_freelistN(&added_passes); + if (fake_name) { - fake_name = NULL; - rpass = &rpass_fake; - nr = 0; - goto final; + uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass_fake.name), 0, 0, + UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, 0.0f, 0.0, 0, -1, ""); } BKE_image_release_renderresult(scene, image); @@ -633,7 +633,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt int rp_index = iuser->pass + 1; for (rp = rpass->next; rp; rp = rp->next, rp_index++) { - if (rp->passtype != rpass->passtype) { + if (!STREQ(rp->name, rpass->name)) { iuser->pass = rp_index; changed = true; break; @@ -650,7 +650,7 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt } for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) { - if (rp->passtype == rpass->passtype) { + if (STREQ(rp->name, rpass->name)) { iuser->pass = rp_index - 1; changed = true; break; @@ -712,6 +712,10 @@ static void uiblock_layer_pass_buttons( const char *display_name = ""; const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO) != 0; + if (iuser->scene == NULL) { + return; + } + uiLayoutRow(layout, true); /* layer menu is 1/3 larger than pass */ @@ -769,7 +773,7 @@ static void uiblock_layer_pass_buttons( fake_name = ui_imageuser_pass_fake_name(rl); rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL); - display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : ""); + display_name = rpass ? rpass->name : (fake_name ? fake_name : ""); rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); but = uiDefMenuBut( block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name), @@ -1204,7 +1208,7 @@ void uiTemplateImageStereo3d(uiLayout *layout, PointerRNA *stereo3d_format_ptr) case S3D_DISPLAY_SIDEBYSIDE: { uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE); - /* fall-through */ + ATTR_FALLTHROUGH; } case S3D_DISPLAY_TOPBOTTOM: { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 324a3cb13b7..3c64d1ebb71 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1067,6 +1067,7 @@ typedef struct ImageOpenData { typedef struct ImageFrameRange { struct ImageFrameRange *next, *prev; ListBase frames; + /** The full path of the first file in the list of image files */ char filepath[FILE_MAX]; } ImageFrameRange; @@ -1092,12 +1093,12 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op) /** * \brief Get a list of frames from the list of image files matching the first file name sequence pattern * \param ptr [in] the RNA pointer containing the "directory" entry and "files" collection - * \param frames [out] the list of frame numbers found in the files matching the first one by name - * \param path [out] the full path of the first file in the list of image files + * \param frames_all [out] the list of frame numbers found in the files matching the first one by name */ static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all) { char dir[FILE_MAXDIR]; + const bool do_frame_range = RNA_boolean_get(ptr, "use_sequence_detection"); ImageFrameRange *frame_range = NULL; RNA_string_get(ptr, "directory", dir); @@ -1113,7 +1114,8 @@ static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_al frame->framenr = BLI_stringdec(filename, head, tail, &digits); /* still in the same sequence */ - if ((frame_range != NULL) && + if (do_frame_range && + (frame_range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) && (STREQLEN(base_tail, tail, FILE_MAX))) { @@ -1167,6 +1169,7 @@ static int image_sequence_get_len(ListBase *frames, int *ofs) } return frame_curr - (*ofs); } + *ofs = 0; return 0; } @@ -1325,7 +1328,11 @@ static int image_open_exec(bContext *C, wmOperator *op) iuser->frames = frame_seq_len; iuser->sfra = 1; iuser->framenr = 1; - iuser->offset = frame_ofs - 1; + if (ima->source == IMA_SRC_MOVIE) { + iuser->offset = 0; + } else { + iuser->offset = frame_ofs - 1; + } iuser->fie_ima = 2; iuser->scene = scene; BKE_image_init_imageuser(ima, iuser); @@ -1448,6 +1455,9 @@ void IMAGE_OT_open(wmOperatorType *ot) ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); + + RNA_def_boolean(ot->srna, "use_sequence_detection", true, "Detect Sequences", + "Automatically detect animated sequences in selected images (based on file names)"); } /******************** Match movie length operator ********************/ @@ -1890,7 +1900,6 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } else { colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); - IMB_metadata_copy(colormanaged_ibuf, ibuf); ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy); save_imbuf_post(ibuf, colormanaged_ibuf); } @@ -2900,11 +2909,9 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) } } -/* Returns color in the display space, matching ED_space_node_color_sample(). */ -bool ED_space_image_color_sample(Scene *scene, SpaceImage *sima, ARegion *ar, int mval[2], float r_col[3]) +/* Returns color in linear space, matching ED_space_node_color_sample(). */ +bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], float r_col[3]) { - const char *display_device = scene->display_settings.display_device; - struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); void *lock; ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); float fx, fy; @@ -2938,10 +2945,6 @@ bool ED_space_image_color_sample(Scene *scene, SpaceImage *sima, ARegion *ar, in } } - if (ret) { - IMB_colormanagement_scene_linear_to_display_v3(r_col, display); - } - ED_space_image_release_buffer(sima, ibuf, lock); return ret; } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 0e427623840..b87a0de23b9 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -162,7 +162,6 @@ static int pack_all_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); packAll(bmain, op->reports, true); - G.fileflags |= G_AUTOPACK; return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 5355b8012db..c774b99629c 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -552,7 +552,7 @@ void nla_buttons_register(ARegionType *art) pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers"); strcpy(pt->idname, "NLA_PT_modifiers"); strcpy(pt->label, N_("Modifiers")); - strcpy(pt->category, "Modifiers"); + strcpy(pt->category, "Modifiers"); strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); pt->draw = nla_panel_modifiers; pt->poll = nla_strip_eval_panel_poll; diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 93dcdbb5c02..255fc0d6f8f 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -362,7 +362,7 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri glVertex2f(strip->start, yminc); glEnd(); } - /* fall-through */ + ATTR_FALLTHROUGH; /* this only draws after the strip */ case NLASTRIP_EXTEND_HOLD_FORWARD: diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index e4f5802a395..f58b4050834 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1234,6 +1234,7 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_BSDF_GLOSSY: case SH_NODE_BSDF_GLASS: case SH_NODE_BSDF_REFRACTION: + case SH_NODE_BSDF_PRINCIPLED: ntype->draw_buttons = node_shader_buts_glossy; break; case SH_NODE_BSDF_ANISOTROPIC: @@ -2477,6 +2478,11 @@ static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), P uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE); } +static void node_composit_buts_brightcontrast(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "use_premultiply", 0, NULL, ICON_NONE); +} + /* only once called */ static void node_composit_set_butfunc(bNodeType *ntype) { @@ -2704,6 +2710,8 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_SUNBEAMS: ntype->draw_buttons = node_composit_buts_sunbeams; break; + case CMP_NODE_BRIGHTCONTRAST: + ntype->draw_buttons = node_composit_buts_brightcontrast; } } @@ -3075,7 +3083,7 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, node_file_output_socket_draw(C, layout, ptr, node_ptr); return; } - + if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) { node_socket_button_label(C, layout, ptr, node_ptr, text); return; @@ -3424,7 +3432,6 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, /* store current linewidth */ float linew; float arrow[2], arrow1[2], arrow2[2]; - const float px_fac = UI_DPI_WINDOW_FAC; glGetFloatv(GL_LINE_WIDTH, &linew); /* we can reuse the dist variable here to increment the GL curve eval amount*/ @@ -3451,7 +3458,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, } if (do_triple) { UI_ThemeColorShadeAlpha(th_col3, -80, -120); - glLineWidth(4.0f * px_fac); + glLineWidth(4.0f); glBegin(GL_LINE_STRIP); for (i = 0; i <= LINK_RESOL; i++) { @@ -3471,7 +3478,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, * for Intel hardware, this breaks with GL_LINE_STRIP and * changing color in begin/end blocks. */ - glLineWidth(1.5f * px_fac); + glLineWidth(1.5f); if (do_shaded) { glBegin(GL_LINES); for (i = 0; i < LINK_RESOL; i++) { @@ -3606,7 +3613,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) return; if (link->fromsock->flag & SOCK_UNAVAIL) return; - + if (link->flag & NODE_LINK_VALID) { /* special indicated link, on drop-node */ if (link->flag & NODE_LINKFLAG_HILITE) { @@ -3626,7 +3633,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) th_col1 = TH_REDALERT; } } - + node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); // node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3); } diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index bcd0f6623e1..dc6b06790e0 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -107,13 +107,15 @@ static bool add_reroute_intersect_check(bNodeLink *link, float mcoords[][2], int if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) { - for (i = 0; i < tot - 1; i++) - for (b = 0; b < NODE_LINK_RESOL; b++) + for (i = 0; i < tot - 1; i++) { + for (b = 0; b < NODE_LINK_RESOL; b++) { if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) { result[0] = (mcoords[i][0] + mcoords[i + 1][0]) / 2.0f; result[1] = (mcoords[i][1] + mcoords[i + 1][1]) / 2.0f; return 1; } + } + } } return 0; } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index ab40c55b59d..6e25c87d274 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -820,14 +820,6 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); -#ifdef WITH_COMPOSITOR - if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) { - if (COM_isHighlightedbNode(node)) { - UI_ThemeColorBlend(color_id, TH_ACTIVE, 0.5f); - } - } -#endif - glLineWidth(1.0f); UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); @@ -989,16 +981,6 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b if (node->flag & NODE_MUTED) UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); -#ifdef WITH_COMPOSITOR - if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) { - if (COM_isHighlightedbNode(node)) { - UI_ThemeColorBlend(color_id, TH_ACTIVE, 0.5f); - } - } -#else - (void)ntree; -#endif - UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad); /* outline active and selected emphasis */ @@ -1253,15 +1235,9 @@ static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, const float center[2] static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key) { SpaceNode *snode = CTX_wm_space_node(C); - + node_uiblocks_init(C, ntree); - -#ifdef WITH_COMPOSITOR - if (ntree->type == NTREE_COMPOSIT) { - COM_startReadHighlights(); - } -#endif - + node_update_nodetree(C, ntree); node_draw_nodetree(C, ar, snode, ntree, parent_key); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index fdfe316f5ed..5f8f839025f 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -505,8 +505,6 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce) nodeAddLink(sce->nodetree, in, fromsock, out, tosock); ntreeUpdateTree(CTX_data_main(C), sce->nodetree); - - // XXX ntreeCompositForceHidden(sce->nodetree); } /* assumes nothing being done in ntree yet, sets the default in/out node */ @@ -582,17 +580,11 @@ void snode_set_context(const bContext *C) } } - if (snode->nodetree != ntree || snode->id != id || snode->from != from || snode->treepath.last == NULL) { + if (snode->nodetree != ntree || snode->id != id || snode->from != from || + (snode->treepath.last == NULL && ntree)) + { ED_node_tree_start(snode, ntree, id, from); } - - /* XXX Legacy hack to update render layer node outputs. - * This should be handled by the depsgraph eventually ... - */ - if (ED_node_is_compositor(snode) && snode->nodetree) { - /* update output sockets based on available layers */ - ntreeCompositForceHidden(snode->nodetree); - } } void snode_update(SpaceNode *snode, bNode *node) @@ -2094,7 +2086,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) /* make sure all clipboard nodes would be valid in the target tree */ all_nodes_valid = true; for (node = clipboard_nodes_lb->first; node; node = node->next) { - if (!node->typeinfo->poll_instance(node, ntree)) { + if (!node->typeinfo->poll_instance || !node->typeinfo->poll_instance(node, ntree)) { all_nodes_valid = false; BKE_reportf(op->reports, RPT_ERROR, "Cannot add node %s into node tree %s", node->name, ntree->id.name + 2); } diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 26eeaa91dd0..9d750bfe348 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -37,6 +37,7 @@ #include "DNA_anim_types.h" #include "BLI_listbase.h" +#include "BLI_linklist.h" #include "BLI_math.h" #include "BLT_translation.h" @@ -92,9 +93,9 @@ static int node_group_operator_editable(bContext *C) * Disabled otherwise to allow pynodes define their own operators * with same keymap. */ - if (STREQ(snode->tree_idname, "ShaderNodeTree") || - STREQ(snode->tree_idname, "CompositorNodeTree") || - STREQ(snode->tree_idname, "TextureNodeTree")) + if (ED_node_is_shader(snode) || + ED_node_is_compositor(snode) || + ED_node_is_texture(snode)) { return true; } @@ -112,11 +113,11 @@ static const char *group_node_idname(bContext *C) { SpaceNode *snode = CTX_wm_space_node(C); - if (STREQ(snode->tree_idname, "ShaderNodeTree")) + if (ED_node_is_shader(snode)) return "ShaderNodeGroup"; - else if (STREQ(snode->tree_idname, "CompositorNodeTree")) + else if (ED_node_is_compositor(snode)) return "CompositorNodeGroup"; - else if (STREQ(snode->tree_idname, "TextureNodeTree")) + else if (ED_node_is_texture(snode)) return "TextureNodeGroup"; return ""; @@ -186,6 +187,7 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) bNode *node, *nextnode; bNodeTree *ngroup, *wgroup; ListBase anim_basepaths = {NULL, NULL}; + LinkNode *nodes_delayed_free = NULL; ngroup = (bNodeTree *)gnode->id; @@ -208,8 +210,8 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) * This also removes remaining links to and from interface nodes. */ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) { - nodeFreeNode(wgroup, node); - continue; + /* We must delay removal since sockets will reference this node. see: T52092 */ + BLI_linklist_prepend(&nodes_delayed_free, node); } /* keep track of this node's RNA "base" path (the part of the path identifying the node) @@ -336,6 +338,11 @@ static int node_group_ungroup(bNodeTree *ntree, bNode *gnode) } } + while (nodes_delayed_free) { + node = BLI_linklist_pop(&nodes_delayed_free); + nodeFreeNode(ntree, node); + } + /* delete the group instance */ nodeFreeNode(ntree, gnode); diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 8c5d2d82468..f497a06cb12 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -345,7 +345,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); - if (ibuf == NULL) { + if ((ibuf == NULL) || (ibuf->x == 0) || (ibuf->y == 0)) { BKE_image_release_ibuf(ima, ibuf, lock); return OPERATOR_CANCELLED; } @@ -417,20 +417,18 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) } } -/* Returns color in the display space, matching ED_space_image_color_sample(). +/* Returns color in linear space, matching ED_space_image_color_sample(). * And here we've got recursion in the comments tips... */ -bool ED_space_node_color_sample(Scene *scene, SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3]) +bool ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float r_col[3]) { - const char *display_device = scene->display_settings.display_device; - struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); void *lock; Image *ima; ImBuf *ibuf; float fx, fy, bufx, bufy; bool ret = false; - if (STREQ(snode->tree_idname, ntreeType_Composite->idname) || (snode->flag & SNODE_BACKDRAW) == 0) { + if (!ED_node_is_compositor(snode) || (snode->flag & SNODE_BACKDRAW) == 0) { /* use viewer image for color sampling only if we're in compositor tree * with backdrop enabled */ @@ -471,10 +469,6 @@ bool ED_space_node_color_sample(Scene *scene, SpaceNode *snode, ARegion *ar, int } } - if (ret) { - IMB_colormanagement_scene_linear_to_display_v3(r_col, display); - } - BKE_image_release_ibuf(ima, ibuf, lock); return ret; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index bbdf6feef01..2267316d257 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -753,6 +753,10 @@ static void node_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegi break; } break; + case NC_WM: + if (wmn->data == ND_JOB) + ED_region_tag_redraw(ar); + break; case NC_SCENE: case NC_MATERIAL: case NC_TEXTURE: diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 335eb95da0e..265a19b9e7e 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -1944,7 +1944,7 @@ static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEv { /* present a prompt to informing users that this change is irreversible */ return WM_operator_confirm_message(C, op, - "Purging unused data-blocks cannot be undone. " + "Purging unused data-blocks cannot be undone and saves to current .blend file. " "Click here to proceed..."); } @@ -1966,7 +1966,8 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot) /* identifiers */ ot->idname = "OUTLINER_OT_orphans_purge"; ot->name = "Purge All"; - ot->description = "Clear all orphaned data-blocks without any users from the file (cannot be undone)"; + ot->description = "Clear all orphaned data-blocks without any users from the file " + "(cannot be undone, saves to current .blend file)"; /* callbacks */ ot->invoke = outliner_orphans_purge_invoke; diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 89df471990a..18cc2a015e6 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -470,10 +470,11 @@ static eOLDrawState tree_element_active_defgroup( WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob); } else { - if (ob == OBACT) + if (ob == OBACT) { if (ob->actdef == te->index + 1) { return OL_DRAWSEL_NORMAL; } + } } return OL_DRAWSEL_NONE; } @@ -706,7 +707,12 @@ static eOLDrawState tree_element_active_pose( { Object *ob = (Object *)tselem->id; Base *base = BKE_scene_base_find(scene, ob); - + + if (base == NULL) { + /* Armature not instantiated in current scene (e.g. inside an appended group...). */ + return OL_DRAWSEL_NONE; + } + if (set != OL_SETSEL_NONE) { if (scene->obedit) ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 086cc55366b..29dcf73109c 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -235,8 +235,7 @@ static void unlink_group_cb( } else { Main *bmain = CTX_data_main(C); - BKE_libblock_unlink(bmain, group, false, false); - BKE_libblock_free(bmain, group); + BKE_libblock_delete(bmain, group); } } @@ -399,7 +398,7 @@ static void object_deselect_cb( static void object_delete_cb( bContext *C, ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) + TreeStoreElem *tsep, TreeStoreElem *tselem, void *user_data) { Base *base = (Base *)te->directdata; @@ -431,6 +430,13 @@ static void object_delete_cb( tselem->id = NULL; #endif } + else { + /* No base, means object is no more instantiated in any scene. + * Should not happen ideally, but does happens, see T51625. + * Rather than twisting in all kind of ways to address all possible cases leading to that situation, simpler + * to allow deleting such object as a mere generic data-block. */ + id_delete_cb(C, reports, scene, te, tsep, tselem, user_data); + } } static void id_local_cb( @@ -1051,7 +1057,7 @@ static EnumPropertyItem prop_group_op_types[] = { {OL_GROUPOP_UNLINK, "UNLINK", 0, "Unlink Group", ""}, {OL_GROUPOP_LOCAL, "LOCAL", 0, "Make Local Group", ""}, {OL_GROUPOP_LINK, "LINK", 0, "Link Group Objects to Scene", ""}, - {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", "WARNING: no undo"}, + {OL_GROUPOP_DELETE, "DELETE", 0, "Delete Group", ""}, {OL_GROUPOP_REMAP, "REMAP", 0, "Remap Users", "Make all users of selected data-blocks to use instead current (clicked) one"}, {OL_GROUPOP_INSTANCE, "INSTANCE", 0, "Instance Groups in Scene", ""}, @@ -1090,7 +1096,7 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) DAG_relations_tag_update(CTX_data_main(C)); break; case OL_GROUPOP_DELETE: - WM_operator_name_call(C, "OUTLINER_OT_id_delete", WM_OP_INVOKE_REGION_WIN, NULL); + outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL); break; case OL_GROUPOP_REMAP: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index ec46c5df9a0..09a49f201d4 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1080,6 +1080,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv; PropertyRNA *prop, *iterprop; PropertyType proptype; + + /* Don't display arrays larger, weak but index is stored as a short, + * also the outliner isn't intended for editing such large data-sets. */ + BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!"); + const int tot_limit = SHRT_MAX; + int a, tot; /* we do lazy build, for speed and to avoid infinite recusion */ @@ -1101,6 +1107,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i iterprop = RNA_struct_iterator_property(ptr->type); tot = RNA_property_collection_length(ptr, iterprop); + CLAMP_MAX(tot, tot_limit); /* auto open these cases */ if (!parent || (RNA_property_type(parent->directdata)) == PROP_POINTER) @@ -1147,6 +1154,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i } else if (proptype == PROP_COLLECTION) { tot = RNA_property_collection_length(ptr, prop); + CLAMP_MAX(tot, tot_limit); if (TSELEM_OPEN(tselem, soops)) { for (a = 0; a < tot; a++) { @@ -1159,6 +1167,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i } else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { tot = RNA_property_array_length(ptr, prop); + CLAMP_MAX(tot, tot_limit); if (TSELEM_OPEN(tselem, soops)) { for (a = 0; a < tot; a++) diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 8ae89941bdb..e63569ac386 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -562,7 +562,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen } if (seq1 == NULL) seq1 = seq2; if (seq3 == NULL) seq3 = seq2; - /* fall-through */ + ATTR_FALLTHROUGH; case 2: if (seq1 == NULL || seq2 == NULL) { *error_str = N_("2 selected sequence strips are needed"); @@ -3352,6 +3352,9 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op) if (seq_act->sound) BKE_sound_add_scene_sound_defaults(scene, seq_act); if (seq_other->sound) BKE_sound_add_scene_sound_defaults(scene, seq_other); + BKE_sequence_invalidate_cache(scene, seq_act); + BKE_sequence_invalidate_cache(scene, seq_other); + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -3509,7 +3512,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50"); bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75"); bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100"); - bool override = RNA_boolean_get(op->ptr, "override"); + bool overwrite = RNA_boolean_get(op->ptr, "overwrite"); bool turnon = true; if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) { @@ -3545,7 +3548,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) else seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100; - if (!override) + if (!overwrite) seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING; else seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING; @@ -3577,7 +3580,7 @@ void SEQUENCER_OT_enable_proxies(wmOperatorType *ot) RNA_def_boolean(ot->srna, "proxy_50", false, "50%", ""); RNA_def_boolean(ot->srna, "proxy_75", false, "75%", ""); RNA_def_boolean(ot->srna, "proxy_100", false, "100%", ""); - RNA_def_boolean(ot->srna, "override", false, "Override", ""); + RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", ""); } /* change ops */ diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 48c49f36471..d88ed36e392 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -683,7 +683,7 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op)) if (!select_more_less_seq__internal(scene, false, false)) return OPERATOR_CANCELLED; - + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt index de85ddc40ab..39b48f5b52c 100644 --- a/source/blender/editors/space_text/CMakeLists.txt +++ b/source/blender/editors/space_text/CMakeLists.txt @@ -43,6 +43,8 @@ set(SRC text_format.c text_format_lua.c text_format_osl.c + text_format_pov.c + text_format_pov_ini.c text_format_py.c text_header.c text_ops.c diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 686a10fc785..fcb46ced750 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -158,7 +158,7 @@ static void text_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) } ED_area_tag_redraw(sa); - /* fall-through */ /* fall down to tag redraw */ + ATTR_FALLTHROUGH; /* fall down to tag redraw */ case NA_ADDED: case NA_REMOVED: ED_area_tag_redraw(sa); @@ -636,5 +636,7 @@ void ED_spacetype_text(void) ED_text_format_register_py(); ED_text_format_register_osl(); ED_text_format_register_lua(); + ED_text_format_register_pov(); + ED_text_format_register_pov_ini(); } diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index c38c57b9528..da5fa9da046 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -328,7 +328,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e if (tools & TOOL_SUGG_LIST) { texttool_suggest_clear(); } - if (tools & TOOL_DOCUMENT) { + if (tools & TOOL_DOCUMENT) { texttool_docs_clear(); doc_scroll = 0; } @@ -455,7 +455,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e break; case PAGEDOWNKEY: scroll = SUGG_LIST_SIZE - 1; - /* fall-through */ + ATTR_FALLTHROUGH; case WHEELDOWNMOUSE: case DOWNARROWKEY: if (event->val == KM_PRESS) { @@ -489,7 +489,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e break; case PAGEUPKEY: scroll = SUGG_LIST_SIZE - 1; - /* fall-through */ + ATTR_FALLTHROUGH; case WHEELUPMOUSE: case UPARROWKEY: if (event->val == KM_PRESS) { diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h index b901ec83a9c..d7cf31d0b41 100644 --- a/source/blender/editors/space_text/text_format.h +++ b/source/blender/editors/space_text/text_format.h @@ -102,6 +102,8 @@ void ED_text_format_register(TextFormatType *tft); void ED_text_format_register_py(void); void ED_text_format_register_osl(void); void ED_text_format_register_lua(void); +void ED_text_format_register_pov(void); +void ED_text_format_register_pov_ini(void); #define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \ (strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0) diff --git a/source/blender/editors/space_text/text_format_pov.c b/source/blender/editors/space_text/text_format_pov.c new file mode 100644 index 00000000000..0d19c503798 --- /dev/null +++ b/source/blender/editors/space_text/text_format_pov.c @@ -0,0 +1,809 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_text/text_format_pov.c + * \ingroup sptext + */ + +#include <string.h> + +#include "BLI_blenlib.h" + +#include "DNA_text_types.h" +#include "DNA_space_types.h" + +#include "BKE_text.h" + +#include "text_format.h" + +/* *** POV Keywords (for format_line) *** */ + +/* Checks the specified source string for a POV keyword (minus boolean & 'nil'). + * This name must start at the beginning of the source string and must be + * followed by a non-identifier (see text_check_identifier(char)) or null char. + * + * If a keyword is found, the length of the matching word is returned. + * Otherwise, -1 is returned. + * + * See: + * http://www.povray.org/documentation/view/3.7.0/212/ + */ + +static int txtfmt_pov_find_keyword(const char *string) +{ + int i, len; + /* Language Directives */ + if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + return (i == 0 || text_check_identifier(string[i])) ? -1 : i; +} + +static int txtfmt_pov_find_reserved_keywords(const char *string) +{ + int i, len; + /* POV-Ray Built-in Variables + * list is from... + * http://www.povray.org/documentation/view/3.7.0/212/ + */ + /* Language Keywords */ + if (STR_LITERAL_STARTSWITH(string, "aa_level", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "aa_threshold", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "absorption", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "accuracy", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "adc_bailout", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "albedo", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "all_intersections", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "translucency", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "all", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "alpha", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "altitude", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "always_sample", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ambient_light", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ambient", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "angle", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "aperture", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "arc_angle", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "area_light", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "area_illumination", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "array", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "assumed_gamma", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "autostop", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "black_hole", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "blur_samples", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "brightness", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "brilliance", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "caustics", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "charset", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "collect", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "component", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "composite", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "confidence", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "conserve_energy", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "contained_by", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "coords", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "count", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "crand", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cube", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cutaway_textures", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "diffuse", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "direction", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "dispersion_samples", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "dispersion", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "dist_exp", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "distance", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "eccentricity", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "emission", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "error_bound", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "evaluate", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "expand_thresholds", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "exponent", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "exterior", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "extinction", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "face_indices", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "falloff_angle", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "falloff", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "file_gamma", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "flatness", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "flip", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "focal_point", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fog_alt", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fog_offset", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fog_type", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "form", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fresnel", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "gamma", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "gather", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "global_settings", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "gray_threshold", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "hf_gray_16", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "hierarchy", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "hypercomplex", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "importance", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "inside_vector", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "internal", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "intervals", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ior", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "irid_wavelength", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "irid", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "load_file", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "location", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "look_at", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "looks_like", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "low_error_factor", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "major_radius", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max_distance", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max_gradient", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max_intersections", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max_iteration", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max_sample", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max_trace_level", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max_trace", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "maximum_reuse", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "metallic", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "method", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "metric", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "minimum_reuse", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "nearest_count", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "normal_indices", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "normal_vectors", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "now", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "number_of_waves", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "offset", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "open", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "orientation", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pass_through", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pattern", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "phong_size", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "phong", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "point_at", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pot", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "precision", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "precompute", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pretrace_end", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pretrace_start", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "prod", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pwr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "quaternion", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "radiosity", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "radius", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ratio", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "reciprocal", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "recursion_limit", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "reflection_exponent", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "reflection", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "refraction", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "right", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "roughness", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "samples", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "save_file", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "scattering", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "size", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sky", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "slice", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "smooth", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "solid", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "spacing", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "specular", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "split_union", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "spotlight", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "strength", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sturm", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sum", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "target", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "texture_list", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "thickness", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "threshold", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tightness", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tolerance", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "toroidal", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ttf", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "turb_depth", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "u_steps", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "up", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "use_alpha", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uv_indices", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uv_vectors", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "v_steps", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "variance", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vertex_vectors", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "water_level", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "width", len)) i = len; + + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + return (i == 0 || text_check_identifier(string[i])) ? -1 : i; +} + + +static int txtfmt_pov_find_reserved_builtins(const char *string) +{ + int i, len; + + /* POV-Ray Built-in Variables + * list is from... + * http://www.povray.org/documentation/view/3.7.0/212/ + */ + if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len; + /* Color Identifiers */ + else if (STR_LITERAL_STARTSWITH(string, "blue", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "filter", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "gray", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "green", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "red", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rgbft", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rgbf", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rgbt", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rgb", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "srgb", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sRGB", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "SRGB", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "srgbft", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "srgbf", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "srgbt", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "transmit", len)) i = len; + /* Patterns */ + else if (STR_LITERAL_STARTSWITH(string, "agate", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "aoi", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "average", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "boxed", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bozo", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "brick", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bumps", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cells", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "checker", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "crackle", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cylindrical", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "density_file", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "dents", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "facets", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "gradient", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "granite", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "hexagon", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "image_pattern", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "julia", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "leopard", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "magnet", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "mandel", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "marble", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "onion", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pavement", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pigment_pattern", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "planar", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "quilted", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "radial", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ripples", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "slope", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "spherical", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "spiral1", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "spiral2", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "spotted", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "square", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tile2", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tiling", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tiles", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "triangular", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "waves", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "wood", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "wrinkles", len)) i = len; + /* Objects */ + else if (STR_LITERAL_STARTSWITH(string, "background", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bicubic_patch", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "blob", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "box", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "camera", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cone", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cylinder", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "difference", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "disc", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fog", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "height_field", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "intersection", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "isosurface", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "julia_fractal", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "lathe", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "light_group", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "light_source", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "merge", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "mesh2", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "mesh", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "object", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ovus", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "lemon", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "parametric", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "plane", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "poly", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "polygon", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "polynomial", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "prism", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "quadric", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "quartic", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rainbow", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sky_sphere", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "smooth_triangle", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sphere_sweep", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sphere", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "spline", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "superellipsoid", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sor", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "text", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "torus", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "triangle", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "union", len)) i = len; + /* Filetypes */ + else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len; + /* Spline Identifiers */ + else if (STR_LITERAL_STARTSWITH(string, "b_spline", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bezier_spline", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "conic_sweep", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cubic_spline", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "linear_spline", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "linear_sweep", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "natural_spline", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "quadratic_spline", len)) i = len; + /* Encodings */ + else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len; + /* Camera Types */ + else if (STR_LITERAL_STARTSWITH(string, "fisheye", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "mesh_camera", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "omnimax", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "orthographic", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "panoramic", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "perspective", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ultra_wide_angle", len)) i = len; + /* Built-in Vectors */ + else if (STR_LITERAL_STARTSWITH(string, "t", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "u", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "v", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "x", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "y", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "z", len)) i = len; + + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + return (i == 0 || text_check_identifier(string[i])) ? -1 : i; +} + + +/* Checks the specified source string for a POV modifiers. This + * name must start at the beginning of the source string and must be followed + * by a non-identifier (see text_check_identifier(char)) or null character. + * + * If a special name is found, the length of the matching name is returned. + * Otherwise, -1 is returned. + * + * See: + * http://www.povray.org/documentation/view/3.7.0/212/ + */ + +static int txtfmt_pov_find_specialvar(const char *string) +{ + int i, len; + /* Modifiers */ + if (STR_LITERAL_STARTSWITH(string, "interior_texture", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "double_illuminate", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "media_interaction", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "media_attenuation", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "projected_through", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "noise_generator", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "agate_turb", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bounded_by", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "brick_size", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bump_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bump_size", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "circular", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "clipped_by", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cubic", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "color_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "color", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "colour_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "colour", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "control0", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "control1", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cubic_wave", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "density_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "density", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fade_color", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fade_colour", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fade_distance", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fade_power", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "frequency", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "global_lights", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "hollow", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "image_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "adaptive", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "interior", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "interpolate", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "inverse", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "jitter", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "lambda", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "map_type", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "material_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "material", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "matrix", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "media", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "mm_per_unit", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "mortar", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "no_bump_scale", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "no_image", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "no_radiosity", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "no_reflection", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "no_shadow", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "normal_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "normal", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "octaves", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "omega", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "once", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "orient", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "parallel", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "phase", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "photons", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pigment_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pigment", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "finish", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "poly_wave", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "quick_color", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "quick_colour", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ramp_wave", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rotate", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "scale", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "scallop_wave", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "shadowless", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sine_wave", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "slope_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "subsurface", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "texture_map", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "texture", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "transform", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "translate", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "triangle_wave", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "turbulence", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "use_color", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "use_colour", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "use_index", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uv_mapping", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "warp", len)) i = len; + + /* Vector Functions */ + else if (STR_LITERAL_STARTSWITH(string, "max_extent", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "min_extent", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "trace", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vaxis_rotate", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vcross", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vnormalize", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vrotate", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vturbulence", len)) i = len; + /* String Functions */ + else if (STR_LITERAL_STARTSWITH(string, "chr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "concat", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "datetime", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "str", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "strlwr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "strupr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "substr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vstr", len)) i = len; + /* Float Functions */ + else if (STR_LITERAL_STARTSWITH(string, "abs", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "acosh", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "acos", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "asc", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "asinh", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "asin", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "atan2", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "atand", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "atanh", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "atan", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bitwise_and", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bitwise_or", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "bitwise_xor", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ceil", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cosh", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "cos", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "defined", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "degrees", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "dimension_size", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "dimensions", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "div", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "exp", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "file_exists", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "floor", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "inside", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "int", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ln", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "log", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "max", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "min", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "mod", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pow", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "radians", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rand", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "seed", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sinh", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sin", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sqrt", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sqr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "strcmp", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "strlen", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tanh", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tan", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "val", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vdot", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "vlength", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + return (i == 0 || text_check_identifier(string[i])) ? -1 : i; +} + +static int txtfmt_pov_find_bool(const char *string) +{ + int i, len; + /*Built-in Constants*/ + if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */ + return (i == 0 || text_check_identifier(string[i])) ? -1 : i; +} + +static char txtfmt_pov_format_identifier(const char *str) +{ + char fmt; + if ((txtfmt_pov_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL; + else if ((txtfmt_pov_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD; + else if ((txtfmt_pov_find_reserved_keywords(str)) != -1) fmt = FMT_TYPE_RESERVED; + else if ((txtfmt_pov_find_reserved_builtins(str)) != -1) fmt = FMT_TYPE_RESERVED; + else fmt = FMT_TYPE_DEFAULT; + return fmt; +} + +static void txtfmt_pov_format_line(SpaceText *st, TextLine *line, const bool do_next) +{ + FlattenString fs; + const char *str; + char *fmt; + char cont_orig, cont, find, prev = ' '; + int len, i; + + /* Get continuation from previous line */ + if (line->prev && line->prev->format != NULL) { + fmt = line->prev->format; + cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ + BLI_assert((FMT_CONT_ALL & cont) == cont); + } + else { + cont = FMT_CONT_NOP; + } + + /* Get original continuation from this line */ + if (line->format != NULL) { + fmt = line->format; + cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ + BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig); + } + else { + cont_orig = 0xFF; + } + + len = flatten_string(st, &fs, line->line); + str = fs.buf; + if (!text_check_format_len(line, len)) { + flatten_string_free(&fs); + return; + } + fmt = line->format; + + while (*str) { + /* Handle escape sequences by skipping both \ and next char */ + if (*str == '\\') { + *fmt = prev; fmt++; str++; + if (*str == '\0') break; + *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str); + continue; + } + /* Handle continuations */ + else if (cont) { + /* C-Style comments */ + if (cont & FMT_CONT_COMMENT_C) { + if (*str == '*' && *(str + 1) == '/') { + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; + cont = FMT_CONT_NOP; + } + else { + *fmt = FMT_TYPE_COMMENT; + } + /* Handle other comments */ + } + else { + find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\''; + if (*str == find) cont = 0; + *fmt = FMT_TYPE_STRING; + } + + str += BLI_str_utf8_size_safe(str) - 1; + } + /* Not in a string... */ + else { + /* C-Style (multi-line) comments */ + if (*str == '/' && *(str + 1) == '*') { + cont = FMT_CONT_COMMENT_C; + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; + } + /* Single line comment */ + else if (*str == '/' && *(str + 1) == '/') { + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format)); + } + else if (*str == '"' || *str == '\'') { + /* Strings */ + find = *str; + cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE; + *fmt = FMT_TYPE_STRING; + } + /* Whitespace (all ws. has been converted to spaces) */ + else if (*str == ' ') { + *fmt = FMT_TYPE_WHITESPACE; + } + /* Numbers (digits not part of an identifier and periods followed by digits) */ + else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) || + (*str == '.' && text_check_digit(*(str + 1)))) + { + *fmt = FMT_TYPE_NUMERAL; + } + /* Booleans */ + else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_pov_find_bool(str)) != -1) { + if (i > 0) { + text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i); + } + else { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + } + /* Punctuation */ + else if (text_check_delim(*str)) { + *fmt = FMT_TYPE_SYMBOL; + } + /* Identifiers and other text (no previous ws. or delims. so text continues) */ + else if (prev == FMT_TYPE_DEFAULT) { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ + else { + /* Special vars(v) or built-in keywords(b) */ + /* keep in sync with 'txtfmt_pov_format_identifier()' */ + if ((i = txtfmt_pov_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL; + else if ((i = txtfmt_pov_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD; + else if ((i = txtfmt_pov_find_reserved_keywords(str)) != -1) prev = FMT_TYPE_RESERVED; + else if ((i = txtfmt_pov_find_reserved_builtins(str)) != -1) prev = FMT_TYPE_RESERVED; + + if (i > 0) { + text_format_fill_ascii(&str, &fmt, prev, i); + } + else { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + } + } + prev = *fmt; fmt++; str++; + } + + /* Terminate and add continuation char */ + *fmt = '\0'; fmt++; + *fmt = cont; + + /* If continuation has changed and we're allowed, process the next line */ + if (cont != cont_orig && do_next && line->next) { + txtfmt_pov_format_line(st, line->next, do_next); + } + + flatten_string_free(&fs); +} + +void ED_text_format_register_pov(void) +{ + static TextFormatType tft = {NULL}; + static const char *ext[] = {"pov", "inc", "mcr", "mac", NULL}; + + tft.format_identifier = txtfmt_pov_format_identifier; + tft.format_line = txtfmt_pov_format_line; + tft.ext = ext; + + ED_text_format_register(&tft); +} diff --git a/source/blender/editors/space_text/text_format_pov_ini.c b/source/blender/editors/space_text/text_format_pov_ini.c new file mode 100644 index 00000000000..719f4e3c036 --- /dev/null +++ b/source/blender/editors/space_text/text_format_pov_ini.c @@ -0,0 +1,488 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_text/text_format_pov_ini.c + * \ingroup sptext + */ + +#include <string.h> + +#include "BLI_blenlib.h" + +#include "DNA_text_types.h" +#include "DNA_space_types.h" + +#include "BKE_text.h" + +#include "text_format.h" + +/* *** POV INI Keywords (for format_line) *** */ + +/* Checks the specified source string for a POV INI keyword (minus boolean & 'nil'). + * This name must start at the beginning of the source string and must be + * followed by a non-identifier (see text_check_identifier(char)) or null char. + * + * If a keyword is found, the length of the matching word is returned. + * Otherwise, -1 is returned. + * + * See: + * http://www.povray.org/documentation/view/3.7.0/212/ + */ + +static int txtfmt_ini_find_keyword(const char *string) +{ + int i, len; + /* Language Directives */ + if (STR_LITERAL_STARTSWITH(string, "append", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "case", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "debug", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "declare", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "default", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "deprecated", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fclose", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "fopen", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ifdef", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ifndef", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "include", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "macro", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "range", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "read", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "render", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "statistics", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "switch", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "undef", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "version", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "warning", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "write", len)) i = len; + + else if (STR_LITERAL_STARTSWITH(string, "I", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "S", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "A", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Q", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "U", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "F", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "C", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "N", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "P", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "T", len)) i = len; + + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + return (i == 0 || text_check_identifier(string[i])) ? -1 : i; +} + +static int txtfmt_ini_find_reserved(const char *string) +{ + int i, len; + /* POV-Ray Built-in INI Variables + * list is from... + * http://www.povray.org/documentation/view/3.7.0/212/ + */ + if (STR_LITERAL_STARTSWITH(string, "Antialias_Threshold", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Bounding_Method", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Antialias_Gamma", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "clock_delta", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "clock_on", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "clock", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "final_clock", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "final_frame", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "frame_number", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "initial_clock", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "initial_frame", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "image_height", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "image_width", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "input_file_name", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Subset_Start_Frame", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Subset_End_Frame", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Frame_Step", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Cyclic_Animation", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Field_Render", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Odd_Field", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Height", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Width", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Start_Column", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Start_Row", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "End_Column", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "End_Row", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Test_Abort_Count", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Test_Abort", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Continue_Trace", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Create_Continue_Trace_Log", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Create_Ini", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Display_Gamma", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Display", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Version", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Pause_When_Done", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Verbose", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Preview_Start_Size", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Preview_End_Size", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Output_to_File", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Input_File_Name", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Output_File_Name", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Output_File_Type", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Output_Alpha", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Bits_Per_Color", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Compression", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Dither_Method", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Dither", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Command", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Command", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Command", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Command", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Command", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Command", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Pre_Scene_Return", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Pre_Frame_Return", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Post_Scene_Return", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Post_Frame_Return", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "User_Abort_Return", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Fatal_Error_Return", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Include_Header", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Library_Path", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Debug_Console", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Fatal_Console", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Render_Console", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Statistic_Console", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Warning_Console", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Warning_Level", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "All_Console", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Debug_File", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Fatal_File", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Render_File", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Statistic_File", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Warning_File", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "All_File", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Quality", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Bounding_Threshold", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Bounding", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Light_Buffer", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Vista_Buffer", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Remove_Bounds", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Split_Unions", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Antialias", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Sampling_Method", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Jitter_Amount", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Jitter", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Antialias_Depth", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "CheckNewVersion", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "RunCount", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "CommandLine", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "TextColour", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "WarningColour", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ErrorColour", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "BackgroundColour", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "DropToEditor", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "LastRenderName", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "LastRenderPath", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "LastQueuePath", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "SecondaryINISection", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "BetaVersionNo64", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "LastBitmapName", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "LastBitmapPath", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "LastINIPath", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "SecondaryINIFile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "BackgroundFile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "SaveSettingsOnExit", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "TileBackground", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "HideNewUserHelp", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "SendSystemInfo", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ItsAboutTime", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "LastPath", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Band0Width", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Band1Width", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Band2Width", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Band3Width", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Band4Width", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ShowCmd", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "NormalPositionLeft", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "NormalPositionTop", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "NormalPositionRight", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "NormalPositionBottom", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "UseToolbar", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "UseTooltips", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "NormalPositionX", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "NormalPositionY", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Flags", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Transparency", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Use8BitMode", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "MakeActive", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "KeepAboveMain", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "HideWhenMainMinimized", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "AutoClose", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "PreserveBitmap", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "FontSize", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "FontWeight", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Font", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "KeepMessages", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "AlertSound", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Completion", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Priority", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "DutyCycle", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "AlertOnCompletion", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "AutoRender", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "PreventSleep", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "NoShelloutWait", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "SystemNoActive", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSoundEnabled", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSoundEnabled", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSoundEnabled", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "RenderCompleteSound", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ParseErrorSound", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "RenderErrorSound", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "UseExtensions", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ReadWriteSourceDir", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "NoShellOuts", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "VideoSource", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "SceneFile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "OutputFile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "IniOutputFile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "CurrentDirectory", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "SourceFile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Rendering", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "RenderwinClose", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Append_File", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "Warning Level", len)) i = len; + /* Filetypes */ + else if (STR_LITERAL_STARTSWITH(string, "df3", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "exr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "gif", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "hdr", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "iff", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "jpeg", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pgm", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "png", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ppm", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sys", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tga", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tiff", len)) i = len; + /* Encodings */ + else if (STR_LITERAL_STARTSWITH(string, "ascii", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "utf8", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uint8", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uint16be", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "uint16le", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint8", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint16be", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint16le", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint32be", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "sint32le", len)) i = len; + + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + return (i == 0 || text_check_identifier(string[i])) ? -1 : i; +} + + + + +static int txtfmt_ini_find_bool(const char *string) +{ + int i, len; + /* Built-in Constants */ + if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "no", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "off", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "yes", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "on", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pi", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tau", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "%o", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "%s", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "%n", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "%k", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "%h", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "%w", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */ + return (i == 0 || text_check_identifier(string[i])) ? -1 : i; +} + +static char txtfmt_pov_ini_format_identifier(const char *str) +{ + char fmt; + if ((txtfmt_ini_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD; + else if ((txtfmt_ini_find_reserved(str)) != -1) fmt = FMT_TYPE_RESERVED; + else fmt = FMT_TYPE_DEFAULT; + return fmt; +} + +static void txtfmt_pov_ini_format_line(SpaceText *st, TextLine *line, const bool do_next) +{ + FlattenString fs; + const char *str; + char *fmt; + char cont_orig, cont, find, prev = ' '; + int len, i; + + /* Get continuation from previous line */ + if (line->prev && line->prev->format != NULL) { + fmt = line->prev->format; + cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ + BLI_assert((FMT_CONT_ALL & cont) == cont); + } + else { + cont = FMT_CONT_NOP; + } + + /* Get original continuation from this line */ + if (line->format != NULL) { + fmt = line->format; + cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ + BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig); + } + else { + cont_orig = 0xFF; + } + + len = flatten_string(st, &fs, line->line); + str = fs.buf; + if (!text_check_format_len(line, len)) { + flatten_string_free(&fs); + return; + } + fmt = line->format; + + while (*str) { + /* Handle escape sequences by skipping both \ and next char */ + if (*str == '\\') { + *fmt = prev; fmt++; str++; + if (*str == '\0') break; + *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str); + continue; + } + /* Handle continuations */ + else if (cont) { + /* Multi-line comments */ + if (cont & FMT_CONT_COMMENT_C) { + if (*str == ']' && *(str + 1) == ']') { + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; + cont = FMT_CONT_NOP; + } + else { + *fmt = FMT_TYPE_COMMENT; + } + /* Handle other comments */ + } + else { + find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\''; + if (*str == find) cont = 0; + *fmt = FMT_TYPE_STRING; + } + + str += BLI_str_utf8_size_safe(str) - 1; + } + /* Not in a string... */ + else { + /* Multi-line comments not supported */ + /* Single line comment */ + if (*str == ';') { + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format)); + } + else if (*str == '"' || *str == '\'') { + /* Strings */ + find = *str; + cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE; + *fmt = FMT_TYPE_STRING; + } + /* Whitespace (all ws. has been converted to spaces) */ + else if (*str == ' ') { + *fmt = FMT_TYPE_WHITESPACE; + } + /* Numbers (digits not part of an identifier and periods followed by digits) */ + else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) || + (*str == '.' && text_check_digit(*(str + 1)))) + { + *fmt = FMT_TYPE_NUMERAL; + } + /* Booleans */ + else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_ini_find_bool(str)) != -1) { + if (i > 0) { + text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i); + } + else { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + } + /* Punctuation */ + else if ((*str != '#') && text_check_delim(*str)) { + *fmt = FMT_TYPE_SYMBOL; + } + /* Identifiers and other text (no previous ws. or delims. so text continues) */ + else if (prev == FMT_TYPE_DEFAULT) { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ + else { + /* Special vars(v) or built-in keywords(b) */ + /* keep in sync with 'txtfmt_ini_format_identifier()' */ + if ((i = txtfmt_ini_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD; + else if ((i = txtfmt_ini_find_reserved(str)) != -1) prev = FMT_TYPE_RESERVED; + + if (i > 0) { + text_format_fill_ascii(&str, &fmt, prev, i); + } + else { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + } + } + prev = *fmt; fmt++; str++; + } + + /* Terminate and add continuation char */ + *fmt = '\0'; fmt++; + *fmt = cont; + + /* If continuation has changed and we're allowed, process the next line */ + if (cont != cont_orig && do_next && line->next) { + txtfmt_pov_ini_format_line(st, line->next, do_next); + } + + flatten_string_free(&fs); +} + +void ED_text_format_register_pov_ini(void) +{ + static TextFormatType tft = {NULL}; + static const char *ext[] = {"ini", NULL}; + + tft.format_identifier = txtfmt_pov_ini_format_identifier; + tft.format_line = txtfmt_pov_ini_format_line; + tft.ext = ext; + + ED_text_format_register(&tft); +} diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 314b7bf3335..5208013b6fe 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1903,6 +1903,11 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, } } + /* custom bone may draw outline double-width */ + if (arm->flag & ARM_POSEMODE) { + glLineWidth(1.0f); + } + /* draw custom bone shapes as wireframes */ if (!(arm->flag & ARM_NO_CUSTOM) && (draw_wire || (dt <= OB_WIRE)) ) @@ -1968,11 +1973,6 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, index = -1; } } - - /* custom bone may draw outline double-width */ - if (arm->flag & ARM_POSEMODE) { - glLineWidth(1.0f); - } /* wire draw over solid only in posemode */ if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) { diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 335d0649729..73fd77db477 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -867,7 +867,7 @@ void view3d_cached_text_draw_add(const float co[3], memcpy(vos->str, str, alloc_len); } -void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4]) +void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) { RegionView3D *rv3d = ar->regiondata; ViewCachedString *vos; @@ -877,9 +877,6 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo /* project first and test */ for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) { - if (mat && !(vos->flag & V3D_CACHE_TEXT_WORLDSPACE)) - mul_m4_v3(mat, vos->vec); - if (ED_view3d_project_short_ex(ar, (vos->flag & V3D_CACHE_TEXT_GLOBALSPACE) ? rv3d->persmat : rv3d->persmatob, (vos->flag & V3D_CACHE_TEXT_LOCALCLIP) != 0, @@ -5123,7 +5120,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv copy_m4_m4(imat, rv3d->viewinv); normalize_v3(imat[0]); normalize_v3(imat[1]); - /* fall-through */ + ATTR_FALLTHROUGH; case PART_DRAW_CROSS: case PART_DRAW_AXIS: /* lets calculate the scale: */ @@ -6419,19 +6416,16 @@ static void draw_editnurb( vec_a[0] = fac; vec_a[1] = 0.0f; vec_a[2] = 0.0f; - - vec_b[0] = -fac; - vec_b[1] = 0.0f; - vec_b[2] = 0.0f; mul_qt_v3(bevp->quat, vec_a); - mul_qt_v3(bevp->quat, vec_b); + madd_v3_v3fl(vec_a, bevp->dir, -fac); + + reflect_v3_v3v3(vec_b, vec_a, bevp->dir); + negate_v3(vec_b); + add_v3_v3(vec_a, bevp->vec); add_v3_v3(vec_b, bevp->vec); - madd_v3_v3fl(vec_a, bevp->dir, -fac); - madd_v3_v3fl(vec_b, bevp->dir, -fac); - glBegin(GL_LINE_STRIP); glVertex3fv(vec_a); glVertex3fv(bevp->vec); @@ -6475,7 +6469,6 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b Curve *cu = ob->data; EditFont *ef = cu->editfont; float vec1[3], vec2[3]; - int selstart, selend; draw_editfont_textcurs(rv3d, ef->textcurs); @@ -6528,17 +6521,16 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b setlinestyle(0); - if (BKE_vfont_select_get(ob, &selstart, &selend) && ef->selboxes) { - const int seltot = selend - selstart; + if (ef->selboxes && ef->selboxes_len) { float selboxw; cpack(0xffffff); set_inverted_drawing(1); - for (int i = 0; i <= seltot; i++) { + for (int i = 0; i < ef->selboxes_len; i++) { EditFontSelBox *sb = &ef->selboxes[i]; float tvec[3]; - if (i != seltot) { + if (i + 1 != ef->selboxes_len) { if (ef->selboxes[i + 1].y == sb->y) selboxw = ef->selboxes[i + 1].x - sb->x; else @@ -7355,7 +7347,7 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ theme_id = TH_GROUP_ACTIVE; if (scene->basact != base) { - theme_shade = -16; + theme_shade = -32; } } else { @@ -7831,7 +7823,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag); } invert_m4_m4(ob->imat, ob->obmat); - view3d_cached_text_draw_end(v3d, ar, 0, NULL); + view3d_cached_text_draw_end(v3d, ar, 0); glMultMatrixf(ob->obmat); @@ -8006,7 +7998,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* return warning, this is cached text draw */ invert_m4_m4(ob->imat, ob->obmat); - view3d_cached_text_draw_end(v3d, ar, 1, NULL); + view3d_cached_text_draw_end(v3d, ar, 1); /* return warning, clear temp flag */ v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP; @@ -8386,9 +8378,13 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob) DM_update_materials(dm, ob); - dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, GPU_object_material_bind, NULL, me, DM_DRAW_SKIP_HIDDEN); + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + const int G_f_orig = G.f; + G.f &= ~G_BACKBUFSEL; + + dm->drawMappedFaces(dm, bbs_mesh_solid_hide2__setDrawOpts, NULL, NULL, me, DM_DRAW_SKIP_HIDDEN); - GPU_object_material_unbind(); + G.f |= (G_f_orig & G_BACKBUFSEL); bbs_obmode_mesh_verts(ob, dm, 1); bm_vertoffs = me->totvert + 1; @@ -8445,8 +8441,8 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec bbs_mesh_wire(em, dm, bm_solidoffs); bm_wireoffs = bm_solidoffs + em->bm->totedge; - /* we draw verts if vert select mode or if in transform (for snap). */ - if ((ts->selectmode & SCE_SELECT_VERTEX) || (G.moving & G_TRANSFORM_EDIT)) { + /* we draw verts if vert select mode. */ + if (ts->selectmode & SCE_SELECT_VERTEX) { bbs_mesh_verts(em, dm, bm_wireoffs); bm_vertoffs = bm_wireoffs + em->bm->totvert; } diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c index 9414d39467d..3f23d4aa09a 100644 --- a/source/blender/editors/space_view3d/drawsimdebug.c +++ b/source/blender/editors/space_view3d/drawsimdebug.c @@ -171,7 +171,7 @@ void draw_sim_debug_data(Scene *UNUSED(scene), View3D *v3d, ARegion *ar) view3d_cached_text_draw_begin(); draw_sim_debug_elements(_sim_debug_data, imat); - view3d_cached_text_draw_end(v3d, ar, false, NULL); + view3d_cached_text_draw_end(v3d, ar, false); glPopMatrix(); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 3fb2761d40e..250e6559b8f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -105,7 +105,8 @@ #include "view3d_intern.h" /* own include */ /* prototypes */ -static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar); +static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d); +static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect); static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar, float winmat[4][4], const char *viewname); @@ -2371,17 +2372,11 @@ void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) short zbuf = v3d->zbuf; RegionView3D *rv3d = ar->regiondata; - view3d_winmatrix_set(ar, v3d, NULL); - view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ - - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - invert_m4_m4(rv3d->persinv, rv3d->persmat); - invert_m4_m4(rv3d->viewinv, rv3d->viewmat); + /* Setup view matrix. */ + ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL); glClear(GL_DEPTH_BUFFER_BIT); - glLoadMatrixf(rv3d->viewmat); - v3d->zbuf = true; glEnable(GL_DEPTH_TEST); @@ -2390,46 +2385,15 @@ void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d) } v3d->zbuf = zbuf; - } -void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride) +static void view3d_draw_depth_loop(Scene *scene, ARegion *ar, View3D *v3d) { - RegionView3D *rv3d = ar->regiondata; Base *base; - short zbuf = v3d->zbuf; - short flag = v3d->flag; - float glalphaclip = U.glalphaclip; - int obcenter_dia = U.obcenter_dia; + /* no need for color when drawing depth buffer */ const short dflag_depth = DRAW_CONSTCOLOR; - /* temp set drawtype to solid */ - - /* Setting these temporarily is not nice */ - v3d->flag &= ~V3D_SELECT_OUTLINE; - U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ - U.obcenter_dia = 0; - - view3d_winmatrix_set(ar, v3d, NULL); - view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ - - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - invert_m4_m4(rv3d->persinv, rv3d->persmat); - invert_m4_m4(rv3d->viewinv, rv3d->viewmat); - - glClear(GL_DEPTH_BUFFER_BIT); - - glLoadMatrixf(rv3d->viewmat); - - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); - } - /* get surface depth without bias */ - rv3d->rflag |= RV3D_ZOFFSET_DISABLED; - v3d->zbuf = true; - glEnable(GL_DEPTH_TEST); - /* draw set first */ if (scene->set) { Scene *sce_iter; @@ -2503,8 +2467,39 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover glDepthMask(mask_orig); } +} + +void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride) +{ + RegionView3D *rv3d = ar->regiondata; + short zbuf = v3d->zbuf; + short flag = v3d->flag; + float glalphaclip = U.glalphaclip; + int obcenter_dia = U.obcenter_dia; + /* temp set drawtype to solid */ + + /* Setting these temporarily is not nice */ + v3d->flag &= ~V3D_SELECT_OUTLINE; + U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; /* not that nice but means we wont zoom into billboards */ + U.obcenter_dia = 0; + + /* Setup view matrix. */ + ED_view3d_draw_setup_view(NULL, scene, ar, v3d, rv3d->viewmat, rv3d->winmat, NULL); + + glClear(GL_DEPTH_BUFFER_BIT); if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } + /* get surface depth without bias */ + rv3d->rflag |= RV3D_ZOFFSET_DISABLED; + + v3d->zbuf = true; + glEnable(GL_DEPTH_TEST); + + view3d_draw_depth_loop(scene, ar, v3d); + + if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_disable(); } rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; @@ -2737,7 +2732,8 @@ CustomDataMask ED_view3d_screen_datamask(const bScreen *screen) /** * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore */ -void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]) +void ED_view3d_update_viewmat( + Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) { RegionView3D *rv3d = ar->regiondata; @@ -2745,7 +2741,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view if (winmat) copy_m4_m4(rv3d->winmat, winmat); else - view3d_winmatrix_set(ar, v3d, NULL); + view3d_winmatrix_set(ar, v3d, rect); /* setup view matrix */ if (viewmat) @@ -3008,11 +3004,12 @@ static void view3d_draw_objects( } } -static void view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]) +static void view3d_main_region_setup_view( + Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) { RegionView3D *rv3d = ar->regiondata; - ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat); + ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat, rect); /* set for opengl */ glMatrixMode(GL_PROJECTION); @@ -3195,7 +3192,7 @@ void ED_view3d_draw_offscreen( if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname); else - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat); + view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); /* framebuffer fx needed, we need to draw offscreen first */ if (v3d->fx_settings.fx_flag && fx) { @@ -3258,6 +3255,23 @@ void ED_view3d_draw_offscreen( } /** + * Set the correct matrices + */ +void ED_view3d_draw_setup_view( + wmWindow *win, Scene *scene, ARegion *ar, View3D *v3d, float viewmat[4][4], float winmat[4][4], const rcti *rect) +{ + RegionView3D *rv3d = ar->regiondata; + + /* Setup the view matrix. */ + if (view3d_stereo3d_active(win, scene, v3d, rv3d)) { + view3d_stereo3d_setup(scene, v3d, ar, rect); + } + else { + view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, rect); + } +} + +/** * Utility func for ED_view3d_draw_offscreen * * \param ofs: Optional off-screen buffer, can be NULL. @@ -3624,7 +3638,7 @@ static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene, } /* setup view matrices */ - view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL); + view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL, NULL); /* background draw */ ED_region_pixelspace(ar); @@ -3691,26 +3705,37 @@ static void view3d_main_region_draw_engine_info(View3D *v3d, RegionView3D *rv3d, ED_region_info_draw(ar, rv3d->render_engine->text, fill_color, true); } -static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d) +static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d) { - wmWindow *win = CTX_wm_window(C); - - if ((scene->r.scemode & R_MULTIVIEW) == 0) - return false; - - if (WM_stereo3d_enabled(win, true) == false) + if ((scene->r.scemode & R_MULTIVIEW) == 0) { return false; + } - if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) + if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) { return false; + } - if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) { - if (v3d->stereo3d_camera == STEREO_MONO_ID) + switch (v3d->stereo3d_camera) { + case STEREO_MONO_ID: return false; - - return BKE_scene_multiview_is_stereo3d(&scene->r); + break; + case STEREO_3D_ID: + /* win will be NULL when calling this from the selection or draw loop. */ + if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) { + return false; + } + if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) && + !BKE_scene_multiview_is_stereo3d(&scene->r)) + { + return false; + } + break; + /* We always need the stereo calculation for left and right cameras. */ + case STEREO_LEFT_ID: + case STEREO_RIGHT_ID: + default: + break; } - return true; } @@ -3722,7 +3747,7 @@ static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, * we do a small hack to replace it temporarily so we don't need to change the * view3d)main_region_setup_view() code to account for that. */ -static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar) +static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect) { bool is_left; const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; @@ -3748,7 +3773,7 @@ static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar) data->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL); + view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect); data->shiftx = shiftx; BLI_unlock_thread(LOCK_VIEW3D); @@ -3762,7 +3787,7 @@ static void view3d_stereo3d_setup(Scene *scene, View3D *v3d, ARegion *ar) v3d->camera = camera; BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL); + view3d_main_region_setup_view(scene, v3d, ar, viewmat, NULL, rect); v3d->camera = view_ob; BLI_unlock_thread(LOCK_VIEW3D); @@ -3778,14 +3803,14 @@ static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion * const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat); + view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); } else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ float viewmat[4][4]; Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat); + view3d_main_region_setup_view(scene, v3d, ar, viewmat, winmat, NULL); } } @@ -3823,11 +3848,8 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie GPU_default_lights(); } - /* setup the view matrix */ - if (view3d_stereo3d_active(C, scene, v3d, rv3d)) - view3d_stereo3d_setup(scene, v3d, ar); - else - view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL); + /* Setup the view matrix. */ + ED_view3d_draw_setup_view(CTX_wm_window(C), scene, ar, v3d, NULL, NULL, NULL); rv3d->rflag &= ~RV3D_IS_GAME_ENGINE; #ifdef WITH_GAMEENGINE diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index f07727f8118..4e3f279e12e 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -85,6 +85,8 @@ #include "view3d_intern.h" /* own include */ +static bool view3d_ensure_persp(struct View3D *v3d, ARegion *ar); + bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d) { return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre); @@ -697,16 +699,68 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) return is_set; } +enum eViewOpsOrbit { + VIEWOPS_ORBIT_SELECT = (1 << 0), + VIEWOPS_ORBIT_DEPTH = (1 << 1), +}; + +static enum eViewOpsOrbit viewops_orbit_mode_ex(bool use_select, bool use_depth) +{ + enum eViewOpsOrbit flag = 0; + if (use_select) { + flag |= VIEWOPS_ORBIT_SELECT; + } + if (use_depth) { + flag |= VIEWOPS_ORBIT_DEPTH; + } + + return flag; +} + +static enum eViewOpsOrbit viewops_orbit_mode(void) +{ + return viewops_orbit_mode_ex( + (U.uiflag & USER_ORBIT_SELECTION) != 0, + (U.uiflag & USER_ZBUF_ORBIT) != 0); +} + /** * Calculate the values for #ViewOpsData */ -static void viewops_data_create_ex(bContext *C, wmOperator *op, const wmEvent *event, - const bool use_orbit_select, - const bool use_orbit_zbuf) +static void viewops_data_create_ex( + bContext *C, wmOperator *op, const wmEvent *event, + bool switch_from_camera, enum eViewOpsOrbit orbit_mode) { ViewOpsData *vod = op->customdata; RegionView3D *rv3d = vod->rv3d; + /* we need the depth info before changing any viewport options */ + if (orbit_mode & VIEWOPS_ORBIT_DEPTH) { + float fallback_depth_pt[3]; + + view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ + + negate_v3_v3(fallback_depth_pt, rv3d->ofs); + + vod->use_dyn_ofs = ED_view3d_autodist( + vod->scene, vod->ar, vod->v3d, + event->mval, vod->dyn_ofs, true, fallback_depth_pt); + } + else { + vod->use_dyn_ofs = false; + } + + if (switch_from_camera) { + /* switch from camera view when: */ + if (view3d_ensure_persp(vod->v3d, vod->ar)) { + /* If we're switching from camera view to the perspective one, + * need to tag viewport update, so camera vuew and borders + * are properly updated. + */ + ED_region_tag_redraw(vod->ar); + } + } + /* set the view from the camera, if view locking is enabled. * we may want to make this optional but for now its needed always */ ED_view3d_camera_lock_init(vod->v3d, vod->rv3d); @@ -718,28 +772,19 @@ static void viewops_data_create_ex(bContext *C, wmOperator *op, const wmEvent *e vod->origx = vod->oldx = event->x; vod->origy = vod->oldy = event->y; vod->origkey = event->type; /* the key that triggered the operator. */ - vod->use_dyn_ofs = false; copy_v3_v3(vod->ofs, rv3d->ofs); - if (use_orbit_select) { - - vod->use_dyn_ofs = true; - - view3d_orbit_calc_center(C, vod->dyn_ofs); - - negate_v3(vod->dyn_ofs); + if (orbit_mode & VIEWOPS_ORBIT_SELECT) { + float ofs[3]; + if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) { + vod->use_dyn_ofs = true; + negate_v3_v3(vod->dyn_ofs, ofs); + orbit_mode &= ~VIEWOPS_ORBIT_DEPTH; + } } - else if (use_orbit_zbuf) { - Scene *scene = CTX_data_scene(C); - float fallback_depth_pt[3]; - - view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ - - negate_v3_v3(fallback_depth_pt, rv3d->ofs); - if ((vod->use_dyn_ofs = ED_view3d_autodist(scene, vod->ar, vod->v3d, - event->mval, vod->dyn_ofs, true, fallback_depth_pt))) - { + if (orbit_mode & VIEWOPS_ORBIT_DEPTH) { + if (vod->use_dyn_ofs) { if (rv3d->is_persp) { float my_origin[3]; /* original G.vd->ofs */ float my_pivot[3]; /* view */ @@ -808,12 +853,10 @@ static void viewops_data_create_ex(bContext *C, wmOperator *op, const wmEvent *e rv3d->rflag |= RV3D_NAVIGATING; } -static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event) +static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event, bool switch_from_camera) { - viewops_data_create_ex( - C, op, event, - (U.uiflag & USER_ORBIT_SELECTION) != 0, - (U.uiflag & USER_ZBUF_ORBIT) != 0); + enum eViewOpsOrbit orbit_mode = viewops_orbit_mode(); + viewops_data_create_ex(C, op, event, switch_from_camera, orbit_mode); } static void viewops_data_free(bContext *C, wmOperator *op) @@ -1219,16 +1262,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event) ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); - /* switch from camera view when: */ - if (view3d_ensure_persp(vod->v3d, vod->ar)) { - /* If we're switching from camera view to the perspective one, - * need to tag viewport update, so camera vuew and borders - * are properly updated. - */ - ED_region_tag_redraw(vod->ar); - } - - viewops_data_create(C, op, event); + viewops_data_create(C, op, event, true); if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) { /* Rotate direction we keep always same */ @@ -1637,8 +1671,9 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) const wmNDOFMotionData *ndof = event->customdata; viewops_data_alloc(C, op); - viewops_data_create_ex(C, op, event, - (U.uiflag & USER_ORBIT_SELECTION) != 0, false); + viewops_data_create_ex( + C, op, event, + viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false), false); vod = op->customdata; ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); @@ -1705,8 +1740,9 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev const wmNDOFMotionData *ndof = event->customdata; viewops_data_alloc(C, op); - viewops_data_create_ex(C, op, event, - (U.uiflag & USER_ORBIT_SELECTION) != 0, false); + viewops_data_create_ex( + C, op, event, + viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false), false); vod = op->customdata; @@ -2020,7 +2056,7 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* makes op->customdata */ viewops_data_alloc(C, op); - viewops_data_create(C, op, event); + viewops_data_create(C, op, event, false); vod = op->customdata; ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); @@ -2501,7 +2537,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* makes op->customdata */ viewops_data_alloc(C, op); - viewops_data_create(C, op, event); + viewops_data_create(C, op, event, false); vod = op->customdata; ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); @@ -2774,7 +2810,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event) ED_region_tag_redraw(vod->ar); } - viewops_data_create(C, op, event); + viewops_data_create(C, op, event, false); /* if one or the other zoom position aren't set, set from event */ @@ -4298,7 +4334,7 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event) else { /* makes op->customdata */ viewops_data_alloc(C, op); - viewops_data_create(C, op, event); + viewops_data_create(C, op, event, false); vod = op->customdata; ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); @@ -4375,7 +4411,7 @@ static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event) else if (pandir == V3D_VIEW_PANDOWN) { y = 25; } viewops_data_alloc(C, op); - viewops_data_create(C, op, event); + viewops_data_create(C, op, event, false); ViewOpsData *vod = op->customdata; viewmove_apply(vod, vod->oldx + x, vod->oldy + y); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index c2b8d1f8bda..7a106a27833 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -154,7 +154,7 @@ void view3d_cached_text_draw_begin(void); void view3d_cached_text_draw_add(const float co[3], const char *str, const size_t str_len, short xoffs, short flag, const unsigned char col[4]); -void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, float mat[4][4]); +void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write); bool check_object_draw_texture(struct Scene *scene, struct View3D *v3d, const char drawtype); diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index ce4b7f7deeb..ef7b01f7a21 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -119,7 +119,7 @@ void meshobject_foreachScreenVert( data.clip_flag = clip_flag; if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat); } dm->foreachMappedVert(dm, meshobject_foreachScreenVert__mapFunc, &data, DM_FOREACH_NOP); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index fe8274064e5..5c13fd37dda 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -449,7 +449,7 @@ void ED_view3d_smooth_view_force_finish( /* force update of view matrix so tools that run immediately after * can use them without redrawing first */ Scene *scene = CTX_data_scene(C); - ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL); + ED_view3d_update_viewmat(scene, v3d, ar, NULL, NULL, NULL); } } @@ -1172,9 +1172,10 @@ int view3d_opengl_select( G.f |= G_PICKSEL; - view3d_winmatrix_set(ar, v3d, &rect); - mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat); - + /* Important we use the 'viewmat' and don't re-calculate since + * the object & bone view locking takes 'rect' into account, see: T51629. */ + ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect); + if (v3d->drawtype > OB_WIRE) { v3d->zbuf = true; glEnable(GL_DEPTH_TEST); @@ -1190,7 +1191,7 @@ int view3d_opengl_select( hits = GPU_select_end(); /* second pass, to get the closest object to camera */ - if (do_passes) { + if (do_passes && (hits > 0)) { GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); ED_view3d_draw_select_loop(vc, scene, v3d, ar, use_obedit_skip, use_nearest); @@ -1199,8 +1200,7 @@ int view3d_opengl_select( } G.f &= ~G_PICKSEL; - view3d_winmatrix_set(ar, v3d, NULL); - mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat); + ED_view3d_draw_setup_view(vc->win, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL); if (v3d->drawtype > OB_WIRE) { v3d->zbuf = 0; diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 542dc410bc3..c6b73056a9a 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -674,16 +674,6 @@ static int walkEnd(bContext *C, WalkInfo *walk) return OPERATOR_CANCELLED; } -static bool wm_event_is_last_mousemove(const wmEvent *event) -{ - while ((event = event->next)) { - if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - return false; - } - } - return true; -} - static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event) { if (event->type == TIMER && event->customdata == walk->timer) { @@ -736,7 +726,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent } else #endif - if (wm_event_is_last_mousemove(event)) { + if (WM_event_is_last_mousemove(event)) { wmWindow *win = CTX_wm_window(C); #ifdef __APPLE__ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 7d9063c3285..ca6e2267218 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1605,7 +1605,7 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size) offset = -offset; length = -length; size = -size; - /* fall-through */ + ATTR_FALLTHROUGH; case RIGHT: glBegin(GL_LINES); glVertex2s(offset, 0); @@ -1621,7 +1621,7 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size) offset = -offset; length = -length; size = -size; - /* fall-through */ + ATTR_FALLTHROUGH; case UP: glBegin(GL_LINES); glVertex2s(0, offset); @@ -1640,7 +1640,7 @@ static void drawArrowHead(ArrowDirection d, short size) switch (d) { case LEFT: size = -size; - /* fall-through */ + ATTR_FALLTHROUGH; case RIGHT: glBegin(GL_LINES); glVertex2s(0, 0); @@ -1652,7 +1652,7 @@ static void drawArrowHead(ArrowDirection d, short size) case DOWN: size = -size; - /* fall-through */ + ATTR_FALLTHROUGH; case UP: glBegin(GL_LINES); glVertex2s(0, 0); @@ -3051,19 +3051,13 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) /** \name Transform Shear * \{ */ -static void postInputShear(TransInfo *UNUSED(t), float values[3]) -{ - mul_v3_fl(values, 0.05f); -} - static void initShear(TransInfo *t) { t->mode = TFM_SHEAR; t->transform = applyShear; t->handleEvent = handleEventShear; - - setInputPostFct(&t->mouse, postInputShear); - initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE); + + initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); t->idx_max = 0; t->num.idx_max = 0; @@ -3085,24 +3079,24 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event) if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { /* Use custom.mode.data pointer to signal Shear direction */ if (t->custom.mode.data == NULL) { - initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); + initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_RATIO); t->custom.mode.data = (void *)1; } else { - initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE); + initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); t->custom.mode.data = NULL; } status = TREDRAW_HARD; } else if (event->type == XKEY && event->val == KM_PRESS) { - initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE); + initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); t->custom.mode.data = NULL; status = TREDRAW_HARD; } else if (event->type == YKEY && event->val == KM_PRESS) { - initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); + initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_RATIO); t->custom.mode.data = (void *)1; status = TREDRAW_HARD; @@ -4073,13 +4067,15 @@ static void initTrackball(TransInfo *t) static void applyTrackballValue(TransInfo *t, const float axis1[3], const float axis2[3], float angles[2]) { TransData *td = t->data; - float mat[3][3], smat[3][3], totmat[3][3]; + float mat[3][3]; + float axis[3]; + float angle; int i; - axis_angle_normalized_to_mat3(smat, axis1, angles[0]); - axis_angle_normalized_to_mat3(totmat, axis2, angles[1]); - - mul_m3_m3m3(mat, smat, totmat); + mul_v3_v3fl(axis, axis1, angles[0]); + madd_v3_v3fl(axis, axis2, angles[1]); + angle = normalize_v3(axis); + axis_angle_normalized_to_mat3(mat, axis, angle); for (i = 0; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) @@ -4089,10 +4085,7 @@ static void applyTrackballValue(TransInfo *t, const float axis1[3], const float continue; if (t->flag & T_PROP_EDIT) { - axis_angle_normalized_to_mat3(smat, axis1, td->factor * angles[0]); - axis_angle_normalized_to_mat3(totmat, axis2, td->factor * angles[1]); - - mul_m3_m3m3(mat, smat, totmat); + axis_angle_normalized_to_mat3(mat, axis, td->factor * angle); } ElementRotation(t, td, mat, t->around); @@ -4278,7 +4271,7 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, do_split, false); } - else if (dist > 1e10f || dist < -1e10f) { + else if (dist > 1e10f || dist < -1e10f) { /* prevent string buffer overflow */ BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist); } @@ -4948,7 +4941,7 @@ static void initPushPull(TransInfo *t) static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3], axis[3]; + float vec[3], axis_global[3]; float distance; int i; char str[UI_MAX_DRAW_STR]; @@ -4976,7 +4969,7 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) } if (t->con.applyRot && t->con.mode & CON_APPLY) { - t->con.applyRot(t, NULL, axis, NULL); + t->con.applyRot(t, NULL, axis_global, NULL); } for (i = 0; i < t->total; i++, td++) { @@ -4988,7 +4981,11 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) sub_v3_v3v3(vec, t->center, td->center); if (t->con.applyRot && t->con.mode & CON_APPLY) { + float axis[3]; + copy_v3_v3(axis, axis_global); t->con.applyRot(t, td, axis, NULL); + + mul_m3_v3(td->smtx, axis); if (isLockConstraint(t)) { float dvec[3]; project_v3_v3v3(dvec, vec, axis); @@ -5561,7 +5558,7 @@ static void slide_origdata_interp_data_vert( float v_proj[3][3]; if (do_loop_weight || do_loop_mdisps) { - project_plane_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis); + project_plane_normalized_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis); } // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) { @@ -5595,19 +5592,19 @@ static void slide_origdata_interp_data_vert( /* In the unlikely case that we're next to a zero length edge - walk around the to the next. * Since we only need to check if the vertex is in this corner, * its not important _which_ loop - as long as its not overlapping 'sv->co_orig_3d', see: T45096. */ - project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis); + project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis); while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) && ((l_prev = l_prev->prev) != l->next))) { co_prev = slide_origdata_orig_vert_co(sod, l_prev->v); - project_plane_v3_v3v3(v_proj[0], co_prev, v_proj_axis); + project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis); } - project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis); + project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis); while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) && ((l_next = l_next->next) != l->prev))) { co_next = slide_origdata_orig_vert_co(sod, l_next->v); - project_plane_v3_v3v3(v_proj[2], co_next, v_proj_axis); + project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis); } if (co_prev_ok && co_next_ok) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 5e67f304755..4429d19613a 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -771,34 +771,43 @@ int count_set_pose_transflags(int *out_mode, short around, Object *ob) /* -------- Auto-IK ---------- */ /* adjust pose-channel's auto-ik chainlen */ -static void pchan_autoik_adjust(bPoseChannel *pchan, short chainlen) +static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen) { bConstraint *con; + bool changed = false; /* don't bother to search if no valid constraints */ - if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) - return; + if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) { + return changed; + } /* check if pchan has ik-constraint */ for (con = pchan->constraints.first; con; con = con->next) { if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) { bKinematicConstraint *data = con->data; - + /* only accept if a temporary one (for auto-ik) */ if (data->flag & CONSTRAINT_IK_TEMP) { /* chainlen is new chainlen, but is limited by maximum chainlen */ - if ((chainlen == 0) || (chainlen > data->max_rootbone)) + const int old_rootbone = data->rootbone; + if ((chainlen == 0) || (chainlen > data->max_rootbone)) { data->rootbone = data->max_rootbone; - else + } + else { data->rootbone = chainlen; + } + changed |= (data->rootbone != old_rootbone); } } } + + return changed; } /* change the chain-length of auto-ik */ void transform_autoik_update(TransInfo *t, short mode) { + const short old_len = t->settings->autoik_chainlen; short *chainlen = &t->settings->autoik_chainlen; bPoseChannel *pchan; @@ -812,13 +821,29 @@ void transform_autoik_update(TransInfo *t, short mode) if (*chainlen > 0) (*chainlen)--; } + /* IK length did not change, skip any updates. */ + if (old_len == *chainlen) { + return; + } + /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */ if (ELEM(NULL, t->poseobj, t->poseobj->pose)) return; /* apply to all pose-channels */ + bool changed = false; for (pchan = t->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) { - pchan_autoik_adjust(pchan, *chainlen); + changed |= pchan_autoik_adjust(pchan, *chainlen); + } + +#ifdef WITH_LEGACY_DEPSGRAPH + if (!DEG_depsgraph_use_legacy()) +#endif + { + if (changed) { + /* TODO(sergey): Consider doing partial update only. */ + DAG_relations_tag_update(G.main); + } } } @@ -828,7 +853,9 @@ static void pose_grab_with_ik_clear(Object *ob) bKinematicConstraint *data; bPoseChannel *pchan; bConstraint *con, *next; +#ifdef WITH_LEGACY_DEPSGRAPH bool need_dependency_update = false; +#endif for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { /* clear all temporary lock flags */ @@ -843,7 +870,9 @@ static void pose_grab_with_ik_clear(Object *ob) data = con->data; if (data->flag & CONSTRAINT_IK_TEMP) { /* iTaSC needs clear for removed constraints */ +#ifdef WITH_LEGACY_DEPSGRAPH need_dependency_update = true; +#endif BIK_clear_data(ob->pose); BLI_remlink(&pchan->constraints, con); @@ -1496,6 +1525,48 @@ static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struc return hdata; } +/** + * For the purpose of transform code we need to behave as if handles are selected, + * even when they aren't (see special case below). + */ +static int bezt_select_to_transform_triple_flag( + const BezTriple *bezt, const bool hide_handles) +{ + int flag = 0; + + if (hide_handles) { + if (bezt->f2 & SELECT) { + flag = (1 << 0) | (1 << 1) | (1 << 2); + } + } + else { + flag = ( + ((bezt->f1 & SELECT) ? (1 << 0) : 0) | + ((bezt->f2 & SELECT) ? (1 << 1) : 0) | + ((bezt->f3 & SELECT) ? (1 << 2) : 0) + ); + } + + /* Special case for auto & aligned handles: + * When a center point is being moved without the handles, + * leaving the handles stationary makes no sense and only causes strange behavior, + * where one handle is arbitrarily anchored, the other one is aligned and lengthened + * based on where the center point is moved. Also a bug when cancelling, see: T52007. + * + * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'. + * However that doesn't resolve odd behavior, so best transform the handles in this case. + */ + if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) { + if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && + ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) + { + flag = (1 << 0) | (1 << 1) | (1 << 2); + } + } + + return flag; +} + static void createTransCurveVerts(TransInfo *t) { Curve *cu = t->obedit->data; @@ -1513,22 +1584,22 @@ static void createTransCurveVerts(TransInfo *t) /* to be sure */ if (cu->editnurb == NULL) return; +#define SEL_F1 (1 << 0) +#define SEL_F2 (1 << 1) +#define SEL_F3 (1 << 2) + /* count total of vertices, check identical as in 2nd loop for making transdata! */ nurbs = BKE_curve_editNurbs_get(cu); for (nu = nurbs->first; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { if (bezt->hide == 0) { - if (hide_handles) { - if (bezt->f2 & SELECT) countsel += 3; - if (is_prop_edit) count += 3; - } - else { - if (bezt->f1 & SELECT) countsel++; - if (bezt->f2 & SELECT) countsel++; - if (bezt->f3 & SELECT) countsel++; - if (is_prop_edit) count += 3; - } + const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles); + if (bezt_tx & SEL_F1) { countsel++; } + if (bezt_tx & SEL_F2) { countsel++; } + if (bezt_tx & SEL_F3) { countsel++; } + if (is_prop_edit) count += 3; + } } } @@ -1579,10 +1650,10 @@ static void createTransCurveVerts(TransInfo *t) } } - if (is_prop_edit || - ((bezt->f2 & SELECT) && hide_handles) || - ((bezt->f1 & SELECT) && hide_handles == 0)) - { + /* Elements that will be transform (not always a match to selection). */ + const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles); + + if (is_prop_edit || bezt_tx & SEL_F1) { copy_v3_v3(td->iloc, bezt->vec[0]); td->loc = bezt->vec[0]; copy_v3_v3(td->center, bezt->vec[(hide_handles || @@ -1613,7 +1684,7 @@ static void createTransCurveVerts(TransInfo *t) } /* This is the Curve Point, the other two are handles */ - if (is_prop_edit || (bezt->f2 & SELECT)) { + if (is_prop_edit || bezt_tx & SEL_F2) { copy_v3_v3(td->iloc, bezt->vec[1]); td->loc = bezt->vec[1]; copy_v3_v3(td->center, td->loc); @@ -1639,7 +1710,7 @@ static void createTransCurveVerts(TransInfo *t) copy_m3_m3(td->axismtx, axismtx); } - if ((bezt->f1 & SELECT) == 0 && (bezt->f3 & SELECT) == 0) + if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0) /* If the middle is selected but the sides arnt, this is needed */ if (hdata == NULL) { /* if the handle was not saved by the previous handle */ hdata = initTransDataCurveHandles(td, bezt); @@ -1649,10 +1720,7 @@ static void createTransCurveVerts(TransInfo *t) count++; tail++; } - if (is_prop_edit || - ((bezt->f2 & SELECT) && hide_handles) || - ((bezt->f3 & SELECT) && hide_handles == 0)) - { + if (is_prop_edit || bezt_tx & SEL_F3) { copy_v3_v3(td->iloc, bezt->vec[2]); td->loc = bezt->vec[2]; copy_v3_v3(td->center, bezt->vec[(hide_handles || @@ -1707,6 +1775,26 @@ static void createTransCurveVerts(TransInfo *t) for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) { if (bp->hide == 0) { if (is_prop_edit || (bp->f1 & SELECT)) { + float axismtx[3][3]; + + if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + if (nu->pntsv == 1) { + float normal[3], plane[3]; + + BKE_nurb_bpoint_calc_normal(nu, bp, normal); + BKE_nurb_bpoint_calc_plane(nu, bp, plane); + + if (createSpaceNormalTangent(axismtx, normal, plane)) { + /* pass */ + } + else { + normalize_v3(normal); + axis_dominant_v3_to_m3(axismtx, normal); + invert_m3(axismtx); + } + } + } + copy_v3_v3(td->iloc, bp->vec); td->loc = bp->vec; copy_v3_v3(td->center, td->loc); @@ -1725,6 +1813,11 @@ static void createTransCurveVerts(TransInfo *t) copy_m3_m3(td->smtx, smtx); copy_m3_m3(td->mtx, mtx); + if (t->around == V3D_AROUND_LOCAL_ORIGINS) { + if (nu->pntsv == 1) { + copy_m3_m3(td->axismtx, axismtx); + } + } td++; count++; @@ -1740,6 +1833,10 @@ static void createTransCurveVerts(TransInfo *t) calc_distanceCurveVerts(head, tail - 1); } } + +#undef SEL_F1 +#undef SEL_F2 +#undef SEL_F3 } /* ********************* lattice *************** */ @@ -2004,9 +2101,9 @@ static bool bmesh_test_dist_add( } /** - * \parm mtx: Measure disatnce in this space. - * \parm dists: Store the closest connected distance to selected vertices. - * \parm index: Optionally store the original index we're measuring the distance to (can be NULL). + * \param mtx: Measure disatnce in this space. + * \param dists: Store the closest connected distance to selected vertices. + * \param index: Optionally store the original index we're measuring the distance to (can be NULL). */ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index) { @@ -2276,7 +2373,7 @@ static struct TransIslandData *editmesh_islands_info_calc( } if (group_tot_single != 0) { - trans_islands = MEM_reallocN(trans_islands, group_tot + group_tot_single); + trans_islands = MEM_reallocN(trans_islands, sizeof(*trans_islands) * (group_tot + group_tot_single)); BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { @@ -2398,7 +2495,8 @@ static void createTransEditVerts(TransInfo *t) int island_info_tot; int *island_vert_map = NULL; - const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION); + /* Even for translation this is needed because of island-orientation, see: T51651. */ + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS); /* Original index of our connected vertex when connected distances are calculated. * Optional, allocate if needed. */ int *dists_index = NULL; @@ -2464,11 +2562,6 @@ static void createTransEditVerts(TransInfo *t) editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index); } - /* Only in case of rotation and resize, we want the elements of the edited - * object to behave as groups whose pivot are the individual origins - * - * TODO: use island_info to detect the closest point when the "Snap Target" - * in Blender UI is "Closest" */ if (is_island_center) { /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */ const bool calc_single_islands = ( @@ -5349,7 +5442,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) } /* update object's loc/rot to get current rigid body transform */ mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); - BKE_object_mat3_to_rot(ob, rot, false); + sub_v3_v3(ob->loc, ob->dloc); + BKE_object_mat3_to_rot(ob, rot, false); /* drot is already corrected here */ } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index f78a23be7b8..c23da19f830 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -971,7 +971,7 @@ static void recalcData_sequencer(TransInfo *t) /* force recalculation of triangles during transformation */ static void recalcData_gpencil_strokes(TransInfo *t) - { +{ TransData *td = t->data; for (int i = 0; i < t->total; i++, td++) { bGPDstroke *gps = td->extra; diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 42cc918ec8c..5f2e5a99090 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -86,12 +86,11 @@ static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const double mv output[1] *= mi->factor; } -static void InputHorizontalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3]) +static void InputHorizontalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]) { const int winx = t->ar ? t->ar->winx : 1; - const double pad = winx / 10; - output[0] = (mval[0] - pad) / (winx - 2 * pad); + output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f; } static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]) @@ -104,12 +103,11 @@ static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double m output[0] = dot_v3v3(t->viewinv[0], vec) * 2.0f; } -static void InputVerticalRatio(TransInfo *t, MouseInput *UNUSED(mi), const double mval[2], float output[3]) +static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]) { const int winy = t->ar ? t->ar->winy : 1; - const double pad = winy / 10; - output[0] = (mval[1] - pad) / (winy - 2 * pad); + output[0] = ((mval[1] - mi->imval[1]) / winy) * 2.0f; } static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]) @@ -187,7 +185,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2 /* use doubles here, to make sure a "1.0" (no rotation) doesn't become 9.999999e-01, which gives 0.02 for acos */ double deler = (((dx1 * dx1 + dy1 * dy1) + (dx2 * dx2 + dy2 * dy2) - - (dx3 * dx3 + dy3 * dy3)) / (2.0 * ((A * B) ? (A * B) : 1.0))); + (dx3 * dx3 + dy3 * dy3)) / (2.0 * (((A * B) != 0.0) ? (A * B) : 1.0))); /* ((A * B) ? (A * B) : 1.0) this takes care of potential divide by zero errors */ float dphi; @@ -314,7 +312,6 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) t->helpline = HLP_TRACKBALL; break; case INPUT_HORIZONTAL_RATIO: - mi->factor = (float)(mi->center[0] - mi->imval[0]); mi->apply = InputHorizontalRatio; t->helpline = HLP_HARROW; break; diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index f23c913da1e..ec066ba91a4 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -619,7 +619,7 @@ static int calc_manipulator_stats(const bContext *C) break; } /* if not gimbal, fall through to normal */ - /* fall-through */ + ATTR_FALLTHROUGH; } case V3D_MANIP_NORMAL: { @@ -630,7 +630,7 @@ static int calc_manipulator_stats(const bContext *C) break; } /* no break we define 'normal' as 'local' in Object mode */ - /* fall-through */ + ATTR_FALLTHROUGH; } case V3D_MANIP_LOCAL: { @@ -1716,7 +1716,7 @@ void BIF_draw_manipulator(const bContext *C) } } -static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], float hotspot) +static int manipulator_selectbuf(Scene *scene, ScrArea *sa, ARegion *ar, const int mval[2], float hotspot) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; @@ -1726,9 +1726,6 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl const bool is_picksel = true; const bool do_passes = GPU_select_query_check_active(); - /* XXX check a bit later on this... (ton) */ - extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rcti *rect); - /* when looking through a selected camera, the manipulator can be at the * exact same position as the view, skip so we don't break selection */ if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f) @@ -1739,8 +1736,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl rect.ymin = mval[1] - hotspot; rect.ymax = mval[1] + hotspot; - view3d_winmatrix_set(ar, v3d, &rect); - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); + ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL, &rect); if (do_passes) GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0); @@ -1759,7 +1755,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl hits = GPU_select_end(); - if (do_passes) { + if (do_passes && (hits > 0)) { GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); /* do the drawing */ @@ -1775,8 +1771,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl GPU_select_end(); } - view3d_winmatrix_set(ar, v3d, NULL); - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); + ED_view3d_draw_setup_view(NULL, scene, ar, v3d, NULL, NULL, NULL); if (hits == 1) return buffer[3]; else if (hits > 1) { @@ -1841,6 +1836,7 @@ static const char *manipulator_get_operator_name(int man_val) /* return 0; nothing happened */ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; ARegion *ar = CTX_wm_region(C); @@ -1855,7 +1851,7 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) RNA_enum_set(op->ptr, "constraint_orientation", v3d->twmode); // find the hotspots first test narrow hotspot - val = manipulator_selectbuf(sa, ar, event->mval, 0.5f * (float)U.tw_hotspot); + val = manipulator_selectbuf(scene, sa, ar, event->mval, 0.5f * (float)U.tw_hotspot); if (val) { wmOperatorType *ot; PointerRNA props_ptr; @@ -1863,7 +1859,7 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) const char *opname; // drawflags still global, for drawing call above - drawflags = manipulator_selectbuf(sa, ar, event->mval, 0.2f * (float)U.tw_hotspot); + drawflags = manipulator_selectbuf(scene, sa, ar, event->mval, 0.2f * (float)U.tw_hotspot); if (drawflags == 0) drawflags = val; /* Planar constraint doesn't make sense for rotation, give other keymaps a chance */ diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 674d2c376bb..54959304d72 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -455,14 +455,14 @@ void initTransformOrientation(bContext *C, TransInfo *t) BLI_strncpy(t->spacename, IFACE_("gimbal"), sizeof(t->spacename)); break; } - /* fall-through */ /* no gimbal fallthrough to normal */ + ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */ case V3D_MANIP_NORMAL: if (obedit || (ob && ob->mode & OB_MODE_POSE)) { BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename)); ED_getTransformOrientationMatrix(C, t->spacemtx, t->around); break; } - /* fall-through */ /* we define 'normal' as 'local' in Object mode */ + ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */ case V3D_MANIP_LOCAL: BLI_strncpy(t->spacename, IFACE_("local"), sizeof(t->spacename)); @@ -817,15 +817,21 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { Curve *cu = obedit->data; Nurb *nu = NULL; - BezTriple *bezt = NULL; int a; ListBase *nurbs = BKE_curve_editNurbs_get(cu); - if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bezt)) { + void *vert_act = NULL; + if (activeOnly && BKE_curve_nurb_vert_active_get(cu, &nu, &vert_act)) { if (nu->type == CU_BEZIER) { + BezTriple *bezt = vert_act; BKE_nurb_bezt_calc_normal(nu, bezt, normal); BKE_nurb_bezt_calc_plane(nu, bezt, plane); } + else { + BPoint *bp = vert_act; + BKE_nurb_bpoint_calc_normal(nu, bp, normal); + BKE_nurb_bpoint_calc_plane(nu, bp, plane); + } } else { const bool use_handle = (cu->drawflag & CU_HIDE_HANDLES) == 0; @@ -833,7 +839,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 for (nu = nurbs->first; nu; nu = nu->next) { /* only bezier has a normal */ if (nu->type == CU_BEZIER) { - bezt = nu->bezt; + BezTriple *bezt = nu->bezt; a = nu->pntsu; while (a--) { short flag = 0; @@ -885,6 +891,36 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3 bezt++; } } + else if (nu->bp && (nu->pntsv == 1)) { + BPoint *bp = nu->bp; + a = nu->pntsu; + while (a--) { + if (bp->f1 & SELECT) { + float tvec[3]; + + BPoint *bp_prev = BKE_nurb_bpoint_get_prev(nu, bp); + BPoint *bp_next = BKE_nurb_bpoint_get_next(nu, bp); + + const bool is_prev_sel = bp_prev && (bp_prev->f1 & SELECT); + const bool is_next_sel = bp_next && (bp_next->f1 & SELECT); + if (is_prev_sel == false && is_next_sel == false) { + /* Isolated, add based on surrounding */ + BKE_nurb_bpoint_calc_normal(nu, bp, tvec); + add_v3_v3(normal, tvec); + } + else if (is_next_sel) { + /* A segment, add the edge normal */ + sub_v3_v3v3(tvec, bp->vec, bp_next->vec ); + normalize_v3(tvec); + add_v3_v3(normal, tvec); + } + + BKE_nurb_bpoint_calc_plane(nu, bp, tvec); + add_v3_v3(plane, tvec); + } + bp++; + } + } } } diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index b33528b4149..6c62c091a78 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -130,18 +130,150 @@ struct SnapObjectContext { }; -static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt); +/** \} */ /* -------------------------------------------------------------------- */ -/** \name Support for storing all depths, not just the first (raycast 'all') +/** Common utilities +* \{ */ + + +typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data); + +/** + * Walks through all objects in the scene to create the list of objets to snap. * - * This uses a list of #SnapObjectHitDepth structs. + * \param sctx: Snap context to store data. + * \param snap_select : from enum SnapSelect. + * \param obedit : Object Edited to use its coordinates of BMesh(if any) to do the snapping. + */ +static void iter_snap_objects( + SnapObjectContext *sctx, + const SnapSelect snap_select, + Object *obedit, + IterSnapObjsCallback sob_callback, + void *data) +{ + Base *base_act = sctx->scene->basact; + /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA + * which makes the loop skip it, even the derived mesh will never change + * + * To solve that problem, we do it first as an exception. + * */ + if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) { + sob_callback(sctx, false, base_act->object, base_act->object->obmat, data); + } + + for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) { + if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) && + (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && + !((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL))) || + (snap_select == SNAP_NOT_ACTIVE && base == base_act))) + { + bool use_obedit; + Object *obj = base->object; + if (obj->transflag & OB_DUPLI) { + DupliObject *dupli_ob; + ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, obj); + for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { + use_obedit = obedit && dupli_ob->ob->data == obedit->data; + sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data); + } + free_object_duplilist(lb); + } + + use_obedit = obedit && obj->data == obedit->data; + sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data); + } + } +} + + +/** + * Generates a struct with the immutable parameters that will be used on all objects. * - * \{ */ + * \param snap_to: Element to snap, Vertice, Edge or Face. + * \param view_proj: ORTHO or PERSP. + * Currently only works one at a time, but can eventually operate as flag. + * + * \param mval: Mouse coords. + * (When NULL, ray-casting is handled without any projection matrix correction.) + * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. + * \param ray_start: ray_origin moved for the start clipping plane (clip_min). + * \param ray_direction: Unit length direction of the ray. + * \param depth_range: distances of clipe plane min and clip plane max; + */ +static void snap_data_set( + SnapData *snapdata, + const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj, + const float mval[2], const float ray_origin[3], const float ray_start[3], + const float ray_direction[3], const float depth_range[2]) +{ + copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat); + snapdata->win_half[0] = ar->winx / 2; + snapdata->win_half[1] = ar->winy / 2; + copy_v2_v2(snapdata->mval, mval); + snapdata->snap_to = snap_to; + copy_v3_v3(snapdata->ray_origin, ray_origin); + copy_v3_v3(snapdata->ray_start, ray_start); + copy_v3_v3(snapdata->ray_dir, ray_direction); + snapdata->view_proj = view_proj; + copy_v2_v2(snapdata->depth_range, depth_range); +} + + +MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) +{ + float dvec[3]; + sub_v3_v3v3(dvec, co, ray_start); + return dot_v3v3(dvec, ray_dir); +} + + +static bool walk_parent_bvhroot_cb(const BVHTreeAxisRange *bounds, void *userdata) +{ + BVHTreeRay *ray = userdata; + const float bbmin[3] = {bounds[0].min, bounds[1].min, bounds[2].min}; + const float bbmax[3] = {bounds[0].max, bounds[1].max, bounds[2].max}; + if (!isect_ray_aabb_v3_simple(ray->origin, ray->direction, bbmin, bbmax, &ray->radius, NULL)) { + ray->radius = -1; + } + return false; +} + + +static bool isect_ray_bvhroot_v3(struct BVHTree *tree, const float ray_start[3], const float ray_dir[3], float *depth) +{ + BVHTreeRay ray; + copy_v3_v3(ray.origin, ray_start); + copy_v3_v3(ray.direction, ray_dir); + + BLI_bvhtree_walk_dfs(tree, walk_parent_bvhroot_cb, NULL, NULL, &ray); + + if (ray.radius > 0) { + *depth = ray.radius; + return true; + } + else { + return false; + } +} + + +static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt); + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Ray Cast Funcs +* \{ */ + +/* Store all ray-hits + * Support for storing all depths, not just the first (raycast 'all') */ -/* Store all ray-hits */ struct RayCastAll_Data { void *bvhdata; @@ -162,6 +294,7 @@ struct RayCastAll_Data { bool retval; }; + static struct SnapObjectHitDepth *hit_depth_create( const float depth, const float co[3], const float no[3], int index, Object *ob, const float obmat[4][4], unsigned int ob_uuid) @@ -229,57 +362,508 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH } } -/** \} */ +static bool raycastDerivedMesh( + SnapObjectContext *sctx, + const float ray_start[3], const float ray_dir[3], + Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index, + /* read/write args */ + float *ray_depth, + /* return args */ + float r_loc[3], float r_no[3], int *r_index, + ListBase *r_hit_list) +{ + bool retval = false; -/* -------------------------------------------------------------------- */ + if (dm->getNumPolys(dm) == 0) { + return retval; + } + + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_start_local[3], ray_normal_local[3]; + float local_scale, local_depth, len_diff = 0.0f; + + invert_m4_m4(imat, obmat); + transpose_m3_m4(timat, imat); + + copy_v3_v3(ray_start_local, ray_start); + copy_v3_v3(ray_normal_local, ray_dir); + + mul_m4_v3(imat, ray_start_local); + mul_mat3_m4_v3(imat, ray_normal_local); + + /* local scale in normal direction */ + local_scale = normalize_v3(ray_normal_local); + local_depth = *ray_depth; + if (local_depth != BVH_RAYCAST_DIST_MAX) { + local_depth *= local_scale; + } + + /* Test BoundBox */ + BoundBox *bb = BKE_object_boundbox_get(ob); + if (bb) { + /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ + if (!isect_ray_aabb_v3_simple( + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL)) + { + return retval; + } + } + + SnapObjectData_Mesh *sod = NULL; + BVHTreeFromMesh *treedata; + + void **sod_p; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + sod = *sod_p; + } + else { + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_MESH; + } + + if (sod->bvh_trees[2] == NULL) { + sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); + } + + treedata = sod->bvh_trees[2]; + + if (treedata) { + /* the tree is owned by the DM and may have been freed since we last used! */ + if (treedata->tree) { + if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) { + free_bvhtree_from_mesh(treedata); + } + else { + if (!treedata->vert_allocated) { + treedata->vert = DM_get_vert_array(dm, &treedata->vert_allocated); + } + if (!treedata->loop_allocated) { + treedata->loop = DM_get_loop_array(dm, &treedata->loop_allocated); + } + if (!treedata->looptri_allocated) { + if (!sod->poly_allocated) { + sod->mpoly = DM_get_poly_array(dm, &sod->poly_allocated); + } + treedata->looptri = DM_get_looptri_array( + dm, treedata->vert, + sod->mpoly, dm->getNumPolys(dm), + treedata->loop, dm->getNumLoops(dm), + &treedata->looptri_allocated); + } + } + } + + if (treedata->tree == NULL) { + bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); + + if (treedata->tree == NULL) { + return retval; + } + } + } + else { + return retval; + } + + /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already + * been *inside* boundbox, leading to snap failures (see T38409). + * Note also ar might be null (see T38435), in this case we assume ray_start is ok! + */ + if (len_diff == 0.0f) { /* do_ray_start_correction */ + /* We *need* a reasonably valid len_diff in this case. + * Get the distance to bvhtree root */ + if (!isect_ray_bvhroot_v3(treedata->tree, ray_start_local, ray_normal_local, &len_diff)) + { + return retval; + } + } + /* You need to make sure that ray_start is really far away, + * because even in the Orthografic view, in some cases, + * the ray can start inside the object (see T50486) */ + if (len_diff > 400.0f) { + /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with + * very far away ray_start values (as returned in case of ortho view3d), see T38358. + */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff); + local_depth -= len_diff; + } + else { + len_diff = 0.0f; + } + if (r_hit_list) { + struct RayCastAll_Data data; + + data.bvhdata = treedata; + data.raycast_callback = treedata->raycast_callback; + data.obmat = obmat; + data.timat = timat; + data.len_diff = len_diff; + data.local_scale = local_scale; + data.ob = ob; + data.ob_uuid = ob_index; + data.hit_list = r_hit_list; + data.retval = retval; + + BLI_bvhtree_ray_cast_all( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); + + retval = data.retval; + } + else { + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; + + if (BLI_bvhtree_ray_cast( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + &hit, treedata->raycast_callback, treedata) != -1) + { + hit.dist += len_diff; + hit.dist /= local_scale; + if (hit.dist <= *ray_depth) { + *ray_depth = hit.dist; + copy_v3_v3(r_loc, hit.co); + + /* back to worldspace */ + mul_m4_v3(obmat, r_loc); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + + retval = true; + + if (r_index) { + *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]); + } + } + } + } + + return retval; +} + +static bool raycastEditMesh( + SnapObjectContext *sctx, + const float ray_start[3], const float ray_dir[3], + Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index, + /* read/write args */ + float *ray_depth, + /* return args */ + float r_loc[3], float r_no[3], int *r_index, + ListBase *r_hit_list) +{ + bool retval = false; + if (em->bm->totface == 0) { + return retval; + } + + SnapObjectData_EditMesh *sod = NULL; + BVHTreeFromEditMesh *treedata = NULL; + + void **sod_p; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { + sod = *sod_p; + } + else { + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod->sd.type = SNAP_EDIT_MESH; + } + + if (sod->bvh_trees[2] == NULL) { + sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); + } + treedata = sod->bvh_trees[2]; + + if (treedata) { + if (treedata->tree == NULL) { + BLI_bitmap *elem_mask = NULL; + int looptri_num_active = -1; + + if (sctx->callbacks.edit_mesh.test_face_fn) { + elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); + looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( + em->bm, elem_mask, + sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); + } + bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL); + + if (elem_mask) { + MEM_freeN(elem_mask); + } + } + if (treedata->tree == NULL) { + return retval; + } + } + else { + return retval; + } + + float imat[4][4]; + float timat[3][3]; /* transpose inverse matrix for normals */ + float ray_normal_local[3], ray_start_local[3], len_diff = 0.0f; + + invert_m4_m4(imat, obmat); + transpose_m3_m4(timat, imat); + + copy_v3_v3(ray_normal_local, ray_dir); + mul_mat3_m4_v3(imat, ray_normal_local); + + copy_v3_v3(ray_start_local, ray_start); + mul_m4_v3(imat, ray_start_local); + + /* local scale in normal direction */ + float local_scale = normalize_v3(ray_normal_local); + float local_depth = *ray_depth; + if (local_depth != BVH_RAYCAST_DIST_MAX) { + local_depth *= local_scale; + } + + /* Only use closer ray_start in case of ortho view! In perspective one, ray_start + * may already been *inside* boundbox, leading to snap failures (see T38409). + * Note also ar might be null (see T38435), in this case we assume ray_start is ok! + */ + if (sctx->use_v3d && !((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp) { /* do_ray_start_correction */ + /* We *need* a reasonably valid len_diff in this case. + * Get the distance to bvhtree root */ + if (!isect_ray_bvhroot_v3(treedata->tree, ray_start_local, ray_normal_local, &len_diff)) + { + return retval; + } + /* You need to make sure that ray_start is really far away, + * because even in the Orthografic view, in some cases, + * the ray can start inside the object (see T50486) */ + if (len_diff > 400.0f) { + /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with + * very far away ray_start values (as returned in case of ortho view3d), see T38358. + */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff); + local_depth -= len_diff; + } + else len_diff = 0.0f; + } + if (r_hit_list) { + struct RayCastAll_Data data; + + data.bvhdata = treedata; + data.raycast_callback = treedata->raycast_callback; + data.obmat = obmat; + data.timat = timat; + data.len_diff = len_diff; + data.local_scale = local_scale; + data.ob = ob; + data.ob_uuid = ob_index; + data.hit_list = r_hit_list; + data.retval = retval; + + BLI_bvhtree_ray_cast_all( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); + + retval = data.retval; + } + else { + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; + + if (BLI_bvhtree_ray_cast( + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + &hit, treedata->raycast_callback, treedata) != -1) + { + hit.dist += len_diff; + hit.dist /= local_scale; + if (hit.dist <= *ray_depth) { + *ray_depth = hit.dist; + copy_v3_v3(r_loc, hit.co); + + /* back to worldspace */ + mul_m4_v3(obmat, r_loc); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + + retval = true; + + if (r_index) { + *r_index = hit.index; + } + } + } + } + + return retval; +} -/** \Common utilities - * \{ */ /** - * Generates a struct with the immutable parameters that will be used on all objects. - * - * \param snap_to: Element to snap, Vertice, Edge or Face. - * \param view_proj: ORTHO or PERSP. - * Currently only works one at a time, but can eventually operate as flag. + * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; * - * \param mval: Mouse coords. - * (When NULL, ray-casting is handled without any projection matrix correction.) - * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. - * \param ray_start: ray_origin moved for the start clipping plane (clip_min). - * \param ray_direction: Unit length direction of the ray. - * \param depth_range: distances of clipe plane min and clip plane max; + * \note Duplicate args here are documented at #snapObjectsRay */ -static void snap_data_set( - SnapData *snapdata, - const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj, - const float mval[2], const float ray_origin[3], const float ray_start[3], - const float ray_direction[3], const float depth_range[2]) +static bool raycastObj( + SnapObjectContext *sctx, + const float ray_start[3], const float ray_dir[3], + Object *ob, float obmat[4][4], const unsigned int ob_index, + bool use_obedit, + /* read/write args */ + float *ray_depth, + /* return args */ + float r_loc[3], float r_no[3], int *r_index, + Object **r_ob, float r_obmat[4][4], + ListBase *r_hit_list) { - if (ar) { - copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat); - snapdata->win_half[0] = ar->winx / 2; - snapdata->win_half[1] = ar->winy / 2; + bool retval = false; + + if (ob->type == OB_MESH) { + BMEditMesh *em; + + if (use_obedit) { + em = BKE_editmesh_from_object(ob); + retval = raycastEditMesh( + sctx, + ray_start, ray_dir, + ob, em, obmat, ob_index, + ray_depth, r_loc, r_no, r_index, r_hit_list); + } + else { + /* in this case we want the mesh from the editmesh, avoids stale data. see: T45978. + * still set the 'em' to NULL, since we only want the 'dm'. */ + DerivedMesh *dm; + em = BKE_editmesh_from_object(ob); + if (em) { + editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm); + } + else { + dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH); + } + retval = raycastDerivedMesh( + sctx, + ray_start, ray_dir, + ob, dm, obmat, ob_index, + ray_depth, r_loc, r_no, r_index, r_hit_list); + + dm->release(dm); + } } - if (mval) { - copy_v2_v2(snapdata->mval, mval); + + if (retval) { + if (r_ob) { + *r_ob = ob; + copy_m4_m4(r_obmat, obmat); + } } - snapdata->snap_to = snap_to; - copy_v3_v3(snapdata->ray_origin, ray_origin); - copy_v3_v3(snapdata->ray_start, ray_start); - copy_v3_v3(snapdata->ray_dir, ray_direction); - snapdata->view_proj = view_proj; - copy_v2_v2(snapdata->depth_range, depth_range); + + return retval; } -MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) + +struct RaycastObjUserData { + const float *ray_start; + const float *ray_dir; + unsigned int ob_index; + /* read/write args */ + float *ray_depth; + /* return args */ + float *r_loc; + float *r_no; + int *r_index; + Object **r_ob; + float (*r_obmat)[4]; + ListBase *r_hit_list; + bool ret; +}; + +static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) { - float dvec[3]; - sub_v3_v3v3(dvec, co, ray_start); - return dot_v3v3(dvec, ray_dir); + struct RaycastObjUserData *dt = data; + dt->ret |= raycastObj( + sctx, + dt->ray_start, dt->ray_dir, + ob, obmat, dt->ob_index++, is_obedit, + dt->ray_depth, + dt->r_loc, dt->r_no, dt->r_index, + dt->r_ob, dt->r_obmat, + dt->r_hit_list); +} + +/** + * Main RayCast Function + * ====================== + * + * Walks through all objects in the scene to find the `hit` on object surface. + * + * \param sctx: Snap context to store data. + * \param snapdata: struct generated in `set_snapdata`. + * \param snap_select : from enum SnapSelect. + * \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping. + * \param obj_list: List with objects to snap (created in `create_object_list`). + * + * Read/Write Args + * --------------- + * + * \param ray_depth: maximum depth allowed for r_co, elements deeper than this value will be ignored. + * + * Output Args + * ----------- + * + * \param r_loc: Hit location. + * \param r_no: Hit normal (optional). + * \param r_index: Hit index or -1 when no valid index is found. + * (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``). + * \param r_ob: Hit object. + * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). + * \param r_hit_list: List of #SnapObjectHitDepth (caller must free). + * + */ +static bool raycastObjects( + SnapObjectContext *sctx, + const float ray_start[3], const float ray_dir[3], + const SnapSelect snap_select, const bool use_object_edit_cage, + /* read/write args */ + float *ray_depth, + /* return args */ + float r_loc[3], float r_no[3], int *r_index, + Object **r_ob, float r_obmat[4][4], + ListBase *r_hit_list) +{ + Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL; + + struct RaycastObjUserData data = { + .ray_start = ray_start, + .ray_dir = ray_dir, + .ob_index = 0, + .ray_depth = ray_depth, + .r_loc = r_loc, + .r_no = r_no, + .r_index = r_index, + .r_ob = r_ob, + .r_obmat = r_obmat, + .r_hit_list = r_hit_list, + .ret = false, + }; + + iter_snap_objects(sctx, snap_select, obedit, raycast_obj_cb, &data); + + return data.ret; } + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** Snap Nearest utilities + * \{ */ + static void copy_dm_vert_no(const int index, float r_no[3], const BVHTreeFromMesh *data) { const MVert *vert = data->vert + index; @@ -558,15 +1142,12 @@ static float dist_squared_to_projected_aabb( vb2d[0] *= data->win_half[0]; vb2d[1] *= data->win_half[1]; - //float dvec[2], edge[2], rdist; - //sub_v2_v2v2(dvec, data->mval, va2d); - //sub_v2_v2v2(edge, vb2d, va2d); - float rdist; - short dvec[2] = {data->mval[0] - va2d[0], data->mval[1] - va2d[1]}; - short edge[2] = {vb2d[0] - va2d[0], vb2d[1] - va2d[1]}; - float lambda = dvec[0] * edge[0] + dvec[1] * edge[1]; + float dvec[2], edge[2], lambda, rdist; + sub_v2_v2v2(dvec, data->mval, va2d); + sub_v2_v2v2(edge, vb2d, va2d); + lambda = dot_v2v2(dvec, edge); if (lambda != 0.0f) { - lambda /= edge[0] * edge[0] + edge[1] * edge[1]; + lambda /= len_squared_v2(edge); if (lambda <= 0.0f) { rdist = len_squared_v2v2(data->mval, va2d); r_axis_closest[main_axis] = true; @@ -603,24 +1184,12 @@ static float dist_squared_to_projected_aabb_simple( return dist_squared_to_projected_aabb(&data, bbmin, bbmax, dummy); } -static float dist_aabb_to_plane( - const float bbmin[3], const float bbmax[3], - const float plane_co[3], const float plane_no[3]) -{ - const float local_bvmin[3] = { - (plane_no[0] < 0) ? bbmax[0] : bbmin[0], - (plane_no[1] < 0) ? bbmax[1] : bbmin[1], - (plane_no[2] < 0) ? bbmax[2] : bbmin[2], - }; - return depth_get(local_bvmin, plane_co, plane_no); -} - /** \} */ /* -------------------------------------------------------------------- */ -/** \Walk DFS +/** Walk DFS * \{ */ typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data); @@ -1053,21 +1622,15 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) static bool snapDerivedMesh( SnapObjectContext *sctx, SnapData *snapdata, - Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index, + Object *ob, DerivedMesh *dm, float obmat[4][4], /* read/write args */ float *ray_depth, float *dist_px, /* return args */ - float r_loc[3], float r_no[3], int *r_index, - ListBase *r_hit_list) + float r_loc[3], float r_no[3]) { bool retval = false; - if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { - if (dm->getNumPolys(dm) == 0) { - return retval; - } - } - else if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { + if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { if (dm->getNumEdges(dm) == 0) { return retval; } @@ -1078,38 +1641,27 @@ static bool snapDerivedMesh( } } - bool need_ray_start_correction_init = - (snapdata->snap_to == SCE_SNAP_MODE_FACE) && - (snapdata->view_proj == VIEW_PROJ_ORTHO); - float imat[4][4]; float timat[3][3]; /* transpose inverse matrix for normals */ - float ray_start_local[3], ray_normal_local[3]; - float local_scale, local_depth, len_diff; + float ray_normal_local[3]; + float local_scale; invert_m4_m4(imat, obmat); transpose_m3_m4(timat, imat); - copy_v3_v3(ray_start_local, snapdata->ray_start); copy_v3_v3(ray_normal_local, snapdata->ray_dir); - mul_m4_v3(imat, ray_start_local); mul_mat3_m4_v3(imat, ray_normal_local); /* local scale in normal direction */ local_scale = normalize_v3(ray_normal_local); - local_depth = *ray_depth; - if (local_depth != BVH_RAYCAST_DIST_MAX) { - local_depth *= local_scale; - } float lpmat[4][4]; float ray_org_local[3]; float ray_min_dist; - if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { - mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - ray_min_dist = snapdata->depth_range[0] * local_scale; - } + + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + ray_min_dist = snapdata->depth_range[0] * local_scale; copy_v3_v3(ray_org_local, snapdata->ray_origin); mul_m4_v3(imat, ray_org_local); @@ -1118,26 +1670,12 @@ static bool snapDerivedMesh( BoundBox *bb = BKE_object_boundbox_get(ob); if (bb) { /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ - if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { - float dist_px_sq = dist_squared_to_projected_aabb_simple( - lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, - ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); - if (dist_px_sq > SQUARE(*dist_px)) { - return retval; - } - } - else { - /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ - if (!isect_ray_aabb_v3_simple( - ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) - { - return retval; - } + float dist_px_sq = dist_squared_to_projected_aabb_simple( + lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, + ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); + if (dist_px_sq > SQUARE(*dist_px)) { + return retval; } - /* was local_depth, see: T47838 */ - len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local); - if (len_diff < 0) len_diff = 0.0f; - need_ray_start_correction_init = false; } SnapObjectData_Mesh *sod = NULL; @@ -1154,9 +1692,6 @@ static bool snapDerivedMesh( int tree_index = -1; switch (snapdata->snap_to) { - case SCE_SNAP_MODE_FACE: - tree_index = 2; - break; case SCE_SNAP_MODE_EDGE: tree_index = 1; break; @@ -1180,179 +1715,71 @@ static bool snapDerivedMesh( treedata->vert = DM_get_vert_array(dm, &treedata->vert_allocated); } if ((tree_index == 1) && !treedata->edge_allocated) { - treedata->edge = DM_get_edge_array(dm, &treedata->vert_allocated); - } - if (tree_index == 2) { - if (!treedata->loop_allocated) { - treedata->loop = DM_get_loop_array(dm, &treedata->loop_allocated); - } - if (!treedata->looptri_allocated) { - if (!sod->poly_allocated) { - sod->mpoly = DM_get_poly_array(dm, &sod->poly_allocated); - } - treedata->looptri = DM_get_looptri_array( - dm, treedata->vert, - sod->mpoly, dm->getNumPolys(dm), - treedata->loop, dm->getNumLoops(dm), - &treedata->looptri_allocated); - } + treedata->edge = DM_get_edge_array(dm, &treedata->edge_allocated); } } } } - if (treedata && treedata->tree == NULL) { - switch (snapdata->snap_to) { - case SCE_SNAP_MODE_FACE: - bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6); - break; - case SCE_SNAP_MODE_EDGE: - bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6); - break; - case SCE_SNAP_MODE_VERTEX: - bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6); - break; + if (treedata) { + if (treedata->tree == NULL) { + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_EDGE: + bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6); + break; + case SCE_SNAP_MODE_VERTEX: + bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6); + break; + } + } + if (treedata->tree == NULL) { + return retval; } } - if (!treedata || !treedata->tree) { + else { return retval; } - if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { - /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already - * been *inside* boundbox, leading to snap failures (see T38409). - * Note also ar might be null (see T38435), in this case we assume ray_start is ok! - */ - if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ - if (need_ray_start_correction_init) { - /* We *need* a reasonably valid len_diff in this case. - * Use BHVTree to find the closest face from ray_start_local. - */ - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); - if (nearest.index != -1) { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - } - } - /* You need to make sure that ray_start is really far away, - * because even in the Orthografic view, in some cases, - * the ray can start inside the object (see T50486) */ - if (len_diff > 400.0f) { - /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with - * very far away ray_start values (as returned in case of ortho view3d), see T38358. - */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, - len_diff + snapdata->depth_range[0] * local_scale); - local_depth -= len_diff; - } - else len_diff = 0.0f; - } - else { - len_diff = 0.0f; - } - if (r_hit_list) { - struct RayCastAll_Data data; - - data.bvhdata = treedata; - data.raycast_callback = treedata->raycast_callback; - data.obmat = obmat; - data.timat = timat; - data.len_diff = len_diff; - data.local_scale = local_scale; - data.ob = ob; - data.ob_uuid = ob_index; - data.hit_list = r_hit_list; - data.retval = retval; - - BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); - - retval = data.retval; - } - else { - BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; + /* Warning: the depth_max is currently being used only in perspective view. + * It is not correct to limit the maximum depth for elements obtained with nearest + * since this limitation depends on the normal and the size of the occlusion face. + * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */ + const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0]; - if (BLI_bvhtree_ray_cast( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - &hit, treedata->raycast_callback, treedata) != -1) - { - hit.dist += len_diff; - hit.dist /= local_scale; - if (hit.dist <= *ray_depth) { - *ray_depth = hit.dist; - copy_v3_v3(r_loc, hit.co); - - /* back to worldspace */ - mul_m4_v3(obmat, r_loc); - - if (r_no) { - copy_v3_v3(r_no, hit.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } + Nearest2dUserData neasrest2d = { + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], ray_depth_max_global}, + .userdata = treedata, + .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts, + .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no, + .index = -1}; - retval = true; + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, + ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local); - if (r_index) { - *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]); - } - } - } - } - } - /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */ - else { + BVHTree_WalkLeafCallback cb_walk_leaf = + (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - /* Warning: the depth_max is currently being used only in perspective view. - * It is not correct to limit the maximum depth for elements obtained with nearest - * since this limitation depends on the normal and the size of the occlusion face. - * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */ - const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0]; - - Nearest2dUserData neasrest2d = { - .dist_px_sq = SQUARE(*dist_px), - .r_axis_closest = {1.0f, 1.0f, 1.0f}, - .depth_range = {snapdata->depth_range[0], ray_depth_max_global}, - .userdata = treedata, - .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts, - .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no, - .index = -1}; - - dist_squared_to_projected_aabb_precalc( - &neasrest2d.data_precalc, lpmat, - snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, - ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local); - - BVHTree_WalkLeafCallback cb_walk_leaf = - (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? - cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - - BLI_bvhtree_walk_dfs( - treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); - - if (neasrest2d.index != -1) { - copy_v3_v3(r_loc, neasrest2d.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, neasrest2d.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } - *dist_px = sqrtf(neasrest2d.dist_px_sq); - *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); - retval = true; + if (neasrest2d.index != -1) { + copy_v3_v3(r_loc, neasrest2d.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest2d.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); } + *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + + retval = true; } return retval; @@ -1360,20 +1787,14 @@ static bool snapDerivedMesh( static bool snapEditMesh( SnapObjectContext *sctx, SnapData *snapdata, - Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index, + Object *ob, BMEditMesh *em, float obmat[4][4], /* read/write args */ float *ray_depth, float *dist_px, /* return args */ - float r_loc[3], float r_no[3], int *r_index, - ListBase *r_hit_list) + float r_loc[3], float r_no[3]) { bool retval = false; - if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { - if (em->bm->totface == 0) { - return retval; - } - } if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { if (em->bm->totedge == 0) { return retval; @@ -1398,13 +1819,8 @@ static bool snapEditMesh( /* local scale in normal direction */ float local_scale = normalize_v3(ray_normal_local); - float local_depth = *ray_depth; - if (local_depth != BVH_RAYCAST_DIST_MAX) { - local_depth *= local_scale; - } SnapObjectData_EditMesh *sod = NULL; - BVHTreeFromEditMesh *treedata = NULL; void **sod_p; @@ -1418,9 +1834,6 @@ static bool snapEditMesh( int tree_index = -1; switch (snapdata->snap_to) { - case SCE_SNAP_MODE_FACE: - tree_index = 2; - break; case SCE_SNAP_MODE_EDGE: tree_index = 1; break; @@ -1435,197 +1848,90 @@ static bool snapEditMesh( treedata = sod->bvh_trees[tree_index]; } - if (treedata && treedata->tree == NULL) { - BLI_bitmap *elem_mask = NULL; - switch (snapdata->snap_to) { - case SCE_SNAP_MODE_FACE: - { - int looptri_num_active = -1; - if (sctx->callbacks.edit_mesh.test_face_fn) { - elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); - looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( - em->bm, elem_mask, - sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); + if (treedata) { + if (treedata->tree == NULL) { + BLI_bitmap *elem_mask = NULL; + switch (snapdata->snap_to) { + case SCE_SNAP_MODE_EDGE: + { + int edges_num_active = -1; + if (sctx->callbacks.edit_mesh.test_edge_fn) { + elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); + edges_num_active = BM_iter_mesh_bitmap_from_filter( + BM_EDGES_OF_MESH, em->bm, elem_mask, + (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, + sctx->callbacks.edit_mesh.user_data); + } + bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6); + break; } - bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL); - break; - } - case SCE_SNAP_MODE_EDGE: - { - int edges_num_active = -1; - if (sctx->callbacks.edit_mesh.test_edge_fn) { - elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); - edges_num_active = BM_iter_mesh_bitmap_from_filter( - BM_EDGES_OF_MESH, em->bm, elem_mask, - (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, - sctx->callbacks.edit_mesh.user_data); + case SCE_SNAP_MODE_VERTEX: + { + int verts_num_active = -1; + if (sctx->callbacks.edit_mesh.test_vert_fn) { + elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + verts_num_active = BM_iter_mesh_bitmap_from_filter( + BM_VERTS_OF_MESH, em->bm, elem_mask, + (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, + sctx->callbacks.edit_mesh.user_data); + } + bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6); + break; } - bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6); - break; } - case SCE_SNAP_MODE_VERTEX: - { - int verts_num_active = -1; - if (sctx->callbacks.edit_mesh.test_vert_fn) { - elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); - verts_num_active = BM_iter_mesh_bitmap_from_filter( - BM_VERTS_OF_MESH, em->bm, elem_mask, - (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, - sctx->callbacks.edit_mesh.user_data); - } - bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6); - break; + if (elem_mask) { + MEM_freeN(elem_mask); } } - if (elem_mask) { - MEM_freeN(elem_mask); + if (treedata->tree == NULL) { + return retval; } } - - if (!treedata || !treedata->tree) { + else { return retval; } - if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { - float ray_start_local[3]; - copy_v3_v3(ray_start_local, snapdata->ray_start); - mul_m4_v3(imat, ray_start_local); + float ray_org_local[3]; + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); - /* Only use closer ray_start in case of ortho view! In perspective one, ray_start - * may already been *inside* boundbox, leading to snap failures (see T38409). - * Note also ar might be null (see T38435), in this case we assume ray_start is ok! - */ - float len_diff = 0.0f; - if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ - /* We *need* a reasonably valid len_diff in this case. - * Use BHVTree to find the closest face from ray_start_local. - */ - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - if (BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) - { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - /* You need to make sure that ray_start is really far away, - * because even in the Orthografic view, in some cases, - * the ray can start inside the object (see T50486) */ - if (len_diff > 400.0f) { - float ray_org_local[3]; - - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); - - /* We pass a temp ray_start, set from object's boundbox, - * to avoid precision issues with very far away ray_start values - * (as returned in case of ortho view3d), see T38358. - */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl( - ray_start_local, ray_org_local, ray_normal_local, - len_diff + snapdata->depth_range[0] * local_scale); - local_depth -= len_diff; - } - else len_diff = 0.0f; - } - } - if (r_hit_list) { - struct RayCastAll_Data data; - - data.bvhdata = treedata; - data.raycast_callback = treedata->raycast_callback; - data.obmat = obmat; - data.timat = timat; - data.len_diff = len_diff; - data.local_scale = local_scale; - data.ob = ob; - data.ob_uuid = ob_index; - data.hit_list = r_hit_list; - data.retval = retval; - - BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); - - retval = data.retval; - } - else { - BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; + Nearest2dUserData neasrest2d = { + .dist_px_sq = SQUARE(*dist_px), + .r_axis_closest = {1.0f, 1.0f, 1.0f}, + .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, + .userdata = treedata, + .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts, + .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no, + .index = -1}; - if (BLI_bvhtree_ray_cast( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - &hit, treedata->raycast_callback, treedata) != -1) - { - hit.dist += len_diff; - hit.dist /= local_scale; - if (hit.dist <= *ray_depth) { - *ray_depth = hit.dist; - copy_v3_v3(r_loc, hit.co); - - /* back to worldspace */ - mul_m4_v3(obmat, r_loc); - - if (r_no) { - copy_v3_v3(r_no, hit.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } + float lpmat[4][4]; + mul_m4_m4m4(lpmat, snapdata->pmat, obmat); + dist_squared_to_projected_aabb_precalc( + &neasrest2d.data_precalc, lpmat, + snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, + (snapdata->depth_range[0] * local_scale), snapdata->mval, + ray_org_local, ray_normal_local); - retval = true; + BVHTree_WalkLeafCallback cb_walk_leaf = + (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - if (r_index) { - *r_index = hit.index; - } - } - } - } - } - else { - float ray_org_local[3]; - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); - - Nearest2dUserData neasrest2d = { - .dist_px_sq = SQUARE(*dist_px), - .r_axis_closest = {1.0f, 1.0f, 1.0f}, - .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, - .userdata = treedata, - .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts, - .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no, - .index = -1}; - - float lpmat[4][4]; - mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - dist_squared_to_projected_aabb_precalc( - &neasrest2d.data_precalc, lpmat, - snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half, - (snapdata->depth_range[0] * local_scale), snapdata->mval, - ray_org_local, ray_normal_local); - - BVHTree_WalkLeafCallback cb_walk_leaf = - (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? - cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - - BLI_bvhtree_walk_dfs( - treedata->tree, - cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); - - if (neasrest2d.index != -1) { - copy_v3_v3(r_loc, neasrest2d.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, neasrest2d.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); - } - *dist_px = sqrtf(neasrest2d.dist_px_sq); - *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d); - retval = true; + if (neasrest2d.index != -1) { + copy_v3_v3(r_loc, neasrest2d.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest2d.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); } + *dist_px = sqrtf(neasrest2d.dist_px_sq); + *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); + + retval = true; } return retval; @@ -1638,14 +1944,13 @@ static bool snapEditMesh( */ static bool snapObject( SnapObjectContext *sctx, SnapData *snapdata, - Object *ob, float obmat[4][4], const unsigned int ob_index, + Object *ob, float obmat[4][4], bool use_obedit, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ - float r_loc[3], float r_no[3], int *r_index, - Object **r_ob, float r_obmat[4][4], - ListBase *r_hit_list) + float r_loc[3], float r_no[3], + Object **r_ob, float r_obmat[4][4]) { bool retval = false; @@ -1655,10 +1960,9 @@ static bool snapObject( if (use_obedit) { em = BKE_editmesh_from_object(ob); retval = snapEditMesh( - sctx, snapdata, ob, em, obmat, ob_index, + sctx, snapdata, ob, em, obmat, ray_depth, dist_px, - r_loc, r_no, r_index, - r_hit_list); + r_loc, r_no); } else { /* in this case we want the mesh from the editmesh, avoids stale data. see: T45978. @@ -1672,10 +1976,9 @@ static bool snapObject( dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH); } retval = snapDerivedMesh( - sctx, snapdata, ob, dm, obmat, ob_index, + sctx, snapdata, ob, dm, obmat, ray_depth, dist_px, - r_loc, r_no, - r_index, r_hit_list); + r_loc, r_no); dm->release(dm); } @@ -1720,6 +2023,34 @@ static bool snapObject( return retval; } + +struct SnapObjUserData { + SnapData *snapdata; + /* read/write args */ + float *ray_depth; + float *dist_px; + /* return args */ + float *r_loc; + float *r_no; + Object **r_ob; + float (*r_obmat)[4]; + bool ret; +}; + +static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) +{ + struct SnapObjUserData *dt = data; + dt->ret |= snapObject( + sctx, dt->snapdata, + ob, obmat, is_obedit, + /* read/write args */ + dt->ray_depth, dt->dist_px, + /* return args */ + dt->r_loc, dt->r_no, + dt->r_ob, dt->r_obmat); +} + + /** * Main Snapping Function * ====================== @@ -1728,8 +2059,8 @@ static bool snapObject( * * \param sctx: Snap context to store data. * \param snapdata: struct generated in `get_snapdata`. - * \param snap_select: from enum SnapSelect. - * \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping. + * \param snap_select : from enum SnapSelect. + * \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping. * * Read/Write Args * --------------- @@ -1746,89 +2077,33 @@ static bool snapObject( * (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``). * \param r_ob: Hit object. * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). - * \param r_hit_list: List of #SnapObjectHitDepth (caller must free). * */ static bool snapObjectsRay( SnapObjectContext *sctx, SnapData *snapdata, - const SnapSelect snap_select, - const bool use_object_edit_cage, + const SnapSelect snap_select, const bool use_object_edit_cage, /* read/write args */ float *ray_depth, float *dist_px, /* return args */ - float r_loc[3], float r_no[3], int *r_index, - Object **r_ob, float r_obmat[4][4], - ListBase *r_hit_list) + float r_loc[3], float r_no[3], + Object **r_ob, float r_obmat[4][4]) { - bool retval = false; - - unsigned int ob_index = 0; Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL; - /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA - * which makes the loop skip it, even the derived mesh will never change - * - * To solve that problem, we do it first as an exception. - * */ - Base *base_act = sctx->scene->basact; - if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) { - Object *ob = base_act->object; - - retval |= snapObject( - sctx, snapdata, ob, ob->obmat, ob_index++, false, - ray_depth, dist_px, - r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); - } - - bool ignore_object_selected = false, ignore_object_active = false; - switch (snap_select) { - case SNAP_ALL: - break; - case SNAP_NOT_SELECTED: - ignore_object_selected = true; - break; - case SNAP_NOT_ACTIVE: - ignore_object_active = true; - break; - } - for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) { - if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) && - (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && - - !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) || - (ignore_object_active && base == base_act))) - { - Object *ob = base->object; - - if (ob->transflag & OB_DUPLI) { - DupliObject *dupli_ob; - ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob); - - for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { - bool use_obedit_dupli = (obedit && dupli_ob->ob->data == obedit->data); - Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob; - - retval |= snapObject( - sctx, snapdata, dupli_snap, dupli_ob->mat, - ob_index++, use_obedit_dupli, - ray_depth, dist_px, - r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); - } - - free_object_duplilist(lb); - } + struct SnapObjUserData data = { + .snapdata = snapdata, + .ray_depth = ray_depth, + .dist_px = dist_px, + .r_loc = r_loc, + .r_no = r_no, + .r_ob = r_ob, + .r_obmat = r_obmat, + .ret = false, + }; - bool use_obedit = (obedit != NULL) && (ob->data == obedit->data); - Object *ob_snap = use_obedit ? obedit : ob; + iter_snap_objects(sctx, snap_select, obedit, sanp_obj_cb, &data); - retval |= snapObject( - sctx, snapdata, ob_snap, ob->obmat, ob_index++, use_obedit, - ray_depth, dist_px, - r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); - } - } - - return retval; + return data.ret; } /** \} */ @@ -1922,25 +2197,17 @@ void ED_transform_snap_object_context_set_editmesh_callbacks( bool ED_transform_snap_object_project_ray_ex( SnapObjectContext *sctx, - const unsigned short snap_to, const struct SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float *ray_depth, float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4]) { - const float depth_range[2] = {0.0f, FLT_MAX}; - - SnapData snapdata; - snap_data_set( - &snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, - NULL, ray_start, ray_start, ray_normal, depth_range); - - return snapObjectsRay( - sctx, &snapdata, + return raycastObjects( + sctx, + ray_start, ray_normal, params->snap_select, params->use_object_edit_cage, - ray_depth, NULL, - r_loc, r_no, r_index, r_ob, r_obmat, NULL); + ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL); } /** @@ -1952,13 +2219,11 @@ bool ED_transform_snap_object_project_ray_ex( */ bool ED_transform_snap_object_project_ray_all( SnapObjectContext *sctx, - const unsigned short snap_to, const struct SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float ray_depth, bool sort, ListBase *r_hit_list) { - const float depth_range[2] = {0.0f, FLT_MAX}; if (ray_depth == -1.0f) { ray_depth = BVH_RAYCAST_DIST_MAX; } @@ -1967,15 +2232,11 @@ bool ED_transform_snap_object_project_ray_all( float ray_depth_prev = ray_depth; #endif - SnapData snapdata; - snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, - ray_start, ray_start, ray_normal, depth_range); - - bool retval = snapObjectsRay( - sctx, &snapdata, + bool retval = raycastObjects( + sctx, + ray_start, ray_normal, params->snap_select, params->use_object_edit_cage, - &ray_depth, NULL, - NULL, NULL, NULL, NULL, NULL, + &ray_depth, NULL, NULL, NULL, NULL, NULL, r_hit_list); /* meant to be readonly for 'all' hits, ensure it is */ @@ -2008,7 +2269,6 @@ static bool transform_snap_context_project_ray_impl( /* try snap edge, then face if it fails */ ret = ED_transform_snap_object_project_ray_ex( sctx, - SCE_SNAP_MODE_FACE, params, ray_start, ray_normal, ray_depth, r_co, r_no, NULL, @@ -2154,16 +2414,24 @@ bool ED_transform_snap_object_project_view3d_ex( ray_depth = &ray_depth_fallback; } - SnapData snapdata; - const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; - snap_data_set(&snapdata, ar, snap_to, view_proj, mval, - ray_origin, ray_start, ray_normal, depth_range); + if (snap_to == SCE_SNAP_MODE_FACE) { + return raycastObjects( + sctx, + ray_start, ray_normal, + params->snap_select, params->use_object_edit_cage, + ray_depth, r_loc, r_no, r_index, NULL, NULL, NULL); + } + else { + SnapData snapdata; + const enum eViewProj view_proj = ((RegionView3D *)ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; + snap_data_set(&snapdata, ar, snap_to, view_proj, mval, + ray_origin, ray_start, ray_normal, depth_range); - return snapObjectsRay( - sctx, &snapdata, - params->snap_select, params->use_object_edit_cage, - ray_depth, dist_px, - r_loc, r_no, r_index, NULL, NULL, NULL); + return snapObjectsRay( + sctx, &snapdata, + params->snap_select, params->use_object_edit_cage, + ray_depth, dist_px, r_loc, r_no, NULL, NULL); + } } bool ED_transform_snap_object_project_view3d( @@ -2204,7 +2472,6 @@ bool ED_transform_snap_object_project_all_view3d_ex( return ED_transform_snap_object_project_ray_all( sctx, - SCE_SNAP_MODE_FACE, params, ray_start, ray_normal, ray_depth, sort, r_hit_list); diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 3727be1842c..61142fdc887 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -296,7 +296,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) } /* Else, common behavior with DELKEY, only difference is remove char(s) before/after the cursor. */ dir = STRCUR_DIR_PREV; - /* fall-through */ + ATTR_FALLTHROUGH; case DELKEY: if ((n->val_flag[idx] & NUM_EDITED) && n->str[0]) { int t_cur = cur = n->str_cur; @@ -322,7 +322,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) break; case LEFTARROWKEY: dir = STRCUR_DIR_PREV; - /* fall-through */ + ATTR_FALLTHROUGH; case RIGHTARROWKEY: cur = n->str_cur; if (event->ctrl) { diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index 4e021d4833e..419c15bf83f 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -334,6 +334,12 @@ static int ed_undo_redo_exec(bContext *C, wmOperator *UNUSED(op)) return ret ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } +static int ed_undo_redo_poll(bContext *C) +{ + wmOperator *last_op = WM_operator_last_redo(C); + return last_op && ED_operator_screenactive(C) && + WM_operator_check_ui_enabled(C, last_op->type->name); +} /* ********************** */ @@ -385,7 +391,7 @@ void ED_OT_undo_redo(wmOperatorType *ot) /* api callbacks */ ot->exec = ed_undo_redo_exec; - ot->poll = ED_operator_screenactive; + ot->poll = ed_undo_redo_poll; } /* ui callbacks should call this rather than calling WM_operator_repeat() themselves */ diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 5c5e84ee5f0..15be6ab3b78 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -502,7 +502,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) ma = give_current_material(ob, ob->actcol); - if (me->mtpoly) { + if (me->mloopuv) { MPoly *mpoly = me->mpoly; MLoopUV *mloopuv, *mloopuv_base; int a, b; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 193b006cf0d..d7361f5a259 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1136,8 +1136,13 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ - /* use winding so we don't consider overlapping islands as connected, see T44320 */ - vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, true); + /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320 + * this made *every* projection split the island into front/back islands. + * Keep 'use_winding' to false, see: T50970. + * + * Better solve this by having a delimit option for select-linked operator, + * keeping island-select working as is. */ + vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false); if (vmap == NULL) return; diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index bdfff123aa4..8c76d03035a 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -2859,7 +2859,7 @@ static PBool p_chart_symmetry_pins(PChart *chart, PEdge *outer, PVert **pin1, PV PEdge *cure = NULL, *firste1 = NULL, *firste2 = NULL, *nextbe; float maxlen = 0.0f, curlen = 0.0f, totlen = 0.0f, firstlen = 0.0f; float len1, len2; - + /* find longest series of verts split in the chart itself, these are * marked during construction */ be = outer; diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 50aec737c8e..d5233f0ed28 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -2116,6 +2116,7 @@ static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event) } break; } + ATTR_FALLTHROUGH; case PADENTER: case RETKEY: if (event->val == KM_PRESS) { diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp index c331d1de9c9..9b1b02c8ee2 100644 --- a/source/blender/freestyle/intern/application/AppView.cpp +++ b/source/blender/freestyle/intern/application/AppView.cpp @@ -22,12 +22,6 @@ * \ingroup freestyle */ -/* This header file needs to be included first, in order to avoid a - compilation with MinGW (see the commit log of revision 28253) */ -extern "C" { -#include "BLI_jitter.h" -} - #include <iostream> #include "Controller.h" diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index f63cf771120..1dbac1848b7 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -524,7 +524,7 @@ void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const // We'll generate both with tips and without tips // coordinates, on two different UV layers. - if (ma->mtex[a]->texflag & MTEX_TIPS) { + if (ma->mtex[a]->texflag & MTEX_TIPS) { BLI_strncpy(ma->mtex[a]->uvname, uvNames[1], sizeof(ma->mtex[a]->uvname)); } else { diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 223bc607e21..ea22633c50e 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -448,15 +448,13 @@ static void prepare(Render *re, SceneRenderLayer *srl) RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name); bool diffuse = false, z = false; for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) { - switch (rpass->passtype) { - case SCE_PASS_DIFFUSE: + if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty); diffuse = true; - break; - case SCE_PASS_Z: + } + if (STREQ(rpass->name, RE_PASSNAME_Z)) { controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty); z = true; - break; } } if (G.debug & G_DEBUG_FREESTYLE) { @@ -492,7 +490,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r return; } - src = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, freestyle_render->viewname); + src = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, freestyle_render->viewname); if (!src) { if (G.debug & G_DEBUG_FREESTYLE) { cout << "No source result image to composite" << endl; @@ -512,7 +510,7 @@ void FRS_composite_result(Render *re, SceneRenderLayer *srl, Render *freestyle_r } return; } - dest = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); + dest = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname); if (!dest) { if (G.debug & G_DEBUG_FREESTYLE) { cout << "No destination result image to composite to" << endl; diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h index d65b0ea803b..444fd7c4785 100644 --- a/source/blender/freestyle/intern/geometry/matrix_util.h +++ b/source/blender/freestyle/intern/geometry/matrix_util.h @@ -50,15 +50,15 @@ namespace MatrixUtil { /** * computes the eigen values and eigen vectors of a semi definite symmetric matrix * - * @param matrix is stored in column symmetric storage, i.e. + * \param mat: The matrix stored in column symmetric storage, i.e. * matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... } * size = n(n+1)/2 * - * @param eigen_vectors (return) = { v1, v2, v3, ..., vn } + * \param eigen_vec: (return) = { v1, v2, v3, ..., vn } * where vk = vk0, vk1, ..., vkn * size = n^2, must be allocated by caller * - * @param eigen_values (return) are in decreasing order + * \param eigen_val: (return) are in decreasing order * size = n, must be allocated by caller */ void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val); diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index b693d473bd8..e4a837d0a5f 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -222,50 +222,53 @@ void GPU_interleaved_attrib_unbind(void); typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers; /* build */ -GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( +GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( const int (*face_vert_indices)[3], const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopTri *looptri, const struct MVert *verts, const int *face_indices, const int face_indices_len); -GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers( +GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( int *grid_indices, int totgrid, unsigned int **grid_hidden, int gridsize, const struct CCGKey *key, struct GridCommonGPUBuffer **grid_common_gpu_buffer); -GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading); +GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading); /* update */ -void GPU_update_mesh_pbvh_buffers( +void GPU_pbvh_mesh_buffers_update( GPU_PBVH_Buffers *buffers, const struct MVert *mvert, const int *vert_indices, int totvert, const float *vmask, const int (*face_vert_indices)[3], bool show_diffuse_color); -void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, - struct BMesh *bm, - struct GSet *bm_faces, - struct GSet *bm_unique_verts, - struct GSet *bm_other_verts, - bool show_diffuse_color); +void GPU_pbvh_bmesh_buffers_update( + GPU_PBVH_Buffers *buffers, + struct BMesh *bm, + struct GSet *bm_faces, + struct GSet *bm_unique_verts, + struct GSet *bm_other_verts, + bool show_diffuse_color); -void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, struct CCGElem **grids, - const struct DMFlagMat *grid_flag_mats, - int *grid_indices, int totgrid, const struct CCGKey *key, - bool show_diffuse_color); +void GPU_pbvh_grid_buffers_update( + GPU_PBVH_Buffers *buffers, struct CCGElem **grids, + const struct DMFlagMat *grid_flag_mats, + int *grid_indices, int totgrid, const struct CCGKey *key, + bool show_diffuse_color); /* draw */ -void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, - bool wireframe, bool fast); +void GPU_pbvh_buffers_draw( + GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, + bool wireframe, bool fast); /* debug PBVH draw*/ -void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf); -void GPU_end_draw_pbvh_BB(void); -void GPU_init_draw_pbvh_BB(void); +void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf); +void GPU_pbvh_BB_draw_init(void); +void GPU_pbvh_BB_draw_end(void); bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, struct GSet *bm_faces, bool show_diffuse_color); -void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers); -void GPU_free_pbvh_buffer_multires(struct GridCommonGPUBuffer **grid_common_gpu_buffer); +void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers); +void GPU_pbvh_multires_buffers_free(struct GridCommonGPUBuffer **grid_common_gpu_buffer); #endif diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 0d92d22a173..6db23686832 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -98,6 +98,7 @@ typedef enum GPUBuiltin { GPU_PARTICLE_ANG_VELOCITY = (1 << 12), GPU_LOC_TO_VIEW_MATRIX = (1 << 13), GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14), + GPU_OBJECT_INFO = (1 << 15) } GPUBuiltin; typedef enum GPUOpenGLBuiltin { @@ -213,6 +214,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); void GPU_material_enable_alpha(GPUMaterial *material); +GPUBuiltin GPU_get_material_builtins(GPUMaterial *material); GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); /* High level functions to create and use GPU materials */ @@ -230,7 +232,7 @@ void GPU_material_bind( float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock); void GPU_material_bind_uniforms( GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4], - float autobumpscale, GPUParticleInfo *pi); + float autobumpscale, GPUParticleInfo *pi, float object_info[3]); void GPU_material_unbind(GPUMaterial *material); bool GPU_material_bound(GPUMaterial *material); struct Scene *GPU_material_scene(GPUMaterial *material); @@ -345,6 +347,7 @@ struct GPUParticleInfo float location[3]; float velocity[3]; float angular_velocity[3]; + int random_id; }; #ifdef WITH_OPENSUBDIV diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c index a2b89239344..8505bd847a0 100644 --- a/source/blender/gpu/intern/gpu_basic_shader.c +++ b/source/blender/gpu/intern/gpu_basic_shader.c @@ -407,7 +407,7 @@ static GPUShader *gpu_basic_shader(int options) return shader; } -static void GPU_basic_shader_uniform_autoset(GPUShader *shader, int options) +static void gpu_basic_shader_uniform_autoset(GPUShader *shader, int options) { if (options & GPU_SHADER_LINE) { glGetIntegerv(GL_VIEWPORT, &GPU_MATERIAL_STATE.viewport[0]); @@ -443,7 +443,7 @@ void GPU_basic_shader_bind(int options) if (shader) { GPU_shader_bind(shader); - GPU_basic_shader_uniform_autoset(shader, options); + gpu_basic_shader_uniform_autoset(shader, options); } } else { diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 370841327aa..9f1fe3a5a67 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -743,7 +743,7 @@ void GPU_triangle_setup(struct DerivedMesh *dm) GLStates |= GPU_BUFFER_ELEMENT_STATE; } -static int GPU_typesize(int type) +static int gpu_typesize(int type) { switch (type) { case GL_FLOAT: @@ -766,7 +766,7 @@ int GPU_attrib_element_size(GPUAttrib data[], int numdata) int i, elementsize = 0; for (i = 0; i < numdata; i++) { - int typesize = GPU_typesize(data[i].type); + int typesize = gpu_typesize(data[i].type); if (typesize != 0) elementsize += typesize * data[i].size; } @@ -803,7 +803,7 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda glVertexAttribPointer(data[i].index, data[i].size, data[i].type, GL_TRUE, elementsize, BUFFER_OFFSET(offset)); - offset += data[i].size * GPU_typesize(data[i].type); + offset += data[i].size * gpu_typesize(data[i].type); attribData[i].index = data[i].index; attribData[i].size = data[i].size; @@ -1030,13 +1030,13 @@ static void gpu_color_from_mask_quad_copy(const CCGKey *key, out[2] = diffuse_color[2] * mask_color; } -void GPU_update_mesh_pbvh_buffers( +void GPU_pbvh_mesh_buffers_update( GPU_PBVH_Buffers *buffers, const MVert *mvert, const int *vert_indices, int totvert, const float *vmask, const int (*face_vert_indices)[3], bool show_diffuse_color) { VertexBufferFormat *vert_data; - int i, j; + int i; buffers->vmask = vmask; buffers->show_diffuse_color = show_diffuse_color; @@ -1057,6 +1057,9 @@ void GPU_update_mesh_pbvh_buffers( copy_v4_v4(buffers->diffuse_color, diffuse_color); + uchar diffuse_color_ub[4]; + rgba_float_to_uchar(diffuse_color_ub, diffuse_color); + /* Build VBO */ if (buffers->vert_buf) GPU_buffer_free(buffers->vert_buf); @@ -1076,28 +1079,20 @@ void GPU_update_mesh_pbvh_buffers( memcpy(out->no, v->no, sizeof(short) * 3); } -#define UPDATE_VERTEX(face, vertex, index, diffuse_color) \ - { \ - VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \ - if (vmask) \ - gpu_color_from_mask_copy(vmask[vertex], diffuse_color, out->color); \ - else \ - rgb_float_to_uchar(out->color, diffuse_color); \ - } (void)0 - for (i = 0; i < buffers->face_indices_len; i++) { const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - const unsigned int vtri[3] = { - buffers->mloop[lt->tri[0]].v, - buffers->mloop[lt->tri[1]].v, - buffers->mloop[lt->tri[2]].v, - }; + for (uint j = 0; j < 3; j++) { + VertexBufferFormat *out = vert_data + face_vert_indices[i][j]; - UPDATE_VERTEX(i, vtri[0], 0, diffuse_color); - UPDATE_VERTEX(i, vtri[1], 1, diffuse_color); - UPDATE_VERTEX(i, vtri[2], 2, diffuse_color); + if (vmask) { + uint v_index = buffers->mloop[lt->tri[j]].v; + gpu_color_from_mask_copy(vmask[v_index], diffuse_color, out->color); + } + else { + copy_v3_v3_uchar(out->color, diffuse_color_ub); + } + } } -#undef UPDATE_VERTEX } else { /* calculate normal for each polygon only once */ @@ -1112,8 +1107,6 @@ void GPU_update_mesh_pbvh_buffers( buffers->mloop[lt->tri[2]].v, }; - float fmask; - if (paint_is_face_hidden(lt, mvert, buffers->mloop)) continue; @@ -1126,23 +1119,22 @@ void GPU_update_mesh_pbvh_buffers( mpoly_prev = lt->poly; } + uchar color_ub[3]; if (vmask) { - fmask = (vmask[vtri[0]] + - vmask[vtri[1]] + - vmask[vtri[2]]) / 3.0f; + float fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f; + gpu_color_from_mask_copy(fmask, diffuse_color, color_ub); + } + else { + copy_v3_v3_uchar(color_ub, diffuse_color_ub); } - for (j = 0; j < 3; j++) { + for (uint j = 0; j < 3; j++) { const MVert *v = &mvert[vtri[j]]; VertexBufferFormat *out = vert_data; copy_v3_v3(out->co, v->co); copy_v3_v3_short(out->no, no); - - if (vmask) - gpu_color_from_mask_copy(fmask, diffuse_color, out->color); - else - rgb_float_to_uchar(out->color, diffuse_color); + copy_v3_v3_uchar(out->color, color_ub); vert_data++; } @@ -1160,7 +1152,7 @@ void GPU_update_mesh_pbvh_buffers( buffers->mvert = mvert; } -GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( +GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( const int (*face_vert_indices)[3], const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri, const MVert *mvert, @@ -1244,9 +1236,10 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers( return buffers; } -void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids, - const DMFlagMat *grid_flag_mats, int *grid_indices, - int totgrid, const CCGKey *key, bool show_diffuse_color) +void GPU_pbvh_grid_buffers_update( + GPU_PBVH_Buffers *buffers, CCGElem **grids, + const DMFlagMat *grid_flag_mats, int *grid_indices, + int totgrid, const CCGKey *key, bool show_diffuse_color) { VertexBufferFormat *vert_data; int i, j, k, x, y; @@ -1466,7 +1459,7 @@ static GPUBuffer *gpu_get_grid_buffer( } \ } (void)0 -GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers( +GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key, GridCommonGPUBuffer **grid_common_gpu_buffer) { @@ -1612,12 +1605,13 @@ static int gpu_bmesh_face_visible_count(GSet *bm_faces) /* Creates a vertex buffer (coordinate, normal, color) and, if smooth * shading, an element index buffer. */ -void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, - BMesh *bm, - GSet *bm_faces, - GSet *bm_unique_verts, - GSet *bm_other_verts, - bool show_diffuse_color) +void GPU_pbvh_bmesh_buffers_update( + GPU_PBVH_Buffers *buffers, + BMesh *bm, + GSet *bm_faces, + GSet *bm_unique_verts, + GSet *bm_other_verts, + bool show_diffuse_color) { VertexBufferFormat *vert_data; void *tri_data; @@ -1803,7 +1797,7 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, } } -GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading) +GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) { GPU_PBVH_Buffers *buffers; @@ -1816,8 +1810,9 @@ GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading) return buffers; } -void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, - bool wireframe, bool fast) +void GPU_pbvh_buffers_draw( + GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, + bool wireframe, bool fast) { bool do_fast = fast && buffers->index_buf_fast; /* sets material from the first face, to solve properly face would need to @@ -1956,7 +1951,8 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, } } -bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color) +bool GPU_pbvh_buffers_diffuse_changed( + GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color) { float diffuse_color[4]; bool use_matcaps = GPU_material_use_matcaps_get(); @@ -1999,7 +1995,7 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, return !equals_v3v3(diffuse_color, buffers->diffuse_color); } -void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers) +void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers) { if (buffers) { if (buffers->vert_buf) @@ -2017,7 +2013,7 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers) } } -void GPU_free_pbvh_buffer_multires(GridCommonGPUBuffer **grid_common_gpu_buffer) +void GPU_pbvh_multires_buffers_free(GridCommonGPUBuffer **grid_common_gpu_buffer) { GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer; @@ -2033,7 +2029,7 @@ void GPU_free_pbvh_buffer_multires(GridCommonGPUBuffer **grid_common_gpu_buffer) } /* debug function, draws the pbvh BB */ -void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf) +void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf) { const float quads[4][4][3] = { { @@ -2074,7 +2070,7 @@ void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf) glDrawArrays(GL_QUADS, 0, 16); } -void GPU_init_draw_pbvh_BB(void) +void GPU_pbvh_BB_draw_init(void) { glPushAttrib(GL_ENABLE_BIT); glDisable(GL_CULL_FACE); @@ -2084,7 +2080,7 @@ void GPU_init_draw_pbvh_BB(void) glEnable(GL_BLEND); } -void GPU_end_draw_pbvh_BB(void) +void GPU_pbvh_BB_draw_end(void) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPopAttrib(); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index c3896fbd659..b5512aa108d 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -410,6 +410,8 @@ const char *GPU_builtin_name(GPUBuiltin builtin) return "unfparticlevel"; else if (builtin == GPU_PARTICLE_ANG_VELOCITY) return "unfparticleangvel"; + else if (builtin == GPU_OBJECT_INFO) + return "unfobjectinfo"; else return ""; } diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 964c2b5051e..2f2a16f9e1d 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -798,7 +798,9 @@ bool GPU_fx_do_composite_pass( ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp); if (ssao_shader) { const GPUSSAOSettings *fx_ssao = fx->settings.ssao; - float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f}; + /* adjust attenuation to be scale invariant */ + float attenuation = fx_ssao->attenuation / (fx_ssao->distance_max * fx_ssao->distance_max); + float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, attenuation, 0.0f}; float sample_params[3]; sample_params[0] = fx->ssao_sample_count_cache; diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c index ba68d1a6a0f..7a0562617d6 100644 --- a/source/blender/gpu/intern/gpu_debug.c +++ b/source/blender/gpu/intern/gpu_debug.c @@ -29,6 +29,7 @@ * \ingroup gpu */ +#include "BLI_compiler_attrs.h" #include "BLI_utildefines.h" #include "BLI_sys_types.h" #include "BLI_system.h" @@ -219,7 +220,7 @@ static void APIENTRY gpu_debug_proc( switch (severity) { case GL_DEBUG_SEVERITY_HIGH: backtrace = true; - /* fall through */ + ATTR_FALLTHROUGH; case GL_DEBUG_SEVERITY_MEDIUM: case GL_DEBUG_SEVERITY_LOW: case GL_DEBUG_SEVERITY_NOTIFICATION: /* KHR has this, ARB does not */ @@ -249,7 +250,7 @@ static void APIENTRY gpu_debug_proc_amd( switch (severity) { case GL_DEBUG_SEVERITY_HIGH: backtrace = true; - /* fall through */ + ATTR_FALLTHROUGH; case GL_DEBUG_SEVERITY_MEDIUM: case GL_DEBUG_SEVERITY_LOW: fprintf(stderr, "GL %s: %s\n", category_name_amd(category), message); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7936811ab4d..1583d16ca27 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -45,6 +45,7 @@ #include "BLI_math.h" #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLI_hash.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" @@ -1203,7 +1204,7 @@ void GPU_paint_set_mipmap(bool mipmap) /* check if image has been downscaled and do scaled partial update */ -static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h) +static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h) { if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) || is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) @@ -1296,7 +1297,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0; IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data); - if (GPU_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) { + if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) { MEM_freeN(buffer); BKE_image_release_ibuf(ima, ibuf, NULL); return; @@ -1320,7 +1321,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i return; } - if (GPU_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) { + if (gpu_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) { BKE_image_release_ibuf(ima, ibuf, NULL); return; } @@ -1870,7 +1871,7 @@ void GPU_begin_object_materials( GPU_object_material_unbind(); } -static int GPU_get_particle_info(GPUParticleInfo *pi) +static int gpu_get_particle_info(GPUParticleInfo *pi) { DupliObject *dob = GMS.dob; if (dob->particle_system) { @@ -1899,6 +1900,21 @@ static int GPU_get_particle_info(GPUParticleInfo *pi) return 0; } +static void GPU_get_object_info(float oi[3], Material *mat) +{ + Object *ob = GMS.gob; + oi[0] = ob->index; + oi[1] = mat->index; + unsigned int random; + if (GMS.dob) { + random = GMS.dob->random_id; + } + else { + random = BLI_hash_int_2d(BLI_hash_string(GMS.gob->id.name + 2), 0); + } + oi[2] = random * (1.0f / (float)0xFFFFFFFF); +} + int GPU_object_material_bind(int nr, void *attribs) { GPUVertexAttribs *gattribs = attribs; @@ -1958,21 +1974,27 @@ int GPU_object_material_bind(int nr, void *attribs) /* bind glsl material and get attributes */ Material *mat = GMS.gmatbuf[nr]; GPUParticleInfo partile_info; + float object_info[3] = {0}; float auto_bump_scale; GPUMaterial *gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv); GPU_material_vertex_attributes(gpumat, gattribs); - if (GMS.dob) - GPU_get_particle_info(&partile_info); + if (GMS.dob) { + gpu_get_particle_info(&partile_info); + } + + if (GPU_get_material_builtins(gpumat) & GPU_OBJECT_INFO) { + GPU_get_object_info(object_info, mat); + } GPU_material_bind( gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock); auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info); + GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gob->col, auto_bump_scale, &partile_info, object_info); GMS.gboundmat = mat; /* for glsl use alpha blend mode, unless it's set to solid and diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index f62ef677434..e7a8beae5cc 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -52,7 +52,7 @@ struct GPUFrameBuffer { GPUTexture *depthtex; }; -static void GPU_print_framebuffer_error(GLenum status, char err_out[256]) +static void gpu_print_framebuffer_error(GLenum status, char err_out[256]) { const char *err = "unknown"; @@ -164,7 +164,7 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot if (error == GL_INVALID_OPERATION) { GPU_framebuffer_restore(); - GPU_print_framebuffer_error(error, err_out); + gpu_print_framebuffer_error(error, err_out); return 0; } @@ -331,7 +331,7 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]) if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { GPU_framebuffer_restore(); - GPU_print_framebuffer_error(status, err_out); + gpu_print_framebuffer_error(status, err_out); return false; } diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 4e2043471b6..1f3ae7f708a 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -122,6 +122,8 @@ struct GPUMaterial { int partvel; int partangvel; + int objectinfoloc; + ListBase lamps; bool bound; @@ -225,7 +227,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material) attribs->totlayer = b; } -static int GPU_material_construct_end(GPUMaterial *material, const char *passname) +static int gpu_material_construct_end(GPUMaterial *material, const char *passname) { if (material->outlink) { GPUNodeLink *outlink = material->outlink; @@ -268,6 +270,8 @@ static int GPU_material_construct_end(GPUMaterial *material, const char *passnam material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY)); if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY)); + if (material->builtins & GPU_OBJECT_INFO) + material->objectinfoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_INFO)); return 1; } else { @@ -398,9 +402,14 @@ void GPU_material_bind( } } +GPUBuiltin GPU_get_material_builtins(GPUMaterial *material) +{ + return material->builtins; +} + void GPU_material_bind_uniforms( GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float obcol[4], - float autobumpscale, GPUParticleInfo *pi) + float autobumpscale, GPUParticleInfo *pi, float object_info[3]) { if (material->pass) { GPUShader *shader = GPU_pass_shader(material->pass); @@ -449,6 +458,9 @@ void GPU_material_bind_uniforms( if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) { GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity); } + if (material->builtins & GPU_OBJECT_INFO) { + GPU_shader_uniform_vector(shader, material->objectinfoloc, 3, 1, object_info); + } } } @@ -1891,7 +1903,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv GPU_material_output_link(mat, outlink); - GPU_material_construct_end(mat, "matcap_pass"); + gpu_material_construct_end(mat, "matcap_pass"); /* note that even if building the shader fails in some way, we still keep * it to avoid trying to compile again and again, and simple do not use @@ -2044,7 +2056,7 @@ static void do_world_tex(GPUShadeInput *shi, struct World *wo, GPUNodeLink **hor } } -static void GPU_material_old_world(struct GPUMaterial *mat, struct World *wo) +static void gpu_material_old_world(struct GPUMaterial *mat, struct World *wo) { GPUShadeInput shi; GPUShadeResult shr; @@ -2112,17 +2124,18 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) mat->type = GPU_MATERIAL_TYPE_WORLD; /* create nodes */ - if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes) + if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes) { ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING); + } else { - GPU_material_old_world(mat, wo); + gpu_material_old_world(mat, wo); } if (GPU_material_do_color_management(mat)) if (mat->outlink) GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); - GPU_material_construct_end(mat, wo->id.name); + gpu_material_construct_end(mat, wo->id.name); /* note that even if building the shader fails in some way, we still keep * it to avoid trying to compile again and again, and simple do not use @@ -2188,7 +2201,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_open if (mat->outlink) GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); - GPU_material_construct_end(mat, ma->id.name); + gpu_material_construct_end(mat, ma->id.name); /* note that even if building the shader fails in some way, we still keep * it to avoid trying to compile again and again, and simple do not use diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c index 9496ff137dc..632b0cfee1b 100644 --- a/source/blender/gpu/intern/gpu_select.c +++ b/source/blender/gpu/intern/gpu_select.c @@ -75,6 +75,12 @@ static GPUSelectState g_select_state = {0}; */ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *input, char mode, int oldhits) { + if (mode == GPU_SELECT_NEAREST_SECOND_PASS) { + /* In the case hits was '-1', don't start the second pass since it's not going to give useful results. + * As well as buffer overflow in 'gpu_select_query_load_id'. */ + BLI_assert(oldhits != -1); + } + g_select_state.select_is_active = true; g_select_state.use_gpu_select = GPU_select_query_check_active(); g_select_state.mode = mode; diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c index ba5fefc5227..3d589986281 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.c +++ b/source/blender/gpu/intern/gpu_select_sample_query.c @@ -142,13 +142,17 @@ bool gpu_select_query_load_id(unsigned int id) g_query_state.active_query++; g_query_state.query_issued = true; - if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS && g_query_state.index < g_query_state.oldhits) { - if (g_query_state.buffer[g_query_state.index][3] == id) { - g_query_state.index++; - return true; - } - else { - return false; + if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) { + /* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */ + BLI_assert(g_query_state.oldhits != -1); + if (g_query_state.index < g_query_state.oldhits) { + if (g_query_state.buffer[g_query_state.index][3] == id) { + g_query_state.index++; + return true; + } + else { + return false; + } } } diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 14f2764b009..b579f87698c 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -39,6 +39,7 @@ #include "GPU_glew.h" #include "GPU_shader.h" #include "GPU_texture.h" +#include "GPU_material.h" /* TODO(sergey): Find better default values for this constants. */ #define MAX_DEFINE_LENGTH 1024 diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 54f0003c086..1c97c2ce811 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -79,7 +79,7 @@ static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixel return pixels; } -static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h) +static void gpu_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h) { void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels"); @@ -193,7 +193,7 @@ static GPUTexture *GPU_texture_create_nD( pixels ? pixels : fpixels); if (tex->w > w) { - GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1); + gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1); } } } @@ -210,10 +210,12 @@ static GPUTexture *GPU_texture_create_nD( glTexSubImage2D(tex->target, 0, 0, 0, w, h, format, type, pixels ? pixels : fpixels); - if (tex->w > w) - GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h); - if (tex->h > h) - GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h); + if (tex->w > w) { + gpu_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h); + } + if (tex->h > h) { + gpu_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h); + } } } diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl index 50c8e255162..f19ff4ec65a 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl @@ -75,7 +75,7 @@ float calculate_ssao_factor(float depth) float f = dot(dir, normal); /* use minor bias here to avoid self shadowing */ - if (f > 0.05 * len + 0.0001) + if (f > 0.05 * len) factor += f * 1.0 / (len * (1.0 + len * len * ssao_params.z)); } } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 0f3ffa8244b..f14db57a26a 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -403,7 +403,7 @@ void math_modulo(float val1, float val2, out float outval) /* change sign to match C convention, mod in GLSL will take absolute for negative numbers, * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */ - outval = (val1 > 0.0) ? outval : -outval; + outval = (val1 > 0.0) ? outval : outval - val2; } void math_abs(float val1, out float outval) @@ -2378,11 +2378,19 @@ void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol) /*********** NEW SHADER UTILITIES **************/ -float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) +float fresnel_dielectric_0(float eta) +{ + /* compute fresnel reflactance at normal incidence => cosi = 1.0 */ + float A = (eta - 1.0) / (eta + 1.0); + + return A * A; +} + +float fresnel_dielectric_cos(float cosi, float eta) { /* compute fresnel reflectance without explicitly computing * the refracted direction */ - float c = abs(dot(Incoming, Normal)); + float c = abs(cosi); float g = eta * eta - 1.0 + c * c; float result; @@ -2399,6 +2407,13 @@ float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) return result; } +float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) +{ + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + return fresnel_dielectric_cos(dot(Incoming, Normal), eta); +} + float hypot(float x, float y) { return sqrt(x * x + y * y); @@ -2492,6 +2507,57 @@ float floorfrac(float x, out int i) return x - i; } + +/* Principled BSDF operations */ + +float sqr(float a) +{ + return a*a; +} + +float schlick_fresnel(float u) +{ + float m = clamp(1.0 - u, 0.0, 1.0); + float m2 = m * m; + return m2 * m2 * m; // pow(m,5) +} + +float GTR1(float NdotH, float a) +{ + if (a >= 1.0) return M_1_PI; + float a2 = a*a; + float t = 1.0 + (a2 - 1.0) * NdotH*NdotH; + return (a2 - 1.0) / (M_PI * log(a2) * t); +} + +float GTR2(float NdotH, float a) +{ + float a2 = a*a; + float t = 1.0 + (a2 - 1.0) * NdotH*NdotH; + return a2 / (M_PI * t*t); +} + +float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay) +{ + return 1.0 / (M_PI * ax*ay * sqr(sqr(HdotX / ax) + sqr(HdotY / ay) + NdotH*NdotH)); +} + +float smithG_GGX(float NdotV, float alphaG) +{ + float a = alphaG*alphaG; + float b = NdotV*NdotV; + return 1.0 / (NdotV + sqrt(a + b - a * b)); +} + +vec3 rotate_vector(vec3 p, vec3 n, float theta) { + return ( + p * cos(theta) + cross(n, p) * + sin(theta) + n * dot(p, n) * + (1.0 - cos(theta)) + ); +} + + /*********** NEW SHADER NODES ***************/ #define NUM_LIGHTS 3 @@ -2553,6 +2619,125 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 resu node_bsdf_diffuse(color, 0.0, N, result); } +void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, + float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, + float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result) +{ + /* ambient light */ + // TODO: set ambient light to an appropriate value + vec3 L = mix(0.1, 0.03, metallic) * mix(base_color.rgb, subsurface_color.rgb, subsurface * (1.0 - metallic)); + + float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0; + + /* set the viewing vector */ + vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? -normalize(I) : vec3(0.0, 0.0, 1.0); + + /* get the tangent */ + vec3 Tangent = T; + if (T == vec3(0.0)) { + // if no tangent is set, use a default tangent + if(N.x != N.y || N.x != N.z) { + Tangent = vec3(N.z-N.y, N.x-N.z, N.y-N.x); // (1,1,1) x N + } + else { + Tangent = vec3(N.z-N.y, N.x+N.z, -N.y-N.x); // (-1,1,1) x N + } + } + + /* rotate tangent */ + if (anisotropic_rotation != 0.0) { + Tangent = rotate_vector(Tangent, N, anisotropic_rotation * 2.0 * M_PI); + } + + /* calculate the tangent and bitangent */ + vec3 Y = normalize(cross(N, Tangent)); + vec3 X = cross(Y, N); + + /* fresnel normalization parameters */ + float F0 = fresnel_dielectric_0(eta); + float F0_norm = 1.0 / (1.0 - F0); + + /* directional lights */ + for (int i = 0; i < NUM_LIGHTS; i++) { + vec3 light_position_world = gl_LightSource[i].position.xyz; + vec3 light_position = normalize(light_position_world); + + vec3 H = normalize(light_position + V); + + vec3 light_diffuse = gl_LightSource[i].diffuse.rgb; + vec3 light_specular = gl_LightSource[i].specular.rgb; + + float NdotL = dot(N, light_position); + float NdotV = dot(N, V); + float LdotH = dot(light_position, H); + + vec3 diffuse_and_specular_bsdf = vec3(0.0); + if (NdotL >= 0.0 && NdotV >= 0.0) { + float NdotH = dot(N, H); + + float Cdlum = 0.3 * base_color.r + 0.6 * base_color.g + 0.1 * base_color.b; // luminance approx. + + vec3 Ctint = Cdlum > 0 ? base_color.rgb / Cdlum : vec3(1.0); // normalize lum. to isolate hue+sat + vec3 Cspec0 = mix(specular * 0.08 * mix(vec3(1.0), Ctint, specular_tint), base_color.rgb, metallic); + vec3 Csheen = mix(vec3(1.0), Ctint, sheen_tint); + + // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing + // and mix in diffuse retro-reflection based on roughness + + float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV); + float Fd90 = 0.5 + 2.0 * LdotH*LdotH * roughness; + float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV); + + // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf + // 1.25 scale is used to (roughly) preserve albedo + // Fss90 used to "flatten" retroreflection based on roughness + float Fss90 = LdotH*LdotH * roughness; + float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV); + float ss = 1.25 * (Fss * (1.0 / (NdotL + NdotV) - 0.5) + 0.5); + + // specular + float aspect = sqrt(1.0 - anisotropic * 0.9); + float a = sqr(roughness); + float ax = max(0.001, a / aspect); + float ay = max(0.001, a * aspect); + float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay); //GTR2(NdotH, a); + float FH = (fresnel_dielectric_cos(LdotH, eta) - F0) * F0_norm; + vec3 Fs = mix(Cspec0, vec3(1.0), FH); + float roughg = sqr(roughness * 0.5 + 0.5); + float Gs = smithG_GGX(NdotL, roughg) * smithG_GGX(NdotV, roughg); + + // sheen + vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen; + + vec3 diffuse_bsdf = (mix(Fd * base_color.rgb, ss * subsurface_color.rgb, subsurface) + Fsheen) * light_diffuse; + vec3 specular_bsdf = Gs * Fs * Ds * light_specular; + diffuse_and_specular_bsdf = diffuse_bsdf * (1.0 - metallic) + specular_bsdf; + } + diffuse_and_specular_bsdf *= max(NdotL, 0.0); + + float CNdotL = dot(CN, light_position); + float CNdotV = dot(CN, V); + + vec3 clearcoat_bsdf = vec3(0.0); + if (CNdotL >= 0.0 && CNdotV >= 0.0 && clearcoat > 0.0) { + float CNdotH = dot(CN, H); + //float FH = schlick_fresnel(LdotH); + + // clearcoat (ior = 1.5 -> F0 = 0.04) + float Dr = GTR1(CNdotH, sqr(clearcoat_roughness)); + float Fr = fresnel_dielectric_cos(LdotH, 1.5); //mix(0.04, 1.0, FH); + float Gr = smithG_GGX(CNdotL, 0.25) * smithG_GGX(CNdotV, 0.25); + + clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25) * light_specular; + } + clearcoat_bsdf *= max(CNdotL, 0.0); + + L += diffuse_and_specular_bsdf + clearcoat_bsdf; + } + + result = vec4(L, 1.0); +} + void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result) { node_bsdf_diffuse(color, 0.0, N, result); @@ -2846,10 +3031,10 @@ vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bi float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0); float min_dist = min(min(x, y), min(brick_width - x, row_height - y)); - if(min_dist >= mortar_size) { + if (min_dist >= mortar_size) { return vec2(tint, 0.0); } - else if(mortar_smooth == 0.0) { + else if (mortar_smooth == 0.0) { return vec2(tint, 1.0); } else { @@ -3563,12 +3748,12 @@ void node_light_falloff(float strength, float tsmooth, out float quadratic, out constant = strength; } -void node_object_info(out vec3 location, out float object_index, out float material_index, out float random) +void node_object_info(mat4 obmat, vec3 info, out vec3 location, out float object_index, out float material_index, out float random) { - location = vec3(0.0); - object_index = 0.0; - material_index = 0.0; - random = 0.0; + location = obmat[3].xyz; + object_index = info.x; + material_index = info.y; + random = info.z; } void node_normal_map(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index 6ea311b2c7b..f837789914e 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -217,9 +217,27 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3]) // nr = copy_m4_m3(ikmat, ik_mat); if (pchan->parent) - mul_m4_series(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat); + mul_m4_m4m4(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat); else - mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, ikmat); + copy_m4_m4(pchan->pose_mat, pchan->chan_mat); + +#ifdef USE_NONUNIFORM_SCALE + /* apply IK mat, but as if the bones have uniform scale since the IK solver + * is not aware of non-uniform scale */ + float scale[3]; + mat4_to_size(scale, pchan->pose_mat); + normalize_v3_length(pchan->pose_mat[0], scale[1]); + normalize_v3_length(pchan->pose_mat[2], scale[1]); +#endif + + mul_m4_m4m4(pchan->pose_mat, pchan->pose_mat, ikmat); + +#ifdef USE_NONUNIFORM_SCALE + float ik_scale[3]; + mat3_to_size(ik_scale, ik_mat); + normalize_v3_length(pchan->pose_mat[0], scale[0] * ik_scale[0]); + normalize_v3_length(pchan->pose_mat[2], scale[2] * ik_scale[2]); +#endif /* calculate head */ copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]); @@ -308,6 +326,10 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) /* change length based on bone size */ length = bone->length * len_v3(R_bonemat[1]); + /* basis must be pure rotation */ + normalize_m3(R_bonemat); + normalize_m3(R_parmat); + /* compute rest basis and its inverse */ copy_m3_m3(rest_basis, bone->bone_mat); transpose_m3_m3(irest_basis, bone->bone_mat); @@ -317,11 +339,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) mul_m3_m3m3(full_basis, iR_parmat, R_bonemat); mul_m3_m3m3(basis, irest_basis, full_basis); - /* basis must be pure rotation */ - normalize_m3(basis); - /* transform offset into local bone space */ - normalize_m3(iR_parmat); mul_m3_v3(iR_parmat, start); IK_SetTransform(seg, start, rest_basis, basis, length); @@ -545,18 +563,6 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan tree->pchan[a]->flag |= POSE_CHAIN; } -#ifdef USE_NONUNIFORM_SCALE - float (*pchan_scale_data)[3] = MEM_mallocN(sizeof(float[3]) * tree->totchannel, __func__); - - for (a = 0; a < tree->totchannel; a++) { - mat4_to_size(pchan_scale_data[a], tree->pchan[a]->pose_mat); - - /* make uniform at y scale since this controls the length */ - normalize_v3_length(tree->pchan[a]->pose_mat[0], pchan_scale_data[a][1]); - normalize_v3_length(tree->pchan[a]->pose_mat[2], pchan_scale_data[a][1]); - } -#endif - /* 5. execute the IK solver */ execute_posetree(scene, ob, tree); @@ -571,14 +577,6 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan where_is_ik_bone(tree->pchan[a], tree->basis_change[a]); } -#ifdef USE_NONUNIFORM_SCALE - for (a = 0; a < tree->totchannel; a++) { - normalize_v3_length(tree->pchan[a]->pose_mat[0], pchan_scale_data[a][0]); - normalize_v3_length(tree->pchan[a]->pose_mat[2], pchan_scale_data[a][2]); - } - MEM_freeN(pchan_scale_data); -#endif - /* 7. and free */ BLI_remlink(&pchan_root->iktree, tree); free_posetree(tree); diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 4164f5fa75d..ff1784c54dd 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -162,7 +162,7 @@ void IMB_colormanagment_colorspace_from_ibuf_ftype(struct ColorManagedColorspace /* ** RNA helper functions ** */ void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int *totitem); void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *totitem, const char *display_name); -void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem); +void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem, const char *view_name); void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem); /* ** Tile-based buffer management ** */ diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 93d2b3e0cd0..f1f36351e79 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -166,7 +166,7 @@ struct ImBuf *IMB_makeSingleUser(struct ImBuf *ibuf); * * \attention Defined in allocimbuf.c */ -struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1); +struct ImBuf *IMB_dupImBuf(const struct ImBuf *ibuf1); /** * @@ -205,6 +205,7 @@ typedef enum IMB_BlendMode { IMB_BLEND_SATURATION = 21, IMB_BLEND_LUMINOSITY = 22, IMB_BLEND_COLOR = 23, + IMB_BLEND_INTERPOLATE = 24, IMB_BLEND_COPY = 1000, IMB_BLEND_COPY_RGB = 1001, diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index f4b2539d7d7..1701c2ba307 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -237,9 +237,8 @@ typedef struct ImBuf { /** * \name Imbuf Component flags * \brief These flags determine the components of an ImBuf struct. - */ -/**@{*/ -/** \brief Flag defining the components of the ImBuf struct. */ + * + * \{ */ #define IB_rect (1 << 0) #define IB_test (1 << 1) @@ -259,15 +258,20 @@ typedef struct ImBuf { #define IB_thumbnail (1 << 15) #define IB_multiview (1 << 16) +/** \} */ + /** * \name Imbuf preset profile tags * \brief Some predefined color space profiles that 8 bit imbufs can represent - */ + * + * \{ */ #define IB_PROFILE_NONE 0 #define IB_PROFILE_LINEAR_RGB 1 #define IB_PROFILE_SRGB 2 #define IB_PROFILE_CUSTOM 3 +/** \} */ + /* dds */ #ifdef WITH_DDS #ifndef DDS_MAKEFOURCC @@ -298,8 +302,16 @@ extern const char *imb_ext_audio[]; /* image formats that can only be loaded via filepath */ extern const char *imb_ext_image_filepath_only[]; +/** + * \name Imbuf Color Management Flag + * \brief Used with #ImBuf.colormanage_flag + * + * \{ */ + enum { IMB_COLORMANAGE_IS_DATA = (1 << 0) }; -#endif +/** \} */ + +#endif /* __IMB_IMBUF_TYPES_H__ */ diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index d89393b9903..6d7ad7985f9 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -40,10 +40,7 @@ # include <mmsystem.h> # include <memory.h> # include <commdlg.h> - -# ifndef FREE_WINDOWS -# include <vfw.h> -# endif +# include <vfw.h> # undef AVIIF_KEYFRAME // redefined in AVI_avi.h # undef AVIIF_LIST // redefined in AVI_avi.h @@ -130,7 +127,7 @@ struct anim { /* avi */ struct _AviMovie *avi; -#if defined(_WIN32) && !defined(FREE_WINDOWS) +#if defined(_WIN32) /* windows avi */ int avistreams; int firstvideo; diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index b75f12b239d..0b4557e7bef 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -79,6 +79,8 @@ typedef struct ColorManagedLook { struct ColorManagedLook *next, *prev; int index; char name[MAX_COLORSPACE_NAME]; + char ui_name[MAX_COLORSPACE_NAME]; + char view[MAX_COLORSPACE_NAME]; char process_space[MAX_COLORSPACE_NAME]; bool is_noop; } ColorManagedLook; diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 33750478bb4..6e9bfa1fc4e 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -506,7 +506,7 @@ bool IMB_initImBuf(struct ImBuf *ibuf, } /* does no zbuffers? */ -ImBuf *IMB_dupImBuf(ImBuf *ibuf1) +ImBuf *IMB_dupImBuf(const ImBuf *ibuf1) { ImBuf *ibuf2, tbuf; int flags = 0; diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index a40b257b75b..9806ff006d7 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -37,10 +37,7 @@ #include <mmsystem.h> #include <memory.h> #include <commdlg.h> - -#ifndef FREE_WINDOWS #include <vfw.h> -#endif #undef AVIIF_KEYFRAME /* redefined in AVI_avi.h */ #undef AVIIF_LIST /* redefined in AVI_avi.h */ @@ -173,7 +170,7 @@ static void an_stringenc(char *string, const char *head, const char *tail, unsig #ifdef WITH_AVI static void free_anim_avi(struct anim *anim) { -#if defined(_WIN32) && !defined(FREE_WINDOWS) +#if defined(_WIN32) int i; #endif @@ -184,7 +181,7 @@ static void free_anim_avi(struct anim *anim) MEM_freeN(anim->avi); anim->avi = NULL; -#if defined(_WIN32) && !defined(FREE_WINDOWS) +#if defined(_WIN32) if (anim->pgf) { AVIStreamGetFrameClose(anim->pgf); @@ -283,7 +280,7 @@ static int startavi(struct anim *anim) { AviError avierror; -#if defined(_WIN32) && !defined(FREE_WINDOWS) +#if defined(_WIN32) HRESULT hr; int i, firstvideo = -1; int streamcount; @@ -304,7 +301,7 @@ static int startavi(struct anim *anim) avierror = AVI_open_movie(anim->name, anim->avi); -#if defined(_WIN32) && !defined(FREE_WINDOWS) +#if defined(_WIN32) if (avierror == AVI_ERROR_COMPRESSION) { AVIFileInit(); hr = AVIFileOpen(&anim->pfile, anim->name, OF_READ, 0L); @@ -401,7 +398,7 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position) return NULL; } -#if defined(_WIN32) && !defined(FREE_WINDOWS) +#if defined(_WIN32) if (anim->avistreams) { LPBITMAPINFOHEADER lpbi; diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index 8b4e95ac452..429a19936a5 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -183,7 +183,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf if (verbose) printf("DPX: File is LSB.\n"); } else { - if (verbose) { + if (verbose) { printf("DPX: Bad magic number %u in \"%s\".\n", header.fileHeader.magic_num, byteStuff); } diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c index 6fb1bccf491..600642f5e44 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.c +++ b/source/blender/imbuf/intern/cineon/logImageCore.c @@ -177,19 +177,18 @@ unsigned int getRowLength(int width, LogImageElement logElement) return ((width * logElement.depth * 10 - 1) / 32 + 1) * 4; else if (logElement.packing == 1 || logElement.packing == 2) return ((width * logElement.depth - 1) / 3 + 1) * 4; - + break; case 12: if (logElement.packing == 0) return ((width * logElement.depth * 12 - 1) / 32 + 1) * 4; else if (logElement.packing == 1 || logElement.packing == 2) return width * logElement.depth * 2; - + break; case 16: return width * logElement.depth * 2; - default: - return 0; } + return 0; } @@ -572,20 +571,20 @@ static int logImageElementGetData(LogImageFile *logImage, LogImageElement logEle return logImageElementGetData10Packed(logImage, logElement, data); else if (logElement.packing == 1 || logElement.packing == 2) return logImageElementGetData10(logImage, logElement, data); + break; case 12: if (logElement.packing == 0) return logImageElementGetData12Packed(logImage, logElement, data); else if (logElement.packing == 1 || logElement.packing == 2) return logImageElementGetData12(logImage, logElement, data); + break; case 16: return logImageElementGetData16(logImage, logElement, data); - - default: - /* format not supported */ - return 1; } + /* format not supported */ + return 1; } static int logImageElementGetData1(LogImageFile *logImage, LogImageElement logElement, float *data) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 48cba3e0800..03f71b5878c 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -63,6 +63,7 @@ #include "BKE_context.h" #include "BKE_image.h" #include "BKE_main.h" +#include "BKE_sequencer.h" #include "RNA_define.h" @@ -214,7 +215,7 @@ typedef struct ColormanageCacheKey { int display; /* display device name */ } ColormanageCacheKey; -typedef struct ColormnaageCacheData { +typedef struct ColormanageCacheData { int flag; /* view flags of cached buffer */ int look; /* Additional artistics transform */ float exposure; /* exposure value cached buffer is calculated with */ @@ -222,12 +223,12 @@ typedef struct ColormnaageCacheData { float dither; /* dither value cached buffer is calculated with */ CurveMapping *curve_mapping; /* curve mapping used for cached buffer */ int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */ -} ColormnaageCacheData; +} ColormanageCacheData; typedef struct ColormanageCache { struct MovieCache *moviecache; - ColormnaageCacheData *data; + ColormanageCacheData *data; } ColormanageCache; static struct MovieCache *colormanage_moviecache_get(const ImBuf *ibuf) @@ -238,7 +239,7 @@ static struct MovieCache *colormanage_moviecache_get(const ImBuf *ibuf) return ibuf->colormanage_cache->moviecache; } -static ColormnaageCacheData *colormanage_cachedata_get(const ImBuf *ibuf) +static ColormanageCacheData *colormanage_cachedata_get(const ImBuf *ibuf) { if (!ibuf->colormanage_cache) return NULL; @@ -281,7 +282,7 @@ static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf) return ibuf->colormanage_cache->moviecache; } -static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data) +static void colormanage_cachedata_set(ImBuf *ibuf, ColormanageCacheData *data) { if (!ibuf->colormanage_cache) ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache"); @@ -361,7 +362,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle); if (cache_ibuf) { - ColormnaageCacheData *cache_data; + ColormanageCacheData *cache_data; BLI_assert(cache_ibuf->x == ibuf->x && cache_ibuf->y == ibuf->y); @@ -402,7 +403,7 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting { ColormanageCacheKey key; ImBuf *cache_ibuf; - ColormnaageCacheData *cache_data; + ColormanageCacheData *cache_data; int view_flag = 1 << (view_settings->view - 1); struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf); CurveMapping *curve_mapping = view_settings->curve_mapping; @@ -421,7 +422,7 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting cache_ibuf->flags |= IB_rect; /* store data which is needed to check whether cached buffer could be used for color managed display settings */ - cache_data = MEM_callocN(sizeof(ColormnaageCacheData), "color manage cache imbuf data"); + cache_data = MEM_callocN(sizeof(ColormanageCacheData), "color manage cache imbuf data"); cache_data->look = view_settings->look; cache_data->exposure = view_settings->exposure; cache_data->gamma = view_settings->gamma; @@ -710,7 +711,7 @@ void colormanage_cache_free(ImBuf *ibuf) } if (ibuf->colormanage_cache) { - ColormnaageCacheData *cache_data = colormanage_cachedata_get(ibuf); + ColormanageCacheData *cache_data = colormanage_cachedata_get(ibuf); struct MovieCache *moviecache = colormanage_moviecache_get(ibuf); if (cache_data) { @@ -1112,6 +1113,7 @@ void IMB_colormanagement_check_file_config(Main *bmain) for (scene = bmain->scene.first; scene; scene = scene->id.next) { ColorManagedColorspaceSettings *sequencer_colorspace_settings; + /* check scene color management settings */ colormanage_check_display_settings(&scene->display_settings, "scene", default_display); colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene"); @@ -1122,6 +1124,15 @@ void IMB_colormanagement_check_file_config(Main *bmain) if (sequencer_colorspace_settings->name[0] == '\0') { BLI_strncpy(sequencer_colorspace_settings->name, global_role_default_sequencer, MAX_COLORSPACE_NAME); } + + /* check sequencer strip input color space settings */ + Sequence *seq; + SEQ_BEGIN (scene->ed, seq) { + if (seq->strip) { + colormanage_check_colorspace_settings(&seq->strip->colorspace_settings, "sequencer strip"); + } + } + SEQ_END } /* ** check input color space settings ** */ @@ -1406,7 +1417,7 @@ static void *do_display_buffer_apply_thread(void *handle_v) bool is_data = handle->is_data; if (cm_processor == NULL) { - if (display_buffer_byte) { + if (display_buffer_byte && display_buffer_byte != handle->byte_buffer) { IMB_buffer_byte_from_byte(display_buffer_byte, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, width, height, width, width); } @@ -1759,9 +1770,14 @@ void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsig return; } if (STREQ(from_colorspace, to_colorspace)) { - /* If source and destination color spaces are identical, skip - * threading overhead and simply do nothing + /* Because this function always takes a byte buffer and returns a float buffer, it must + * always do byte-to-float conversion of some kind. To avoid threading overhead + * IMB_buffer_float_from_byte is used when color spaces are identical. See T51002. */ + IMB_buffer_float_from_byte(float_buffer, byte_buffer, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, + true, + width, height, width, width); return; } cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); @@ -2060,6 +2076,10 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, boo } } + if (colormanaged_ibuf != ibuf) { + IMB_metadata_copy(colormanaged_ibuf, ibuf); + } + return colormanaged_ibuf; } @@ -2568,9 +2588,17 @@ ColorManagedLook *colormanage_look_add(const char *name, const char *process_spa look = MEM_callocN(sizeof(ColorManagedLook), "ColorManagedLook"); look->index = index + 1; BLI_strncpy(look->name, name, sizeof(look->name)); + BLI_strncpy(look->ui_name, name, sizeof(look->ui_name)); BLI_strncpy(look->process_space, process_space, sizeof(look->process_space)); look->is_noop = is_noop; + /* Detect view specific looks. */ + const char *separator_offset = strstr(look->name, " - "); + if (separator_offset) { + BLI_strncpy(look->view, look->name, separator_offset - look->name + 1); + BLI_strncpy(look->ui_name, separator_offset + strlen(" - "), sizeof(look->ui_name)); + } + BLI_addtail(&global_looks, look); global_tot_looks++; @@ -2671,15 +2699,27 @@ void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem, } } -void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem) +void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items, int *totitem, const char *view_name) { ColorManagedLook *look; + const char *view_filter = NULL; + + /* Test if this view transform is limited to specific looks. */ + for (look = global_looks.first; look; look = look->next) { + if (STREQ(look->view, view_name)) { + view_filter = view_name; + } + } for (look = global_looks.first; look; look = look->next) { + if (!look->is_noop && view_filter && !STREQ(look->view, view_filter)) { + continue; + } + EnumPropertyItem item; item.value = look->index; - item.name = look->name; + item.name = look->ui_name; item.identifier = look->name; item.icon = 0; item.description = ""; diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 12e03f55450..67a0b0ffd00 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -37,7 +37,7 @@ extern "C" { #include <stdio.h> // printf #include <fstream> -#if defined (WIN32) && !defined(FREE_WINDOWS) +#if defined (WIN32) #include "utfconv.h" #endif @@ -62,7 +62,7 @@ int imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/) /* open file for writing */ std::ofstream fildes; -#if defined (WIN32) && !defined(FREE_WINDOWS) +#if defined (WIN32) wchar_t *wname = alloc_utf16_from_8(name, 0); fildes.open(wname); free(wname); diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 1987c6d2a9a..38609d0a342 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -406,7 +406,7 @@ void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter) const int height = ibuf->y; const int depth = 4; /* always 4 channels */ const int chsize = ibuf->rect_float ? sizeof(float) : sizeof(unsigned char); - const int bsize = width * height * depth * chsize; + const size_t bsize = ((size_t)width) * height * depth * chsize; const bool is_float = (ibuf->rect_float != NULL); void *dstbuf = (void *) MEM_dupallocN(ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect); char *dstmask = mask == NULL ? NULL : (char *) MEM_dupallocN(mask); @@ -499,7 +499,9 @@ void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter) /* keep the original buffer up to date. */ memcpy(srcbuf, dstbuf, bsize); - if (dstmask != NULL) memcpy(srcmask, dstmask, width * height); + if (dstmask != NULL) { + memcpy(srcmask, dstmask, ((size_t)width) * height); + } } /* free memory */ diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index 134bbe88f15..da39967a4fe 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -81,7 +81,9 @@ bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, con void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb) { + BLI_assert(dimb != simb); if (simb->metadata) { + IMB_metadata_free(dimb); dimb->metadata = IDP_CopyProperty(simb->metadata); } } diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 11bf45418d6..b123d508f99 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -31,7 +31,7 @@ #include <set> -#if defined(WIN32) && !defined(FREE_WINDOWS) +#if defined(WIN32) #include "utfconv.h" #endif @@ -213,7 +213,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac in = ImageInput::create(filename); if (!in) { std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl - << OpenImageIO::geterror() << std::endl; + << OIIO_NAMESPACE::geterror() << std::endl; return NULL; } diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 89e796fb7ee..1fa3b943524 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -69,7 +69,7 @@ #include <openexr_api.h> -#if defined (WIN32) && !defined(FREE_WINDOWS) +#if defined (WIN32) #include "utfconv.h" #endif @@ -77,7 +77,7 @@ extern "C" { // The following prevents a linking error in debug mode for MSVC using the libs in CVS -#if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && !defined(__MINGW32__) && _MSC_VER < 1900 +#if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && _MSC_VER < 1900 _CRTIMP void __cdecl _invalid_parameter_noinfo(void) { } @@ -180,7 +180,7 @@ public: : IStream(filename) { /* utf-8 file path support on windows */ -#if defined (WIN32) && !defined(FREE_WINDOWS) +#if defined (WIN32) wchar_t *wfilename = alloc_utf16_from_8(filename, 0); ifs.open(wfilename, std::ios_base::binary); free(wfilename); @@ -243,7 +243,7 @@ public: : OStream(filename) { /* utf-8 file path support on windows */ -#if defined (WIN32) && !defined(FREE_WINDOWS) +#if defined (WIN32) wchar_t *wfilename = alloc_utf16_from_8(filename, 0); ofs.open(wfilename, std::ios_base::binary); free(wfilename); @@ -1026,15 +1026,16 @@ void IMB_exr_set_channel(void *handle, const char *layname, const char *passname ExrChannel *echan; char name[EXR_TOT_MAXNAME + 1]; - if (layname) { + if (layname && layname[0] != '\0') { char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1]; BLI_strncpy(lay, layname, EXR_LAY_MAXNAME); BLI_strncpy(pass, passname, EXR_PASS_MAXNAME); BLI_snprintf(name, sizeof(name), "%s.%s", lay, pass); } - else + else { BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1); + } echan = (ExrChannel *)BLI_findstring(&data->channels, name, offsetof(ExrChannel, name)); @@ -1043,8 +1044,9 @@ void IMB_exr_set_channel(void *handle, const char *layname, const char *passname echan->ystride = ystride; echan->rect = rect; } - else + else { printf("IMB_exr_set_channel error %s\n", name); + } } float *IMB_exr_channel_rect(void *handle, const char *layname, const char *passname, const char *viewname) @@ -1102,7 +1104,7 @@ void IMB_exr_write_channels(void *handle) if (data->channels.first) { const size_t num_pixels = ((size_t)data->width) * data->height; - half *rect_half = NULL, *current_rect_half; + half *rect_half = NULL, *current_rect_half = NULL; /* We allocate teporary storage for half pixels for all the channels at once. */ if (data->num_half_channels != 0) { diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 5192e3f2d26..503e63a3fb1 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -613,11 +613,12 @@ ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colors int unit_type; png_uint_32 xres, yres; - if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) + if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) { if (unit_type == PNG_RESOLUTION_METER) { ibuf->ppm[0] = xres; ibuf->ppm[1] = yres; } + } } } else { diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 71e74928e20..a21468e474c 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -340,13 +340,14 @@ static int fwritecolrs(FILE *file, int width, int channels, unsigned char *ibufs } if (((beg - j) > 1) && ((beg - j) < MINRUN)) { c2 = j + 1; - while (rgbe_scan[c2++][i] == rgbe_scan[j][i]) + while (rgbe_scan[c2++][i] == rgbe_scan[j][i]) { if (c2 == beg) { /* short run */ putc((unsigned char)(128 + beg - j), file); putc((unsigned char)(rgbe_scan[j][i]), file); j = beg; break; } + } } while (j < beg) { /* write out non-run */ if ((c2 = beg - j) > 128) c2 = 128; diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 3360fd7548e..c4325caac91 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -301,8 +301,8 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height, IMB_BlendMode mode, bool accumulate) { - unsigned int *drect = NULL, *orect, *srect = NULL, *dr, *or, *sr; - float *drectf = NULL, *orectf, *srectf = NULL, *drf, *orf, *srf; + unsigned int *drect = NULL, *orect = NULL, *srect = NULL, *dr, *or, *sr; + float *drectf = NULL, *orectf = NULL, *srectf = NULL, *drf, *orf, *srf; unsigned short *cmaskrect = curvemask, *cmr; unsigned short *dmaskrect = dmask, *dmr; unsigned short *texmaskrect = texmask, *tmr; @@ -424,6 +424,7 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, else { switch (mode) { case IMB_BLEND_MIX: + case IMB_BLEND_INTERPOLATE: func = blend_color_mix_byte; func_float = blend_color_mix_float; break; @@ -563,9 +564,15 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, mask_src[0] = src[0]; mask_src[1] = src[1]; mask_src[2] = src[2]; - mask_src[3] = divide_round_i(src[3] * mask, 65535); - func((unsigned char *)dr, (unsigned char *)or, mask_src); + if (mode == IMB_BLEND_INTERPOLATE) { + mask_src[3] = src[3]; + blend_color_interpolate_byte((unsigned char *)dr, (unsigned char *)or, mask_src, mask / 65535.0f); + } + else { + mask_src[3] = divide_round_i(src[3] * mask, 65535); + func((unsigned char *)dr, (unsigned char *)or, mask_src); + } } } } @@ -588,9 +595,15 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, mask_src[0] = src[0]; mask_src[1] = src[1]; mask_src[2] = src[2]; - mask_src[3] = divide_round_i(src[3] * mask, 65535); - func((unsigned char *)dr, (unsigned char *)or, mask_src); + if (mode == IMB_BLEND_INTERPOLATE) { + mask_src[3] = src[3]; + blend_color_interpolate_byte((unsigned char *)dr, (unsigned char *)or, mask_src, mask / 65535.0f); + } + else { + mask_src[3] = divide_round_i(src[3] * mask, 65535); + func((unsigned char *)dr, (unsigned char *)or, mask_src); + } } } } @@ -642,12 +655,16 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, mask = min_ff(mask, 65535.0); if (mask > *dmr) { - float mask_srf[4]; - *dmr = mask; - mul_v4_v4fl(mask_srf, srf, mask / 65535.0f); - func_float(drf, orf, mask_srf); + if (mode == IMB_BLEND_INTERPOLATE) { + blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f); + } + else { + float mask_srf[4]; + mul_v4_v4fl(mask_srf, srf, mask / 65535.0f); + func_float(drf, orf, mask_srf); + } } } } @@ -664,11 +681,15 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, mask = min_ff(mask, 65535.0); if (srf[3] && (mask > 0.0f)) { - float mask_srf[4]; - - mul_v4_v4fl(mask_srf, srf, mask / 65535.0f); + if (mode == IMB_BLEND_INTERPOLATE) { + blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f); + } + else { + float mask_srf[4]; + mul_v4_v4fl(mask_srf, srf, mask / 65535.0f); + func_float(drf, orf, mask_srf); + } - func_float(drf, orf, mask_srf); } } } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 2c6f3d2fc66..da0f505c4f3 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -82,8 +82,6 @@ enum { IDP_FLOAT = 2, IDP_ARRAY = 5, IDP_GROUP = 6, - /* the ID link property type hasn't been implemented yet, this will require - * some cleanup of blenkernel, most likely. */ IDP_ID = 7, IDP_DOUBLE = 8, IDP_IDPARRAY = 9, diff --git a/source/blender/makesdna/DNA_cachefile_types.h b/source/blender/makesdna/DNA_cachefile_types.h index 46b1adf2725..a353c94ae64 100644 --- a/source/blender/makesdna/DNA_cachefile_types.h +++ b/source/blender/makesdna/DNA_cachefile_types.h @@ -47,10 +47,12 @@ enum { CACHEFILE_KEYFRAME_DRAWN = (1 << 0), }; +/* Representation of an object's path inside the Alembic file. + * Note that this is not a file path. */ typedef struct AlembicObjectPath { struct AlembicObjectPath *next, *prev; - char path[1024]; /* 1024 = FILE_MAX, might use PATH_MAX in the future. */ + char path[4096]; } AlembicObjectPath; typedef struct CacheFile { diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 621807d111c..3676066a399 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -164,8 +164,8 @@ typedef struct MLoop { * MEdge *ed = &medge[mloop[lt->tri[j]].e]; * unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v}; * - * if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) && - * ELEM(ed->v2, tri_edge[0], tri_edge[1])) + * if (((ed->v1 == tri_edge[0]) && (ed->v1 == tri_edge[1])) || + * ((ed->v1 == tri_edge[1]) && (ed->v1 == tri_edge[0]))) * { * printf("real edge found %u %u\n", tri_edge[0], tri_edge[1]); * } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 47677e50451..b922ac072b0 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -569,9 +569,9 @@ typedef struct NodeEllipseMask { /* layer info for image node outputs */ typedef struct NodeImageLayer { /* index in the Image->layers->passes lists */ - int pass_index; - /* render pass flag, in case this is an original render pass */ - int pass_flag; + int pass_index DNA_DEPRECATED; + /* render pass name */ + char pass_name[64]; /* amount defined in openexr_multi.h */ } NodeImageLayer; typedef struct NodeBlurData { diff --git a/source/blender/makesdna/DNA_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h index a714195dd5d..846d5788d63 100644 --- a/source/blender/makesdna/DNA_object_fluidsim.h +++ b/source/blender/makesdna/DNA_object_fluidsim.h @@ -179,6 +179,7 @@ typedef struct FluidsimSettings { #define OB_FLUIDSIM_ACTIVE (1 << 1) #define OB_FLUIDSIM_OVERRIDE_TIME (1 << 2) +#define OB_FLUIDSIM_SURF_DIR_DEFAULT "cache_fluid" #define OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME "fluidsurface_preview_####.bobj.gz" #define OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME "fluidsurface_final_####.bobj.gz" #define OB_FLUIDSIM_SURF_FINAL_VEL_FNAME "fluidsurface_final_####.bvel.gz" diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index d24c7faa9f5..6d79e6d49f8 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -335,6 +335,8 @@ typedef struct DupliObject { /* particle this dupli was generated from */ struct ParticleSystem *particle_system; + unsigned int random_id; + unsigned int pad; } DupliObject; /* **************** OBJECT ********************* */ diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 1deb9bf3787..f6bed37dfa2 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -323,7 +323,7 @@ typedef struct ParticleSystem { struct ParticleDrawData *pdd; float dt_frac; /* current time step, as a fraction of a frame */ - float _pad; /* spare capacity */ + float lattice_strength; /* influence of the lattice modifier */ } ParticleSystem; typedef enum eParticleDrawFlag { diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 918d0f00040..c2711c465e1 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -229,7 +229,9 @@ typedef struct SceneRenderLayer { int samples; float pass_alpha_threshold; - + + IDProperty *prop; + struct FreestyleConfig freestyleConfig; } SceneRenderLayer; @@ -283,9 +285,43 @@ typedef enum ScenePassType { SCE_PASS_SUBSURFACE_DIRECT = (1 << 28), SCE_PASS_SUBSURFACE_INDIRECT = (1 << 29), SCE_PASS_SUBSURFACE_COLOR = (1 << 30), - SCE_PASS_DEBUG = (1 << 31), /* This is a virtual pass. */ } ScenePassType; +#define RE_PASSNAME_COMBINED "Combined" +#define RE_PASSNAME_Z "Depth" +#define RE_PASSNAME_VECTOR "Vector" +#define RE_PASSNAME_NORMAL "Normal" +#define RE_PASSNAME_UV "UV" +#define RE_PASSNAME_RGBA "Color" +#define RE_PASSNAME_EMIT "Emit" +#define RE_PASSNAME_DIFFUSE "Diffuse" +#define RE_PASSNAME_SPEC "Spec" +#define RE_PASSNAME_SHADOW "Shadow" + +#define RE_PASSNAME_AO "AO" +#define RE_PASSNAME_ENVIRONMENT "Env" +#define RE_PASSNAME_INDIRECT "Indirect" +#define RE_PASSNAME_REFLECT "Reflect" +#define RE_PASSNAME_REFRACT "Refract" +#define RE_PASSNAME_INDEXOB "IndexOB" +#define RE_PASSNAME_INDEXMA "IndexMA" +#define RE_PASSNAME_MIST "Mist" + +#define RE_PASSNAME_RAYHITS "RayHits" +#define RE_PASSNAME_DIFFUSE_DIRECT "DiffDir" +#define RE_PASSNAME_DIFFUSE_INDIRECT "DiffInd" +#define RE_PASSNAME_DIFFUSE_COLOR "DiffCol" +#define RE_PASSNAME_GLOSSY_DIRECT "GlossDir" +#define RE_PASSNAME_GLOSSY_INDIRECT "GlossInd" +#define RE_PASSNAME_GLOSSY_COLOR "GlossCol" +#define RE_PASSNAME_TRANSM_DIRECT "TransDir" +#define RE_PASSNAME_TRANSM_INDIRECT "TransInd" +#define RE_PASSNAME_TRANSM_COLOR "TransCol" + +#define RE_PASSNAME_SUBSURFACE_DIRECT "SubsurfaceDir" +#define RE_PASSNAME_SUBSURFACE_INDIRECT "SubsurfaceInd" +#define RE_PASSNAME_SUBSURFACE_COLOR "SubsurfaceCol" + /* note, srl->passflag is treestore element 'nr' in outliner, short still... */ /* View - MultiView */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 5e015544dc9..0e5d9bd33e6 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1151,7 +1151,7 @@ typedef enum eSpaceNode_Flag { SNODE_SHOW_G = (1 << 8), SNODE_SHOW_B = (1 << 9), SNODE_AUTO_RENDER = (1 << 5), - SNODE_SHOW_HIGHLIGHT = (1 << 6), +// SNODE_SHOW_HIGHLIGHT = (1 << 6), DNA_DEPRECATED // SNODE_USE_HIDDEN_PREVIEW = (1 << 10), DNA_DEPRECATED December2013 SNODE_NEW_SHADERS = (1 << 11), SNODE_PIN = (1 << 12), diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index f9aaec69ce7..a1af3f98274 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -767,6 +767,8 @@ void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type); struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create); bool RNA_struct_idprops_check(StructRNA *srna); bool RNA_struct_idprops_register_check(const StructRNA *type); +bool RNA_struct_idprops_datablock_allowed(const StructRNA *type); +bool RNA_struct_idprops_contains_datablock(const StructRNA *type); bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier); PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier); diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 2a680b6eaeb..6e62313b00a 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -167,6 +167,7 @@ void RNA_def_property_editable_func(PropertyRNA *prop, const char *editable); void RNA_def_property_editable_array_func(PropertyRNA *prop, const char *editable); void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func); +void RNA_def_property_poll_runtime(PropertyRNA *prop, const void *func); void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength); void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const char *set); diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index dee8df7d933..cd04f9e8a6d 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -434,6 +434,8 @@ typedef enum StructFlag { STRUCT_GENERATED = (1 << 4), STRUCT_FREE_POINTERS = (1 << 5), STRUCT_NO_IDPROPERTIES = (1 << 6), /* Menus and Panels don't need properties */ + STRUCT_NO_DATABLOCK_IDPROPERTIES = (1 << 7), /* e.g. for Operator */ + STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES = (1 << 8), /* for PropertyGroup which contains pointers to datablocks */ } StructFlag; typedef int (*StructValidateFunc)(struct PointerRNA *ptr, void *data, int *have_function); diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 0f3ea27a7f9..6a08d762920 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -176,9 +176,6 @@ set(INC_SYS if(WITH_CYCLES) add_definitions(-DWITH_CYCLES) - if(WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) - endif() endif() if(WITH_PYTHON) diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 9d68c05dda0..de436172bfd 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3746,7 +3746,7 @@ static const char *cpp_classes = "" "template<typename T, TBeginFunc Tbegin, TNextFunc Tnext, TEndFunc Tend>\n" "class CollectionIterator {\n" "public:\n" -" CollectionIterator() : t(iter.ptr), init(false) { iter.valid = false; }\n" +" CollectionIterator() : iter(), t(iter.ptr), init(false) { iter.valid = false; }\n" " ~CollectionIterator(void) { if (init) Tend(&iter); };\n" "\n" " operator bool(void)\n" diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 671902c5cc7..a74758a4f71 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -342,7 +342,7 @@ static void rna_ID_user_clear(ID *id) static void rna_ID_user_remap(ID *id, Main *bmain, ID *new_id) { - if (GS(id->name) == GS(new_id->name)) { + if ((GS(id->name) == GS(new_id->name)) && (id != new_id)) { /* For now, do not allow remapping data in linked data from here... */ BKE_libblock_remap(bmain, id, new_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE); } @@ -802,7 +802,11 @@ static void rna_def_ID_properties(BlenderRNA *brna) RNA_def_struct_name_property(srna, prop); #endif - /* IDP_ID -- not implemented yet in id properties */ + /* IDP_ID */ + prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EXPORT | PROP_IDPROPERTY | PROP_NEVER_UNLINK); + RNA_def_property_struct_type(prop, "ID"); + /* ID property groups > level 0, since level 0 group is merged * with native RNA properties. the builtin_properties will take diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 7266cfb12d6..5a4db47d281 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -50,6 +50,7 @@ #include "BKE_idcode.h" #include "BKE_idprop.h" #include "BKE_fcurve.h" +#include "BKE_library.h" #include "BKE_main.h" #include "BKE_report.h" @@ -380,6 +381,7 @@ static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDPr return false; break; case IDP_GROUP: + case IDP_ID: if (prop->type != PROP_POINTER) return false; break; @@ -395,7 +397,8 @@ static PropertyRNA *typemap[IDP_NUMTYPES] = { (PropertyRNA *)&rna_PropertyGroupItem_int, (PropertyRNA *)&rna_PropertyGroupItem_float, NULL, NULL, NULL, - (PropertyRNA *)&rna_PropertyGroupItem_group, NULL, + (PropertyRNA *)&rna_PropertyGroupItem_group, + (PropertyRNA *)&rna_PropertyGroupItem_id, (PropertyRNA *)&rna_PropertyGroupItem_double, (PropertyRNA *)&rna_PropertyGroupItem_idp_array }; @@ -587,6 +590,21 @@ bool RNA_struct_idprops_register_check(const StructRNA *type) return (type->flag & STRUCT_NO_IDPROPERTIES) == 0; } +bool RNA_struct_idprops_datablock_allowed(const StructRNA *type) +{ + return (type->flag & (STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_NO_IDPROPERTIES)) == 0; +} + +/** + * Whether given type implies datablock usage by IDProperties. + * This is used to prevent classes allowed to have IDProperties, but not datablock ones, to indirectly use some + * (e.g. by assigning an IDP_GROUP containing some IDP_ID pointers...). + */ +bool RNA_struct_idprops_contains_datablock(const StructRNA *type) +{ + return (type->flag & (STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES | STRUCT_ID)) != 0; +} + /* remove an id-property */ bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier) { @@ -628,8 +646,11 @@ PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier) /* id prop lookup, not so common */ PropertyRNA *r_prop = NULL; PointerRNA r_ptr; /* only support single level props */ - if (RNA_path_resolve(ptr, identifier, &r_ptr, &r_prop) && (r_ptr.type == ptr->type) && (r_ptr.data == ptr->data)) + if (RNA_path_resolve_property(ptr, identifier, &r_ptr, &r_prop) && + (r_ptr.type == ptr->type) && (r_ptr.data == ptr->data)) + { return r_prop; + } } else { /* most common case */ @@ -1201,13 +1222,20 @@ int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *va if (prop->type == PROP_POINTER) { PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; - if (pprop->poll) - return pprop->poll(ptr, *value); + + if (pprop->poll) { + if (rna_idproperty_check(&prop, ptr)) { + return ((PropPointerPollFuncPy) pprop->poll)(ptr, *value, prop); + } + else { + return pprop->poll(ptr, *value); + } + } return 1; } - printf("%s %s: is not a pointer property.\n", __func__, prop->identifier); + printf("%s: %s is not a pointer property.\n", __func__, prop->identifier); return 0; } @@ -2967,6 +2995,10 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) if ((idprop = rna_idproperty_check(&prop, ptr))) { pprop = (PointerPropertyRNA *)prop; + if (RNA_struct_is_ID(pprop->type)) { + return rna_pointer_inherit_refine(ptr, pprop->type, IDP_Id(idprop)); + } + /* for groups, data is idprop itself */ if (pprop->typef) return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop); @@ -2989,22 +3021,32 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value) { - /*IDProperty *idprop;*/ - + PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; BLI_assert(RNA_property_type(prop) == PROP_POINTER); - if ((/*idprop = */ rna_idproperty_check(&prop, ptr))) { - /* not supported */ - /* rna_idproperty_touch(idprop); */ + /* Check types */ + if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, pprop->type)) { + printf("%s: expected %s type, not %s.\n", __func__, pprop->type->identifier, ptr_value.type->identifier); + return; } - else { - PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; - if (pprop->set && - !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) && - !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)) - { - pprop->set(ptr, ptr_value); + /* RNA */ + if (pprop->set && + !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) && + !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)) + { + pprop->set(ptr, ptr_value); + } + /* IDProperty */ + else if (prop->flag & PROP_EDITABLE) { + IDPropertyTemplate val = {0}; + IDProperty *group; + + val.id = ptr_value.data; + + group = RNA_struct_idprops(ptr, true); + if (group) { + IDP_ReplaceInGroup(group, IDP_New(IDP_ID, &val, prop->identifier)); } } } @@ -5557,12 +5599,13 @@ static char *rna_pointer_as_string__bldata(PointerRNA *ptr) } } -char *RNA_pointer_as_string(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *prop_ptr, PointerRNA *ptr_prop) +char *RNA_pointer_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop_ptr, PointerRNA *ptr_prop) { + IDProperty *prop; if (ptr_prop->data == NULL) { return BLI_strdup("None"); } - else if (RNA_property_flag(prop_ptr) & PROP_IDPROPERTY) { + else if ((prop = rna_idproperty_check(&prop_ptr, ptr)) && prop->type != IDP_ID) { return RNA_pointer_as_string_id(C, ptr_prop); } else { @@ -6403,7 +6446,7 @@ static int rna_function_parameter_parse(PointerRNA *ptr, PropertyRNA *prop, Prop tid, fid, pid, RNA_struct_identifier(ptype), RNA_struct_identifier(srna)); return -1; } - + *((void **)dest) = *((void **)src); break; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index d3cd3d12c4d..5339df34a38 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -508,12 +508,13 @@ static void rna_ColorManagedViewSettings_look_set(PointerRNA *ptr, int value) } static EnumPropertyItem *rna_ColorManagedViewSettings_look_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) + bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free) { + ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data; EnumPropertyItem *items = NULL; int totitem = 0; - IMB_colormanagement_look_items_add(&items, &totitem); + IMB_colormanagement_look_items_add(&items, &totitem, view->view_transform); RNA_enum_item_end(&items, &totitem); *r_free = true; diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 1d232d2df39..42c0344f46e 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -71,8 +71,8 @@ BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1}; if (description && (description)[0]) { \ int i = strlen(description); \ if (i > 3 && (description)[i - 1] == '.' && (description)[i - 3] != '.') { \ - fprintf(stderr, "%s: '%s' '%s' description ends with a '.' !\n", \ - __func__, id1 ? id1 : "", id2 ? id2 : ""); \ + fprintf(stderr, "%s: '%s' description from '%s' '%s' ends with a '.' !\n", \ + __func__, description, id1 ? id1 : "", id2 ? id2 : ""); \ } \ } (void)0 @@ -2168,6 +2168,16 @@ void RNA_def_property_update_runtime(PropertyRNA *prop, const void *func) prop->update = (void *)func; } +void RNA_def_property_poll_runtime(PropertyRNA *prop, const void *func) +{ + if (prop->type == PROP_POINTER) { + ((PointerPropertyRNA *)prop)->poll = func; + } + else { + fprintf(stderr, "%s: %s is not a Pointer Property.\n", __func__, prop->identifier); + } +} + void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength) { if (!DefRNA.preprocess) { @@ -2982,6 +2992,9 @@ PropertyRNA *RNA_def_pointer_runtime(StructOrFunctionRNA *cont_, const char *ide prop = RNA_def_property(cont, identifier, PROP_POINTER, PROP_NONE); RNA_def_property_struct_runtime(prop, type); + if ((type->flag & STRUCT_ID) != 0) { + prop->flag |= PROP_EDITABLE; + } RNA_def_property_ui_text(prop, ui_name, ui_description); return prop; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index bccc47aa95d..ad63a652b12 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -765,6 +765,38 @@ static void rna_FModifierStepped_end_frame_range(PointerRNA *ptr, float *min, fl *max = MAXFRAMEF; } +static void rna_FModifierStepped_frame_start_set(PointerRNA *ptr, float value) +{ + FModifier *fcm = (FModifier *)ptr->data; + FMod_Stepped *data = fcm->data; + + float prop_clamp_min = -FLT_MAX, prop_clamp_max = FLT_MAX, prop_soft_min, prop_soft_max; + rna_FModifierStepped_start_frame_range(ptr, &prop_clamp_min, &prop_clamp_max, &prop_soft_min, &prop_soft_max); + value = CLAMPIS(value, prop_clamp_min, prop_clamp_max); + + /* Need to set both step-data's start/end and the start/end on the base-data, + * or else Restrict-Range doesn't work due to RNA-property shadowing (T52009) + */ + data->start_frame = value; + fcm->sfra = value; +} + +static void rna_FModifierStepped_frame_end_set(PointerRNA *ptr, float value) +{ + FModifier *fcm = (FModifier *)ptr->data; + FMod_Stepped *data = fcm->data; + + float prop_clamp_min = -FLT_MAX, prop_clamp_max = FLT_MAX, prop_soft_min, prop_soft_max; + rna_FModifierStepped_end_frame_range(ptr, &prop_clamp_min, &prop_clamp_max, &prop_soft_min, &prop_soft_max); + value = CLAMPIS(value, prop_clamp_min, prop_clamp_max); + + /* Need to set both step-data's start/end and the start/end on the base-data, + * or else Restrict-Range doesn't work due to RNA-property shadowing (T52009) + */ + data->end_frame = value; + fcm->efra = value; +} + static BezTriple *rna_FKeyframe_points_insert(FCurve *fcu, float frame, float value, int keyframe_type, int flag) { int index = insert_vert_fcurve(fcu, frame, value, (char)keyframe_type, flag | INSERTKEY_NO_USERPREF); @@ -1284,13 +1316,13 @@ static void rna_def_fmodifier_stepped(BlenderRNA *brna) prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "start_frame"); - RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierStepped_start_frame_range"); + RNA_def_property_float_funcs(prop, NULL, "rna_FModifierStepped_frame_start_set", "rna_FModifierStepped_start_frame_range"); RNA_def_property_ui_text(prop, "Start Frame", "Frame that modifier's influence starts (if applicable)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); prop = RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "end_frame"); - RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifierStepped_end_frame_range"); + RNA_def_property_float_funcs(prop, NULL, "rna_FModifierStepped_frame_end_set", "rna_FModifierStepped_end_frame_range"); RNA_def_property_ui_text(prop, "End Frame", "Frame that modifier's influence ends (if applicable)"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_FModifier_update"); } diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index 091950a8e66..8c3984e4b29 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -185,12 +185,16 @@ static void rna_DomainFluidSettings_memory_estimate_get(PointerRNA *ptr, char *v #endif } -static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *UNUSED(ptr)) +static int rna_DomainFluidSettings_memory_estimate_length(PointerRNA *ptr) { #ifndef WITH_MOD_FLUID + UNUSED_VARS(ptr); return 0; #else - return 31; + char value[32]; + + rna_DomainFluidSettings_memory_estimate_get(ptr, value); + return strlen(value); #endif } diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index f65aa90ea71..b6e84cf8ac3 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -871,7 +871,7 @@ static void rna_def_image(BlenderRNA *brna) prop = RNA_def_property(srna, "has_data", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_Image_has_data_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Has data", "True if this image has data"); + RNA_def_property_ui_text(prop, "Has Data", "True if the image data is loaded into memory"); prop = RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_funcs(prop, "rna_Image_depth_get", NULL, NULL); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 76455adbc78..dfd5af788f6 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -344,6 +344,7 @@ extern IntPropertyRNA rna_PropertyGroupItem_int_array; extern FloatPropertyRNA rna_PropertyGroupItem_float; extern FloatPropertyRNA rna_PropertyGroupItem_float_array; extern PointerPropertyRNA rna_PropertyGroupItem_group; +extern PointerPropertyRNA rna_PropertyGroupItem_id; extern CollectionPropertyRNA rna_PropertyGroupItem_collection; extern CollectionPropertyRNA rna_PropertyGroupItem_idp_array; extern FloatPropertyRNA rna_PropertyGroupItem_double; diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index fce81e6967e..df591659fdb 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -94,6 +94,7 @@ typedef PointerRNA (*PropPointerGetFunc)(struct PointerRNA *ptr); typedef StructRNA *(*PropPointerTypeFunc)(struct PointerRNA *ptr); typedef void (*PropPointerSetFunc)(struct PointerRNA *ptr, const PointerRNA value); typedef int (*PropPointerPollFunc)(struct PointerRNA *ptr, const PointerRNA value); +typedef int (*PropPointerPollFuncPy)(struct PointerRNA *ptr, const PointerRNA value, const PropertyRNA *prop); typedef void (*PropCollectionBeginFunc)(struct CollectionPropertyIterator *iter, struct PointerRNA *ptr); typedef void (*PropCollectionNextFunc)(struct CollectionPropertyIterator *iter); typedef void (*PropCollectionEndFunc)(struct CollectionPropertyIterator *iter); diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c index 1199cccc4e6..a163d9764c1 100644 --- a/source/blender/makesrna/intern/rna_linestyle.c +++ b/source/blender/makesrna/intern/rna_linestyle.c @@ -1620,6 +1620,7 @@ static void rna_def_linestyle(BlenderRNA *brna) prop = RNA_def_property(srna, "panel", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "panel"); RNA_def_property_enum_items(prop, panel_items); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Panel", "Select the property panel to be shown"); prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR); diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index e44a6420045..d72c858a5d5 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -659,7 +659,10 @@ static void rna_def_nlastrip(BlenderRNA *brna) prop = RNA_def_property(srna, "influence", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Influence", "Amount the strip contributes to the current result"); - RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_update"); + /* XXX: Update temporarily disabled so that the property can be edited at all! + * Even autokey only applies after the curves have been re-evaluated, causing the unkeyed values to be lost + */ + RNA_def_property_update(prop, NC_ANIMATION | ND_NLA | NA_EDITED, /*"rna_NlaStrip_update"*/ NULL); prop = RNA_def_property(srna, "strip_time", PROP_FLOAT, PROP_TIME); RNA_def_property_ui_text(prop, "Strip Time", "Frame of referenced Action to evaluate"); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 8d42d746e1c..10422c85579 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -64,6 +64,8 @@ #include "RE_render_ext.h" +#include "NOD_composite.h" + EnumPropertyItem rna_enum_node_socket_in_out_items[] = { { SOCK_IN, "IN", 0, "Input", "" }, { SOCK_OUT, "OUT", 0, "Output", "" }, @@ -2608,7 +2610,7 @@ static void rna_Node_image_layer_update(Main *bmain, Scene *scene, PointerRNA *p rna_Node_update(bmain, scene, ptr); if (scene->nodetree != NULL) { - ntreeCompositForceHidden(scene->nodetree); + ntreeCompositUpdateRLayers(scene->nodetree); } } @@ -2747,7 +2749,7 @@ static void rna_Node_scene_layer_update(Main *bmain, Scene *scene, PointerRNA *p { rna_Node_update(bmain, scene, ptr); if (scene->nodetree != NULL) { - ntreeCompositForceHidden(scene->nodetree); + ntreeCompositUpdateRLayers(scene->nodetree); } } @@ -2995,6 +2997,15 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p ED_node_tag_update_nodetree(bmain, ntree, node); } +static void rna_ShaderNodePrincipled_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + + nodeUpdate(ntree, node); + rna_Node_update(bmain, scene, ptr); +} + static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree *)ptr->id.data; @@ -3254,6 +3265,12 @@ static EnumPropertyItem node_script_mode_items[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem node_principled_distribution_items[] = { + { SHD_GLOSSY_GGX, "GGX", 0, "GGX", "" }, + { SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", "" }, + { 0, NULL, 0, NULL, NULL } +}; + /* -- Common nodes ---------------------------------------------------------- */ static void def_group_input(StructRNA *srna) @@ -4188,6 +4205,17 @@ static void def_glass(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_principled(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, node_principled_distribution_items); + RNA_def_property_ui_text(prop, "Distribution", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_update"); +} + static void def_refraction(StructRNA *srna) { PropertyRNA *prop; @@ -4770,7 +4798,7 @@ static void def_cmp_render_layers(StructRNA *srna) RNA_def_property_struct_type(prop, "Scene"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Scene", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_scene_layer_update"); prop = RNA_def_property(srna, "layer", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "custom1"); @@ -5211,6 +5239,16 @@ static void def_cmp_luma_matte(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_brightcontrast(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); + RNA_def_property_ui_text(prop, "Convert Premul", "Keep output image premultiplied alpha"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_cmp_chroma_matte(StructRNA *srna) { PropertyRNA *prop; @@ -6282,14 +6320,8 @@ static void def_cmp_switch(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -static void def_cmp_switch_view(StructRNA *srna) +static void def_cmp_switch_view(StructRNA *UNUSED(srna)) { - PropertyRNA *prop; - - prop = RNA_def_property(srna, "check", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "custom1", 0); - RNA_def_property_ui_text(prop, "Switch", "Off: first socket, On: second socket"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } static void def_cmp_colorcorrection(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index b3c166a6810..a167ab03ba1 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -432,11 +432,7 @@ static void rna_Object_parent_set(PointerRNA *ptr, PointerRNA value) { Object *ob = (Object *)ptr->data; Object *par = (Object *)value.data; - -#ifdef FREE_WINDOWS - /* NOTE: this dummy check here prevents this method causing weird runtime errors on mingw 4.6.2 */ - if (ob) -#endif + { ED_object_parent(ob, par, ob->partype, ob->parsubstr); } @@ -532,8 +528,9 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value) * thus causing a cycle/infinite-recursion leading to crashes on load [#25298] */ if (BKE_group_object_exists(grp, ob) == 0) { + id_us_min(&ob->dup_group->id); ob->dup_group = grp; - id_lib_extern((ID *)grp); + id_us_plus(&ob->dup_group->id); } else { BKE_report(NULL, RPT_ERROR, @@ -2897,6 +2894,10 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_enum_items(prop, dupli_items); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Dupli Type", "Duplicator type that generated this dupli object"); + + prop = RNA_def_property(srna, "random_id", PROP_INT, PROP_UNSIGNED); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Dupli random id", "Random id for this dupli object"); } static void rna_def_object_base(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index c680abe71a4..9b9f0705bb4 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -321,49 +321,55 @@ static void rna_Object_ray_cast( float origin[3], float direction[3], float distance, int *r_success, float r_location[3], float r_normal[3], int *r_index) { - BVHTreeFromMesh treeData = {NULL}; - + bool success = false; + if (ob->derivedFinal == NULL) { BKE_reportf(reports, RPT_ERROR, "Object '%s' has no mesh data to be used for ray casting", ob->id.name + 2); return; } - /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */ - bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6); + /* Test BoundBox first (efficiency) */ + BoundBox *bb = BKE_object_boundbox_get(ob); + float distmin; + if (!bb || (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && distmin <= distance)) { - /* may fail if the mesh has no faces, in that case the ray-cast misses */ - if (treeData.tree != NULL) { - BVHTreeRayHit hit; + BVHTreeFromMesh treeData = {NULL}; - hit.index = -1; - hit.dist = distance; - - normalize_v3(direction); + /* no need to managing allocation or freeing of the BVH data. this is generated and freed as needed */ + bvhtree_from_mesh_looptri(&treeData, ob->derivedFinal, 0.0f, 4, 6); + + /* may fail if the mesh has no faces, in that case the ray-cast misses */ + if (treeData.tree != NULL) { + BVHTreeRayHit hit; + hit.index = -1; + hit.dist = distance; - if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit, - treeData.raycast_callback, &treeData) != -1) - { - if (hit.dist <= distance) { - *r_success = true; + normalize_v3(direction); - copy_v3_v3(r_location, hit.co); - copy_v3_v3(r_normal, hit.no); - *r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]); - goto finally; + if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit, + treeData.raycast_callback, &treeData) != -1) + { + if (hit.dist <= distance) { + *r_success = success = true; + + copy_v3_v3(r_location, hit.co); + copy_v3_v3(r_normal, hit.no); + *r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]); + } } + + free_bvhtree_from_mesh(&treeData); } } + if (success == false) { + *r_success = false; - *r_success = false; - - zero_v3(r_location); - zero_v3(r_normal); - *r_index = -1; - -finally: - free_bvhtree_from_mesh(&treeData); + zero_v3(r_location); + zero_v3(r_normal); + *r_index = -1; + } } static void rna_Object_closest_point_on_mesh( diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 95dab13571d..00104b8667d 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -446,10 +446,12 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys int totpart; int totchild = 0; int totface; + int totvert; int num = -1; DM_ensure_tessface(modifier->dm_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */ totface = modifier->dm_final->getNumTessFaces(modifier->dm_final); + totvert = modifier->dm_final->getNumVerts(modifier->dm_final); /* 1. check that everything is ok & updated */ if (!particlesystem || !totface) { @@ -484,13 +486,29 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys return num; } } + else if (part->from == PART_FROM_VERT) { + if (num != DMCACHE_NOTFOUND && num < totvert) { + MFace *mface = modifier->dm_final->getTessFaceDataArray(modifier->dm_final, CD_MFACE); + + *r_fuv = &particle->fuv; + + /* This finds the first face to contain the emitting vertex, + * this is not ideal, but is mostly fine as UV seams generally + * map to equal-colored parts of a texture */ + for (int i = 0; i < totface; i++, mface++) { + if (ELEM(num, mface->v1, mface->v2, mface->v3, mface->v4)) { + return i; + } + } + } + } } else { ChildParticle *cpa = particlesystem->child + particle_no - totpart; num = cpa->num; if (part->childtype == PART_CHILD_FACES) { - if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { + if (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME, PART_FROM_VERT)) { if (num != DMCACHE_NOTFOUND && num < totface) { *r_fuv = &cpa->fuv; return num; @@ -510,6 +528,22 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys return num; } } + else if (part->from == PART_FROM_VERT) { + if (num != DMCACHE_NOTFOUND && num < totvert) { + MFace *mface = modifier->dm_final->getTessFaceDataArray(modifier->dm_final, CD_MFACE); + + *r_fuv = &parent->fuv; + + /* This finds the first face to contain the emitting vertex, + * this is not ideal, but is mostly fine as UV seams generally + * map to equal-colored parts of a texture */ + for (int i = 0; i < totface; i++, mface++) { + if (ELEM(num, mface->v1, mface->v2, mface->v3, mface->v4)) { + return i; + } + } + } + } } } @@ -2095,7 +2129,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Even Distribution", "Use even distribution from faces based on face areas or edge lengths"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); - + prop = RNA_def_property(srna, "use_die_on_collision", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_DIE_ON_COL); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); @@ -2300,7 +2334,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_render_adaptive", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_ADAPT); - RNA_def_property_ui_text(prop, "Adaptive render", "Draw steps of the particle path"); + RNA_def_property_ui_text(prop, "Adaptive Render", "Draw steps of the particle path"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); prop = RNA_def_property(srna, "use_velocity_length", PROP_BOOLEAN, PROP_NONE); @@ -2315,7 +2349,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_strand_primitive", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_REN_STRAND); - RNA_def_property_ui_text(prop, "Strand render", "Use the strand primitive for rendering"); + RNA_def_property_ui_text(prop, "Strand Render", "Use the strand primitive for rendering"); RNA_def_property_update(prop, 0, "rna_Particle_redo"); prop = RNA_def_property(srna, "draw_method", PROP_ENUM, PROP_NONE); @@ -2363,7 +2397,8 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Render", "How many steps paths are rendered with (power of 2)"); prop = RNA_def_property(srna, "hair_step", PROP_INT, PROP_NONE); - RNA_def_property_range(prop, 2, 50); + RNA_def_property_range(prop, 2, SHRT_MAX); + RNA_def_property_ui_range(prop, 2, 50, 1, 1); RNA_def_property_ui_text(prop, "Segments", "Number of hair segments"); RNA_def_property_update(prop, 0, "rna_Particle_reset"); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 518c7efd915..44dcb72264a 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -26,6 +26,7 @@ #include <stdlib.h> +#include "DNA_node_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -41,6 +42,7 @@ #include "RE_pipeline.h" +/* Deprecated, only provided for API compatibility. */ EnumPropertyItem rna_enum_render_pass_type_items[] = { {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, {SCE_PASS_Z, "Z", 0, "Z", ""}, @@ -77,18 +79,6 @@ EnumPropertyItem rna_enum_render_pass_type_items[] = { {0, NULL, 0, NULL, NULL} }; -EnumPropertyItem rna_enum_render_pass_debug_type_items[] = { - {RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES, "BVH_TRAVERSED_NODES", 0, "BVH Traversed Nodes", - "Number of nodes traversed in BVH for the camera rays"}, - {RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances", - "Number of BVH instances traversed by camera rays"}, - {RENDER_PASS_DEBUG_BVH_INTERSECTIONS, "BVH_INTERSECTIONS", 0, "BVH Intersections", - "Number of primitive intersections performed by the camera rays"}, - {RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps", - "Number of bounces done by the main integration loop"}, - {0, NULL, 0, NULL, NULL} -}; - EnumPropertyItem rna_enum_bake_pass_type_items[] = { {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, {SCE_PASS_AO, "AO", 0, "AO", ""}, @@ -261,6 +251,24 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt RNA_parameter_list_free(&list); } +static void engine_update_render_passes(RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl) +{ + extern FunctionRNA rna_RenderEngine_update_render_passes_func; + PointerRNA ptr; + ParameterList list; + FunctionRNA *func; + + RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr); + func = &rna_RenderEngine_update_render_passes_func; + + RNA_parameter_list_create(&list, &ptr, func); + RNA_parameter_set_lookup(&list, "scene", &scene); + RNA_parameter_set_lookup(&list, "renderlayer", &srl); + engine->type->ext.call(NULL, &ptr, func, &list); + + RNA_parameter_list_free(&list); +} + /* RenderEngine registration */ static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type) @@ -281,7 +289,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo RenderEngineType *et, dummyet = {NULL}; RenderEngine dummyengine = {NULL}; PointerRNA dummyptr; - int have_function[6]; + int have_function[7]; /* setup dummy engine & engine type to store static properties in */ dummyengine.type = &dummyet; @@ -323,6 +331,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo et->view_update = (have_function[3]) ? engine_view_update : NULL; et->view_draw = (have_function[4]) ? engine_view_draw : NULL; et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL; + et->update_render_passes = (have_function[6]) ? engine_update_render_passes : NULL; BLI_addtail(&R_engines, et); @@ -419,6 +428,11 @@ static RenderPass *rna_RenderPass_find_by_type(RenderLayer *rl, int passtype, co return RE_pass_find_by_type(rl, passtype, view); } +static RenderPass *rna_RenderPass_find_by_name(RenderLayer *rl, const char *name, const char *view) +{ + return RE_pass_find_by_name(rl, name, view); +} + #else /* RNA_RUNTIME */ static void rna_def_render_engine(BlenderRNA *brna) @@ -429,6 +443,13 @@ static void rna_def_render_engine(BlenderRNA *brna) FunctionRNA *func; PropertyRNA *parm; + static EnumPropertyItem render_pass_type_items[] = { + {SOCK_FLOAT, "VALUE", 0, "Value", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_RGBA, "COLOR", 0, "Color", ""}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "RenderEngine", NULL); RNA_def_struct_sdna(srna, "RenderEngine"); RNA_def_struct_ui_text(srna, "Render Engine", "Render engine"); @@ -497,6 +518,12 @@ static void rna_def_render_engine(BlenderRNA *brna) func = RNA_def_function(srna, "tag_update", "engine_tag_update"); RNA_def_function_ui_description(func, "Request update call for viewport rendering"); + func = RNA_def_function(srna, "update_render_passes", NULL); + RNA_def_function_ui_description(func, "Update the render passes that will be generated"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE); + parm = RNA_def_pointer(func, "scene", "Scene", "", ""); + parm = RNA_def_pointer(func, "renderlayer", "SceneRenderLayer", "", ""); + func = RNA_def_function(srna, "begin_result", "RE_engine_begin_result"); RNA_def_function_ui_description(func, "Create render result to write linear floating point render layers and passes"); parm = RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX); @@ -522,8 +549,20 @@ static void rna_def_render_engine(BlenderRNA *brna) parm = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't mark tile as done, don't merge results unless forced"); + RNA_def_boolean(func, "highlight", 0, "Highlight", "Don't mark tile as done yet"); RNA_def_boolean(func, "do_merge_results", 0, "Merge Results", "Merge results even if cancel=true"); + func = RNA_def_function(srna, "add_pass", "RE_engine_add_pass"); + RNA_def_function_ui_description(func, "Add a pass to the render layer"); + parm = RNA_def_string(func, "name", NULL, 0, "Name", "Name of the Pass, without view or channel tag"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_int(func, "channels", 0, 0, INT_MAX, "Channels", "", 0, INT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_string(func, "chan_id", NULL, 0, "Channel IDs", "Channel names, one character per channel"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + RNA_def_string(func, "layer", NULL, 0, "Layer", "Single layer to add render pass to"); /* NULL ok here */ + + func = RNA_def_function(srna, "test_break", "RE_engine_test_break"); RNA_def_function_ui_description(func, "Test if the render operation should been canceled, this is a fast call that should be used regularly for responsiveness"); parm = RNA_def_boolean(func, "do_break", 0, "Break", ""); @@ -646,6 +685,21 @@ static void rna_def_render_engine(BlenderRNA *brna) prop = RNA_def_property(srna, "use_highlight_tiles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_HIGHLIGHT_TILES); + func = RNA_def_function(srna, "register_pass", "RE_engine_register_pass"); + RNA_def_function_ui_description(func, "Register a render pass that will be part of the render with the current settings"); + prop = RNA_def_pointer(func, "scene", "Scene", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_pointer(func, "srl", "SceneRenderLayer", "", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_int(func, "channels", 1, 1, 8, "Channels", "", 1, 4); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_string(func, "chanid", NULL, 8, "Channel IDs", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + prop = RNA_def_enum(func, "type", render_pass_type_items, SOCK_FLOAT, "Type", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + /* registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); @@ -774,6 +828,15 @@ static void rna_def_render_passes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass"); RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "find_by_name", "rna_RenderPass_find_by_name"); + RNA_def_function_ui_description(func, "Get the render pass for a given name and view"); + parm = RNA_def_string(func, "name", RE_PASSNAME_COMBINED, 0, "Pass", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_string(func, "view", NULL, 0, "View", "Render view to get pass from"); /* NULL ok here */ + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "render_pass", "RenderPass", "", "The matching render pass"); + RNA_def_function_return(func, parm); } static void rna_def_render_layer(BlenderRNA *brna) @@ -822,6 +885,11 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_define_verify_sdna(0); + prop = RNA_def_property(srna, "fullname", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "fullname"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_struct_name_property(srna, prop); + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -835,11 +903,6 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "channels"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "passtype"); - RNA_def_property_enum_items(prop, rna_enum_render_pass_type_items); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - prop = RNA_def_property(srna, "rect", PROP_FLOAT, PROP_NONE); RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_multi_array(prop, 2, NULL); @@ -850,11 +913,6 @@ static void rna_def_render_pass(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "view_id"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - prop = RNA_def_property(srna, "debug_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "debug_type"); - RNA_def_property_enum_items(prop, rna_enum_render_pass_debug_type_items); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_define_verify_sdna(1); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 899466f05df..b9231574a24 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -88,7 +88,8 @@ EnumPropertyItem rna_enum_exr_codec_items[] = { {R_IMF_EXR_CODEC_B44, "B44", 0, "B44 (lossy)", ""}, {R_IMF_EXR_CODEC_B44A, "B44A", 0, "B44A (lossy)", ""}, {R_IMF_EXR_CODEC_DWAA, "DWAA", 0, "DWAA (lossy)", ""}, - {R_IMF_EXR_CODEC_DWAB, "DWAB", 0, "DWAB (lossy)", ""}, + /* NOTE: Commented out for until new OpenEXR is released, see T50673. */ + /* {R_IMF_EXR_CODEC_DWAB, "DWAB", 0, "DWAB (lossy)", ""}, */ {0, NULL, 0, NULL, NULL} }; #endif @@ -448,6 +449,7 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = { #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_main.h" #include "BKE_node.h" @@ -1608,6 +1610,18 @@ static void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain), Scene *UNUS #endif } +static IDProperty *rna_SceneRenderLayer_idprops(PointerRNA *ptr, bool create) +{ + SceneRenderLayer *srl = (SceneRenderLayer *)ptr->data; + + if (create && !srl->prop) { + IDPropertyTemplate val = {0}; + srl->prop = IDP_New(IDP_GROUP, &val, "SceneRenderLayer ID properties"); + } + + return srl->prop; +} + static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) { Scene *scene = (Scene *)ptr->id.data; @@ -1712,11 +1726,18 @@ static void rna_SceneRenderLayer_pass_update(Main *bmain, Scene *activescene, Po Scene *scene = (Scene *)ptr->id.data; if (scene->nodetree) - ntreeCompositForceHidden(scene->nodetree); - + ntreeCompositUpdateRLayers(scene->nodetree); + rna_Scene_glsl_update(bmain, activescene, ptr); } +static void rna_SceneRenderLayer_update_render_passes(ID *id) +{ + Scene *scene = (Scene *)id; + if (scene->nodetree) + ntreeCompositUpdateRLayers(scene->nodetree); +} + static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr) { Scene *scene = (Scene *)ptr->data; @@ -1795,7 +1816,7 @@ static void object_simplify_update(Object *ob) } } -static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Scene_use_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Scene *sce = ptr->id.data; Scene *sce_iter; @@ -1806,6 +1827,7 @@ static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), Poi object_simplify_update(base->object); WM_main_add_notifier(NC_GEOM | ND_DATA, NULL); + DAG_id_tag_update(&scene->id, 0); } static void rna_Scene_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -5072,14 +5094,20 @@ static void rna_def_scene_render_layer(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; srna = RNA_def_struct(brna, "SceneRenderLayer", NULL); RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer"); RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS); RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path"); + RNA_def_struct_idprops_func(srna, "rna_SceneRenderLayer_idprops"); rna_def_render_layer_common(srna, 1); + func = RNA_def_function(srna, "update_render_passes", "rna_SceneRenderLayer_update_render_passes"); + RNA_def_function_ui_description(func, "Requery the enabled render passes from the render engine"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_NO_SELF); + /* Freestyle */ rna_def_freestyle_settings(brna); @@ -6742,14 +6770,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_struct_type(prop, "BakeSettings"); RNA_def_property_ui_text(prop, "Bake Data", ""); - /* Debugging settings. */ -#ifdef WITH_CYCLES_DEBUG - prop = RNA_def_property(srna, "debug_pass_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, rna_enum_render_pass_debug_type_items); - RNA_def_property_ui_text(prop, "Debug Pass Type", "Type of the debug pass to use"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); -#endif - /* Nestled Data */ /* *** Non-Animated *** */ RNA_define_animate_sdna(false); @@ -6968,7 +6988,7 @@ static void rna_def_display_safe_areas(BlenderRNA *brna) RNA_def_property_array(prop, 2); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_float_array_default(prop, default_title); - RNA_def_property_ui_text(prop, "Title Safe margins", "Safe area for text and graphics"); + RNA_def_property_ui_text(prop, "Title Safe Margins", "Safe area for text and graphics"); RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL); prop = RNA_def_property(srna, "action", PROP_FLOAT, PROP_XYZ); @@ -6979,7 +6999,6 @@ static void rna_def_display_safe_areas(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Action Safe Margins", "Safe area for general elements"); RNA_def_property_update(prop, NC_SCENE | ND_DRAW_RENDER_VIEWPORT, NULL); - prop = RNA_def_property(srna, "title_center", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "title_center"); RNA_def_property_array(prop, 2); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 9b202120b82..ea7327cfa31 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -164,7 +164,6 @@ static void rna_Scene_ray_cast( bool ret = ED_transform_snap_object_project_ray_ex( sctx, - SCE_SNAP_MODE_FACE, &(const struct SnapObjectParams){ .snap_select = SNAP_ALL, }, @@ -208,6 +207,8 @@ static void rna_Scene_alembic_export( int renderable_only, int face_sets, int use_subdiv_schema, + int export_hair, + int export_particles, int compression_type, int packuv, float scale, @@ -225,8 +226,8 @@ static void rna_Scene_alembic_export( .frame_start = frame_start, .frame_end = frame_end, - .frame_step_xform = 1.0 / (double)xform_samples, - .frame_step_shape = 1.0 / (double)geom_samples, + .frame_samples_xform = xform_samples, + .frame_samples_shape = geom_samples, .shutter_open = shutter_open, .shutter_close = shutter_close, @@ -241,6 +242,8 @@ static void rna_Scene_alembic_export( .renderable_only = renderable_only, .face_sets = face_sets, .use_subdiv_schema = use_subdiv_schema, + .export_hair = export_hair, + .export_particles = export_particles, .compression_type = compression_type, .packuv = packuv, .triangulate = triangulate, @@ -250,7 +253,7 @@ static void rna_Scene_alembic_export( .global_scale = scale, }; - ABC_export(scene, C, filepath, ¶ms); + ABC_export(scene, C, filepath, ¶ms, true); #ifdef WITH_PYTHON BPy_END_ALLOW_THREADS; @@ -276,8 +279,7 @@ static void rna_Scene_collada_export( int include_shapekeys, int deform_bones_only, int active_uv_only, - int include_uv_textures, - int include_material_textures, + int export_texture_type, int use_texture_copies, int triangulate, int use_object_instantiation, @@ -301,8 +303,7 @@ static void rna_Scene_collada_export( deform_bones_only, active_uv_only, - include_uv_textures, - include_material_textures, + export_texture_type, use_texture_copies, triangulate, @@ -399,11 +400,8 @@ void RNA_api_scene(StructRNA *srna) RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map"); - RNA_def_boolean(func, "include_uv_textures", false, - "Include UV Textures", "Export textures assigned to the object UV Maps"); - - RNA_def_boolean(func, "include_material_textures", false, - "Include Material Textures", "Export textures assigned to the object Materials"); + RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX, + "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX); RNA_def_boolean(func, "use_texture_copies", true, "Copy", "Copy textures to same folder where the .dae file is exported"); @@ -435,8 +433,9 @@ void RNA_api_scene(StructRNA *srna) #endif #ifdef WITH_ALEMBIC + /* XXX Deprecated, will be removed in 2.8 in favour of calling the export operator. */ func = RNA_def_function(srna, "alembic_export", "rna_Scene_alembic_export"); - RNA_def_function_ui_description(func, "Export to Alembic file"); + RNA_def_function_ui_description(func, "Export to Alembic file (deprecated, use the Alembic export operator)"); parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Alembic file"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); @@ -458,6 +457,8 @@ void RNA_api_scene(StructRNA *srna) RNA_def_boolean(func, "renderable_only" , 0, "Renderable objects only", "Export only objects marked renderable in the outliner"); RNA_def_boolean(func, "face_sets" , 0, "Facesets", "Export face sets"); RNA_def_boolean(func, "subdiv_schema", 0, "Use Alembic subdivision Schema", "Use Alembic subdivision Schema"); + RNA_def_boolean(func, "export_hair", 1, "Export Hair", "Exports hair particle systems as animated curves"); + RNA_def_boolean(func, "export_particles", 1, "Export Particles", "Exports non-hair particle systems"); RNA_def_enum(func, "compression_type", rna_enum_abc_compression_items, 0, "Compression", ""); RNA_def_boolean(func, "packuv" , 0, "Export with packed UV islands", "Export with packed UV islands"); RNA_def_float(func, "scale", 1.0f, 0.0001f, 1000.0f, "Scale", "Value by which to enlarge or shrink the objects with respect to the world's origin", 0.0001f, 1000.0f); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 3e6d8441363..f628c5f14d9 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -341,7 +341,7 @@ static void rna_Sequence_use_translation_set(PointerRNA *ptr, int value) } } else { - seq->flag ^= SEQ_USE_TRANSFORM; + seq->flag &= ~SEQ_USE_TRANSFORM; } } @@ -355,7 +355,7 @@ static void rna_Sequence_use_crop_set(PointerRNA *ptr, int value) } } else { - seq->flag ^= SEQ_USE_CROP; + seq->flag &= ~SEQ_USE_CROP; } } @@ -1095,7 +1095,7 @@ static void rna_def_strip_element(BlenderRNA *brna) prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME); RNA_def_property_string_sdna(prop, NULL, "name"); - RNA_def_property_ui_text(prop, "Filename", ""); + RNA_def_property_ui_text(prop, "Filename", "Name of the source file"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceElement_update"); prop = RNA_def_property(srna, "orig_width", PROP_INT, PROP_NONE); @@ -1120,25 +1120,25 @@ static void rna_def_strip_crop(BlenderRNA *brna) prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "top"); - RNA_def_property_ui_text(prop, "Top", ""); + RNA_def_property_ui_text(prop, "Top", "Number of pixels to crop from the top"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "bottom"); - RNA_def_property_ui_text(prop, "Bottom", ""); + RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the bottom"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "left"); - RNA_def_property_ui_text(prop, "Left", ""); + RNA_def_property_ui_text(prop, "Left", "Number of pixels to crop from the left side"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "right"); - RNA_def_property_ui_text(prop, "Right", ""); + RNA_def_property_ui_text(prop, "Right", "Number of pixels to crop from the right side"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); @@ -1156,13 +1156,13 @@ static void rna_def_strip_transform(BlenderRNA *brna) prop = RNA_def_property(srna, "offset_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "xofs"); - RNA_def_property_ui_text(prop, "Offset X", ""); + RNA_def_property_ui_text(prop, "Offset X", "Amount to move the input on the X axis within its boundaries"); RNA_def_property_ui_range(prop, -4096, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update"); prop = RNA_def_property(srna, "offset_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "yofs"); - RNA_def_property_ui_text(prop, "Offset Y", ""); + RNA_def_property_ui_text(prop, "Offset Y", "Amount to move the input on the Y axis within its boundaries"); RNA_def_property_ui_range(prop, -4096, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update"); @@ -1246,7 +1246,7 @@ static void rna_def_strip_proxy(BlenderRNA *brna) prop = RNA_def_property(srna, "timecode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "tc"); RNA_def_property_enum_items(prop, seq_tc_items); - RNA_def_property_ui_text(prop, "Timecode", ""); + RNA_def_property_ui_text(prop, "Timecode", "Method for reading the inputs timecode"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_tcindex_update"); prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE); @@ -1289,17 +1289,17 @@ static void rna_def_color_balance(BlenderRNA *brna) prop = RNA_def_property(srna, "invert_gain", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAIN); - RNA_def_property_ui_text(prop, "Inverse Gain", ""); + RNA_def_property_ui_text(prop, "Inverse Gain", "Invert the gain color`"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update"); prop = RNA_def_property(srna, "invert_gamma", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAMMA); - RNA_def_property_ui_text(prop, "Inverse Gamma", ""); + RNA_def_property_ui_text(prop, "Inverse Gamma", "Invert the gamma color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update"); prop = RNA_def_property(srna, "invert_lift", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_LIFT); - RNA_def_property_ui_text(prop, "Inverse Lift", ""); + RNA_def_property_ui_text(prop, "Inverse Lift", "Invert the lift color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update"); /* not yet used */ @@ -1453,13 +1453,13 @@ static void rna_def_sequence(BlenderRNA *brna) prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MUTE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, true); - RNA_def_property_ui_text(prop, "Mute", ""); + RNA_def_property_ui_text(prop, "Mute", "Disable strip so that it cannot be viewed in the output"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_mute_update"); prop = RNA_def_property(srna, "lock", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_LOCK); RNA_def_property_ui_icon(prop, ICON_UNLOCKED, true); - RNA_def_property_ui_text(prop, "Lock", "Lock strip so that it can't be transformed"); + RNA_def_property_ui_text(prop, "Lock", "Lock strip so that it cannot be transformed"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); /* strip positioning */ @@ -1481,7 +1481,7 @@ static void rna_def_sequence(BlenderRNA *brna) prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "start"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Start Frame", ""); + RNA_def_property_ui_text(prop, "Start Frame", "X position where the strip begins"); RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_start_frame_set", NULL); /* overlap tests and calc_seq_disp */ RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -1552,12 +1552,12 @@ static void rna_def_sequence(BlenderRNA *brna) prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "blend_mode"); RNA_def_property_enum_items(prop, blend_mode_items); - RNA_def_property_ui_text(prop, "Blend Mode", ""); + RNA_def_property_ui_text(prop, "Blend Mode", "Method for controlling how the strip combines with other strips"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "blend_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Blend Opacity", ""); + RNA_def_property_ui_text(prop, "Blend Opacity", "Percentage of how much the strip's colors affect other strips"); /* stupid 0-100 -> 0-1 */ RNA_def_property_float_funcs(prop, "rna_Sequence_opacity_get", "rna_Sequence_opacity_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -1566,7 +1566,7 @@ static void rna_def_sequence(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3); RNA_def_property_float_sdna(prop, NULL, "effect_fader"); - RNA_def_property_ui_text(prop, "Effect fader position", ""); + RNA_def_property_ui_text(prop, "Effect fader position", "Custom fade value"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "use_default_fade", PROP_BOOLEAN, PROP_NONE); @@ -1714,7 +1714,7 @@ static void rna_def_filter_video(StructRNA *srna) RNA_def_property_range(prop, 0.0f, 20.0f); RNA_def_property_ui_range(prop, 0.0f, 2.0f, 3, 3); RNA_def_property_float_default(prop, 1.0f); - RNA_def_property_ui_text(prop, "Saturation", ""); + RNA_def_property_ui_text(prop, "Saturation", "Adjust the intensity of the input's color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "strobe", PROP_FLOAT, PROP_NONE); @@ -2205,13 +2205,13 @@ static void rna_def_transform(StructRNA *srna) prop = RNA_def_property(srna, "scale_start_x", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "ScalexIni"); - RNA_def_property_ui_text(prop, "Scale X", ""); + RNA_def_property_ui_text(prop, "Scale X", "Amount to scale the input in the X axis"); RNA_def_property_ui_range(prop, 0, 10, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "scale_start_y", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "ScaleyIni"); - RNA_def_property_ui_text(prop, "Scale Y", ""); + RNA_def_property_ui_text(prop, "Scale Y", "Amount to scale the input in the Y axis"); RNA_def_property_ui_range(prop, 0, 10, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -2222,33 +2222,33 @@ static void rna_def_transform(StructRNA *srna) prop = RNA_def_property(srna, "translate_start_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "xIni"); - RNA_def_property_ui_text(prop, "Translate X", ""); + RNA_def_property_ui_text(prop, "Translate X", "Amount to move the input on the X axis"); RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "translate_start_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "yIni"); - RNA_def_property_ui_text(prop, "Translate Y", ""); + RNA_def_property_ui_text(prop, "Translate Y", "Amount to move the input on the Y axis"); RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rotIni"); RNA_def_property_range(prop, -360.0f, 360.0f); - RNA_def_property_ui_text(prop, "Rotation", ""); + RNA_def_property_ui_text(prop, "Rotation", "Degrees to rotate the input"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "translation_unit", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "percent"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */ RNA_def_property_enum_items(prop, translation_unit_items); - RNA_def_property_ui_text(prop, "Translation Unit", ""); + RNA_def_property_ui_text(prop, "Translation Unit", "Unit of measure to translate the input"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, interpolation_items); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */ - RNA_def_property_ui_text(prop, "Interpolation", ""); + RNA_def_property_ui_text(prop, "Interpolation", "Method to determine how missing pixels are created"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); } @@ -2260,7 +2260,7 @@ static void rna_def_solid_color(StructRNA *srna) prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "col"); - RNA_def_property_ui_text(prop, "Color", ""); + RNA_def_property_ui_text(prop, "Color", "Effect Strip color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); } @@ -2333,7 +2333,7 @@ static void rna_def_text(StructRNA *srna) prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "color"); - RNA_def_property_ui_text(prop, "Color", ""); + RNA_def_property_ui_text(prop, "Color", "Text color"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA); @@ -2358,13 +2358,13 @@ static void rna_def_text(StructRNA *srna) prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align"); RNA_def_property_enum_items(prop, text_align_x_items); - RNA_def_property_ui_text(prop, "Align X", ""); + RNA_def_property_ui_text(prop, "Align X", "Align the text along the X axis"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align_y"); RNA_def_property_enum_items(prop, text_align_y_items); - RNA_def_property_ui_text(prop, "Align Y", ""); + RNA_def_property_ui_text(prop, "Align Y", "Align the image along the Y axis"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE); @@ -2512,7 +2512,7 @@ static void rna_def_colorbalance_modifier(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "color_multiply"); RNA_def_property_range(prop, 0.0f, 20.0f); RNA_def_property_float_default(prop, 1.0f); - RNA_def_property_ui_text(prop, "Multiply Colors", ""); + RNA_def_property_ui_text(prop, "Multiply Colors", "Multiply the intensity of each pixel"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update"); } @@ -2576,13 +2576,13 @@ static void rna_def_brightcontrast_modifier(BlenderRNA *brna) prop = RNA_def_property(srna, "bright", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "bright"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); - RNA_def_property_ui_text(prop, "Bright", ""); + RNA_def_property_ui_text(prop, "Bright", "Adjust the luminosity of the colors"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update"); prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "contrast"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); - RNA_def_property_ui_text(prop, "Contrast", ""); + RNA_def_property_ui_text(prop, "Contrast", "Adjust the difference in luminosity between pixels"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update"); } @@ -2599,13 +2599,12 @@ static void rna_def_tonemap_modifier(BlenderRNA *brna) srna = RNA_def_struct(brna, "SequencerTonemapModifierData", "SequenceModifier"); RNA_def_struct_sdna(srna, "SequencerTonemapModifierData"); - RNA_def_struct_ui_text(srna, "SequencerTonemapModifierData", - "Tone mapping modifier"); + RNA_def_struct_ui_text(srna, "SequencerTonemapModifierData", "Tone mapping modifier"); prop = RNA_def_property(srna, "tonemap_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, type_items); - RNA_def_property_ui_text(prop, "Tonemap Type", ""); + RNA_def_property_ui_text(prop, "Tonemap Type", "Tone mapping algorithm"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update"); prop = RNA_def_property(srna, "key", PROP_FLOAT, PROP_FACTOR); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 5e364a3adf1..f2e856bf1ba 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -71,10 +71,10 @@ EnumPropertyItem rna_enum_space_type_items[] = { {SPACE_NLA, "NLA_EDITOR", ICON_NLA, "NLA Editor", "Combine and layer Actions"}, {0, "", ICON_NONE, NULL, NULL}, {SPACE_IMAGE, "IMAGE_EDITOR", ICON_IMAGE_COL, "UV/Image Editor", "View and edit images and UV Maps"}, - {SPACE_SEQ, "SEQUENCE_EDITOR", ICON_SEQUENCE, "Video Sequence Editor", "Video editing tools"}, {SPACE_CLIP, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", "Motion tracking tools"}, - {SPACE_TEXT, "TEXT_EDITOR", ICON_TEXT, "Text Editor", "Edit scripts and in-file documentation"}, + {SPACE_SEQ, "SEQUENCE_EDITOR", ICON_SEQUENCE, "Video Sequence Editor", "Video editing tools"}, {SPACE_NODE, "NODE_EDITOR", ICON_NODETREE, "Node Editor", "Editor for node-based shading and compositing tools"}, + {SPACE_TEXT, "TEXT_EDITOR", ICON_TEXT, "Text Editor", "Edit scripts and in-file documentation"}, {SPACE_LOGIC, "LOGIC_EDITOR", ICON_LOGIC, "Logic Editor", "Game logic editing"}, {0, "", ICON_NONE, NULL, NULL}, {SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related data-blocks"}, @@ -492,7 +492,7 @@ static void rna_View3D_CursorLocation_get(PointerRNA *ptr, float *values) bScreen *sc = (bScreen *)ptr->id.data; Scene *scene = (Scene *)sc->scene; const float *loc = ED_view3d_cursor3d_get(scene, v3d); - + copy_v3_v3(values, loc); } @@ -502,7 +502,7 @@ static void rna_View3D_CursorLocation_set(PointerRNA *ptr, const float *values) bScreen *sc = (bScreen *)ptr->id.data; Scene *scene = (Scene *)sc->scene; float *cursor = ED_view3d_cursor3d_get(scene, v3d); - + copy_v3_v3(cursor, values); } @@ -518,7 +518,7 @@ static float rna_View3D_GridScaleUnit_get(PointerRNA *ptr) static void rna_SpaceView3D_layer_set(PointerRNA *ptr, const int *values) { View3D *v3d = (View3D *)(ptr->data); - + v3d->lay = ED_view3d_scene_layer_set(v3d->lay, values, &v3d->layact); } @@ -545,16 +545,16 @@ static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *scene, Poi static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { View3D *v3d = (View3D *)(ptr->data); - + if (v3d->defmaterial) { Material *ma = v3d->defmaterial; - + if (ma->preview) BKE_previewimg_free(&ma->preview); - + if (ma->gpumaterial.first) GPU_material_free(&ma->gpumaterial); - + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma); } } @@ -562,7 +562,7 @@ static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(sce static void rna_SpaceView3D_matcap_enable(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { View3D *v3d = (View3D *)(ptr->data); - + if (v3d->matcap_icon < ICON_MATCAP_01 || v3d->matcap_icon > ICON_MATCAP_24) { @@ -719,7 +719,7 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C { Scene *scene = ((bScreen *)ptr->id.data)->scene; RenderEngineType *type = RE_engines_find(scene->r.engine); - + EnumPropertyItem *item = NULL; int totitem = 0; @@ -728,7 +728,7 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_SOLID); RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_TEXTURE); RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_MATERIAL); - + if (type && type->view_draw) RNA_enum_items_add_value(&item, &totitem, rna_enum_viewport_shade_items, OB_RENDER); @@ -844,7 +844,7 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *UNUS int zbuf, alpha, totitem = 0; ibuf = ED_space_image_acquire_buffer(sima, &lock); - + alpha = ibuf && (ibuf->channels == 4); zbuf = ibuf && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1)); @@ -895,14 +895,14 @@ static void rna_SpaceImageEditor_zoom_get(PointerRNA *ptr, float *values) static void rna_SpaceImageEditor_cursor_location_get(PointerRNA *ptr, float *values) { SpaceImage *sima = (SpaceImage *)ptr->data; - + if (sima->flag & SI_COORDFLOATS) { copy_v2_v2(values, sima->cursor); } else { int w, h; ED_space_image_get_size(sima, &w, &h); - + values[0] = sima->cursor[0] * w; values[1] = sima->cursor[1] * h; } @@ -911,14 +911,14 @@ static void rna_SpaceImageEditor_cursor_location_get(PointerRNA *ptr, float *val static void rna_SpaceImageEditor_cursor_location_set(PointerRNA *ptr, const float *values) { SpaceImage *sima = (SpaceImage *)ptr->data; - + if (sima->flag & SI_COORDFLOATS) { copy_v2_v2(sima->cursor, values); } else { int w, h; ED_space_image_get_size(sima, &w, &h); - + sima->cursor[0] = values[0] / w; sima->cursor[1] = values[1] / h; } @@ -947,7 +947,7 @@ static void rna_SpaceImageEditor_scopes_update(struct bContext *C, struct Pointe SpaceImage *sima = (SpaceImage *)ptr->data; ImBuf *ibuf; void *lock; - + ibuf = ED_space_image_acquire_buffer(sima, &lock); if (ibuf) { ED_space_image_scopes_update(C, sima, ibuf, true); @@ -1026,12 +1026,12 @@ static void rna_SpaceProperties_pin_id_update(Main *UNUSED(bmain), Scene *UNUSED { SpaceButs *sbuts = (SpaceButs *)(ptr->data); ID *id = sbuts->pinid; - + if (id == NULL) { sbuts->flag &= ~SB_PIN_CONTEXT; return; } - + switch (GS(id->name)) { case ID_MA: WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL); @@ -1052,7 +1052,7 @@ static void rna_SpaceProperties_pin_id_update(Main *UNUSED(bmain), Scene *UNUSED static void rna_SpaceProperties_context_set(PointerRNA *ptr, int value) { SpaceButs *sbuts = (SpaceButs *)(ptr->data); - + sbuts->mainb = value; sbuts->mainbuser = value; } @@ -1130,7 +1130,8 @@ static EnumPropertyItem *rna_SpaceProperties_context_itemf(bContext *UNUSED(C), static void rna_SpaceProperties_context_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { SpaceButs *sbuts = (SpaceButs *)(ptr->data); - if (ELEM(sbuts->mainb, BCONTEXT_WORLD, BCONTEXT_MATERIAL, BCONTEXT_TEXTURE)) { + /* XXX BCONTEXT_DATA is ugly, but required for lamps... See T51318. */ + if (ELEM(sbuts->mainb, BCONTEXT_WORLD, BCONTEXT_MATERIAL, BCONTEXT_TEXTURE, BCONTEXT_DATA)) { sbuts->preview = 1; } } @@ -1203,7 +1204,7 @@ static void rna_ConsoleLine_body_set(PointerRNA *ptr, const char *value) { ConsoleLine *ci = (ConsoleLine *)ptr->data; int len = strlen(value); - + if ((len >= ci->len_alloc) || (len * 2 < ci->len_alloc) ) { /* allocate a new string */ MEM_freeN(ci->line); ci->line = MEM_mallocN((len + 1) * sizeof(char), "rna_consoleline"); @@ -1231,7 +1232,7 @@ static void rna_SpaceDopeSheetEditor_action_set(PointerRNA *ptr, PointerRNA valu { SpaceAction *saction = (SpaceAction *)(ptr->data); bAction *act = (bAction *)value.data; - + if ((act == NULL) || (act->idroot == 0)) { /* just set if we're clearing the action or if the action is "amorphous" still */ saction->action = act; @@ -1268,7 +1269,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po /* we must set this action to be the one used by active object (if not pinned) */ if (obact /* && saction->pin == 0*/) { AnimData *adt = NULL; - + if (saction->mode == SACTCONT_ACTION) { /* TODO: context selector could help decide this with more control? */ adt = BKE_animdata_add_id(&obact->id); /* this only adds if non-existent */ @@ -1278,7 +1279,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po if (key) adt = BKE_animdata_add_id(&key->id); /* this only adds if non-existent */ } - + /* set action */ // FIXME: this overlaps a lot with the BKE_animdata_set_action() API method if (adt) { @@ -1286,11 +1287,11 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po if (adt->action != saction->action) { /* NLA Tweak Mode needs special handling... */ if (adt->flag & ADT_NLA_EDIT_ON) { - /* Exit editmode first - we cannot change actions while in tweakmode + /* Exit editmode first - we cannot change actions while in tweakmode * NOTE: This will clear the action ref properly */ BKE_nla_tweakmode_exit(adt); - + /* Assign new action, and adjust the usercounts accordingly */ adt->action = saction->action; id_us_plus((ID *)adt->action); @@ -1300,7 +1301,7 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po if (adt->action) { /* Fix id-count of action we're replacing */ id_us_min(&adt->action->id); - + /* To prevent data loss (i.e. if users flip between actions using the Browse menu), * stash this action if nothing else uses it. * @@ -1317,17 +1318,17 @@ static void rna_SpaceDopeSheetEditor_action_update(Main *bmain, Scene *scene, Po BKE_nla_action_stash(adt); } } - + /* Assign new action, and adjust the usercounts accordingly */ adt->action = saction->action; id_us_plus((ID *)adt->action); } } - + /* Force update of animdata */ adt->recalc |= ADT_RECALC_ANIM; } - + /* force depsgraph flush too */ DAG_id_tag_update(&obact->id, OB_RECALC_OB | OB_RECALC_DATA); /* Update relations as well, so new time source dependency is added. */ @@ -1339,17 +1340,17 @@ static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *sce { SpaceAction *saction = (SpaceAction *)(ptr->data); Object *obact = (scene->basact) ? scene->basact->object : NULL; - + /* special exceptions for ShapeKey Editor mode */ if (saction->mode == SACTCONT_SHAPEKEY) { Key *key = BKE_key_from_object(obact); - + /* 1) update the action stored for the editor */ if (key) saction->action = (key->adt) ? key->adt->action : NULL; else saction->action = NULL; - + /* 2) enable 'show sliders' by default, since one of the main * points of the ShapeKey Editor is to provide a one-stop shop * for controlling the shapekeys, whose main control is the value @@ -1365,7 +1366,7 @@ static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *sce else saction->action = NULL; } - + /* recalculate extents of channel list */ saction->flag |= SACTION_TEMP_NEEDCHANSYNC; } @@ -1375,7 +1376,7 @@ static void rna_SpaceDopeSheetEditor_mode_update(Main *UNUSED(bmain), Scene *sce static void rna_SpaceGraphEditor_display_mode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { ScrArea *sa = rna_area_from_space(ptr); - + /* after changing view mode, must force recalculation of F-Curve colors * which can only be achieved using refresh as opposed to redraw */ @@ -1465,7 +1466,7 @@ static int rna_SpaceNodeEditor_node_tree_poll(PointerRNA *ptr, const PointerRNA { SpaceNode *snode = (SpaceNode *)ptr->data; bNodeTree *ntree = (bNodeTree *)value.data; - + /* node tree type must match the selected type in node editor */ return (STREQ(snode->tree_idname, ntree->idname)); } @@ -1544,7 +1545,7 @@ static void rna_SpaceNodeEditor_show_backdrop_update(Main *UNUSED(bmain), Scene static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode, bContext *C, int x, int y) { ARegion *ar = CTX_wm_region(C); - + UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]); snode->cursor[0] /= UI_DPI_FAC; snode->cursor[1] /= UI_DPI_FAC; @@ -1896,12 +1897,12 @@ static void rna_def_space(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "Space", NULL); RNA_def_struct_sdna(srna, "SpaceLink"); RNA_def_struct_ui_text(srna, "Space", "Space data for a screen area"); RNA_def_struct_refine_func(srna, "rna_Space_refine"); - + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "spacetype"); RNA_def_property_enum_items(prop, rna_enum_space_type_items); @@ -2102,28 +2103,28 @@ static void rna_def_space_outliner(BlenderRNA *brna) "Display data-blocks which are unused and/or will be lost when the file is reloaded"}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "SpaceOutliner", "Space"); RNA_def_struct_sdna(srna, "SpaceOops"); RNA_def_struct_ui_text(srna, "Space Outliner", "Outliner space data"); - + prop = RNA_def_property(srna, "display_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "outlinevis"); RNA_def_property_enum_items(prop, display_mode_items); RNA_def_property_ui_text(prop, "Display Mode", "Type of information to display"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); - + prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "search_string"); RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string"); RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); - + prop = RNA_def_property(srna, "use_filter_case_sensitive", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_CASE_SENSITIVE); RNA_def_property_ui_text(prop, "Case Sensitive Matches Only", "Only use case sensitive matches of search string"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL); - + prop = RNA_def_property(srna, "use_filter_complete", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_COMPLETE); RNA_def_property_ui_text(prop, "Complete Matches Only", "Only use complete matches of search string"); @@ -2219,17 +2220,17 @@ static void rna_def_background_image(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "cuser"); RNA_def_property_ui_text(prop, "Clip User", "Parameters defining which frame of the movie clip is displayed"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "xof"); RNA_def_property_ui_text(prop, "X Offset", "Offset image horizontally from the world origin"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "yof"); RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically from the world origin"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "size"); RNA_def_property_float_funcs(prop, "rna_BackgroundImage_size_get", "rna_BackgroundImage_size_set", NULL); @@ -2349,7 +2350,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) {RV3D_CAMOB, "CAMERA", 0, "Camera", ""}, {0, NULL, 0, NULL, NULL} }; - + static EnumPropertyItem bundle_drawtype_items[] = { {OB_PLAINAXES, "PLAIN_AXES", 0, "Plain Axes", ""}, {OB_ARROWS, "ARROWS", 0, "Arrows", ""}, @@ -2360,7 +2361,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) {OB_EMPTY_CONE, "CONE", 0, "Cone", ""}, {0, NULL, 0, NULL, NULL} }; - + static EnumPropertyItem view3d_matcap_items[] = { {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""}, {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""}, @@ -2388,11 +2389,11 @@ static void rna_def_space_view3d(BlenderRNA *brna) {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""}, {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "SpaceView3D", "Space"); RNA_def_struct_sdna(srna, "View3D"); RNA_def_struct_ui_text(srna, "3D View Space", "3D View space data"); - + prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_pointer_sdna(prop, NULL, "camera"); @@ -2437,7 +2438,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "ob_centre"); RNA_def_property_ui_text(prop, "Lock to Object", "3D View center is locked to this object's position"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "lock_bone", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "ob_centre_bone"); RNA_def_property_ui_text(prop, "Lock to Bone", "3D View center is locked to this bone's position"); @@ -2460,7 +2461,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "localvd"); RNA_def_property_ui_text(prop, "Local View", "Display an isolated sub-set of objects, apart from the scene visibility"); - + prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ_LENGTH); RNA_def_property_array(prop, 3); RNA_def_property_float_funcs(prop, "rna_View3D_CursorLocation_get", "rna_View3D_CursorLocation_set", NULL); @@ -2468,13 +2469,13 @@ static void rna_def_space_view3d(BlenderRNA *brna) "3D cursor location for this view (dependent on local view setting)"); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_UNIT_CAMERA); RNA_def_property_float_sdna(prop, NULL, "lens"); RNA_def_property_ui_text(prop, "Lens", "Viewport lens angle"); RNA_def_property_range(prop, 1.0f, 250.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "near"); RNA_def_property_range(prop, 1e-6f, FLT_MAX); @@ -2505,7 +2506,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_range(prop, 0, 1024); RNA_def_property_int_default(prop, 16); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "grid_subdivisions", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "gridsubdiv"); RNA_def_property_ui_text(prop, "Grid Subdivisions", "Number of subdivisions between grid lines"); @@ -2522,28 +2523,28 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_FLOOR); RNA_def_property_ui_text(prop, "Display Grid Floor", "Show the ground plane grid in perspective view"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "show_axis_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_X); RNA_def_property_ui_text(prop, "Display X Axis", "Show the X axis line in perspective view"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "show_axis_y", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_Y); RNA_def_property_ui_text(prop, "Display Y Axis", "Show the Y axis line in perspective view"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "show_axis_z", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "gridflag", V3D_SHOW_Z); RNA_def_property_ui_text(prop, "Display Z Axis", "Show the Z axis line in perspective view"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "show_outline_selected", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SELECT_OUTLINE); RNA_def_property_ui_text(prop, "Outline Selected", "Show an outline highlight around selected objects in non-wireframe views"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "show_all_objects_origin", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_DRAW_CENTERS); RNA_def_property_ui_text(prop, "All Object Origins", @@ -2555,7 +2556,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Relationship Lines", "Show dashed lines indicating parent or constraint relationships"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SHOW_GPENCIL); RNA_def_property_ui_text(prop, "Show Grease Pencil", @@ -2591,7 +2592,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_RENDER_OVERRIDE); RNA_def_property_ui_text(prop, "Only Render", "Display only objects which will be rendered"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "show_world", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag3", V3D_SHOW_WORLD); RNA_def_property_ui_text(prop, "World Background", "Display world colors in the background"); @@ -2621,7 +2622,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_enum_items(prop, pivot_items_full); RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_pivot_update"); - + prop = RNA_def_property(srna, "use_pivot_point_align", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_ALIGN); RNA_def_property_ui_text(prop, "Align", "Manipulate center points (object, pose and weight paint mode only)"); @@ -2640,7 +2641,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_ENUM_FLAG); RNA_def_property_ui_text(prop, "Transform Manipulators", "Transformation manipulators"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + prop = RNA_def_property(srna, "transform_orientation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "twmode"); RNA_def_property_enum_items(prop, transform_orientation_items); @@ -2678,7 +2679,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_array(prop, 8); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Local View Layers", "Local view layers visible in this 3D View"); - + prop = RNA_def_property(srna, "layers_used", PROP_BOOLEAN, PROP_LAYER_MEMBER); RNA_def_property_boolean_sdna(prop, NULL, "lay_used", 1); RNA_def_property_array(prop, 20); @@ -2730,7 +2731,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SOLID_MATCAP); RNA_def_property_ui_text(prop, "Matcap", "Active Objects draw images mapped on normals, enhancing Solid Draw Mode"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_enable"); - + prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "matcap_icon"); RNA_def_property_enum_items(prop, view3d_matcap_items); @@ -2793,17 +2794,17 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "viewlock", RV3D_LOCKED); RNA_def_property_ui_text(prop, "Lock", "Lock view rotation in side views"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_RegionView3D_quadview_update"); - + prop = RNA_def_property(srna, "show_sync_view", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "viewlock", RV3D_BOXVIEW); RNA_def_property_ui_text(prop, "Box", "Sync view position between side views"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_RegionView3D_quadview_update"); - + prop = RNA_def_property(srna, "use_box_clip", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "viewlock", RV3D_BOXCLIP); RNA_def_property_ui_text(prop, "Clip", "Clip objects based on what's visible in other side views"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_RegionView3D_quadview_clip_update"); - + prop = RNA_def_property(srna, "perspective_matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "persmat"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX: for now, it's too risky for users to do this */ @@ -2816,7 +2817,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_ui_text(prop, "Window Matrix", "Current window matrix"); - + prop = RNA_def_property(srna, "view_matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "viewmat"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); @@ -2834,7 +2835,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "is_persp", 1); RNA_def_property_ui_text(prop, "Is Perspective", ""); RNA_def_property_flag(prop, PROP_EDITABLE); - + prop = RNA_def_property(srna, "view_location", PROP_FLOAT, PROP_TRANSLATION); #if 0 RNA_def_property_float_sdna(prop, NULL, "ofs"); /* cant use because its negated */ @@ -2846,7 +2847,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "View Location", "View pivot location"); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_update(prop, NC_WINDOW, NULL); - + prop = RNA_def_property(srna, "view_rotation", PROP_FLOAT, PROP_QUATERNION); /* cant use because its inverted */ #if 0 RNA_def_property_float_sdna(prop, NULL, "viewquat"); @@ -2857,7 +2858,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) #endif RNA_def_property_ui_text(prop, "View Rotation", "Rotation in quaternions (keep normalized)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - + /* not sure we need rna access to these but adding anyway */ prop = RNA_def_property(srna, "view_distance", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "dist"); @@ -2893,14 +2894,14 @@ static void rna_def_space_buttons(BlenderRNA *brna) srna = RNA_def_struct(brna, "SpaceProperties", "Space"); RNA_def_struct_sdna(srna, "SpaceButs"); RNA_def_struct_ui_text(srna, "Properties Space", "Properties space data"); - + prop = RNA_def_property(srna, "context", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mainb"); RNA_def_property_enum_items(prop, buttons_context_items); RNA_def_property_enum_funcs(prop, NULL, "rna_SpaceProperties_context_set", "rna_SpaceProperties_context_itemf"); RNA_def_property_ui_text(prop, "Context", "Type of active data to display and edit"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, "rna_SpaceProperties_context_update"); - + prop = RNA_def_property(srna, "align", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "align"); RNA_def_property_enum_items(prop, align_items); @@ -2988,7 +2989,7 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_float_funcs(prop, "rna_SpaceImageEditor_zoom_get", NULL, NULL); RNA_def_property_ui_text(prop, "Zoom", "Zoom factor"); - + /* image draw */ prop = RNA_def_property(srna, "show_repeat", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_TILE); @@ -3020,7 +3021,7 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_property_struct_type(prop, "SpaceUVEditor"); RNA_def_property_pointer_funcs(prop, "rna_SpaceImageEditor_uvedit_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "UV Editor", "UV editor settings"); - + /* mode */ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); @@ -3050,7 +3051,7 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); - + /* update */ prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "lock", 0); @@ -3089,7 +3090,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static EnumPropertyItem view_type_items[] = { {SEQ_VIEW_SEQUENCE, "SEQUENCER", ICON_SEQ_SEQUENCER, "Sequencer", ""}, {SEQ_VIEW_PREVIEW, "PREVIEW", ICON_SEQ_PREVIEW, "Image Preview", ""}, @@ -3143,7 +3144,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna) srna = RNA_def_struct(brna, "SpaceSequenceEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceSeq"); RNA_def_struct_ui_text(srna, "Space Sequence Editor", "Sequence editor space data"); - + /* view type, fairly important */ prop = RNA_def_property(srna, "view_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "view"); @@ -3164,17 +3165,17 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - + prop = RNA_def_property(srna, "show_frames", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES); RNA_def_property_ui_text(prop, "Draw Frames", "Draw frames rather than seconds"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - + prop = RNA_def_property(srna, "use_marker_sync", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MARKER_TRANS); RNA_def_property_ui_text(prop, "Sync Markers", "Transform markers as well as strips"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - + prop = RNA_def_property(srna, "show_separate_color", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_DRAW_COLOR_SEPARATED); RNA_def_property_ui_text(prop, "Separate Colors", "Separate color channels in preview"); @@ -3199,7 +3200,7 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES); RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - + prop = RNA_def_property(srna, "show_grease_pencil", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_GPENCIL); RNA_def_property_ui_text(prop, "Show Grease Pencil", @@ -3230,14 +3231,14 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Overexposed", "Show overexposed areas with zebra stripes"); RNA_def_property_range(prop, 0, 110); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - + prop = RNA_def_property(srna, "proxy_render_size", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "render_size"); RNA_def_property_enum_items(prop, proxy_render_size_items); RNA_def_property_ui_text(prop, "Proxy render size", "Draw preview using full resolution or different proxy resolutions"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - + /* grease pencil */ prop = RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "gpd"); @@ -3298,7 +3299,7 @@ static void rna_def_space_text(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Syntax Highlight", "Syntax highlight for scripting"); RNA_def_property_ui_icon(prop, ICON_SYNTAX_OFF, 1); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL); - + prop = RNA_def_property(srna, "show_line_highlight", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "line_hlight", 0); RNA_def_property_ui_text(prop, "Highlight Line", "Highlight the current line"); @@ -3343,12 +3344,12 @@ static void rna_def_space_text(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "overwrite", 1); RNA_def_property_ui_text(prop, "Overwrite", "Overwrite characters when typing rather than inserting them"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL); - + prop = RNA_def_property(srna, "use_live_edit", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "live_edit", 1); RNA_def_property_ui_text(prop, "Live Edit", "Run python while editing"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TEXT, NULL); - + /* find */ prop = RNA_def_property(srna, "use_find_all", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", ST_FIND_ALL); @@ -3382,7 +3383,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + /* XXX: action-editor is currently for object-level only actions, so show that using object-icon hint */ static EnumPropertyItem mode_items[] = { {SACTCONT_DOPESHEET, "DOPESHEET", ICON_OOPS, "Dope Sheet", "Edit all keyframes in scene"}, @@ -3393,8 +3394,8 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) {SACTCONT_CACHEFILE, "CACHEFILE", ICON_FILE, "Cache File", "Edit timings for Cache File data-blocks"}, {0, NULL, 0, NULL, NULL} }; - - + + srna = RNA_def_struct(brna, "SpaceDopeSheetEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceAction"); RNA_def_struct_ui_text(srna, "Space Dope Sheet Editor", "Dope Sheet space data"); @@ -3406,51 +3407,51 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) "rna_Action_actedit_assign_poll"); RNA_def_property_ui_text(prop, "Action", "Action displayed and edited in this space"); RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, "rna_SpaceDopeSheetEditor_action_update"); - + /* mode */ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, mode_items); RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, "rna_SpaceDopeSheetEditor_mode_update"); - + /* display */ prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_DRAWTIME); RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - + prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWCFRANUM); RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - + prop = RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SLIDERS); RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - + prop = RNA_def_property(srna, "show_pose_markers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_POSEMARKERS_SHOW); RNA_def_property_ui_text(prop, "Show Pose Markers", "Show markers belonging to the active action instead of Scene markers " "(Action and Shape Key Editors only)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - + prop = RNA_def_property(srna, "show_group_colors", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWGCOLORS); RNA_def_property_ui_text(prop, "Show Group Colors", "Draw groups and channels with colors matching their corresponding groups " "(pose bones only currently)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - + /* editing */ prop = RNA_def_property(srna, "use_auto_merge_keyframes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NOTRANSKEYCULL); RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Automatically merge nearby keyframes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - + prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NOREALTIMEUPDATES); RNA_def_property_ui_text(prop, "Realtime Updates", @@ -3479,14 +3480,14 @@ static void rna_def_space_graph(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static EnumPropertyItem mode_items[] = { {SIPO_MODE_ANIMATION, "FCURVES", ICON_IPO, "F-Curve", "Edit animation/keyframes displayed as 2D curves"}, {SIPO_MODE_DRIVERS, "DRIVERS", ICON_DRIVER, "Drivers", "Edit drivers"}, {0, NULL, 0, NULL, NULL} }; - + /* this is basically the same as the one for the 3D-View, but with some entries omitted */ static EnumPropertyItem gpivot_items[] = { {V3D_AROUND_CENTER_BOUNDS, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", ""}, @@ -3497,93 +3498,93 @@ static void rna_def_space_graph(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - + srna = RNA_def_struct(brna, "SpaceGraphEditor", "Space"); RNA_def_struct_sdna(srna, "SpaceIpo"); RNA_def_struct_ui_text(srna, "Space Graph Editor", "Graph Editor space data"); - + /* mode */ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, mode_items); RNA_def_property_ui_text(prop, "Mode", "Editing context being displayed"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, "rna_SpaceGraphEditor_display_mode_update"); - + /* display */ prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_DRAWTIME); RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWCFRANUM); RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SLIDERS); RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "show_handles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NOHANDLES); RNA_def_property_ui_text(prop, "Show Handles", "Show handles of Bezier control points"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "use_only_selected_curves_handles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SELCUVERTSONLY); RNA_def_property_ui_text(prop, "Only Selected Curve Keyframes", "Only keyframes of selected F-Curves are visible and editable"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "use_only_selected_keyframe_handles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SELVHANDLESONLY); RNA_def_property_ui_text(prop, "Only Selected Keyframes Handles", "Only show and edit handles of selected keyframes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "use_beauty_drawing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_BEAUTYDRAW_OFF); RNA_def_property_ui_text(prop, "Use High Quality Drawing", "Draw F-Curves using Anti-Aliasing and other fancy effects " "(disable for better performance)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "show_group_colors", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWGCOLORS); RNA_def_property_ui_text(prop, "Show Group Colors", "Draw groups and channels with colors matching their corresponding groups"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + /* editing */ prop = RNA_def_property(srna, "use_auto_merge_keyframes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NOTRANSKEYCULL); RNA_def_property_ui_text(prop, "AutoMerge Keyframes", "Automatically merge nearby keyframes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NOREALTIMEUPDATES); RNA_def_property_ui_text(prop, "Realtime Updates", "When transforming keyframes, changes to the animation data are flushed to other views"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + /* cursor */ prop = RNA_def_property(srna, "show_cursor", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWCURSOR); RNA_def_property_ui_text(prop, "Show Cursor", "Show 2D cursor"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "cursor_position_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "cursorTime"); RNA_def_property_ui_text(prop, "Cursor X-Value", "Graph Editor 2D-Value cursor - X-Value component"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "cursor_position_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "cursorVal"); RNA_def_property_ui_text(prop, "Cursor Y-Value", "Graph Editor 2D-Value cursor - Y-Value component"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - + prop = RNA_def_property(srna, "pivot_point", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "around"); RNA_def_property_enum_items(prop, gpivot_items); @@ -3627,34 +3628,34 @@ static void rna_def_space_nla(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SpaceNLA", "Space"); RNA_def_struct_sdna(srna, "SpaceNla"); RNA_def_struct_ui_text(srna, "Space Nla Editor", "NLA editor space data"); - + /* display */ prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_DRAWTIME); RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); - + prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NODRAWCFRANUM); RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); - + prop = RNA_def_property(srna, "show_strip_curves", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOSTRIPCURVES); RNA_def_property_ui_text(prop, "Show Control F-Curves", "Show influence F-Curves on strips"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); - + prop = RNA_def_property(srna, "show_local_markers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOLOCALMARKERS); RNA_def_property_ui_text(prop, "Show Local Markers", "Show action-local markers on the strips, useful when synchronizing timing across strips"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); - + /* editing */ prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOREALTIMEUPDATES); @@ -3680,54 +3681,54 @@ static void rna_def_space_time(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SpaceTimeline", "Space"); RNA_def_struct_sdna(srna, "SpaceTime"); RNA_def_struct_ui_text(srna, "Space Timeline Editor", "Timeline editor space data"); - + /* view settings */ prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", TIME_CFRA_NUM); RNA_def_property_ui_text(prop, "Show Frame Number Indicator", "Show frame number beside the current frame indicator line"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); - + prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", TIME_DRAWFRAMES); RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); - + /* displaying cache status */ prop = RNA_def_property(srna, "show_cache", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DISPLAY); RNA_def_property_ui_text(prop, "Show Cache", "Show the status of cached frames in the timeline"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); - + prop = RNA_def_property(srna, "cache_softbody", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_SOFTBODY); RNA_def_property_ui_text(prop, "Softbody", "Show the active object's softbody point cache"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); - + prop = RNA_def_property(srna, "cache_particles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_PARTICLES); RNA_def_property_ui_text(prop, "Particles", "Show the active object's particle point cache"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); - + prop = RNA_def_property(srna, "cache_cloth", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_CLOTH); RNA_def_property_ui_text(prop, "Cloth", "Show the active object's cloth point cache"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); - + prop = RNA_def_property(srna, "cache_smoke", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_SMOKE); RNA_def_property_ui_text(prop, "Smoke", "Show the active object's smoke cache"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); - + prop = RNA_def_property(srna, "cache_dynamicpaint", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DYNAMICPAINT); RNA_def_property_ui_text(prop, "Dynamic Paint", "Show the active object's Dynamic Paint cache"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); - + prop = RNA_def_property(srna, "cache_rigidbody", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_RIGIDBODY); RNA_def_property_ui_text(prop, "Rigid Body", "Show the active object's Rigid Body cache"); @@ -3746,17 +3747,17 @@ static void rna_def_console_line(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "ConsoleLine", NULL); RNA_def_struct_ui_text(srna, "Console Input", "Input line for the interactive console"); - + prop = RNA_def_property(srna, "body", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_ConsoleLine_body_get", "rna_ConsoleLine_body_length", "rna_ConsoleLine_body_set"); RNA_def_property_ui_text(prop, "Line", "Text in the line"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CONSOLE, NULL); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_TEXT); - + prop = RNA_def_property(srna, "current_character", PROP_INT, PROP_NONE); /* copied from text editor */ RNA_def_property_int_sdna(prop, NULL, "cursor"); RNA_def_property_int_funcs(prop, NULL, NULL, "rna_ConsoleLine_cursor_index_range"); @@ -3767,16 +3768,16 @@ static void rna_def_console_line(BlenderRNA *brna) RNA_def_property_enum_items(prop, console_line_type_items); RNA_def_property_ui_text(prop, "Type", "Console line type when used in scrollback"); } - + static void rna_def_space_console(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SpaceConsole", "Space"); RNA_def_struct_sdna(srna, "SpaceConsole"); RNA_def_struct_ui_text(srna, "Space Console", "Interactive python console"); - + /* display */ prop = RNA_def_property(srna, "font_size", PROP_INT, PROP_NONE); /* copied from text editor */ RNA_def_property_int_sdna(prop, NULL, "lheight"); @@ -3788,14 +3789,14 @@ static void rna_def_space_console(BlenderRNA *brna) prop = RNA_def_property(srna, "select_start", PROP_INT, PROP_UNSIGNED); /* copied from text editor */ RNA_def_property_int_sdna(prop, NULL, "sel_start"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CONSOLE, NULL); - + prop = RNA_def_property(srna, "select_end", PROP_INT, PROP_UNSIGNED); /* copied from text editor */ RNA_def_property_int_sdna(prop, NULL, "sel_end"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CONSOLE, NULL); prop = RNA_def_property(srna, "prompt", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Prompt", "Command line prompt"); - + prop = RNA_def_property(srna, "language", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Language", "Command line prompt language"); @@ -3803,7 +3804,7 @@ static void rna_def_space_console(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "history", NULL); RNA_def_property_struct_type(prop, "ConsoleLine"); RNA_def_property_ui_text(prop, "History", "Command history"); - + prop = RNA_def_property(srna, "scrollback", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "scrollback", NULL); RNA_def_property_struct_type(prop, "ConsoleLine"); @@ -3814,7 +3815,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + static EnumPropertyItem file_display_items[] = { {FILE_SHORTDISPLAY, "LIST_SHORT", ICON_SHORTDISPLAY, "Short List", "Display files as short list"}, {FILE_LONGDISPLAY, "LIST_LONG", ICON_LONGDISPLAY, "Long List", "Display files as a detailed list"}, @@ -4078,7 +4079,7 @@ static void rna_def_space_filebrowser(BlenderRNA *brna) prop = RNA_def_property(srna, "params", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "params"); RNA_def_property_ui_text(prop, "Filebrowser Parameter", "Parameters and Settings for the Filebrowser"); - + prop = RNA_def_property(srna, "active_operator", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "op"); RNA_def_property_ui_text(prop, "Active Operator", ""); @@ -4159,28 +4160,28 @@ static void rna_def_space_info(BlenderRNA *brna) srna = RNA_def_struct(brna, "SpaceInfo", "Space"); RNA_def_struct_sdna(srna, "SpaceInfo"); RNA_def_struct_ui_text(srna, "Space Info", "Info space data"); - + /* reporting display */ prop = RNA_def_property(srna, "show_report_debug", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_DEBUG); RNA_def_property_ui_text(prop, "Show Debug", "Display debug reporting info"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); - + prop = RNA_def_property(srna, "show_report_info", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_INFO); RNA_def_property_ui_text(prop, "Show Info", "Display general information"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); - + prop = RNA_def_property(srna, "show_report_operator", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_OP); RNA_def_property_ui_text(prop, "Show Operator", "Display the operator log"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); - + prop = RNA_def_property(srna, "show_report_warning", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_WARN); RNA_def_property_ui_text(prop, "Show Warn", "Display warnings"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); - + prop = RNA_def_property(srna, "show_report_error", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "rpt_mask", INFO_RPT_ERR); RNA_def_property_ui_text(prop, "Show Error", "Display error text"); @@ -4196,7 +4197,7 @@ static void rna_def_space_userpref(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "SpaceUserPreferences", "Space"); RNA_def_struct_sdna(srna, "SpaceUserPref"); RNA_def_struct_ui_text(srna, "Space User Preferences", "User preferences space data"); @@ -4218,7 +4219,7 @@ static void rna_def_node_tree_path(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - + srna = RNA_def_struct(brna, "NodeTreePath", NULL); RNA_def_struct_sdna(srna, "bNodeTreePath"); RNA_def_struct_ui_text(srna, "Node Tree Path", "Element of the node space tree path"); @@ -4385,7 +4386,7 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_AUTO_RENDER); RNA_def_property_ui_text(prop, "Auto Render", "Re-render and composite changed layers on 3D edits"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); - + prop = RNA_def_property(srna, "backdrop_zoom", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "zoom"); RNA_def_property_float_default(prop, 1.0f); @@ -4393,7 +4394,7 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.01, 100, 1, 2); RNA_def_property_ui_text(prop, "Backdrop Zoom", "Backdrop zoom factor"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); - + prop = RNA_def_property(srna, "backdrop_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "xof"); RNA_def_property_ui_text(prop, "Backdrop X", "Backdrop X offset"); @@ -4410,11 +4411,6 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the image to draw"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); - prop = RNA_def_property(srna, "show_highlight", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_SHOW_HIGHLIGHT); - RNA_def_property_ui_text(prop, "Highlight", "Highlight nodes that are being calculated"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); - /* the mx/my "cursor" in the node editor is used only by operators to store the mouse position */ prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ); RNA_def_property_array(prop, 2); @@ -4453,12 +4449,12 @@ static void rna_def_space_logic(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_SENS_SEL); RNA_def_property_ui_text(prop, "Show Selected Object", "Show sensors of all selected objects"); RNA_def_property_update(prop, NC_LOGIC, NULL); - + prop = RNA_def_property(srna, "show_sensors_active_object", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_SENS_ACT); RNA_def_property_ui_text(prop, "Show Active Object", "Show sensors of active object"); RNA_def_property_update(prop, NC_LOGIC, NULL); - + prop = RNA_def_property(srna, "show_sensors_linked_controller", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_SENS_LINK); RNA_def_property_ui_text(prop, "Show Linked to Controller", "Show linked objects to the controller"); @@ -4474,7 +4470,7 @@ static void rna_def_space_logic(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_CONT_SEL); RNA_def_property_ui_text(prop, "Show Selected Object", "Show controllers of all selected objects"); RNA_def_property_update(prop, NC_LOGIC, NULL); - + prop = RNA_def_property(srna, "show_controllers_active_object", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_CONT_ACT); RNA_def_property_ui_text(prop, "Show Active Object", "Show controllers of active object"); @@ -4490,12 +4486,12 @@ static void rna_def_space_logic(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_ACT_SEL); RNA_def_property_ui_text(prop, "Show Selected Object", "Show actuators of all selected objects"); RNA_def_property_update(prop, NC_LOGIC, NULL); - + prop = RNA_def_property(srna, "show_actuators_active_object", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_ACT_ACT); RNA_def_property_ui_text(prop, "Show Active Object", "Show actuators of active object"); RNA_def_property_update(prop, NC_LOGIC, NULL); - + prop = RNA_def_property(srna, "show_actuators_linked_controller", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "scaflag", BUTS_ACT_LINK); RNA_def_property_ui_text(prop, "Show Linked to Actuator", "Show linked objects to the actuator"); diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c index c72d6d9e581..8f771eda99d 100644 --- a/source/blender/makesrna/intern/rna_space_api.c +++ b/source/blender/makesrna/intern/rna_space_api.c @@ -47,7 +47,7 @@ static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d) v3d = (View3D *)sa->spacedata.first; - ED_view3d_update_viewmat(sc->scene, v3d, ar, NULL, NULL); + ED_view3d_update_viewmat(sc->scene, v3d, ar, NULL, NULL, NULL); } } diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 7a3c862f04c..54b82fc89d6 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -1039,6 +1039,7 @@ static void rna_def_uilist(BlenderRNA *brna) RNA_def_struct_refine_func(srna, "rna_UIList_refine"); RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL); RNA_def_struct_idprops_func(srna, "rna_UIList_idprops"); + RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); /* Registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 46775af21db..7d8d24670a7 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -557,8 +557,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text"); parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item"); - parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", - "Operator properties to fill in, return when 'properties' is set to true"); + parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", "Operator properties to fill in"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR); RNA_def_function_return(func, parm); RNA_def_function_ui_description(func, "Item. Places a button into the layout to call an Operator"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 4d70b87843a..7a978c35810 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3156,6 +3156,7 @@ static void rna_def_userdef_addon_pref(BlenderRNA *brna) RNA_def_struct_refine_func(srna, "rna_AddonPref_refine"); RNA_def_struct_register_funcs(srna, "rna_AddonPref_register", "rna_AddonPref_unregister", NULL); RNA_def_struct_idprops_func(srna, "rna_AddonPref_idprops"); + RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); /* Mandatory! */ /* registration */ RNA_define_verify_sdna(0); @@ -3316,7 +3317,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) prop = RNA_def_property(srna, "ui_scale", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "UI Scale", "Changes the size of the fonts and buttons in the interface"); RNA_def_property_range(prop, 0.25f, 4.0f); - RNA_def_property_ui_range(prop, 0.5f, 2.0f, 1, 1); + RNA_def_property_ui_range(prop, 0.5f, 2.0f, 1, 2); RNA_def_property_float_default(prop, 1.0f); RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); @@ -3925,12 +3926,18 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); + RNA_def_property_ui_text(prop, "DPI", + "DPI for addons to use when drawing custom user interface elements. Controlled by " + "operating system settings and Blender UI scale, with a reference value of 72 DPI. " + "Note that since this value includes a user defined scale, it is not always the " + "actual monitor DPI"); prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_float_sdna(prop, NULL, "pixelsize"); - RNA_def_property_ui_text(prop, "Pixel Size", ""); + RNA_def_property_ui_text(prop, "Pixel Size", + "Suggested line thickness and point size in pixels, for addons drawing custom user " + "interface elements. Controlled by operating system settings and Blender UI scale"); prop = RNA_def_property(srna, "font_path_ui", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "font_path_ui"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 35c9c9bcc89..b5ecaf739c7 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -939,35 +939,8 @@ static void rna_wmClipboard_set(PointerRNA *UNUSED(ptr), const char *value) } #ifdef WITH_PYTHON -static void rna_Operator_unregister(struct Main *bmain, StructRNA *type) -{ - const char *idname; - wmOperatorType *ot = RNA_struct_blender_type_get(type); - wmWindowManager *wm; - - if (!ot) - return; - - /* update while blender is running */ - wm = bmain->wm.first; - if (wm) { - WM_operator_stack_clear(wm); - WM_operator_handlers_clear(wm, ot); - } - WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); - - RNA_struct_free_extension(type, &ot->ext); - - idname = ot->idname; - WM_operatortype_remove_ptr(ot); - MEM_freeN((void *)idname); - - /* not to be confused with the RNA_struct_free that WM_operatortype_remove calls, they are 2 different srna's */ - RNA_struct_free(&BLENDER_RNA, type); -} - -static int operator_poll(bContext *C, wmOperatorType *ot) +static int rna_operator_poll_cb(bContext *C, wmOperatorType *ot) { extern FunctionRNA rna_Operator_poll_func; @@ -992,7 +965,7 @@ static int operator_poll(bContext *C, wmOperatorType *ot) return visible; } -static int operator_execute(bContext *C, wmOperator *op) +static int rna_operator_execute_cb(bContext *C, wmOperator *op) { extern FunctionRNA rna_Operator_execute_func; @@ -1018,7 +991,7 @@ static int operator_execute(bContext *C, wmOperator *op) } /* same as execute() but no return value */ -static bool operator_check(bContext *C, wmOperator *op) +static bool rna_operator_check_cb(bContext *C, wmOperator *op) { extern FunctionRNA rna_Operator_check_func; @@ -1043,7 +1016,7 @@ static bool operator_check(bContext *C, wmOperator *op) return result; } -static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int rna_operator_invoke_cb(bContext *C, wmOperator *op, const wmEvent *event) { extern FunctionRNA rna_Operator_invoke_func; @@ -1070,7 +1043,7 @@ static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event) } /* same as invoke */ -static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event) +static int rna_operator_modal_cb(bContext *C, wmOperator *op, const wmEvent *event) { extern FunctionRNA rna_Operator_modal_func; @@ -1096,7 +1069,7 @@ static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event) return result; } -static void operator_draw(bContext *C, wmOperator *op) +static void rna_operator_draw_cb(bContext *C, wmOperator *op) { extern FunctionRNA rna_Operator_draw_func; @@ -1115,7 +1088,7 @@ static void operator_draw(bContext *C, wmOperator *op) } /* same as exec(), but call cancel */ -static void operator_cancel(bContext *C, wmOperator *op) +static void rna_operator_cancel_cb(bContext *C, wmOperator *op) { extern FunctionRNA rna_Operator_cancel_func; @@ -1133,35 +1106,42 @@ static void operator_cancel(bContext *C, wmOperator *op) RNA_parameter_list_free(&list); } -void operator_wrapper(wmOperatorType *ot, void *userdata); -void macro_wrapper(wmOperatorType *ot, void *userdata); +static void rna_Operator_unregister(struct Main *bmain, StructRNA *type); -static char _operator_idname[OP_MAX_TYPENAME]; -static char _operator_name[OP_MAX_TYPENAME]; -static char _operator_descr[RNA_DYN_DESCR_MAX]; -static char _operator_ctxt[RNA_DYN_DESCR_MAX]; -static char _operator_undo_group[OP_MAX_TYPENAME]; -static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *data, const char *identifier, - StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) +/* bpy_operator_wrap.c */ +extern void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata); +extern void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata); + +static StructRNA *rna_Operator_register( + Main *bmain, ReportList *reports, void *data, const char *identifier, + StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) { wmOperatorType dummyot = {NULL}; wmOperator dummyop = {NULL}; PointerRNA dummyotr; int have_function[7]; + struct { + char idname[OP_MAX_TYPENAME]; + char name[OP_MAX_TYPENAME]; + char descr[RNA_DYN_DESCR_MAX]; + char ctxt[RNA_DYN_DESCR_MAX]; + char undo_group[OP_MAX_TYPENAME]; + } temp_buffers; + /* setup dummy operator & operator type to store static properties in */ dummyop.type = &dummyot; - dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */ - dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */ - dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */ - dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */ - dummyot.undo_group = _operator_undo_group; /* only assigne the pointer, string is NULL'd */ + dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */ + dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */ + dummyot.description = temp_buffers.descr; /* only assigne the pointer, string is NULL'd */ + dummyot.translation_context = temp_buffers.ctxt; /* only assigne the pointer, string is NULL'd */ + dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */ RNA_pointer_create(NULL, &RNA_Operator, &dummyop, &dummyotr); /* clear in case they are left unset */ - _operator_idname[0] = _operator_name[0] = _operator_descr[0] = _operator_undo_group[0] = '\0'; + temp_buffers.idname[0] = temp_buffers.name[0] = temp_buffers.descr[0] = temp_buffers.undo_group[0] = '\0'; /* We have to set default op context! */ - strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT); + strcpy(temp_buffers.ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT); /* validate the python class */ if (validate(&dummyotr, data, have_function) != 0) @@ -1172,7 +1152,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * /* inconveniently long name sanity check */ { - char *ch = _operator_idname; + char *ch = temp_buffers.idname; int i; int dot = 0; for (i = 0; *ch; i++) { @@ -1185,7 +1165,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * else { BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', at position %d", - identifier, _operator_idname, i); + identifier, temp_buffers.idname, i); return NULL; } @@ -1194,7 +1174,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * if (i > ((int)sizeof(dummyop.idname)) - 3) { BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', " - "is too long, maximum length is %d", identifier, _operator_idname, + "is too long, maximum length is %d", identifier, temp_buffers.idname, (int)sizeof(dummyop.idname) - 3); return NULL; } @@ -1202,34 +1182,34 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * if (dot != 1) { BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s', invalid bl_idname '%s', must contain 1 '.' character", - identifier, _operator_idname); + identifier, temp_buffers.idname); return NULL; } } /* end sanity check */ { - int idlen = strlen(_operator_idname) + 4; - int namelen = strlen(_operator_name) + 1; - int desclen = strlen(_operator_descr) + 1; - int ctxtlen = strlen(_operator_ctxt) + 1; - int ugrouplen = strlen(_operator_undo_group) + 1; - char *ch; + const uint idname_len = strlen(temp_buffers.idname) + 4; + const uint name_len = strlen(temp_buffers.name) + 1; + const uint desc_len = strlen(temp_buffers.descr) + 1; + const uint ctxt_len = strlen(temp_buffers.ctxt) + 1; + const uint undo_group_len = strlen(temp_buffers.undo_group) + 1; /* 2 terminators and 3 to convert a.b -> A_OT_b */ - ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen + ugrouplen), "_operator_idname"); - WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */ + char *ch = MEM_mallocN( + sizeof(char) * (idname_len + name_len + desc_len + ctxt_len + undo_group_len), __func__); + WM_operator_bl_idname(ch, temp_buffers.idname); /* convert the idname from python */ dummyot.idname = ch; - ch += idlen; - strcpy(ch, _operator_name); + ch += idname_len; + memcpy(ch, temp_buffers.name, name_len); dummyot.name = ch; - ch += namelen; - strcpy(ch, _operator_descr); + ch += name_len; + memcpy(ch, temp_buffers.descr, desc_len); dummyot.description = ch; - ch += desclen; - strcpy(ch, _operator_ctxt); + ch += desc_len; + memcpy(ch, temp_buffers.ctxt, ctxt_len); dummyot.translation_context = ch; - ch += ctxtlen; - strcpy(ch, _operator_undo_group); + ch += ctxt_len; + memcpy(ch, temp_buffers.undo_group, undo_group_len); dummyot.undo_group = ch; } } @@ -1252,14 +1232,14 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * dummyot.ext.call = call; dummyot.ext.free = free; - dummyot.pyop_poll = (have_function[0]) ? operator_poll : NULL; - dummyot.exec = (have_function[1]) ? operator_execute : NULL; - dummyot.check = (have_function[2]) ? operator_check : NULL; - dummyot.invoke = (have_function[3]) ? operator_invoke : NULL; - dummyot.modal = (have_function[4]) ? operator_modal : NULL; - dummyot.ui = (have_function[5]) ? operator_draw : NULL; - dummyot.cancel = (have_function[6]) ? operator_cancel : NULL; - WM_operatortype_append_ptr(operator_wrapper, (void *)&dummyot); + dummyot.pyop_poll = (have_function[0]) ? rna_operator_poll_cb : NULL; + dummyot.exec = (have_function[1]) ? rna_operator_execute_cb : NULL; + dummyot.check = (have_function[2]) ? rna_operator_check_cb : NULL; + dummyot.invoke = (have_function[3]) ? rna_operator_invoke_cb : NULL; + dummyot.modal = (have_function[4]) ? rna_operator_modal_cb : NULL; + dummyot.ui = (have_function[5]) ? rna_operator_draw_cb : NULL; + dummyot.cancel = (have_function[6]) ? rna_operator_cancel_cb : NULL; + WM_operatortype_append_ptr(BPY_RNA_operator_wrapper, (void *)&dummyot); /* update while blender is running */ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); @@ -1267,70 +1247,107 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * return dummyot.ext.srna; } +static void rna_Operator_unregister(struct Main *bmain, StructRNA *type) +{ + const char *idname; + wmOperatorType *ot = RNA_struct_blender_type_get(type); + wmWindowManager *wm; + + if (!ot) + return; + + /* update while blender is running */ + wm = bmain->wm.first; + if (wm) { + WM_operator_stack_clear(wm); + + WM_operator_handlers_clear(wm, ot); + } + WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); + + RNA_struct_free_extension(type, &ot->ext); + + idname = ot->idname; + WM_operatortype_remove_ptr(ot); + MEM_freeN((void *)idname); + + /* not to be confused with the RNA_struct_free that WM_operatortype_remove calls, they are 2 different srna's */ + RNA_struct_free(&BLENDER_RNA, type); +} + static void **rna_Operator_instance(PointerRNA *ptr) { wmOperator *op = ptr->data; return &op->py_instance; } -static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, void *data, const char *identifier, - StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) +static StructRNA *rna_MacroOperator_register( + Main *bmain, ReportList *reports, void *data, const char *identifier, + StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) { wmOperatorType dummyot = {NULL}; wmOperator dummyop = {NULL}; PointerRNA dummyotr; int have_function[4]; + struct { + char idname[OP_MAX_TYPENAME]; + char name[OP_MAX_TYPENAME]; + char descr[RNA_DYN_DESCR_MAX]; + char ctxt[RNA_DYN_DESCR_MAX]; + char undo_group[OP_MAX_TYPENAME]; + } temp_buffers; + /* setup dummy operator & operator type to store static properties in */ dummyop.type = &dummyot; - dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */ - dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */ - dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */ - dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */ - dummyot.undo_group = _operator_undo_group; /* only assigne the pointer, string is NULL'd */ + dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */ + dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */ + dummyot.description = temp_buffers.descr; /* only assigne the pointer, string is NULL'd */ + dummyot.translation_context = temp_buffers.ctxt; /* only assigne the pointer, string is NULL'd */ + dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */ RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr); /* clear in case they are left unset */ - _operator_idname[0] = _operator_name[0] = _operator_descr[0] = _operator_undo_group[0] = '\0'; + temp_buffers.idname[0] = temp_buffers.name[0] = temp_buffers.descr[0] = temp_buffers.undo_group[0] = '\0'; /* We have to set default op context! */ - strcpy(_operator_ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT); + strcpy(temp_buffers.ctxt, BLT_I18NCONTEXT_OPERATOR_DEFAULT); /* validate the python class */ if (validate(&dummyotr, data, have_function) != 0) return NULL; + if (strlen(identifier) >= sizeof(dummyop.idname)) { + BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s' is too long, maximum length is %d", + identifier, (int)sizeof(dummyop.idname)); + return NULL; + } + { /* convert foo.bar to FOO_OT_bar * allocate the description and the idname in 1 go */ - int idlen = strlen(_operator_idname) + 4; - int namelen = strlen(_operator_name) + 1; - int desclen = strlen(_operator_descr) + 1; - int ctxtlen = strlen(_operator_ctxt) + 1; - int ugrouplen = strlen(_operator_undo_group) + 1; - char *ch; + const uint idname_len = strlen(temp_buffers.idname) + 4; + const uint name_len = strlen(temp_buffers.name) + 1; + const uint desc_len = strlen(temp_buffers.descr) + 1; + const uint ctxt_len = strlen(temp_buffers.ctxt) + 1; + const uint undo_group_len = strlen(temp_buffers.undo_group) + 1; /* 2 terminators and 3 to convert a.b -> A_OT_b */ - ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen + ugrouplen), "_operator_idname"); - WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */ + char *ch = MEM_mallocN( + sizeof(char) * (idname_len + name_len + desc_len + ctxt_len + undo_group_len), __func__); + WM_operator_bl_idname(ch, temp_buffers.idname); /* convert the idname from python */ dummyot.idname = ch; - ch += idlen; - strcpy(ch, _operator_name); + ch += idname_len; + memcpy(ch, temp_buffers.name, name_len); dummyot.name = ch; - ch += namelen; - strcpy(ch, _operator_descr); + ch += name_len; + memcpy(ch, temp_buffers.descr, desc_len); dummyot.description = ch; - ch += desclen; - strcpy(ch, _operator_ctxt); + ch += desc_len; + memcpy(ch, temp_buffers.ctxt, ctxt_len); dummyot.translation_context = ch; - ch += ctxtlen; - strcpy(ch, _operator_undo_group); + ch += ctxt_len; + memcpy(ch, temp_buffers.undo_group, undo_group_len); dummyot.undo_group = ch; } - if (strlen(identifier) >= sizeof(dummyop.idname)) { - BKE_reportf(reports, RPT_ERROR, "Registering operator class: '%s' is too long, maximum length is %d", - identifier, (int)sizeof(dummyop.idname)); - return NULL; - } - /* check if we have registered this operator type before, and remove it */ { wmOperatorType *ot = WM_operatortype_find(dummyot.idname, true); @@ -1348,10 +1365,10 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v dummyot.ext.call = call; dummyot.ext.free = free; - dummyot.pyop_poll = (have_function[0]) ? operator_poll : NULL; - dummyot.ui = (have_function[3]) ? operator_draw : NULL; + dummyot.pyop_poll = (have_function[0]) ? rna_operator_poll_cb : NULL; + dummyot.ui = (have_function[3]) ? rna_operator_draw_cb : NULL; - WM_operatortype_append_macro_ptr(macro_wrapper, (void *)&dummyot); + WM_operatortype_append_macro_ptr(BPY_RNA_operator_macro_wrapper, (void *)&dummyot); /* update while blender is running */ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); @@ -1556,6 +1573,7 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Operator Properties", "Input properties of an Operator"); RNA_def_struct_refine_func(srna, "rna_OperatorProperties_refine"); RNA_def_struct_idprops_func(srna, "rna_OperatorProperties_idprops"); + RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); } static void rna_def_macro_operator(BlenderRNA *brna) diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 2b739dc0093..874ac34b613 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -50,6 +50,7 @@ #include "BKE_curve.h" #include "BKE_library_query.h" #include "BKE_modifier.h" +#include "BKE_mesh.h" #include "MOD_util.h" @@ -137,7 +138,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, static void updateDepsgraph(ModifierData *md, struct Main *UNUSED(bmain), - struct Scene *scene, + struct Scene *UNUSED(scene), Object *UNUSED(ob), struct DepsNodeHandle *node) { @@ -149,33 +150,15 @@ static void updateDepsgraph(ModifierData *md, DEG_add_object_relation(node, amd->end_cap, DEG_OB_COMP_TRANSFORM, "Array Modifier End Cap"); } if (amd->curve_ob) { + struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node); DEG_add_object_relation(node, amd->curve_ob, DEG_OB_COMP_GEOMETRY, "Array Modifier Curve"); - DEG_add_special_eval_flag(scene->depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH); + DEG_add_special_eval_flag(depsgraph, &amd->curve_ob->id, DAG_EVAL_NEED_CURVE_PATH); } if (amd->offset_ob != NULL) { DEG_add_object_relation(node, amd->offset_ob, DEG_OB_COMP_TRANSFORM, "Array Modifier Offset"); } } -static float vertarray_size(const MVert *mvert, int numVerts, int axis) -{ - int i; - float min_co, max_co; - - /* if there are no vertices, width is 0 */ - if (numVerts == 0) return 0; - - /* find the minimum and maximum coordinates on the desired axis */ - min_co = max_co = mvert->co[axis]; - mvert++; - for (i = 1; i < numVerts; ++i, ++mvert) { - if (mvert->co[axis] < min_co) min_co = mvert->co[axis]; - if (mvert->co[axis] > max_co) max_co = mvert->co[axis]; - } - - return max_co - min_co; -} - BLI_INLINE float sum_v3(const float v[3]) { return v[0] + v[1] + v[2]; @@ -472,12 +455,22 @@ static DerivedMesh *arrayModifier_doArray( unit_m4(offset); src_mvert = dm->getVertArray(dm); - if (amd->offset_type & MOD_ARR_OFF_CONST) - add_v3_v3v3(offset[3], offset[3], amd->offset); + if (amd->offset_type & MOD_ARR_OFF_CONST) { + add_v3_v3(offset[3], amd->offset); + } if (amd->offset_type & MOD_ARR_OFF_RELATIVE) { - for (j = 0; j < 3; j++) - offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j); + float min[3], max[3]; + const MVert *src_mv; + + INIT_MINMAX(min, max); + for (src_mv = src_mvert, j = chunk_nverts; j--; src_mv++) { + minmax_v3v3_v3(min, max, src_mv->co); + } + + for (j = 3; j--; ) { + offset[3][j] += amd->scale[j] * (max[j] - min[j]); + } } if (use_offset_ob) { diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 09444476bfe..3c6ba7acc88 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -111,7 +111,7 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, static void updateDepsgraph(ModifierData *md, struct Main *UNUSED(bmain), - struct Scene *scene, + struct Scene *UNUSED(scene), Object *object, struct DepsNodeHandle *node) { @@ -123,8 +123,9 @@ static void updateDepsgraph(ModifierData *md, /* TODO(sergey): Currently path is evaluated as a part of modifier stack, * might be changed in the future. */ + struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node); DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier"); - DEG_add_special_eval_flag(scene->depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH); + DEG_add_special_eval_flag(depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH); } DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Curve Modifier"); diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 18f60bab490..3325f05025f 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -384,6 +384,7 @@ static void displaceModifier_do( data.vert_clnors = vert_clnors; if (dmd->texture != NULL) { data.pool = BKE_image_pool_new(); + BKE_texture_fetch_images_for_pool(dmd->texture, data.pool); } BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512); diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index bb75d655802..83a42504180 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -36,6 +36,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_dynamicpaint.h" +#include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_modifier.h" @@ -58,6 +59,15 @@ static void copyData(ModifierData *md, ModifierData *target) DynamicPaintModifierData *tpmd = (DynamicPaintModifierData *)target; dynamicPaint_Modifier_copy(pmd, tpmd); + + if (tpmd->canvas) { + for (DynamicPaintSurface *surface = tpmd->canvas->surfaces.first; surface; surface = surface->next) { + id_us_plus((ID *)surface->init_texture); + } + } + if (tpmd->brush) { + id_us_plus((ID *)tpmd->brush->mat); + } } static void freeData(ModifierData *md) diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c index c202c5e1cb4..1964e940cb2 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim.c +++ b/source/blender/modifiers/intern/MOD_fluidsim.c @@ -68,12 +68,13 @@ static void copyData(ModifierData *md, ModifierData *target) FluidsimModifierData *fluidmd = (FluidsimModifierData *) md; FluidsimModifierData *tfluidmd = (FluidsimModifierData *) target; - if (tfluidmd->fss) - MEM_freeN(tfluidmd->fss); - - tfluidmd->fss = MEM_dupallocN(fluidmd->fss); - if (tfluidmd->fss && (tfluidmd->fss->meshVelocities != NULL)) { - tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities); + fluidsim_free(tfluidmd); + + if (fluidmd->fss) { + tfluidmd->fss = MEM_dupallocN(fluidmd->fss); + if (tfluidmd->fss && (tfluidmd->fss->meshVelocities != NULL)) { + tfluidmd->fss->meshVelocities = MEM_dupallocN(tfluidmd->fss->meshVelocities); + } } } diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index ffbbb1b0745..3684e947fe0 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -78,8 +78,8 @@ void fluidsim_init(FluidsimModifierData *fluidmd) fss->resolutionxyz = 65; fss->previewresxyz = 45; fss->realsize = 0.5; - fss->guiDisplayMode = 2; // preview - fss->renderDisplayMode = 3; // render + fss->guiDisplayMode = OB_FSDOM_PREVIEW; + fss->renderDisplayMode = OB_FSDOM_FINAL; fss->viscosityValue = 1.0; fss->viscosityExponent = 6; @@ -98,7 +98,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd) /* fluid/inflow settings * fss->iniVel --> automatically set to 0 */ - modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), "cache_fluid"); + modifier_path_init(fss->surfdataPath, sizeof(fss->surfdataPath), OB_FLUIDSIM_SURF_DIR_DEFAULT); /* first init of bounding box */ /* no bounding box needed */ @@ -150,9 +150,8 @@ void fluidsim_free(FluidsimModifierData *fluidmd) if (fluidmd && fluidmd->fss) { if (fluidmd->fss->meshVelocities) { MEM_freeN(fluidmd->fss->meshVelocities); - fluidmd->fss->meshVelocities = NULL; } - MEM_freeN(fluidmd->fss); + MEM_SAFE_FREE(fluidmd->fss); } return; @@ -423,8 +422,6 @@ static void fluidsim_read_vel_cache(FluidsimModifierData *fluidmd, DerivedMesh * static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams) { - int displaymode = 0; - int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */ /* why start with 0 as start frame?? Animations + time are frozen for frame 0 anyway. (See physics_fluid.c for that. - DG */ /* If we start with frame 0, we need to remap all animation channels, too, because they will all be 1 frame late if using frame-1! - DG */ @@ -435,25 +432,23 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, MPoly *mpoly; MPoly mp_example = {0}; - if (!useRenderParams) { - displaymode = fss->guiDisplayMode; - } - else { - displaymode = fss->renderDisplayMode; - } + const int displaymode = useRenderParams ? fss->renderDisplayMode : fss->guiDisplayMode; switch (displaymode) { - case 1: + case OB_FSDOM_GEOM: /* just display original object */ return NULL; - case 2: + case OB_FSDOM_PREVIEW: /* use preview mesh */ BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_PREVIEW_OBJ_FNAME); break; - default: /* 3 */ - /* 3. use final mesh */ + case OB_FSDOM_FINAL: + /* use final mesh */ BLI_join_dirfile(targetFile, sizeof(targetFile), fss->surfdataPath, OB_FLUIDSIM_SURF_FINAL_OBJ_FNAME); break; + default: + BLI_assert(!"Wrong fluidsim display type"); + return NULL; } /* offset baked frame */ @@ -494,7 +489,7 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, /* load vertex velocities, if they exist... * TODO? use generate flag as loading flag as well? * warning, needs original .bobj.gz mesh loading filename */ - if (displaymode == 3) { + if (displaymode == OB_FSDOM_FINAL) { fluidsim_read_vel_cache(fluidmd, dm, targetFile); } else { diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c index 90fc750de3b..3dd3a5fc598 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_mdd.c +++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c @@ -35,6 +35,9 @@ #ifdef __LITTLE_ENDIAN__ # include "BLI_endian_switch.h" #endif +#ifdef WIN32 +# include "BLI_winstuff.h" +#endif #include "MOD_meshcache_util.h" /* own include */ @@ -157,7 +160,7 @@ bool MOD_meshcache_read_mdd_index(FILE *fp, return false; } - if (fseek(fp, index * mdd_head.verts_tot * sizeof(float) * 3, SEEK_CUR) != 0) { + if (fseek(fp, sizeof(float) * 3 * index * mdd_head.verts_tot, SEEK_CUR) != 0) { *err_str = "Failed to seek frame"; return false; } diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c index 219eae4ecca..8360c8ffda7 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c +++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c @@ -35,6 +35,10 @@ # include "BLI_endian_switch.h" #endif +#ifdef WIN32 +# include "BLI_winstuff.h" +#endif + #include "MOD_meshcache_util.h" /* own include */ #include "DNA_modifier_types.h" @@ -142,7 +146,7 @@ bool MOD_meshcache_read_pc2_index(FILE *fp, return false; } - if (fseek(fp, index * pc2_head.verts_tot * sizeof(float) * 3, SEEK_CUR) != 0) { + if (fseek(fp, sizeof(float) * 3 * index * pc2_head.verts_tot , SEEK_CUR) != 0) { *err_str = "Failed to seek frame"; return false; } diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 406ce398ee0..b1938395a7b 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -83,7 +83,7 @@ static void copyData(ModifierData *md, ModifierData *target) MeshDeformModifierData *mmd = (MeshDeformModifierData *) md; MeshDeformModifierData *tmmd = (MeshDeformModifierData *) target; - *tmmd = *mmd; + modifier_copyData_generic(md, target); if (mmd->bindinfluences) tmmd->bindinfluences = MEM_dupallocN(mmd->bindinfluences); if (mmd->bindoffsets) tmmd->bindoffsets = MEM_dupallocN(mmd->bindoffsets); @@ -91,8 +91,8 @@ static void copyData(ModifierData *md, ModifierData *target) if (mmd->dyngrid) tmmd->dyngrid = MEM_dupallocN(mmd->dyngrid); if (mmd->dyninfluences) tmmd->dyninfluences = MEM_dupallocN(mmd->dyninfluences); if (mmd->dynverts) tmmd->dynverts = MEM_dupallocN(mmd->dynverts); - if (mmd->bindweights) tmmd->dynverts = MEM_dupallocN(mmd->bindweights); /* deprecated */ - if (mmd->bindcos) tmmd->dynverts = MEM_dupallocN(mmd->bindcos); /* deprecated */ + if (mmd->bindweights) tmmd->bindweights = MEM_dupallocN(mmd->bindweights); /* deprecated */ + if (mmd->bindcos) tmmd->bindcos = MEM_dupallocN(mmd->bindcos); /* deprecated */ } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index e77cc655c16..2c0bfc86e7d 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -160,40 +160,19 @@ static void freeData(ModifierData *md) static void copyData(ModifierData *md, ModifierData *target) { #ifdef WITH_OCEANSIM +#if 0 OceanModifierData *omd = (OceanModifierData *) md; +#endif OceanModifierData *tomd = (OceanModifierData *) target; - tomd->geometry_mode = omd->geometry_mode; - tomd->resolution = omd->resolution; - tomd->spatial_size = omd->spatial_size; - - tomd->wind_velocity = omd->wind_velocity; - - tomd->damp = omd->damp; - tomd->smallest_wave = omd->smallest_wave; - tomd->depth = omd->depth; + freeData(target); - tomd->wave_alignment = omd->wave_alignment; - tomd->wave_direction = omd->wave_direction; - tomd->wave_scale = omd->wave_scale; - - tomd->chop_amount = omd->chop_amount; - tomd->foam_coverage = omd->foam_coverage; - tomd->time = omd->time; - - tomd->seed = omd->seed; - tomd->flag = omd->flag; + modifier_copyData_generic(md, target); tomd->refresh = 0; - tomd->size = omd->size; - tomd->repeat_x = omd->repeat_x; - tomd->repeat_y = omd->repeat_y; - /* XXX todo: copy cache runtime too */ tomd->cached = 0; - tomd->bakestart = omd->bakestart; - tomd->bakeend = omd->bakeend; tomd->oceancache = NULL; tomd->ocean = BKE_ocean_add(); diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 776cf02754e..b692137b604 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -138,7 +138,9 @@ static void copyData(ModifierData *md, ModifierData *target) SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target; - *tsmd = *smd; + freeData(target); + + modifier_copyData_generic(md, target); if (smd->verts) { tsmd->verts = MEM_dupallocN(smd->verts); @@ -1120,6 +1122,11 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un tdm = smd->target->derivedFinal; } + if (!tdm) { + modifier_setError(md, "No valid target mesh"); + return; + } + tnumverts = tdm->getNumVerts(tdm); tnumpoly = tdm->getNumPolys(tdm); @@ -1139,19 +1146,19 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un /* Poly count checks */ if (smd->numverts != numverts) { modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts); - tdm->release(tdm); return; } else if (smd->numpoly != tnumpoly) { modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); - tdm->release(tdm); return; } /* Actual vertex location update starts here */ - SDefDeformData data = {.bind_verts = smd->verts, - .targetCos = MEM_mallocN(sizeof(float[3]) * tnumverts, "SDefTargetVertArray"), - .vertexCos = vertexCos}; + SDefDeformData data = { + .bind_verts = smd->verts, + .targetCos = MEM_mallocN(sizeof(float[3]) * tnumverts, "SDefTargetVertArray"), + .vertexCos = vertexCos, + }; if (data.targetCos != NULL) { bool tdm_vert_alloc; @@ -1170,8 +1177,6 @@ static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], un MEM_freeN(data.targetCos); } - - tdm->release(tdm); } static void deformVerts(ModifierData *md, Object *ob, @@ -1194,7 +1199,7 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams)) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; - return !smd->target; + return !smd->target && !(smd->verts && !(smd->flags & MOD_SDEF_BIND)); } ModifierTypeInfo modifierType_SurfaceDeform = { diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 78dc1ea8bcb..01468c1143a 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -45,6 +45,7 @@ #include "BKE_camera.h" +#include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_mesh.h" #include "BKE_DerivedMesh.h" @@ -70,9 +71,12 @@ static void copyData(ModifierData *md, ModifierData *target) { #if 0 UVProjectModifierData *umd = (UVProjectModifierData *) md; - UVProjectModifierData *tumd = (UVProjectModifierData *) target; #endif + UVProjectModifierData *tumd = (UVProjectModifierData *) target; + modifier_copyData_generic(md, target); + + id_us_plus((ID *)tumd->image); } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md)) diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 92d44257d03..b340356467a 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -66,6 +66,10 @@ static void copyData(ModifierData *md, ModifierData *target) WarpModifierData *wmd = (WarpModifierData *) md; WarpModifierData *twmd = (WarpModifierData *) target; + if (twmd->curfalloff != NULL) { + curvemapping_free(twmd->curfalloff); + } + modifier_copyData_generic(md, target); twmd->curfalloff = curvemapping_copy(wmd->curfalloff); diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 2a822ac07b5..cd30b54350c 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -226,8 +226,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der if (!do_add) return dm; /* Else, add a valid data layer! */ - dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, - NULL, numVerts, wmd->defgrp_name); + dvert = CustomData_add_layer(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts); /* Ultimate security check. */ if (!dvert) return dm; diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 9bff7bf11f1..1b3188c83b3 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -282,8 +282,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der if (wmd->mix_set != MOD_WVG_SET_ALL) return dm; /* Else, add a valid data layer! */ - dvert = CustomData_add_layer_named(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, - NULL, numVerts, wmd->defgrp_name_a); + dvert = CustomData_add_layer(&dm->vertData, CD_MDEFORMVERT, CD_CALLOC, NULL, numVerts); /* Ultimate security check. */ if (!dvert) return dm; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index d20881df150..c5a3c70100b 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -163,6 +163,7 @@ set(SRC shader/nodes/node_shader_background.c shader/nodes/node_shader_bsdf_anisotropic.c shader/nodes/node_shader_bsdf_diffuse.c + shader/nodes/node_shader_bsdf_principled.c shader/nodes/node_shader_bsdf_glass.c shader/nodes/node_shader_bsdf_glossy.c shader/nodes/node_shader_bsdf_toon.c @@ -288,8 +289,4 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() -if(WITH_CYCLES AND WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) -endif() - blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 0215db1dd55..a5c2e604f46 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -139,6 +139,8 @@ void register_node_type_cmp_trackpos(void); void register_node_type_cmp_planetrackdeform(void); void register_node_type_cmp_cornerpin(void); -void node_cmp_rlayers_force_hidden_passes(struct bNode *node); +void node_cmp_rlayers_outputs(struct bNodeTree *ntree, struct bNode *node); +void node_cmp_rlayers_register_pass(struct bNodeTree *ntree, struct bNode *node, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type); +const char *node_cmp_rlayers_sock_to_pass(int sock_index); #endif diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 4c0047f1d58..804c1897a27 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -106,6 +106,7 @@ void register_node_type_sh_bsdf_transparent(void); void register_node_type_sh_bsdf_velvet(void); void register_node_type_sh_bsdf_toon(void); void register_node_type_sh_bsdf_anisotropic(void); +void register_node_type_sh_bsdf_principled(void); void register_node_type_sh_emission(void); void register_node_type_sh_holdout(void); void register_node_type_sh_volume_absorption(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index a9c0df7d7e8..02422a8622a 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -80,6 +80,7 @@ DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BA DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" ) DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, def_anisotropic, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse BSDF", "" ) +DefNode( ShaderNode, SH_NODE_BSDF_PRINCIPLED, def_principled, "BSDF_PRINCIPLED", BsdfPrincipled, "Principled BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glass, "BSDF_GLASS", BsdfGlass, "Glass BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_refraction, "BSDF_REFRACTION", BsdfRefraction, "Refraction BSDF", "" ) @@ -178,7 +179,7 @@ DefNode( CompositorNode, CMP_NODE_DISPLACE, 0, "DISPL DefNode( CompositorNode, CMP_NODE_COMBHSVA, 0, "COMBHSVA", CombHSVA, "Combine HSVA", "" ) DefNode( CompositorNode, CMP_NODE_MATH, def_math, "MATH", Math, "Math", "" ) DefNode( CompositorNode, CMP_NODE_LUMA_MATTE, def_cmp_luma_matte, "LUMA_MATTE", LumaMatte, "Luminance Key", "" ) -DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, 0, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" ) +DefNode( CompositorNode, CMP_NODE_BRIGHTCONTRAST, def_cmp_brightcontrast, "BRIGHTCONTRAST", BrightContrast, "Bright/Contrast", "" ) DefNode( CompositorNode, CMP_NODE_GAMMA, 0, "GAMMA", Gamma, "Gamma", "" ) DefNode( CompositorNode, CMP_NODE_INVERT, def_cmp_invert, "INVERT", Invert, "Invert", "" ) DefNode( CompositorNode, CMP_NODE_NORMALIZE, 0, "NORMALIZE", Normalize, "Normalize", "" ) diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index cb565bd5491..36778a18f77 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -240,8 +240,15 @@ void ntreeCompositExecTree(Scene *scene, bNodeTree *ntree, RenderData *rd, int r /* *********************************************** */ -/* based on rules, force sockets hidden always */ -void ntreeCompositForceHidden(bNodeTree *ntree) +/* Update the outputs of the render layer nodes. + * Since the outputs depend on the render engine, this part is a bit complex: + * - ntreeCompositUpdateRLayers is called and loops over all render layer nodes + * - Each render layer node calls the update function of the render engine that's used for its scene + * - The render engine calls RE_engine_register_pass for each pass + * - RE_engine_register_pass calls ntreeCompositRegisterPass, + * which calls node_cmp_rlayers_register_pass for every render layer node + */ +void ntreeCompositUpdateRLayers(bNodeTree *ntree) { bNode *node; @@ -249,16 +256,20 @@ void ntreeCompositForceHidden(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = node->next) { if (node->type == CMP_NODE_R_LAYERS) - node_cmp_rlayers_force_hidden_passes(node); - - /* XXX this stuff is called all the time, don't want that. - * Updates should only happen when actually necessary. - */ -#if 0 - else if (node->type == CMP_NODE_IMAGE) { - nodeUpdate(ntree, node); - } -#endif + node_cmp_rlayers_outputs(ntree, node); + } + +} + +void ntreeCompositRegisterPass(bNodeTree *ntree, Scene *scene, SceneRenderLayer *srl, const char *name, int type) +{ + bNode *node; + + if (ntree == NULL) return; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS) + node_cmp_rlayers_register_pass(ntree, node, scene, srl, name, type); } } diff --git a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c index 2ad097013ef..fde7dccb4ac 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c @@ -47,6 +47,7 @@ static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *no { NodeBilateralBlurData *nbbd = MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data"); node->storage = nbbd; + nbbd->iter = 1; nbbd->sigma_color = 0.3; nbbd->sigma_space = 5.0; } diff --git a/source/blender/nodes/composite/nodes/node_composite_brightness.c b/source/blender/nodes/composite/nodes/node_composite_brightness.c index 62f23f417b2..26e4d3a52c9 100644 --- a/source/blender/nodes/composite/nodes/node_composite_brightness.c +++ b/source/blender/nodes/composite/nodes/node_composite_brightness.c @@ -46,6 +46,10 @@ static bNodeSocketTemplate cmp_node_brightcontrast_out[] = { { -1, 0, "" } }; +static void node_composit_init_brightcontrast(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = 1; +} void register_node_type_cmp_brightcontrast(void) { @@ -53,6 +57,7 @@ void register_node_type_cmp_brightcontrast(void) cmp_node_type_base(&ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, cmp_node_brightcontrast_in, cmp_node_brightcontrast_out); + node_type_init(&ntype, node_composit_init_brightcontrast); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c index 6eb27a228ad..336eb3409ff 100644 --- a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c @@ -46,6 +46,7 @@ static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node) { NodeDBlurData *ndbd = MEM_callocN(sizeof(NodeDBlurData), "node dblur data"); node->storage = ndbd; + ndbd->iter = 1; ndbd->center_x = 0.5; ndbd->center_y = 0.5; } diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 4f02c106569..8139e29bade 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -32,192 +32,108 @@ #include "node_composite_util.h" #include "BLI_utildefines.h" +#include "BLI_linklist.h" #include "DNA_scene_types.h" +#include "RE_engine.h" + #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" -#ifdef WITH_CYCLES_DEBUG -# include "RE_pipeline.h" -#endif - /* **************** IMAGE (and RenderResult, multilayer image) ******************** */ static bNodeSocketTemplate cmp_node_rlayers_out[] = { - { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Z"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("UV"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, N_("Speed"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Specular"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Shadow"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("AO"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Reflect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Refract"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("IndexOB"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("IndexMA"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 0, N_("Mist"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Emit"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Environment"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Diffuse Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Glossy Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Transmission Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Direct"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Indirect"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, N_("Subsurface Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, -#ifdef WITH_CYCLES_DEBUG - { SOCK_RGBA, 0, N_("Debug"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, -#endif + { SOCK_RGBA, 0, N_("Image"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_Z), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_NORMAL), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_UV), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_(RE_PASSNAME_VECTOR), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_RGBA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SPEC), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SHADOW), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_AO), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_REFLECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_REFRACT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXOB), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_INDEXMA), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_(RE_PASSNAME_MIST), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_EMIT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_ENVIRONMENT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_DIFFUSE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_GLOSSY_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_TRANSM_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_DIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_INDIRECT), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int pass, int rres_index) +static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node, + const char *name, const char *passname, + int rres_index, int type, int is_rlayers, + LinkNodePair *available_sockets, int *prev_index) { bNodeSocket *sock; - NodeImageLayer *sockdata; - - sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); - /* extra socket info */ - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); - sock->storage = sockdata; - - sockdata->pass_flag = pass; - - return sock; -} - -static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag) -{ - if (passflag & SCE_PASS_COMBINED) { - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE); - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA); - } - - if (passflag & SCE_PASS_Z) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z); - if (passflag & SCE_PASS_NORMAL) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL); - if (passflag & SCE_PASS_VECTOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC); - if (passflag & SCE_PASS_UV) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV); - if (passflag & SCE_PASS_RGBA) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA); - if (passflag & SCE_PASS_DIFFUSE) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF); - if (passflag & SCE_PASS_SPEC) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC); - if (passflag & SCE_PASS_SHADOW) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW); - if (passflag & SCE_PASS_AO) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO); - if (passflag & SCE_PASS_REFLECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT); - if (passflag & SCE_PASS_REFRACT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT); - if (passflag & SCE_PASS_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT); - if (passflag & SCE_PASS_INDEXOB) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB); - if (passflag & SCE_PASS_INDEXMA) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA); - if (passflag & SCE_PASS_MIST) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST); - if (passflag & SCE_PASS_EMIT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT); - if (passflag & SCE_PASS_ENVIRONMENT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV); - - if (passflag & SCE_PASS_DIFFUSE_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT); - if (passflag & SCE_PASS_DIFFUSE_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT); - if (passflag & SCE_PASS_DIFFUSE_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR); - - if (passflag & SCE_PASS_GLOSSY_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT); - if (passflag & SCE_PASS_GLOSSY_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT); - if (passflag & SCE_PASS_GLOSSY_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR); - - if (passflag & SCE_PASS_TRANSM_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT); - if (passflag & SCE_PASS_TRANSM_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT); - if (passflag & SCE_PASS_TRANSM_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR); - - if (passflag & SCE_PASS_SUBSURFACE_DIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_DIRECT, RRES_OUT_SUBSURFACE_DIRECT); - if (passflag & SCE_PASS_SUBSURFACE_INDIRECT) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_INDIRECT, RRES_OUT_SUBSURFACE_INDIRECT); - if (passflag & SCE_PASS_SUBSURFACE_COLOR) - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SUBSURFACE_COLOR, RRES_OUT_SUBSURFACE_COLOR); - -#ifdef WITH_CYCLES_DEBUG - cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DEBUG, RRES_OUT_DEBUG); -#endif -} - -static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl) -{ - bNodeSocket *sock; - NodeImageLayer *sockdata; - RenderPass *rpass; - int index; - int passflag = 0; - for (rpass = rl->passes.first, index = 0; rpass; rpass = rpass->next, ++index) { - int type; - if (rpass->channels == 1) - type = SOCK_FLOAT; - else - type = SOCK_RGBA; - - /* we only need one socket per type */ - if (passflag & rpass->passtype) - continue; - - passflag |= rpass->passtype; - - sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->internal_name, rpass->internal_name); + int sock_index = BLI_findstringindex(&node->outputs, name, offsetof(bNodeSocket, name)); + + if (sock_index < 0) { + /* The first 31 sockets always are the legacy hardcoded sockets. + * Any dynamically allocated sockets follow afterwards, and are sorted in the order in which they were stored in the RenderResult. + * Therefore, we remember the index of the last matched socket. New sockets are placed behind the previously traversed one, but always after the first 31. */ + int after_index = *prev_index; + if (is_rlayers && after_index < 30) + after_index = 30; + + if (rres_index >= 0) { + sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT); + } + else { + sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, name, name); + } /* extra socket info */ - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); + NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); sock->storage = sockdata; - - sockdata->pass_index = index; - sockdata->pass_flag = rpass->passtype; - - if (rpass->passtype == SCE_PASS_COMBINED) { - sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha"); - sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); - sock->storage = sockdata; - sockdata->pass_index = index; - sockdata->pass_flag = rpass->passtype; + + BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name)); + + sock_index = BLI_listbase_count(&node->outputs) - 1; + if (sock_index != after_index + 1) { + bNodeSocket *after_sock = BLI_findlink(&node->outputs, after_index); + BLI_remlink(&node->outputs, sock); + BLI_insertlinkafter(&node->outputs, after_sock, sock); + } + } + else { + sock = BLI_findlink(&node->outputs, sock_index); + NodeImageLayer *sockdata = sock->storage; + if (sockdata) { + BLI_strncpy(sockdata->pass_name, passname, sizeof(sockdata->pass_name)); } } + + BLI_linklist_append(available_sockets, sock); + *prev_index = sock_index; } -static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) +static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets) { Image *ima = (Image *)node->id; + ImBuf *ibuf; + int prev_index = -1; if (ima) { ImageUser *iuser = node->storage; ImageUser load_iuser = {NULL}; - ImBuf *ibuf; int offset = BKE_image_sequence_guess_offset(ima); /* It is possible that image user in this node is not @@ -238,104 +154,144 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) RenderLayer *rl = BLI_findlink(&ima->rr->layers, iuser->layer); if (rl) { - if (ima->type != IMA_TYPE_MULTILAYER) - cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag); - else - cmp_node_image_add_multilayer_outputs(ntree, node, rl); + RenderPass *rpass; + for (rpass = rl->passes.first; rpass; rpass = rpass->next) { + int type; + if (rpass->channels == 1) + type = SOCK_FLOAT; + else + type = SOCK_RGBA; + + cmp_node_image_add_pass_output(ntree, node, rpass->name, rpass->name, -1, type, false, available_sockets, &prev_index); + /* Special handling for the Combined pass to ensure compatibility. */ + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { + cmp_node_image_add_pass_output(ntree, node, "Alpha", rpass->name, -1, SOCK_FLOAT, false, available_sockets, &prev_index); + } + } + BKE_image_release_ibuf(ima, ibuf, NULL); + return; } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA); } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA | RRES_OUT_Z); - + } + + cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, -1, SOCK_RGBA, false, available_sockets, &prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, -1, SOCK_FLOAT, false, available_sockets, &prev_index); + + if (ima) { BKE_image_release_ibuf(ima, ibuf, NULL); } - else - cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE | RRES_OUT_ALPHA); } -static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist) -{ - bNodeSocket *sock; - - for (sock = oldsocklist->first; sock; sock = sock->next) - if (STREQ(sock->name, newsock->name)) - return sock; - return NULL; -} +typedef struct RLayerUpdateData { + LinkNodePair *available_sockets; + int prev_index; +} RLayerUpdateData; -static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex) +void node_cmp_rlayers_register_pass(bNodeTree *ntree, bNode *node, Scene *scene, SceneRenderLayer *srl, const char *name, int type) { - bNodeSocket *sock; - - /* first try to find matching socket name */ - for (sock = node->outputs.first; sock; sock = sock->next) - if (STREQ(sock->name, oldsock->name)) - return sock; - - /* no matching name, simply link to same index */ - return BLI_findlink(&node->outputs, oldindex); + RLayerUpdateData *data = node->storage; + + if (scene == NULL || srl == NULL || data == NULL || node->id != (ID *)scene) { + return; + } + + SceneRenderLayer *node_srl = BLI_findlink(&scene->r.layers, node->custom1); + if (node_srl != srl) { + return; + } + + /* Special handling for the Combined pass to ensure compatibility. */ + if (STREQ(name, RE_PASSNAME_COMBINED)) { + cmp_node_image_add_pass_output(ntree, node, "Image", name, -1, type, true, data->available_sockets, &data->prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", name, -1, SOCK_FLOAT, true, data->available_sockets, &data->prev_index); + } + else { + cmp_node_image_add_pass_output(ntree, node, name, name, -1, type, true, data->available_sockets, &data->prev_index); + } } -static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock)) +static void cmp_node_rlayer_create_outputs(bNodeTree *ntree, bNode *node, LinkNodePair *available_sockets) { - /* pass */ + Scene *scene = (Scene *)node->id; + + if (scene) { + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + if (engine_type && engine_type->update_render_passes) { + SceneRenderLayer *srl = BLI_findlink(&scene->r.layers, node->custom1); + if (srl) { + RLayerUpdateData *data = MEM_mallocN(sizeof(RLayerUpdateData), "render layer update data"); + data->available_sockets = available_sockets; + data->prev_index = -1; + node->storage = data; + + RenderEngine *engine = RE_engine_create(engine_type); + engine_type->update_render_passes(engine, scene, srl); + RE_engine_free(engine); + + MEM_freeN(data); + node->storage = NULL; + + return; + } + } + } + + int prev_index = -1; + cmp_node_image_add_pass_output(ntree, node, "Image", RE_PASSNAME_COMBINED, RRES_OUT_IMAGE, SOCK_RGBA, true, available_sockets, &prev_index); + cmp_node_image_add_pass_output(ntree, node, "Alpha", RE_PASSNAME_COMBINED, RRES_OUT_ALPHA, SOCK_FLOAT, true, available_sockets, &prev_index); } /* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */ -static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node) +static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rlayer) { - bNodeSocket *newsock, *oldsock, *oldsock_next; - ListBase oldsocklist; - int oldindex; - bNodeLink *link; - - /* store current nodes in oldsocklist, then clear socket list */ - oldsocklist = node->outputs; - BLI_listbase_clear(&node->outputs); + bNodeSocket *sock, *sock_next; + LinkNodePair available_sockets = {NULL, NULL}; + int sock_index; /* XXX make callback */ - cmp_node_image_create_outputs(ntree, node); - - for (newsock = node->outputs.first; newsock; newsock = newsock->next) { - /* XXX make callback */ - oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist); - if (oldsock) { - /* XXX make callback */ - cmp_node_image_sync_output(node, newsock, oldsock); + if (rlayer) + cmp_node_rlayer_create_outputs(ntree, node, &available_sockets); + else + cmp_node_image_create_outputs(ntree, node, &available_sockets); + + /* Get rid of sockets whose passes are not available in the image. + * If sockets that are not available would be deleted, the connections to them would be lost + * when e.g. opening a file (since there's no render at all yet). + * Therefore, sockets with connected links will just be set as unavailable. + * + * Another important detail comes from compatibility with the older socket model, where there + * was a fixed socket per pass type that was just hidden or not. Therefore, older versions expect + * the first 31 passes to belong to a specific pass type. + * So, we keep those 31 always allocated before the others as well, even if they have no links attached. */ + sock_index = 0; + for (sock = node->outputs.first; sock; sock = sock_next, sock_index++) { + sock_next = sock->next; + if (BLI_linklist_index(available_sockets.list, sock) >= 0) { + sock->flag &= ~(SOCK_UNAVAIL | SOCK_HIDDEN); } - } - - /* move links to new socket */ - for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) { - newsock = cmp_node_image_output_relink(node, oldsock, oldindex); - - if (newsock) { + else { + bNodeLink *link; for (link = ntree->links.first; link; link = link->next) { - if (link->fromsock == oldsock) - link->fromsock = newsock; + if (link->fromsock == sock) break; + } + if (!link && (!rlayer || sock_index > 30)) { + MEM_freeN(sock->storage); + nodeRemoveSocket(ntree, node, sock); + } + else { + sock->flag |= SOCK_UNAVAIL; } } } - - /* delete old sockets - * XXX oldsock is not actually in the node->outputs list any more, - * but the nodeRemoveSocket function works anyway. In future this - * should become part of the core code, so can take care of this behavior. - */ - for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) { - oldsock_next = oldsock->next; - MEM_freeN(oldsock->storage); - nodeRemoveSocket(ntree, node, oldsock); - } + + BLI_linklist_free(available_sockets.list, NULL); } static void cmp_node_image_update(bNodeTree *ntree, bNode *node) { /* avoid unnecessary updates, only changes to the image/image user data are of interest */ if (node->update & NODE_UPDATE_ID) - cmp_node_image_verify_outputs(ntree, node); + cmp_node_image_verify_outputs(ntree, node, false); } static void node_composit_init_image(bNodeTree *ntree, bNode *node) @@ -348,7 +304,7 @@ static void node_composit_init_image(bNodeTree *ntree, bNode *node) iuser->ok = 1; /* setup initial outputs */ - cmp_node_image_verify_outputs(ntree, node); + cmp_node_image_verify_outputs(ntree, node, false); } static void node_composit_free_image(bNode *node) @@ -388,87 +344,44 @@ void register_node_type_cmp_image(void) /* **************** RENDER RESULT ******************** */ -static void set_output_visible(bNode *node, int passflag, int index, int pass) +void node_cmp_rlayers_outputs(bNodeTree *ntree, bNode *node) { - bNodeSocket *sock = BLI_findlink(&node->outputs, index); - bool pass_enabled = ((passflag & pass) != 0); -#ifdef WITH_CYCLES_DEBUG - pass_enabled |= (pass == SCE_PASS_DEBUG); -#endif - /* clear the SOCK_HIDDEN flag as well, in case a socket was hidden before */ - if (pass_enabled) - sock->flag &= ~(SOCK_HIDDEN | SOCK_UNAVAIL); - else - sock->flag |= SOCK_UNAVAIL; + cmp_node_image_verify_outputs(ntree, node, true); } -/* clumsy checking... should do dynamic outputs once */ -void node_cmp_rlayers_force_hidden_passes(bNode *node) +const char *node_cmp_rlayers_sock_to_pass(int sock_index) { - Scene *scene = (Scene *)node->id; - SceneRenderLayer *srl; - int passflag; - bNodeSocket *sock; - - /* must always have valid scene pointer */ - if (!scene) - return; - - srl = BLI_findlink(&scene->r.layers, node->custom1); - if (!srl) - return; - - passflag = srl->passflag; - - for (sock = node->outputs.first; sock; sock = sock->next) - sock->flag &= ~SOCK_UNAVAIL; - - set_output_visible(node, passflag, RRES_OUT_IMAGE, SCE_PASS_COMBINED); - set_output_visible(node, passflag, RRES_OUT_ALPHA, SCE_PASS_COMBINED); - - set_output_visible(node, passflag, RRES_OUT_Z, SCE_PASS_Z); - set_output_visible(node, passflag, RRES_OUT_NORMAL, SCE_PASS_NORMAL); - set_output_visible(node, passflag, RRES_OUT_VEC, SCE_PASS_VECTOR); - set_output_visible(node, passflag, RRES_OUT_UV, SCE_PASS_UV); - set_output_visible(node, passflag, RRES_OUT_RGBA, SCE_PASS_RGBA); - set_output_visible(node, passflag, RRES_OUT_DIFF, SCE_PASS_DIFFUSE); - set_output_visible(node, passflag, RRES_OUT_SPEC, SCE_PASS_SPEC); - set_output_visible(node, passflag, RRES_OUT_SHADOW, SCE_PASS_SHADOW); - set_output_visible(node, passflag, RRES_OUT_AO, SCE_PASS_AO); - set_output_visible(node, passflag, RRES_OUT_REFLECT, SCE_PASS_REFLECT); - set_output_visible(node, passflag, RRES_OUT_REFRACT, SCE_PASS_REFRACT); - set_output_visible(node, passflag, RRES_OUT_INDIRECT, SCE_PASS_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_INDEXOB, SCE_PASS_INDEXOB); - set_output_visible(node, passflag, RRES_OUT_INDEXMA, SCE_PASS_INDEXMA); - set_output_visible(node, passflag, RRES_OUT_MIST, SCE_PASS_MIST); - set_output_visible(node, passflag, RRES_OUT_EMIT, SCE_PASS_EMIT); - set_output_visible(node, passflag, RRES_OUT_ENV, SCE_PASS_ENVIRONMENT); - set_output_visible(node, passflag, RRES_OUT_DIFF_DIRECT, SCE_PASS_DIFFUSE_DIRECT); - set_output_visible(node, passflag, RRES_OUT_DIFF_INDIRECT, SCE_PASS_DIFFUSE_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_DIFF_COLOR, SCE_PASS_DIFFUSE_COLOR); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_DIRECT, SCE_PASS_GLOSSY_DIRECT); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_INDIRECT, SCE_PASS_GLOSSY_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_GLOSSY_COLOR, SCE_PASS_GLOSSY_COLOR); - set_output_visible(node, passflag, RRES_OUT_TRANSM_DIRECT, SCE_PASS_TRANSM_DIRECT); - set_output_visible(node, passflag, RRES_OUT_TRANSM_INDIRECT, SCE_PASS_TRANSM_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_TRANSM_COLOR, SCE_PASS_TRANSM_COLOR); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_DIRECT, SCE_PASS_SUBSURFACE_DIRECT); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_INDIRECT, SCE_PASS_SUBSURFACE_INDIRECT); - set_output_visible(node, passflag, RRES_OUT_SUBSURFACE_COLOR, SCE_PASS_SUBSURFACE_COLOR); - -#ifdef WITH_CYCLES_DEBUG - set_output_visible(node, passflag, RRES_OUT_DEBUG, SCE_PASS_DEBUG); -#endif + const char *sock_to_passname[] = { + RE_PASSNAME_COMBINED, RE_PASSNAME_COMBINED, + RE_PASSNAME_Z, RE_PASSNAME_NORMAL, RE_PASSNAME_UV, RE_PASSNAME_VECTOR, RE_PASSNAME_RGBA, + RE_PASSNAME_DIFFUSE, RE_PASSNAME_SPEC, RE_PASSNAME_SHADOW, RE_PASSNAME_AO, + RE_PASSNAME_REFLECT, RE_PASSNAME_REFRACT, RE_PASSNAME_INDIRECT, + RE_PASSNAME_INDEXOB, RE_PASSNAME_INDEXMA, RE_PASSNAME_MIST, RE_PASSNAME_EMIT, RE_PASSNAME_ENVIRONMENT, + RE_PASSNAME_DIFFUSE_DIRECT, RE_PASSNAME_DIFFUSE_INDIRECT, RE_PASSNAME_DIFFUSE_COLOR, + RE_PASSNAME_GLOSSY_DIRECT, RE_PASSNAME_GLOSSY_INDIRECT, RE_PASSNAME_GLOSSY_COLOR, + RE_PASSNAME_TRANSM_DIRECT, RE_PASSNAME_TRANSM_INDIRECT, RE_PASSNAME_TRANSM_COLOR, + RE_PASSNAME_SUBSURFACE_DIRECT, RE_PASSNAME_SUBSURFACE_INDIRECT, RE_PASSNAME_SUBSURFACE_COLOR + }; + if (sock_index > 30) { + return NULL; + } + return sock_to_passname[sock_index]; } static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); bNode *node = ptr->data; - + int sock_index = 0; + node->id = &scene->id; - - node_cmp_rlayers_force_hidden_passes(node); + + for (bNodeSocket *sock = node->outputs.first; sock; sock = sock->next, sock_index++) { + NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); + sock->storage = sockdata; + + BLI_strncpy(sockdata->pass_name, node_cmp_rlayers_sock_to_pass(sock_index), sizeof(sockdata->pass_name)); + } } static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree) @@ -489,6 +402,29 @@ static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree return false; } +static void node_composit_free_rlayers(bNode *node) +{ + bNodeSocket *sock; + + /* free extra socket info */ + for (sock = node->outputs.first; sock; sock = sock->next) + MEM_freeN(sock->storage); +} + +static void node_composit_copy_rlayers(bNodeTree *UNUSED(dest_ntree), bNode *UNUSED(dest_node), bNode *src_node) +{ + bNodeSocket *sock; + + /* copy extra socket info */ + for (sock = src_node->outputs.first; sock; sock = sock->next) + sock->new_sock->storage = MEM_dupallocN(sock->storage); +} + +static void cmp_node_rlayers_update(bNodeTree *ntree, bNode *node) +{ + cmp_node_image_verify_outputs(ntree, node, true); +} + void register_node_type_cmp_rlayers(void) { static bNodeType ntype; @@ -497,6 +433,9 @@ void register_node_type_cmp_rlayers(void) node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out); ntype.initfunc_api = node_composit_init_rlayers; ntype.poll = node_composit_poll_rlayers; + node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers); + node_type_update(&ntype, cmp_node_rlayers_update, NULL); + node_type_init(&ntype, node_cmp_rlayers_outputs); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c index d805cf4d87f..e0d9fa33f13 100644 --- a/source/blender/nodes/composite/nodes/node_composite_switchview.c +++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c @@ -137,7 +137,6 @@ static void init_switch_view(const bContext *C, PointerRNA *ptr) cmp_node_switch_view_sanitycheck(ntree, node); } -/* custom1 = mix type */ void register_node_type_cmp_switch_view(void) { static bNodeType ntype; diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 2347564c696..0cf131adbdc 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -78,7 +78,8 @@ void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack static void node_init_input_index(bNodeSocket *sock, int *index) { - if (sock->link && sock->link->fromsock) { + /* Only consider existing link if from socket is valid! */ + if (sock->link && sock->link->fromsock && sock->link->fromsock->stack_index >= 0) { sock->stack_index = sock->link->fromsock->stack_index; } else { diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 9bd43f331fb..5bc97f13b41 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -142,28 +142,40 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns) { memset(gs, 0, sizeof(*gs)); - nodestack_get_vec(gs->vec, type, ns); - gs->link = ns->data; - - if (type == SOCK_FLOAT) - gs->type = GPU_FLOAT; - else if (type == SOCK_VECTOR) - gs->type = GPU_VEC3; - else if (type == SOCK_RGBA) - gs->type = GPU_VEC4; - else if (type == SOCK_SHADER) - gs->type = GPU_VEC4; - else + if (ns == NULL) { + /* node_get_stack() will generate NULL bNodeStack pointers for unknown/unsuported types of sockets... */ + zero_v4(gs->vec); + gs->link = NULL; gs->type = GPU_NONE; + gs->name = ""; + gs->hasinput = false; + gs->hasoutput = false; + gs->sockettype = type; + } + else { + nodestack_get_vec(gs->vec, type, ns); + gs->link = ns->data; - gs->name = ""; - gs->hasinput = ns->hasinput && ns->data; - /* XXX Commented out the ns->data check here, as it seems it's not always set, - * even though there *is* a valid connection/output... But that might need - * further investigation. - */ - gs->hasoutput = ns->hasoutput /*&& ns->data*/; - gs->sockettype = ns->sockettype; + if (type == SOCK_FLOAT) + gs->type = GPU_FLOAT; + else if (type == SOCK_VECTOR) + gs->type = GPU_VEC3; + else if (type == SOCK_RGBA) + gs->type = GPU_VEC4; + else if (type == SOCK_SHADER) + gs->type = GPU_VEC4; + else + gs->type = GPU_NONE; + + gs->name = ""; + gs->hasinput = ns->hasinput && ns->data; + /* XXX Commented out the ns->data check here, as it seems it's not always set, + * even though there *is* a valid connection/output... But that might need + * further investigation. + */ + gs->hasoutput = ns->hasoutput /*&& ns->data*/; + gs->sockettype = ns->sockettype; + } } void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs) diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c new file mode 100644 index 00000000000..e0330d110ca --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c @@ -0,0 +1,114 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_bsdf_principled_in[] = { + { SOCK_RGBA, 1, N_("Base Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Subsurface"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_VECTOR, 1, N_("Subsurface Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f}, + { SOCK_RGBA, 1, N_("Subsurface Color"), 0.7f, 0.1f, 0.1f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Metallic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Specular"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Specular Tint"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Roughness"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Anisotropic"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Anisotropic Rotation"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Sheen"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Sheen Tint"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Clearcoat"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Clearcoat Roughness"), 0.03f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, + { SOCK_FLOAT, 1, N_("Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Transmission Roughness"),0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_VECTOR, 1, N_("Clearcoat Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_VECTOR, 1, N_("Tangent"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_bsdf_principled_out[] = { + { SOCK_SHADER, 0, N_("BSDF")}, + { -1, 0, "" } +}; + +static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node) +{ + node->custom1 = SHD_GLOSSY_MULTI_GGX; +} + +static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + // normal + if (!in[17].link) + in[17].link = GPU_builtin(GPU_VIEW_NORMAL); + else + GPU_link(mat, "direction_transform_m4v3", in[17].link, GPU_builtin(GPU_VIEW_MATRIX), &in[17].link); + + // clearcoat normal + if (!in[18].link) + in[18].link = GPU_builtin(GPU_VIEW_NORMAL); + else + GPU_link(mat, "direction_transform_m4v3", in[18].link, GPU_builtin(GPU_VIEW_MATRIX), &in[18].link); + + return GPU_stack_link(mat, "node_bsdf_principled", in, out, GPU_builtin(GPU_VIEW_POSITION)); +} + +static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock; + int distribution = node->custom1; + + for (sock = node->inputs.first; sock; sock = sock->next) { + if (STREQ(sock->name, "Transmission Roughness")) { + if (distribution == SHD_GLOSSY_GGX) + sock->flag &= ~SOCK_UNAVAIL; + else + sock->flag |= SOCK_UNAVAIL; + + } + } +} + +/* node type definition */ +void register_node_type_sh_bsdf_principled(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_bsdf_principled_in, sh_node_bsdf_principled_out); + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); + node_type_init(&ntype, node_shader_init_principled); + node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_shader_gpu_bsdf_principled); + node_type_update(&ntype, node_shader_update_principled, NULL); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c index e0bf34f42e4..36d7522e3e6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -46,8 +46,10 @@ static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node) node->storage = attr; } -static void node_shader_exec_normal_map(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out) - { +static void node_shader_exec_normal_map( + void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), + bNodeStack **in, bNodeStack **out) +{ if (data) { ShadeInput *shi = ((ShaderCallData *)data)->shi; diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c index d1905246fd4..63d3bac88a0 100644 --- a/source/blender/nodes/shader/nodes/node_shader_object_info.c +++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c @@ -39,7 +39,16 @@ static bNodeSocketTemplate sh_node_object_info_out[] = { static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return GPU_stack_link(mat, "node_object_info", in, out); + return GPU_stack_link(mat, "node_object_info", in, out, GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_OBJECT_INFO)); +} + +static void node_shader_exec_object_info(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **UNUSED(in), bNodeStack **out) +{ + ShaderCallData *scd = (ShaderCallData *)data; + copy_v4_v4(out[0]->vec, RE_object_instance_get_matrix(scd->shi->obi, RE_OBJECT_INSTANCE_MATRIX_OB)[3]); + out[1]->vec[0] = RE_object_instance_get_object_pass_index(scd->shi->obi); + out[2]->vec[0] = scd->shi->mat->index; + out[3]->vec[0] = RE_object_instance_get_random_id(scd->shi->obi) * (1.0f / (float)0xFFFFFFFF); } /* node type definition */ @@ -53,6 +62,7 @@ void register_node_type_sh_object_info(void) node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); node_type_gpu(&ntype, node_shader_gpu_object_info); + node_type_exec(&ntype, NULL, NULL, node_shader_exec_object_info); nodeRegisterType(&ntype); } diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index ed2752d8372..7ab6447d21a 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -248,8 +248,17 @@ PyObject *bpy_text_reimport(PyObject *module, int *found) if ((name = PyModule_GetName(module)) == NULL) return NULL; - if ((filepath = (char *)PyModule_GetFilename(module)) == NULL) - return NULL; + { + PyObject *module_file = PyModule_GetFilenameObject(module); + if (module_file == NULL) { + return NULL; + } + filepath = (char *)_PyUnicode_AsString(module_file); + Py_DECREF(module_file); + if (filepath == NULL) { + return NULL; + } + } /* look up the text object */ text = BLI_findstring(&maggie->text, BLI_path_basename(filepath), offsetof(ID, name) + 2); diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 0a9931f2683..5d6a7c578a2 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -43,6 +43,9 @@ #include "python_utildefines.h" +extern bool pyrna_id_FromPyObject(PyObject *obj, ID **id); +extern PyObject *pyrna_id_CreatePyObject(ID *id); +extern bool pyrna_id_CheckPyObject(PyObject *obj); /*********************** ID Property Main Wrapper Stuff ***************/ @@ -88,6 +91,11 @@ static PyObject *idprop_py_from_idp_group(ID *id, IDProperty *prop, IDProperty * return (PyObject *)group; } +static PyObject *idprop_py_from_idp_id(IDProperty *prop) +{ + return pyrna_id_CreatePyObject(prop->data.pointer); +} + static PyObject *idprop_py_from_idp_array(ID *id, IDProperty *prop) { BPy_IDProperty *array = PyObject_New(BPy_IDProperty, &BPy_IDArray_Type); @@ -148,6 +156,7 @@ PyObject *BPy_IDGroup_WrapData(ID *id, IDProperty *prop, IDProperty *parent) case IDP_GROUP: return idprop_py_from_idp_group(id, prop, parent); case IDP_ARRAY: return idprop_py_from_idp_array(id, prop); case IDP_IDPARRAY: return idprop_py_from_idp_idparray(id, prop); /* this could be better a internal type */ + case IDP_ID: return idprop_py_from_idp_id(prop); default: Py_RETURN_NONE; } } @@ -586,8 +595,15 @@ static IDProperty *idp_from_PyMapping(const char *name, PyObject *ob) return prop; } +static IDProperty *idp_from_DatablockPointer(const char *name, PyObject *ob, IDPropertyTemplate *val) +{ + pyrna_id_FromPyObject(ob, &val->id); + return IDP_New(IDP_ID, val, name); +} + static IDProperty *idp_from_PyObject(PyObject *name_obj, PyObject *ob) { + IDPropertyTemplate val = {0}; const char *name = idp_try_read_name(name_obj); if (name == NULL) { return NULL; @@ -608,6 +624,9 @@ static IDProperty *idp_from_PyObject(PyObject *name_obj, PyObject *ob) else if (PySequence_Check(ob)) { return idp_from_PySequence(name, ob); } + else if (ob == Py_None || pyrna_id_CheckPyObject(ob)) { + return idp_from_DatablockPointer(name, ob, &val); + } else if (PyMapping_Check(ob)) { return idp_from_PyMapping(name, ob); } @@ -732,6 +751,8 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop) return idprop_py_from_idp_float(prop); case IDP_DOUBLE: return idprop_py_from_idp_double(prop); + case IDP_ID: + return idprop_py_from_idp_id(prop); case IDP_ARRAY: { PyObject *seq = PyList_New(prop->len); diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 2e789d6d4b3..861e2dbb0df 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -300,7 +300,14 @@ void PyC_FileAndNum(const char **filename, int *lineno) if (mod_name) { PyObject *mod = PyDict_GetItem(PyImport_GetModuleDict(), mod_name); if (mod) { - *filename = PyModule_GetFilename(mod); + PyObject *mod_file = PyModule_GetFilenameObject(mod); + if (mod_file) { + *filename = _PyUnicode_AsString(mod_name); + Py_DECREF(mod_file); + } + else { + PyErr_Clear(); + } } /* unlikely, fallback */ diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 038c1e7eb10..be4db6477fe 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -55,6 +55,7 @@ set(SRC bpy_app_handlers.c bpy_app_ocio.c bpy_app_oiio.c + bpy_app_opensubdiv.c bpy_app_openvdb.c bpy_app_sdl.c bpy_app_translations.c @@ -89,6 +90,7 @@ set(SRC bpy_app_handlers.h bpy_app_ocio.h bpy_app_oiio.h + bpy_app_opensubdiv.h bpy_app_openvdb.h bpy_app_sdl.h bpy_app_translations.h @@ -295,6 +297,13 @@ if(WITH_OPENIMAGEIO) ) endif() +if(WITH_OPENSUBDIV) + add_definitions(-DWITH_OPENSUBDIV) + list(APPEND INC + ../../../../intern/opensubdiv + ) +endif() + if(WITH_PLAYER) add_definitions(-DWITH_PLAYER) endif() diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index ed7cec2f2d5..e47bf21f04b 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -37,6 +37,7 @@ #include "bpy_app_ffmpeg.h" #include "bpy_app_ocio.h" #include "bpy_app_oiio.h" +#include "bpy_app_opensubdiv.h" #include "bpy_app_openvdb.h" #include "bpy_app_sdl.h" #include "bpy_app_build_options.h" @@ -88,6 +89,7 @@ static PyStructSequence_Field app_info_fields[] = { {(char *)"version_cycle", (char *)"The release status of this build alpha/beta/rc/release"}, {(char *)"binary_path", (char *)"The location of blenders executable, useful for utilities that spawn new instances"}, {(char *)"background", (char *)"Boolean, True when blender is running without a user interface (started with -b)"}, + {(char *)"factory_startup", (char *)"Boolean, True when blender is running with --factory-startup)"}, /* buildinfo */ {(char *)"build_date", (char *)"The date this blender instance was built"}, @@ -109,6 +111,7 @@ static PyStructSequence_Field app_info_fields[] = { {(char *)"ffmpeg", (char *)"FFmpeg library information backend"}, {(char *)"ocio", (char *)"OpenColorIO library information backend"}, {(char *)"oiio", (char *)"OpenImageIO library information backend"}, + {(char *)"opensubdiv", (char *)"OpenSubdiv library information backend"}, {(char *)"openvdb", (char *)"OpenVDB library information backend"}, {(char *)"sdl", (char *)"SDL library information backend"}, {(char *)"build_options", (char *)"A set containing most important enabled optional build features"}, @@ -117,9 +120,21 @@ static PyStructSequence_Field app_info_fields[] = { {NULL}, }; +PyDoc_STRVAR(bpy_app_doc, +"This module contains application values that remain unchanged during runtime.\n" +"\n" +"Submodules:\n" +"\n" +".. toctree::\n" +" :maxdepth: 1\n" +"\n" +" bpy.app.handlers.rst\n" +" bpy.app.translations.rst\n" +); + static PyStructSequence_Desc app_info_desc = { (char *)"bpy.app", /* name */ - (char *)"This module contains application values that remain unchanged during runtime.", /* doc */ + bpy_app_doc, /* doc */ app_info_fields, /* fields */ ARRAY_SIZE(app_info_fields) - 1 }; @@ -151,6 +166,7 @@ static PyObject *make_app_info(void) SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE)); SetStrItem(BKE_appdir_program_path()); SetObjItem(PyBool_FromLong(G.background)); + SetObjItem(PyBool_FromLong(G.factory_startup)); /* build info, use bytes since we can't assume _any_ encoding: * see patch [#30154] for issue */ @@ -188,6 +204,7 @@ static PyObject *make_app_info(void) SetObjItem(BPY_app_ffmpeg_struct()); SetObjItem(BPY_app_ocio_struct()); SetObjItem(BPY_app_oiio_struct()); + SetObjItem(BPY_app_opensubdiv_struct()); SetObjItem(BPY_app_openvdb_struct()); SetObjItem(BPY_app_sdl_struct()); SetObjItem(BPY_app_build_options_struct()); diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 1cc2d6f1307..fdc2371c259 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -126,7 +126,7 @@ static PyObject *bpy_app_handlers_persistent_new(PyTypeObject *UNUSED(type), PyO /* dummy type because decorators can't be PyCFunctions */ static PyTypeObject BPyPersistent_Type = { -#if defined(_MSC_VER) || defined(FREE_WINDOWS) +#if defined(_MSC_VER) PyVarObject_HEAD_INIT(NULL, 0) #else PyVarObject_HEAD_INIT(&PyType_Type, 0) @@ -206,7 +206,7 @@ PyObject *BPY_app_handlers_struct(void) { PyObject *ret; -#if defined(_MSC_VER) || defined(FREE_WINDOWS) +#if defined(_MSC_VER) BPyPersistent_Type.ob_base.ob_base.ob_type = &PyType_Type; #endif diff --git a/source/blender/python/intern/bpy_app_opensubdiv.c b/source/blender/python/intern/bpy_app_opensubdiv.c new file mode 100644 index 00000000000..7f269baf2b0 --- /dev/null +++ b/source/blender/python/intern/bpy_app_opensubdiv.c @@ -0,0 +1,109 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_opensubdiv.c + * \ingroup pythonintern + */ + +#include <Python.h> +#include "BLI_utildefines.h" + +#include "bpy_app_opensubdiv.h" + +#ifdef WITH_OPENSUBDIV +# include "opensubdiv_capi.h" +#endif + +static PyTypeObject BlenderAppOpenSubdivType; + +static PyStructSequence_Field app_opensubdiv_info_fields[] = { + {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenSubdiv support")}, + {(char *)("version"), (char *)("The OpenSubdiv version as a tuple of 3 numbers")}, + {(char *)("version_string"), (char *)("The OpenSubdiv version formatted as a string")}, + {NULL} +}; + +static PyStructSequence_Desc app_opensubdiv_info_desc = { + (char *)"bpy.app.opensubdiv", /* name */ + (char *)"This module contains information about OpenSubdiv blender is linked against", /* doc */ + app_opensubdiv_info_fields, /* fields */ + ARRAY_SIZE(app_opensubdiv_info_fields) - 1 +}; + +static PyObject *make_opensubdiv_info(void) +{ + PyObject *opensubdiv_info; + int pos = 0; + + opensubdiv_info = PyStructSequence_New(&BlenderAppOpenSubdivType); + if (opensubdiv_info == NULL) { + return NULL; + } + +#ifndef WITH_OPENSUBDIV +#define SetStrItem(str) \ + PyStructSequence_SET_ITEM(opensubdiv_info, pos++, PyUnicode_FromString(str)) +#endif + +#define SetObjItem(obj) \ + PyStructSequence_SET_ITEM(opensubdiv_info, pos++, obj) + +#ifdef WITH_OPENSUBDIV + int curversion = openSubdiv_getVersionHex(); + SetObjItem(PyBool_FromLong(1)); + SetObjItem(Py_BuildValue("(iii)", + curversion / 10000, (curversion / 100) % 100, curversion % 100)); + SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d", + curversion / 10000, (curversion / 100) % 100, curversion % 100)); +#else + SetObjItem(PyBool_FromLong(0)); + SetObjItem(Py_BuildValue("(iii)", 0, 0, 0)); + SetStrItem("Unknown"); +#endif + + if (PyErr_Occurred()) { + Py_CLEAR(opensubdiv_info); + return NULL; + } + +#undef SetStrItem +#undef SetObjItem + + return opensubdiv_info; +} + +PyObject *BPY_app_opensubdiv_struct(void) +{ + PyObject *ret; + + PyStructSequence_InitType(&BlenderAppOpenSubdivType, &app_opensubdiv_info_desc); + + ret = make_opensubdiv_info(); + + /* prevent user from creating new instances */ + BlenderAppOpenSubdivType.tp_init = NULL; + BlenderAppOpenSubdivType.tp_new = NULL; + /* without this we can't do set(sys.modules) [#29635] */ + BlenderAppOpenSubdivType.tp_hash = (hashfunc)_Py_HashPointer; + + return ret; +} diff --git a/source/blender/depsgraph/util/deg_util_hash.h b/source/blender/python/intern/bpy_app_opensubdiv.h index e490be1a7a1..b1da218b168 100644 --- a/source/blender/depsgraph/util/deg_util_hash.h +++ b/source/blender/python/intern/bpy_app_opensubdiv.h @@ -15,27 +15,18 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * The Original Code is Copyright (C) 2014 Blender Foundation. - * All rights reserved. - * - * Original Author: Brecht van Lommel - * Contributor(s): Lukas Toenne + * Contributor(s): Sergey Sharybin * * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/depsgraph/util/deg_util_hash.h - * \ingroup depsgraph +/** \file blender/python/intern/bpy_app_opensubdiv.h + * \ingroup pythonintern */ -#pragma once - -#include "BLI_utildefines.h" +#ifndef __BPY_APP_OPENSUBDIV_H__ +#define __BPY_APP_OPENSUBDIV_H__ -#include "BLI_ghash.h" +PyObject *BPY_app_opensubdiv_struct(void); -/* XXX this might require 2 different variants for sizeof(size_t) (32 vs 64 bit) */ -BLI_INLINE size_t hash_combine(size_t hash_a, size_t hash_b) -{ - return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); -} +#endif /* __BPY_APP_OPENSUBDIV_H__ */ diff --git a/source/blender/python/intern/bpy_app_sdl.c b/source/blender/python/intern/bpy_app_sdl.c index 2f4d8e6c325..76dab775953 100644 --- a/source/blender/python/intern/bpy_app_sdl.c +++ b/source/blender/python/intern/bpy_app_sdl.c @@ -56,7 +56,7 @@ static PyStructSequence_Field app_sdl_info_fields[] = { {(char *)"available", (char *)("Boolean, True when SDL is available. This is False when " "either *supported* is False, or *dynload* is True and " "Blender cannot find the correct library.")}, - {NULL} + {NULL} }; static PyStructSequence_Desc app_sdl_info_desc = { diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 55e477b0214..20cfd364a0c 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -480,11 +480,20 @@ static bool python_script_exec( * object, but as written in the Python/C API Ref Manual, chapter 2, * 'FILE structs for different C libraries can be different and * incompatible'. - * So now we load the script file data to a buffer */ + * So now we load the script file data to a buffer. + * + * Note on use of 'globals()', it's important not copy the dictionary because + * tools may inspect 'sys.modules["__main__"]' for variables defined in the code + * where using a copy of 'globals()' causes code execution + * to leave the main namespace untouched. see: T51444 + * + * This leaves us with the problem of variables being included, + * currently this is worked around using 'dict.__del__' it's ugly but works. + */ { const char *pystring = - "ns = globals().copy()\n" - "with open(__file__, 'rb') as f: exec(compile(f.read(), __file__, 'exec'), ns)"; + "with open(__file__, 'rb') as f:" + "exec(compile(f.read(), __file__, 'exec'), globals().__delitem__('f') or globals())"; fclose(fp); @@ -860,6 +869,7 @@ static void bpy_module_delay_init(PyObject *bpy_proxy) BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs)); BLI_path_cwd(filename_abs, sizeof(filename_abs)); + Py_DECREF(filename_obj); argv[0] = filename_abs; argv[1] = NULL; diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 11e27ca3e3c..90719905a79 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -118,7 +118,7 @@ static void operator_properties_init(wmOperatorType *ot) } -void operator_wrapper(wmOperatorType *ot, void *userdata) +void BPY_RNA_operator_wrapper(wmOperatorType *ot, void *userdata) { /* take care not to overwrite anything set in * WM_operatortype_append_ptr before opfunc() is called */ @@ -134,7 +134,7 @@ void operator_wrapper(wmOperatorType *ot, void *userdata) operator_properties_init(ot); } -void macro_wrapper(wmOperatorType *ot, void *userdata) +void BPY_RNA_operator_macro_wrapper(wmOperatorType *ot, void *userdata) { wmOperatorType *data = (wmOperatorType *)userdata; diff --git a/source/blender/python/intern/bpy_operator_wrap.h b/source/blender/python/intern/bpy_operator_wrap.h index 05a566a1485..0828c58e2bd 100644 --- a/source/blender/python/intern/bpy_operator_wrap.h +++ b/source/blender/python/intern/bpy_operator_wrap.h @@ -33,7 +33,7 @@ struct wmOperatorType; PyObject *PYOP_wrap_macro_define(PyObject *self, PyObject *args); /* exposed to rna/wm api */ -void operator_wrapper(struct wmOperatorType *ot, void *userdata); -void macro_wrapper(struct wmOperatorType *ot, void *userdata); +void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata); +void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata); #endif diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index f7348ac2250..362c0281b36 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -50,11 +50,13 @@ #include "../generic/py_capi_utils.h" /* initial definition of callback slots we'll probably have more than 1 */ -#define BPY_DATA_CB_SLOT_SIZE 3 - -#define BPY_DATA_CB_SLOT_UPDATE 0 -#define BPY_DATA_CB_SLOT_GET 1 -#define BPY_DATA_CB_SLOT_SET 2 +enum { + BPY_DATA_CB_SLOT_UPDATE = 0, + BPY_DATA_CB_SLOT_GET = 1, + BPY_DATA_CB_SLOT_SET = 2, + BPY_DATA_CB_SLOT_POLL = 3, + BPY_DATA_CB_SLOT_SIZE = 4, +}; extern BPy_StructRNA *bpy_context_module; @@ -71,6 +73,9 @@ static EnumPropertyItem property_flag_items[] = { " :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'LIBRARY_EDITABLE', 'PROPORTIONAL'," \ "'TEXTEDIT_UPDATE'].\n" \ " :type options: set\n" \ +" :arg poll: function to be called to determine whether an item is valid for this property.\n" \ +" The function must take 2 values (self,object) and return Bool.\n" \ +" :type poll: function\n" \ static EnumPropertyItem property_flag_enum_items[] = { {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, @@ -389,6 +394,51 @@ static void bpy_prop_boolean_set_cb(struct PointerRNA *ptr, struct PropertyRNA * } } +static int bpy_prop_poll_cb(struct PointerRNA *self, PointerRNA candidate, struct PropertyRNA *prop) +{ + PyObject *py_self; + PyObject *py_candidate; + PyObject *py_func; + PyObject **py_data = RNA_property_py_data_get(prop); + PyObject *args; + PyObject *ret; + bool result; + const int is_write_ok = pyrna_write_check(); + PyGILState_STATE gilstate = PyGILState_Ensure(); + + BLI_assert(self != NULL); + + py_self = pyrna_struct_as_instance(self); + py_candidate = pyrna_struct_as_instance(&candidate); + py_func = py_data[BPY_DATA_CB_SLOT_POLL]; + + if (!is_write_ok) + pyrna_write_set(true); + + args = PyTuple_New(2); + PyTuple_SET_ITEM(args, 0, py_self); + PyTuple_SET_ITEM(args, 1, py_candidate); + + ret = PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if (ret == NULL) { + printf_func_error(py_func); + result = false; + } + else { + result = PyObject_IsTrue(ret); + Py_DECREF(ret); + } + + PyGILState_Release(gilstate); + if (!is_write_ok) + pyrna_write_set(false); + + return result; +} + static void bpy_prop_boolean_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values) { PyObject **py_data = RNA_property_py_data_get(prop); @@ -1598,6 +1648,16 @@ static void bpy_prop_callback_assign_update(struct PropertyRNA *prop, PyObject * } } +static void bpy_prop_callback_assign_pointer(struct PropertyRNA *prop, PyObject *poll_cb) +{ + if (poll_cb && poll_cb != Py_None) { + PyObject **py_data = bpy_prop_py_data_get(prop); + + RNA_def_property_poll_runtime(prop, (void *) bpy_prop_poll_cb); + py_data[BPY_DATA_CB_SLOT_POLL] = poll_cb; + } +} + static void bpy_prop_callback_assign_boolean(struct PropertyRNA *prop, PyObject *get_cb, PyObject *set_cb) { BooleanPropertyGetFunc rna_get_cb = NULL; @@ -1904,7 +1964,7 @@ static void bpy_prop_callback_assign_enum(struct PropertyRNA *prop, PyObject *ge " :type set: function\n" \ #define BPY_PROPDEF_TYPE_DOC \ -" :arg type: A subclass of :class:`bpy.types.PropertyGroup`.\n" \ +" :arg type: A subclass of :class:`bpy.types.PropertyGroup` or :class:`bpy.types.ID`.\n" \ " :type type: class\n" \ #if 0 @@ -2637,7 +2697,8 @@ PyDoc_STRVAR(BPy_EnumProperty_doc, " :icon: An icon string identifier or integer icon value\n" " (e.g. returned by :class:`bpy.types.UILayout.icon`)\n" " :number: Unique value used as the identifier for this item (stored in file data).\n" -" Use when the identifier may need to change.\n" +" Use when the identifier may need to change. If the *ENUM_FLAG* option is used,\n" +" the values are bitmasks and should be powers of two.\n" "\n" " When an item only contains 4 items they define ``(identifier, name, description, number)``.\n" "\n" @@ -2772,7 +2833,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) Py_RETURN_NONE; } -static StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix) +StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix) { StructRNA *srna; @@ -2782,25 +2843,18 @@ static StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix PyObject *msg = PyC_ExceptionBuffer(); const char *msg_char = _PyUnicode_AsString(msg); PyErr_Format(PyExc_TypeError, - "%.200s expected an RNA type derived from PropertyGroup, failed with: %s", + "%.200s expected an RNA type, failed with: %s", error_prefix, msg_char); Py_DECREF(msg); } else { PyErr_Format(PyExc_TypeError, - "%.200s expected an RNA type derived from PropertyGroup, failed with type '%s'", + "%.200s expected an RNA type, failed with type '%s'", error_prefix, Py_TYPE(value)->tp_name); } return NULL; } - if (!RNA_struct_is_a(srna, &RNA_PropertyGroup)) { - PyErr_Format(PyExc_TypeError, - "%.200s expected an RNA type derived from PropertyGroup", - error_prefix); - return NULL; - } - return srna; } @@ -2809,6 +2863,7 @@ PyDoc_STRVAR(BPy_PointerProperty_doc, "name=\"\", " "description=\"\", " "options={'ANIMATABLE'}, " + "poll=None, " "update=None)\n" "\n" " Returns a new pointer property definition.\n" @@ -2819,14 +2874,14 @@ BPY_PROPDEF_DESC_DOC BPY_PROPDEF_OPTIONS_DOC BPY_PROPDEF_UPDATE_DOC ); -static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw) +PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw) { StructRNA *srna; BPY_PROPDEF_HEAD(PointerProperty); if (srna) { - static const char *kwlist[] = {"attr", "type", "name", "description", "options", "update", NULL}; + static const char *kwlist[] = {"attr", "type", "name", "description", "options", "poll", "update", NULL}; const char *id = NULL, *name = NULL, *description = ""; int id_len; PropertyRNA *prop; @@ -2834,33 +2889,47 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k PyObject *type = Py_None; PyObject *pyopts = NULL; int opts = 0; - PyObject *update_cb = NULL; + PyObject *update_cb = NULL, *poll_cb = NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#O|ssO!O:PointerProperty", + "s#O|ssO!OOO:PointerProperty", (char **)kwlist, &id, &id_len, &type, &name, &description, &PySet_Type, &pyopts, - &update_cb)) + &poll_cb, &update_cb)) { return NULL; } BPY_PROPDEF_CHECK(PointerProperty, property_flag_items); - ptype = pointer_type_from_py(type, "PointerProperty(...):"); + ptype = pointer_type_from_py(type, "PointerProperty(...)"); if (!ptype) return NULL; - + if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup) && !RNA_struct_is_ID(ptype)) { + PyErr_Format(PyExc_TypeError, + "PointerProperty(...) expected an RNA type derived from %.200s or %.200s", + RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup)); + return NULL; + } if (bpy_prop_callback_check(update_cb, "update", 2) == -1) { return NULL; } - + if (bpy_prop_callback_check(poll_cb, "poll", 2) == -1) { + return NULL; + } prop = RNA_def_pointer_runtime(srna, id, ptype, name ? name : id, description); if (pyopts) { bpy_prop_assign_flag(prop, opts); } + + if (RNA_struct_idprops_contains_datablock(ptype)) { + if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) { + RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES); + } + } bpy_prop_callback_assign_update(prop, update_cb); + bpy_prop_callback_assign_pointer(prop, poll_cb); RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; @@ -2879,7 +2948,7 @@ BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC BPY_PROPDEF_OPTIONS_DOC ); -static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) +PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) { StructRNA *srna; @@ -2910,17 +2979,30 @@ static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject if (!ptype) return NULL; + if (!RNA_struct_is_a(ptype, &RNA_PropertyGroup)) { + PyErr_Format(PyExc_TypeError, + "CollectionProperty(...) expected an RNA type derived from %.200s", + RNA_struct_ui_name(&RNA_ID), RNA_struct_ui_name(&RNA_PropertyGroup)); + return NULL; + } + prop = RNA_def_collection_runtime(srna, id, ptype, name ? name : id, description); if (pyopts) { bpy_prop_assign_flag(prop, opts); } + + if (RNA_struct_idprops_contains_datablock(ptype)) { + if (RNA_struct_is_a(srna, &RNA_PropertyGroup)) { + RNA_def_struct_flag(srna, STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES); + } + } RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; } PyDoc_STRVAR(BPy_RemoveProperty_doc, -".. function:: RemoveProperty(cls, attr="")\n" +".. function:: RemoveProperty(cls, attr)\n" "\n" " Removes a dynamically defined property.\n" "\n" diff --git a/source/blender/python/intern/bpy_props.h b/source/blender/python/intern/bpy_props.h index c9934ca0cf3..614c1b4b708 100644 --- a/source/blender/python/intern/bpy_props.h +++ b/source/blender/python/intern/bpy_props.h @@ -30,6 +30,10 @@ PyObject *BPY_rna_props(void); +PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw); +PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw); +StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix); + #define PYRNA_STACK_ARRAY 32 #endif diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 2fd46ab94f0..eda880d4dce 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -806,7 +806,7 @@ static PyObject *pyrna_struct_richcmp(PyObject *a, PyObject *b, int op) switch (op) { case Py_NE: ok = !ok; - /* fall-through */ + ATTR_FALLTHROUGH; case Py_EQ: res = ok ? Py_False : Py_True; break; @@ -836,7 +836,7 @@ static PyObject *pyrna_prop_richcmp(PyObject *a, PyObject *b, int op) switch (op) { case Py_NE: ok = !ok; - /* fall-through */ + ATTR_FALLTHROUGH; case Py_EQ: res = ok ? Py_False : Py_True; break; @@ -1934,16 +1934,10 @@ static int pyrna_py_to_prop( } else { /* data == NULL, assign to RNA */ - if (value == Py_None) { - PointerRNA valueptr = {{NULL}}; - RNA_property_pointer_set(ptr, prop, valueptr); - } - else if (RNA_struct_is_a(param->ptr.type, ptr_type)) { - RNA_property_pointer_set(ptr, prop, param->ptr); - } - else { + if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type)) + RNA_property_pointer_set(ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr); + else raise_error = true; - } } if (raise_error) { @@ -3277,6 +3271,20 @@ static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObje return -1; } + if (value && BPy_StructRNA_Check(value)) { + BPy_StructRNA *val = (BPy_StructRNA *)value; + if (val && self->ptr.type && val->ptr.type) { + if (!RNA_struct_idprops_datablock_allowed(self->ptr.type) && + RNA_struct_idprops_contains_datablock(val->ptr.type)) + { + PyErr_SetString( + PyExc_TypeError, + "bpy_struct[key] = val: datablock id properties not supported for this type"); + return -1; + } + } + } + return BPy_Wrap_SetMapItem(group, key, value); } @@ -5160,7 +5168,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat ret = Matrix_CreatePyObject(data, 3, 3, NULL); break; } - /* fall-through */ + ATTR_FALLTHROUGH; #endif default: ret = PyTuple_New(len); @@ -5684,7 +5692,7 @@ PyTypeObject pyrna_struct_meta_idprop_Type = { NULL, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ NULL, /* struct PyGetSetDef *tp_getset; */ -#if defined(_MSC_VER) || defined(FREE_WINDOWS) +#if defined(_MSC_VER) NULL, /* defer assignment */ #else &PyType_Type, /* struct _typeobject *tp_base; */ @@ -6259,7 +6267,7 @@ static PyTypeObject pyrna_prop_collection_iter_Type = { NULL, /* reprfunc tp_str; */ /* will only use these if this is a subtype of a py class */ -#if defined(_MSC_VER) || defined(FREE_WINDOWS) +#if defined(_MSC_VER) NULL, /* defer assignment */ #else PyObject_GenericGetAttr, /* getattrofunc tp_getattro; */ @@ -6292,7 +6300,7 @@ static PyTypeObject pyrna_prop_collection_iter_Type = { #endif /*** Added in release 2.2 ***/ /* Iterators */ -#if defined(_MSC_VER) || defined(FREE_WINDOWS) +#if defined(_MSC_VER) NULL, /* defer assignment */ #else PyObject_SelfIter, /* getiterfunc tp_iter; */ @@ -6745,7 +6753,7 @@ PyObject *pyrna_id_CreatePyObject(ID *id) bool pyrna_id_FromPyObject(PyObject *obj, ID **id) { - if (BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *)obj)->ptr.type))) { + if (pyrna_id_CheckPyObject(obj)) { *id = ((BPy_StructRNA *)obj)->ptr.id.data; return true; } @@ -6755,6 +6763,11 @@ bool pyrna_id_FromPyObject(PyObject *obj, ID **id) } } +bool pyrna_id_CheckPyObject(PyObject *obj) +{ + return BPy_StructRNA_Check(obj) && (RNA_struct_is_ID(((BPy_StructRNA *) obj)->ptr.type)); +} + void BPY_rna_init(void) { #ifdef USE_MATHUTILS /* register mathutils callbacks, ok to run more than once. */ @@ -6763,7 +6776,7 @@ void BPY_rna_init(void) #endif /* for some reason MSVC complains of these */ -#if defined(_MSC_VER) || defined(FREE_WINDOWS) +#if defined(_MSC_VER) pyrna_struct_meta_idprop_Type.tp_base = &PyType_Type; pyrna_prop_collection_iter_Type.tp_iter = PyObject_SelfIter; @@ -7089,6 +7102,21 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item args_fake = PyTuple_New(1); PyTuple_SET_ITEM(args_fake, 0, py_srna_cobject); + PyObject *type = PyDict_GetItemString(py_kw, "type"); + StructRNA *type_srna = srna_from_self(type, ""); + if (type_srna) { + if (!RNA_struct_idprops_datablock_allowed(srna) && + (*(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_PointerProperty || + *(PyCFunctionWithKeywords)PyCFunction_GET_FUNCTION(py_func) == BPy_CollectionProperty) && + RNA_struct_idprops_contains_datablock(type_srna)) + { + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" doesn't support datablock properties \n", + RNA_struct_identifier(srna)); + return -1; + } + } + py_ret = PyObject_Call(py_func, args_fake, py_kw); if (py_ret) { @@ -7237,15 +7265,12 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v { const ListBase *lb; Link *link; - FunctionRNA *func; - PropertyRNA *prop; const char *class_type = RNA_struct_identifier(srna); StructRNA *srna_base = RNA_struct_base(srna); PyObject *py_class = (PyObject *)py_data; PyObject *base_class = RNA_struct_py_type_get(srna); PyObject *item; - int i, flag, arg_count, func_arg_count, func_arg_min_count = 0; - bool is_staticmethod; + int i, arg_count, func_arg_count, func_arg_min_count = 0; const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */ if (srna_base) { @@ -7266,9 +7291,12 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v lb = RNA_struct_type_functions(srna); i = 0; for (link = lb->first; link; link = link->next) { - func = (FunctionRNA *)link; - flag = RNA_function_flag(func); - is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); + FunctionRNA *func = (FunctionRNA *)link; + const int flag = RNA_function_flag(func); + /* TODO(campbell): this is used for classmethod's too, + * even though class methods should have 'FUNC_USE_SELF_TYPE' set, see Operator.poll for eg. + * Keep this as-is since its working but we should be using 'FUNC_USE_SELF_TYPE' for many functions. */ + const bool is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); if (!(flag & FUNC_REGISTER)) continue; @@ -7294,7 +7322,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v if (is_staticmethod) { if (PyMethod_Check(item) == 0) { PyErr_Format(PyExc_TypeError, - "expected %.200s, %.200s class \"%.200s\" attribute to be a method, not a %.200s", + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a static/class method, not a %.200s", class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); return -1; } @@ -7303,7 +7332,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v else { if (PyFunction_Check(item) == 0) { PyErr_Format(PyExc_TypeError, - "expected %.200s, %.200s class \"%.200s\" attribute to be a function, not a %.200s", + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a function, not a %.200s", class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); return -1; } @@ -7315,7 +7345,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; /* note, the number of args we check for and the number of args we give to - * @staticmethods are different (quirk of python), + * '@staticmethods' are different (quirk of python), * this is why rna_function_arg_count() doesn't return the value -1*/ if (is_staticmethod) { func_arg_count++; @@ -7346,8 +7376,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v lb = RNA_struct_type_properties(srna); for (link = lb->first; link; link = link->next) { const char *identifier; - prop = (PropertyRNA *)link; - flag = RNA_property_flag(prop); + PropertyRNA *prop = (PropertyRNA *)link; + const int flag = RNA_property_flag(prop); if (!(flag & PROP_REGISTER)) continue; diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index e38d4f095d6..605f79b1ad8 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -179,6 +179,7 @@ PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop); /* extern'd by other modules which don't deal closely with RNA */ PyObject *pyrna_id_CreatePyObject(struct ID *id); bool pyrna_id_FromPyObject(PyObject *obj, struct ID **id); +bool pyrna_id_CheckPyObject(PyObject *obj); /* operators also need this to set args */ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const bool all_args, const char *error_prefix); diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 5c505247a97..1afb1d7be90 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -1,4 +1,4 @@ -/* +/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -38,18 +38,31 @@ #endif PyDoc_STRVAR(M_Mathutils_doc, -"This module provides access to the math classes:\n" +"This module provides access to math operations.\n" +"\n" +".. note::\n" +"\n" +" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n" +" such as tuples, lists." +"\n\n" +"Submodules:\n" +"\n" +".. toctree::\n" +" :maxdepth: 1\n" +"\n" +" mathutils.geometry.rst\n" +" mathutils.bvhtree.rst\n" +" mathutils.kdtree.rst\n" +" mathutils.interpolate.rst\n" +" mathutils.noise.rst\n" +"\n" +"The :mod:`mathutils` module provides the following classes:\n" "\n" "- :class:`Color`,\n" "- :class:`Euler`,\n" "- :class:`Matrix`,\n" "- :class:`Quaternion`,\n" "- :class:`Vector`,\n" -"\n" -".. note::\n" -"\n" -" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n" -" such as tuples, lists." ); static int mathutils_array_parse_fast(float *array, int size, @@ -219,7 +232,7 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c error_prefix, size, array_min); return -1; } - + *array = PyMem_Malloc(size * sizeof(float)); memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float)); return size; @@ -422,7 +435,7 @@ static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL}; unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb) { unsigned char i; - + /* find the first free slot */ for (i = 0; mathutils_callbacks[i]; i++) { if (mathutils_callbacks[i] == cb) /* already registered? */ @@ -625,14 +638,14 @@ PyMODINIT_FUNC PyInit_mathutils(void) return NULL; mod = PyModule_Create(&M_Mathutils_module_def); - + /* each type has its own new() function */ PyModule_AddObject(mod, vector_Type.tp_name, (PyObject *)&vector_Type); PyModule_AddObject(mod, matrix_Type.tp_name, (PyObject *)&matrix_Type); PyModule_AddObject(mod, euler_Type.tp_name, (PyObject *)&euler_Type); PyModule_AddObject(mod, quaternion_Type.tp_name, (PyObject *)&quaternion_Type); PyModule_AddObject(mod, color_Type.tp_name, (PyObject *)&color_Type); - + /* submodule */ PyModule_AddObject(mod, "geometry", (submodule = PyInit_mathutils_geometry())); /* XXX, python doesnt do imports with this usefully yet diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index add8c2451ff..9997cd9c1f5 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -173,7 +173,7 @@ static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op) switch (op) { case Py_NE: ok = !ok; - /* fall-through */ + ATTR_FALLTHROUGH; case Py_EQ: res = ok ? Py_False : Py_True; break; diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 54adc826af7..9492b6d67f3 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -65,7 +65,7 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) case 2: if ((order = euler_order_from_string(order_str, "mathutils.Euler()")) == -1) return NULL; - /* fall-through */ + ATTR_FALLTHROUGH; case 1: if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1) return NULL; @@ -370,7 +370,7 @@ static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op) switch (op) { case Py_NE: ok = !ok; - /* fall-through */ + ATTR_FALLTHROUGH; case Py_EQ: res = ok ? Py_False : Py_True; break; diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index bd44e77e7c6..e368e8871f3 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -1641,9 +1641,9 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value) PyDoc_STRVAR(Matrix_decompose_doc, ".. method:: decompose()\n" "\n" -" Return the location, rotation and scale components of this matrix.\n" +" Return the translation, rotation and scale components of this matrix.\n" "\n" -" :return: loc, rot, scale triple.\n" +" :return: trans, rot, scale triple.\n" " :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)" ); static PyObject *Matrix_decompose(MatrixObject *self) @@ -1709,10 +1709,10 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) /* TODO, different sized matrix */ if (self->num_col == 4 && self->num_row == 4) { - blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac); + interp_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac); } else if (self->num_col == 3 && self->num_row == 3) { - blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac); + interp_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac); } else { PyErr_SetString(PyExc_ValueError, @@ -2034,7 +2034,7 @@ static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op) switch (op) { case Py_NE: ok = !ok; - /* fall-through */ + ATTR_FALLTHROUGH; case Py_EQ: res = ok ? Py_False : Py_True; break; diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 71b3cf8ddac..d283c717a46 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -552,7 +552,7 @@ static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op) switch (op) { case Py_NE: ok = !ok; - /* fall-through */ + ATTR_FALLTHROUGH; case Py_EQ: res = ok ? Py_False : Py_True; break; diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 569b207c966..a12bdd910c3 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -34,6 +34,7 @@ set(INC ../depsgraph ../makesdna ../makesrna + ../nodes ../physics ../../../intern/atomic ../../../intern/guardedalloc @@ -165,10 +166,6 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() -if(WITH_CYCLES AND WITH_CYCLES_DEBUG) - add_definitions(-DWITH_CYCLES_DEBUG) -endif() - if(APPLE) # SSE math is enabled by default on x86_64 if(CMAKE_OSX_ARCHITECTURES MATCHES "i386") diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index f83a210275f..52491673612 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -96,6 +96,7 @@ typedef struct RenderEngineType { void (*view_draw)(struct RenderEngine *engine, const struct bContext *context); void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node); + void (*update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl); /* RNA integration */ ExtensionRNA ext; @@ -139,7 +140,8 @@ void RE_result_load_from_file(struct RenderResult *result, struct ReportList *re struct RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname); void RE_engine_update_result(RenderEngine *engine, struct RenderResult *result); -void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results); +void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername); +void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int highlight, int merge_results); const char *RE_engine_active_view_get(RenderEngine *engine); void RE_engine_active_view_set(RenderEngine *engine, const char *viewname); @@ -160,6 +162,9 @@ bool RE_engine_is_external(struct Render *re); void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe); +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, + const char *name, int channels, const char *chanid, int type); + /* Engine Types */ void RE_engines_init(void); diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index f535aa5aa71..0d2e29ba4c8 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -83,25 +83,19 @@ typedef struct RenderView { typedef struct RenderPass { struct RenderPass *next, *prev; - int passtype, channels; + int channels; char name[64]; /* amount defined in openexr_multi.h */ char chan_id[8]; /* amount defined in openexr_multi.h */ float *rect; int rectx, recty; - char internal_name[64]; /* EXR_PASS_MAXNAME */ + char fullname[64]; /* EXR_PASS_MAXNAME */ char view[64]; /* EXR_VIEW_MAXNAME */ int view_id; /* quick lookup */ - int debug_type; + int pad; } RenderPass; -enum { - RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES = 0, - RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES = 1, - RENDER_PASS_DEBUG_RAY_BOUNCES = 2, - RENDER_PASS_DEBUG_BVH_INTERSECTIONS = 3, -}; /* a renderlayer is a full image, but with all passes and samples */ /* size of the rects is defined in RenderResult */ @@ -236,7 +230,7 @@ void RE_render_result_rect_from_ibuf( struct ImBuf *ibuf, const int view_id); struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name); -float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname); +float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname); /* add passes for grease pencil */ struct RenderPass *RE_create_gp_pass(struct RenderResult *rr, const char *layername, const char *viewname); @@ -345,6 +339,7 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); bool RE_layers_have_name(struct RenderResult *result); +struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname); struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname); /* shaded view or baking options */ @@ -381,7 +376,7 @@ bool RE_allow_render_generic_object(struct Object *ob); /* RE_updateRenderInstances flag */ enum { RE_OBJECT_INSTANCES_UPDATE_VIEW = (1 << 0), - RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1), + RE_OBJECT_INSTANCES_UPDATE_OBMAT = (1 << 1) }; void RE_updateRenderInstances(Render *re, int flag); @@ -394,13 +389,5 @@ struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char * RenderResult *RE_DuplicateRenderResult(RenderResult *rr); -/******* Debug pass helper functions *********/ - -#ifdef WITH_CYCLES_DEBUG -int RE_debug_pass_num_channels_get(int pass_type); -const char *RE_debug_pass_name_get(int pass_type); -int RE_debug_pass_type_get(struct Render *re); -#endif - #endif /* __RE_PIPELINE_H__ */ diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index ae389fdfd2e..b64c0c8fc52 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -178,6 +178,7 @@ typedef struct ShadeInput { unsigned int lay; int layflag, passflag, combinedflag; + short object_pass_index; struct Group *light_override; struct Material *mat_override; @@ -241,6 +242,9 @@ enum { const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4]; +float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi); +float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi); + enum { RE_VIEW_MATRIX, RE_VIEWINV_MATRIX, diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 0c4f4e20325..4057d8c1052 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -67,6 +67,11 @@ void render_result_views_new(struct RenderResult *rr, struct RenderData *rd); void render_result_merge(struct RenderResult *rr, struct RenderResult *rrpart); +/* Add Passes */ + +void render_result_clone_passes(struct Render *re, struct RenderResult *rr, const char *viewname); +void render_result_add_pass(struct RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname); + /* Free */ void render_result_free(struct RenderResult *rr); @@ -84,7 +89,7 @@ void render_result_exr_file_begin(struct Render *re); void render_result_exr_file_end(struct Render *re); /* render pass wrapper for gpencil */ -struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, int passtype, const char *viewname); +struct RenderPass *gp_add_pass(struct RenderResult *rr, struct RenderLayer *rl, int channels, const char *name, const char *viewname); void render_result_exr_file_merge(struct RenderResult *rr, struct RenderResult *rrpart, const char *viewname); diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index b3a5ccdae17..f9942bef61f 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -335,7 +335,7 @@ typedef struct ObjectRen { char (*mcol)[MAX_CUSTOMDATA_LAYER_NAME]; int actmtface, actmcol, bakemtface; - char tangent_mask; /* which tangent layer should be calculated */ + short tangent_mask; /* which tangent layer should be calculated */ float obmat[4][4]; /* only used in convertblender.c, for instancing */ @@ -382,6 +382,8 @@ typedef struct ObjectInstanceRen { float part_co[3]; float part_vel[3]; float part_avel[3]; + + unsigned int random_id; } ObjectInstanceRen; /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 7254fd25ee6..f4c4a50ac27 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -34,6 +34,12 @@ #include "render_types.h" +#include "RE_engine.h" + +#include "DNA_node_types.h" + +#include "NOD_composite.h" + struct ShadeInput; struct ShadeResult; struct World; @@ -77,6 +83,8 @@ void zbufshade_sss_tile(struct RenderPart *pa); int get_sample_layers(struct RenderPart *pa, struct RenderLayer *rl, struct RenderLayer **rlpp); +void render_internal_update_passes(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl); + /* -------- ray.c ------- */ diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 81e41a20f2e..103fa3e6034 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -59,6 +59,7 @@ static void rtbuild_init(RTBuilder *b) b->primitives.begin = NULL; b->primitives.end = NULL; b->primitives.maxsize = 0; + b->depth = 0; for (int i = 0; i < RTBUILD_MAX_CHILDS; i++) b->child_offset[i] = 0; @@ -178,6 +179,8 @@ RTBuilder *rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) { rtbuild_init(tmp); + tmp->depth = b->depth + 1; + for (int i = 0; i < 3; i++) if (b->sorted_begin[i]) { tmp->sorted_begin[i] = b->sorted_begin[i] + b->child_offset[child]; @@ -336,6 +339,15 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) int baxis = -1, boffset = 0; if (size > nchilds) { + if (b->depth > RTBUILD_MAX_SAH_DEPTH) { + // for degenerate cases we avoid running out of stack space + // by simply splitting the children in the middle + b->child_offset[0] = 0; + b->child_offset[1] = (size+1)/2; + b->child_offset[2] = size; + return 2; + } + float bcost = FLT_MAX; baxis = -1; boffset = size / 2; diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.h b/source/blender/render/intern/raytrace/rayobject_rtbuild.h index 9e296da144b..83042ef3d7e 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.h +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.h @@ -49,7 +49,8 @@ extern "C" { * generate with simple calls, and then convert to the theirs * specific structure on the fly. */ -#define RTBUILD_MAX_CHILDS 32 +#define RTBUILD_MAX_CHILDS 32 +#define RTBUILD_MAX_SAH_DEPTH 256 typedef struct RTBuilder { @@ -79,6 +80,8 @@ typedef struct RTBuilder { float bb[6]; + /* current depth */ + int depth; } RTBuilder; /* used during creation */ diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index 73424a4e846..588c327ab91 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -684,6 +684,10 @@ void RE_bake_pixels_populate( int mat_nr = mp->mat_nr; int image_id = bake_images->lookup[mat_nr]; + if (image_id < 0) { + continue; + } + bd.bk_image = &bake_images->data[image_id]; bd.primitive_id = ++p_id; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 263ea3d4ef2..9633d95855e 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -3439,10 +3439,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if (need_nmap_tangent_concrete || need_tangent) { int uv_start = CustomData_get_layer_index(&dm->faceData, CD_MTFACE); int uv_index = CustomData_get_named_layer_index(&dm->faceData, CD_MTFACE, layer->name); - BLI_assert(uv_start >= 0 && uv_index >= 0); - if ((uv_start < 0 || uv_index < 0)) - continue; - int n = uv_index - uv_start; + + /* if there are no UVs, orco tangents are in first slot */ + int n = (uv_start >= 0 && uv_index >= 0) ? uv_index - uv_start : 0; const float *tangent = (const float *) layer->data; float *ftang = RE_vlakren_get_nmap_tangent(obr, vlr, n, true); @@ -4658,14 +4657,22 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject * index= (dob)? dob->persistent_id[0]: 0; + /* It seems that we may generate psys->renderdata recursively in some nasty intricated cases of + * several levels of bupliobject (see T51524). + * For now, basic rule is, do not restore psys if it was already in 'render state'. + * Another, more robust solution could be to add some reference counting to that renderdata... */ + bool psys_has_renderdata = false; + /* the emitter has to be processed first (render levels of modifiers) */ /* so here we only check if the emitter should be rendered */ if (ob->particlesystem.first) { show_emitter= 0; for (psys=ob->particlesystem.first; psys; psys=psys->next) { show_emitter += psys->part->draw & PART_DRAW_EMITTER; - if (!(re->r.scemode & R_VIEWPORT_PREVIEW)) + if (!(re->r.scemode & R_VIEWPORT_PREVIEW)) { + psys_has_renderdata |= (psys->renderdata != NULL); psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset); + } } /* if no psys has "show emitter" selected don't render emitter */ @@ -4712,8 +4719,9 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject * if (dob) psys->flag |= PSYS_USE_IMAT; init_render_object_data(re, obr, timeoffset); - if (!(re->r.scemode & R_VIEWPORT_PREVIEW)) + if (!(re->r.scemode & R_VIEWPORT_PREVIEW) && !psys_has_renderdata) { psys_render_restore(ob, psys); + } psys->flag &= ~PSYS_USE_IMAT; /* only add instance for objects that have not been used for dupli */ diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index d97e18d6511..156b4215992 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -61,6 +61,7 @@ #include "renderpipeline.h" #include "texture.h" #include "zbuf.h" +#include "render_result.h" /* ------------------------------------------------------------------------- */ @@ -142,8 +143,8 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) /* set up renderdata */ render_copy_renderdata(&envre->r, &re->r); envre->r.mode &= ~(R_BORDER | R_PANORAMA | R_ORTHO | R_MBLUR); - BLI_listbase_clear(&envre->r.layers); - BLI_listbase_clear(&envre->r.views); + BLI_freelistN(&envre->r.layers); + BLI_freelistN(&envre->r.views); envre->r.filtertype = 0; envre->r.tilex = envre->r.xsch / 2; envre->r.tiley = envre->r.ysch / 2; @@ -493,13 +494,20 @@ static void render_envmap(Render *re, EnvMap *env) env_rotate_scene(envre, tmat, 0); if (re->test_break(re->tbh) == 0) { - RenderLayer *rl = envre->result->layers.first; int y; float *alpha; float *rect; + if (envre->result->do_exr_tile) { + BLI_rw_mutex_lock(&envre->resultmutex, THREAD_LOCK_WRITE); + render_result_exr_file_end(envre); + BLI_rw_mutex_unlock(&envre->resultmutex); + } + + RenderLayer *rl = envre->result->layers.first; + /* envmap is rendered independently of multiview */ - rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, ""); + rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, ""); ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat); memcpy(ibuf->rect_float, rect, ibuf->channels * ibuf->x * ibuf->y * sizeof(float)); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index fd9d95c63b6..a581f7bd198 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -62,13 +62,14 @@ #include "renderpipeline.h" #include "render_types.h" #include "render_result.h" +#include "rendercore.h" /* Render Engine Types */ static RenderEngineType internal_render_type = { NULL, NULL, "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL, - NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, render_internal_update_passes, {NULL, NULL, NULL} }; @@ -77,7 +78,7 @@ static RenderEngineType internal_render_type = { static RenderEngineType internal_game_type = { NULL, NULL, "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME, - NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, {NULL, NULL, NULL} }; @@ -212,6 +213,8 @@ RenderResult *RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, /* can be NULL if we CLAMP the width or height to 0 */ if (result) { + render_result_clone_passes(re, result, viewname); + RenderPart *pa; /* Copy EXR tile settings, so pipeline knows whether this is a result @@ -245,7 +248,18 @@ void RE_engine_update_result(RenderEngine *engine, RenderResult *result) } } -void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel, int merge_results) +void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername) +{ + Render *re = engine->re; + + if (!re || !re->result) { + return; + } + + render_result_add_pass(re->result, name, channels, chan_id, layername, NULL); +} + +void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel, int highlight, int merge_results) { Render *re = engine->re; @@ -254,7 +268,7 @@ void RE_engine_end_result(RenderEngine *engine, RenderResult *result, int cancel } /* merge. on break, don't merge in result for preview renders, looks nicer */ - if (!cancel) { + if (!highlight) { /* for exr tile render, detect tiles that are done */ RenderPart *pa = get_part_from_result(re, result); @@ -760,3 +774,22 @@ int RE_engine_render(Render *re, int do_all) return 1; } +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, + const char *name, int UNUSED(channels), const char *UNUSED(chanid), int type) +{ + /* The channel information is currently not used, but is part of the API in case it's needed in the future. */ + + if (!(scene && srl && engine)) { + return; + } + + /* Register the pass in all scenes that have a render layer node for this layer. + * Since multiple scenes can be used in the compositor, the code must loop over all scenes + * and check whether their nodetree has a node that needs to be updated. */ + Scene *sce; + for (sce = G.main->scene.first; sce; sce = sce->id.next) { + if (sce->nodetree) { + ntreeCompositRegisterPass(sce->nodetree, scene, srl, name, type); + } + } +} diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 52eca5f7005..e078365e1ed 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -239,9 +239,9 @@ void RE_FreeRenderResult(RenderResult *res) render_result_free(res); } -float *RE_RenderLayerGetPass(volatile RenderLayer *rl, int passtype, const char *viewname) +float *RE_RenderLayerGetPass(volatile RenderLayer *rl, const char *name, const char *viewname) { - RenderPass *rpass = RE_pass_find_by_type(rl, passtype, viewname); + RenderPass *rpass = RE_pass_find_by_name(rl, name, viewname); return rpass ? rpass->rect : NULL; } @@ -382,13 +382,13 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) if (rl) { if (rv->rectf == NULL) { for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) { - rview->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rview->name); + rview->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rview->name); } } if (rv->rectz == NULL) { for (rview = (RenderView *)rr->views.first; rview; rview = rview->next) { - rview->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rview->name); + rview->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rview->name); } } } @@ -442,10 +442,10 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) if (rl) { if (rv->rectf == NULL) - rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name); + rr->rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, rv->name); if (rv->rectz == NULL) - rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name); + rr->rectz = RE_RenderLayerGetPass(rl, RE_PASSNAME_Z, rv->name); } rr->have_combined = (rv->rectf != NULL); @@ -723,6 +723,8 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, re->r.size = source->r.size; } + re_init_resolution(re, source, winx, winy, disprect); + /* disable border if it's a full render anyway */ if (re->r.border.xmin == 0.0f && re->r.border.xmax == 1.0f && re->r.border.ymin == 0.0f && re->r.border.ymax == 1.0f) @@ -730,8 +732,6 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, re->r.mode &= ~R_BORDER; } - re_init_resolution(re, source, winx, winy, disprect); - if (re->rectx < 1 || re->recty < 1 || (BKE_imtype_is_movie(rd->im_format.imtype) && (re->rectx < 16 || re->recty < 16) )) { @@ -842,7 +842,7 @@ static void render_result_rescale(Render *re) if (src_rectf == NULL) { RenderLayer *rl = render_get_active_layer(re, re->result); if (rl != NULL) { - src_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL); + src_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL); } } @@ -861,7 +861,7 @@ static void render_result_rescale(Render *re) RenderLayer *rl; rl = render_get_active_layer(re, re->result); if (rl != NULL) { - dst_rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, NULL); + dst_rectf = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, NULL); } } @@ -1655,7 +1655,7 @@ static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float b /* passes are allocated in sync */ rpass1 = rl1->passes.first; for (rpass = rl->passes.first; rpass && rpass1; rpass = rpass->next, rpass1 = rpass1->next) { - if ((rpass->passtype & SCE_PASS_COMBINED) && key_alpha) + if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && key_alpha) addblur_rect_key(rr, rpass->rect, rpass1->rect, blurfac); else addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels); @@ -1855,6 +1855,8 @@ static void render_result_uncrop(Render *re) rres = render_result_new(re, &re->disprect, 0, RR_USE_MEM, RR_ALL_LAYERS, RR_ALL_VIEWS); + render_result_clone_passes(re, rres, NULL); + render_result_merge(rres, re->result); render_result_free(re->result); re->result = rres; @@ -3887,7 +3889,7 @@ void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char /* multiview: since the API takes no 'view', we use the first combined pass found */ for (rpass = layer->passes.first; rpass; rpass = rpass->next) - if (rpass->passtype == SCE_PASS_COMBINED) + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) break; if (rpass == NULL) @@ -4013,13 +4015,12 @@ bool RE_layers_have_name(struct RenderResult *rr) return false; } -RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname) +RenderPass *RE_pass_find_by_name(volatile RenderLayer *rl, const char *name, const char *viewname) { RenderPass *rp = NULL; for (rp = rl->passes.last; rp; rp = rp->prev) { - if (rp->passtype == passtype) { - + if (STREQ(rp->name, name)) { if (viewname == NULL || viewname[0] == '\0') break; else if (STREQ(rp->view, viewname)) @@ -4029,6 +4030,50 @@ RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const c return rp; } +/* Only provided for API compatibility, don't use this in new code! */ +RenderPass *RE_pass_find_by_type(volatile RenderLayer *rl, int passtype, const char *viewname) +{ +#define CHECK_PASS(NAME) \ + if (passtype == SCE_PASS_ ## NAME) \ + return RE_pass_find_by_name(rl, RE_PASSNAME_ ## NAME, viewname); + + CHECK_PASS(COMBINED); + CHECK_PASS(Z); + CHECK_PASS(VECTOR); + CHECK_PASS(NORMAL); + CHECK_PASS(UV); + CHECK_PASS(RGBA); + CHECK_PASS(EMIT); + CHECK_PASS(DIFFUSE); + CHECK_PASS(SPEC); + CHECK_PASS(SHADOW); + CHECK_PASS(AO); + CHECK_PASS(ENVIRONMENT); + CHECK_PASS(INDIRECT); + CHECK_PASS(REFLECT); + CHECK_PASS(REFRACT); + CHECK_PASS(INDEXOB); + CHECK_PASS(INDEXMA); + CHECK_PASS(MIST); + CHECK_PASS(RAYHITS); + CHECK_PASS(DIFFUSE_DIRECT); + CHECK_PASS(DIFFUSE_INDIRECT); + CHECK_PASS(DIFFUSE_COLOR); + CHECK_PASS(GLOSSY_DIRECT); + CHECK_PASS(GLOSSY_INDIRECT); + CHECK_PASS(GLOSSY_COLOR); + CHECK_PASS(TRANSM_DIRECT); + CHECK_PASS(TRANSM_INDIRECT); + CHECK_PASS(TRANSM_COLOR); + CHECK_PASS(SUBSURFACE_DIRECT); + CHECK_PASS(SUBSURFACE_INDIRECT); + CHECK_PASS(SUBSURFACE_COLOR); + +#undef CHECK_PASS + + return NULL; +} + /* create a renderlayer and renderpass for grease pencil layer */ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const char *viewname) { @@ -4046,7 +4091,7 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha } /* clear previous pass if exist or the new image will be over previous one*/ - RenderPass *rp = RE_pass_find_by_type(rl, SCE_PASS_COMBINED, viewname); + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); if (rp) { if (rp->rect) { MEM_freeN(rp->rect); @@ -4054,5 +4099,5 @@ RenderPass *RE_create_gp_pass(RenderResult *rr, const char *layername, const cha BLI_freelinkN(&rl->passes, rp); } /* create a totally new pass */ - return gp_add_pass(rr, rl, 4, SCE_PASS_COMBINED, viewname); + return gp_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, viewname); } diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index f276c01e86a..8e6e6c9bb7d 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -173,363 +173,72 @@ void render_result_views_shallowdelete(RenderResult *rr) } } -static const char *name_from_passtype(int passtype, int channel) -{ - if (passtype == SCE_PASS_COMBINED) { - if (channel == -1) return "Combined"; - if (channel == 0) return "Combined.R"; - if (channel == 1) return "Combined.G"; - if (channel == 2) return "Combined.B"; - return "Combined.A"; - } - if (passtype == SCE_PASS_Z) { - if (channel == -1) return "Depth"; - return "Depth.Z"; - } - if (passtype == SCE_PASS_VECTOR) { - if (channel == -1) return "Vector"; - if (channel == 0) return "Vector.X"; - if (channel == 1) return "Vector.Y"; - if (channel == 2) return "Vector.Z"; - return "Vector.W"; - } - if (passtype == SCE_PASS_NORMAL) { - if (channel == -1) return "Normal"; - if (channel == 0) return "Normal.X"; - if (channel == 1) return "Normal.Y"; - return "Normal.Z"; - } - if (passtype == SCE_PASS_UV) { - if (channel == -1) return "UV"; - if (channel == 0) return "UV.U"; - if (channel == 1) return "UV.V"; - return "UV.A"; - } - if (passtype == SCE_PASS_RGBA) { - if (channel == -1) return "Color"; - if (channel == 0) return "Color.R"; - if (channel == 1) return "Color.G"; - if (channel == 2) return "Color.B"; - return "Color.A"; - } - if (passtype == SCE_PASS_EMIT) { - if (channel == -1) return "Emit"; - if (channel == 0) return "Emit.R"; - if (channel == 1) return "Emit.G"; - return "Emit.B"; - } - if (passtype == SCE_PASS_DIFFUSE) { - if (channel == -1) return "Diffuse"; - if (channel == 0) return "Diffuse.R"; - if (channel == 1) return "Diffuse.G"; - return "Diffuse.B"; - } - if (passtype == SCE_PASS_SPEC) { - if (channel == -1) return "Spec"; - if (channel == 0) return "Spec.R"; - if (channel == 1) return "Spec.G"; - return "Spec.B"; - } - if (passtype == SCE_PASS_SHADOW) { - if (channel == -1) return "Shadow"; - if (channel == 0) return "Shadow.R"; - if (channel == 1) return "Shadow.G"; - return "Shadow.B"; - } - if (passtype == SCE_PASS_AO) { - if (channel == -1) return "AO"; - if (channel == 0) return "AO.R"; - if (channel == 1) return "AO.G"; - return "AO.B"; - } - if (passtype == SCE_PASS_ENVIRONMENT) { - if (channel == -1) return "Env"; - if (channel == 0) return "Env.R"; - if (channel == 1) return "Env.G"; - return "Env.B"; - } - if (passtype == SCE_PASS_INDIRECT) { - if (channel == -1) return "Indirect"; - if (channel == 0) return "Indirect.R"; - if (channel == 1) return "Indirect.G"; - return "Indirect.B"; - } - if (passtype == SCE_PASS_REFLECT) { - if (channel == -1) return "Reflect"; - if (channel == 0) return "Reflect.R"; - if (channel == 1) return "Reflect.G"; - return "Reflect.B"; - } - if (passtype == SCE_PASS_REFRACT) { - if (channel == -1) return "Refract"; - if (channel == 0) return "Refract.R"; - if (channel == 1) return "Refract.G"; - return "Refract.B"; - } - if (passtype == SCE_PASS_INDEXOB) { - if (channel == -1) return "IndexOB"; - return "IndexOB.X"; - } - if (passtype == SCE_PASS_INDEXMA) { - if (channel == -1) return "IndexMA"; - return "IndexMA.X"; - } - if (passtype == SCE_PASS_MIST) { - if (channel == -1) return "Mist"; - return "Mist.Z"; - } - if (passtype == SCE_PASS_RAYHITS) { - if (channel == -1) return "Rayhits"; - if (channel == 0) return "Rayhits.R"; - if (channel == 1) return "Rayhits.G"; - return "Rayhits.B"; - } - if (passtype == SCE_PASS_DIFFUSE_DIRECT) { - if (channel == -1) return "DiffDir"; - if (channel == 0) return "DiffDir.R"; - if (channel == 1) return "DiffDir.G"; - return "DiffDir.B"; - } - if (passtype == SCE_PASS_DIFFUSE_INDIRECT) { - if (channel == -1) return "DiffInd"; - if (channel == 0) return "DiffInd.R"; - if (channel == 1) return "DiffInd.G"; - return "DiffInd.B"; - } - if (passtype == SCE_PASS_DIFFUSE_COLOR) { - if (channel == -1) return "DiffCol"; - if (channel == 0) return "DiffCol.R"; - if (channel == 1) return "DiffCol.G"; - return "DiffCol.B"; - } - if (passtype == SCE_PASS_GLOSSY_DIRECT) { - if (channel == -1) return "GlossDir"; - if (channel == 0) return "GlossDir.R"; - if (channel == 1) return "GlossDir.G"; - return "GlossDir.B"; - } - if (passtype == SCE_PASS_GLOSSY_INDIRECT) { - if (channel == -1) return "GlossInd"; - if (channel == 0) return "GlossInd.R"; - if (channel == 1) return "GlossInd.G"; - return "GlossInd.B"; - } - if (passtype == SCE_PASS_GLOSSY_COLOR) { - if (channel == -1) return "GlossCol"; - if (channel == 0) return "GlossCol.R"; - if (channel == 1) return "GlossCol.G"; - return "GlossCol.B"; - } - if (passtype == SCE_PASS_TRANSM_DIRECT) { - if (channel == -1) return "TransDir"; - if (channel == 0) return "TransDir.R"; - if (channel == 1) return "TransDir.G"; - return "TransDir.B"; - } - if (passtype == SCE_PASS_TRANSM_INDIRECT) { - if (channel == -1) return "TransInd"; - if (channel == 0) return "TransInd.R"; - if (channel == 1) return "TransInd.G"; - return "TransInd.B"; - } - if (passtype == SCE_PASS_TRANSM_COLOR) { - if (channel == -1) return "TransCol"; - if (channel == 0) return "TransCol.R"; - if (channel == 1) return "TransCol.G"; - return "TransCol.B"; - } - if (passtype == SCE_PASS_SUBSURFACE_DIRECT) { - if (channel == -1) return "SubsurfaceDir"; - if (channel == 0) return "SubsurfaceDir.R"; - if (channel == 1) return "SubsurfaceDir.G"; - return "SubsurfaceDir.B"; - } - if (passtype == SCE_PASS_SUBSURFACE_INDIRECT) { - if (channel == -1) return "SubsurfaceInd"; - if (channel == 0) return "SubsurfaceInd.R"; - if (channel == 1) return "SubsurfaceInd.G"; - return "SubsurfaceInd.B"; - } - if (passtype == SCE_PASS_SUBSURFACE_COLOR) { - if (channel == -1) return "SubsurfaceCol"; - if (channel == 0) return "SubsurfaceCol.R"; - if (channel == 1) return "SubsurfaceCol.G"; - return "SubsurfaceCol.B"; - } - return "Unknown"; -} -static int passtype_from_name(const char *str, int passflag) +static char* set_pass_name(char *outname, const char *name, int channel, const char *chan_id) { - /* We do not really support several pass of the same types, so in case we are opening an EXR file with several pass - * names detected as same pass type, only return that pass type the first time, and return 'uknown' for the others. - * See T48466. */ -#define RETURN_PASS(_passtype) return (passflag & (_passtype)) ? 0 : (_passtype) - - if (STRPREFIX(str, "Combined")) - RETURN_PASS(SCE_PASS_COMBINED); - - if (STRPREFIX(str, "Depth")) - RETURN_PASS(SCE_PASS_Z); - - if (STRPREFIX(str, "Vector")) - RETURN_PASS(SCE_PASS_VECTOR); - - if (STRPREFIX(str, "Normal")) - RETURN_PASS(SCE_PASS_NORMAL); - - if (STRPREFIX(str, "UV")) - RETURN_PASS(SCE_PASS_UV); - - if (STRPREFIX(str, "Color")) - RETURN_PASS(SCE_PASS_RGBA); - - if (STRPREFIX(str, "Emit")) - RETURN_PASS(SCE_PASS_EMIT); - - if (STRPREFIX(str, "Diffuse")) - RETURN_PASS(SCE_PASS_DIFFUSE); - - if (STRPREFIX(str, "Spec")) - RETURN_PASS(SCE_PASS_SPEC); - - if (STRPREFIX(str, "Shadow")) - RETURN_PASS(SCE_PASS_SHADOW); - - if (STRPREFIX(str, "AO")) - RETURN_PASS(SCE_PASS_AO); - - if (STRPREFIX(str, "Env")) - RETURN_PASS(SCE_PASS_ENVIRONMENT); - - if (STRPREFIX(str, "Indirect")) - RETURN_PASS(SCE_PASS_INDIRECT); - - if (STRPREFIX(str, "Reflect")) - RETURN_PASS(SCE_PASS_REFLECT); - - if (STRPREFIX(str, "Refract")) - RETURN_PASS(SCE_PASS_REFRACT); - - if (STRPREFIX(str, "IndexOB")) - RETURN_PASS(SCE_PASS_INDEXOB); - - if (STRPREFIX(str, "IndexMA")) - RETURN_PASS(SCE_PASS_INDEXMA); - - if (STRPREFIX(str, "Mist")) - RETURN_PASS(SCE_PASS_MIST); - - if (STRPREFIX(str, "RayHits")) - RETURN_PASS(SCE_PASS_RAYHITS); - - if (STRPREFIX(str, "DiffDir")) - RETURN_PASS(SCE_PASS_DIFFUSE_DIRECT); - - if (STRPREFIX(str, "DiffInd")) - RETURN_PASS(SCE_PASS_DIFFUSE_INDIRECT); - - if (STRPREFIX(str, "DiffCol")) - RETURN_PASS(SCE_PASS_DIFFUSE_COLOR); - - if (STRPREFIX(str, "GlossDir")) - RETURN_PASS(SCE_PASS_GLOSSY_DIRECT); - - if (STRPREFIX(str, "GlossInd")) - RETURN_PASS(SCE_PASS_GLOSSY_INDIRECT); - - if (STRPREFIX(str, "GlossCol")) - RETURN_PASS(SCE_PASS_GLOSSY_COLOR); - - if (STRPREFIX(str, "TransDir")) - RETURN_PASS(SCE_PASS_TRANSM_DIRECT); - - if (STRPREFIX(str, "TransInd")) - RETURN_PASS(SCE_PASS_TRANSM_INDIRECT); - - if (STRPREFIX(str, "TransCol")) - RETURN_PASS(SCE_PASS_TRANSM_COLOR); - - if (STRPREFIX(str, "SubsurfaceDir")) - RETURN_PASS(SCE_PASS_SUBSURFACE_DIRECT); - - if (STRPREFIX(str, "SubsurfaceInd")) - RETURN_PASS(SCE_PASS_SUBSURFACE_INDIRECT); - - if (STRPREFIX(str, "SubsurfaceCol")) - RETURN_PASS(SCE_PASS_SUBSURFACE_COLOR); - - return 0; - -#undef RETURN_PASS + BLI_strncpy(outname, name, EXR_PASS_MAXNAME); + if (channel >= 0) { + char token[3] = {'.', chan_id[channel], '\0'}; + strncat(outname, token, EXR_PASS_MAXNAME); + } + return outname; } - -static void set_pass_name(char *passname, int passtype, int channel, const char *view) +static void set_pass_full_name(char *fullname, const char *name, int channel, const char *view, const char *chan_id) { - const char delims[] = {'.', '\0'}; - const char *sep; - const char *token; - size_t len; - - const char *passtype_name = name_from_passtype(passtype, channel); - - if (view == NULL || view[0] == '\0') { - BLI_strncpy(passname, passtype_name, EXR_PASS_MAXNAME); - return; - } - - len = BLI_str_rpartition(passtype_name, delims, &sep, &token); - - if (sep) { - BLI_snprintf(passname, EXR_PASS_MAXNAME, "%.*s.%s.%s", (int)len, passtype_name, view, token); + BLI_strncpy(fullname, name, EXR_PASS_MAXNAME); + if (view && view[0]) { + strncat(fullname, ".", EXR_PASS_MAXNAME); + strncat(fullname, view, EXR_PASS_MAXNAME); } - else { - BLI_snprintf(passname, EXR_PASS_MAXNAME, "%s.%s", passtype_name, view); + if (channel >= 0) { + char token[3] = {'.', chan_id[channel], '\0'}; + strncat(fullname, token, EXR_PASS_MAXNAME); } } /********************************** New **************************************/ -static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname) +static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname, const char *chan_id) { const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); - const char *typestr = name_from_passtype(passtype, -1); - RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr); + RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name); size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels; - rpass->passtype = passtype; rpass->channels = channels; rpass->rectx = rl->rectx; rpass->recty = rl->recty; rpass->view_id = view_id; - set_pass_name(rpass->name, rpass->passtype, -1, viewname); - BLI_strncpy(rpass->internal_name, typestr, sizeof(rpass->internal_name)); + BLI_strncpy(rpass->name, name, sizeof(rpass->name)); + BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id)); BLI_strncpy(rpass->view, viewname, sizeof(rpass->view)); + set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id); if (rl->exrhandle) { int a; - for (a = 0; a < channels; a++) - IMB_exr_add_channel(rl->exrhandle, rl->name, name_from_passtype(passtype, a), viewname, 0, 0, NULL, false); + for (a = 0; a < channels; a++) { + char passname[EXR_PASS_MAXNAME]; + IMB_exr_add_channel(rl->exrhandle, rl->name, set_pass_name(passname, rpass->name, a, rpass->chan_id), viewname, 0, 0, NULL, false); + } } else { float *rect; int x; - rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, typestr); + rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, name); if (rpass->rect == NULL) { MEM_freeN(rpass); return NULL; } - if (passtype == SCE_PASS_VECTOR) { + if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { /* initialize to max speed */ rect = rpass->rect; for (x = rectsize - 1; x >= 0; x--) rect[x] = PASS_VECTOR_MAX; } - else if (passtype == SCE_PASS_Z) { + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { rect = rpass->rect; for (x = rectsize - 1; x >= 0; x--) rect[x] = 10e10; @@ -541,58 +250,10 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int return rpass; } /* wrapper called from render_opengl */ -RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype, const char *viewname) -{ - return render_layer_add_pass(rr, rl, channels, passtype, viewname); -} - -#ifdef WITH_CYCLES_DEBUG -const char *RE_debug_pass_name_get(int debug_type) -{ - switch (debug_type) { - case RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES: - return "BVH Traversed Nodes"; - case RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES: - return "BVH Traversed Instances"; - case RENDER_PASS_DEBUG_BVH_INTERSECTIONS: - return "BVH Primitive Intersections"; - case RENDER_PASS_DEBUG_RAY_BOUNCES: - return "Ray Bounces"; - } - return "Unknown"; -} - -int RE_debug_pass_num_channels_get(int UNUSED(debug_type)) -{ - /* Only single case currently, might be handy for further debug passes. */ - return 1; -} - -static RenderPass *render_layer_add_debug_pass(RenderResult *rr, - RenderLayer *rl, - int pass_type, - int debug_type, - const char *view) -{ - const char *name = RE_debug_pass_name_get(debug_type); - int channels = RE_debug_pass_num_channels_get(debug_type); - RenderPass *rpass = render_layer_add_pass(rr, rl, channels, pass_type, view); - if (rpass == NULL) { - return NULL; - } - rpass->debug_type = debug_type; - BLI_strncpy(rpass->name, - name, - sizeof(rpass->name)); - BLI_strncpy(rpass->internal_name, rpass->name, sizeof(rpass->internal_name)); - return rpass; -} - -int RE_debug_pass_type_get(Render *re) +RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname) { - return re->r.debug_pass_type; + return render_layer_add_pass(rr, rl, channels, name, viewname, "RGBA"); } -#endif /* called by main render as well for parts */ /* will read info from Render *re to define layers */ @@ -683,89 +344,77 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf if (rr->do_exr_tile) IMB_exr_add_view(rl->exrhandle, view); -#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, passtype, viewname) \ +#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \ do { \ - if (render_layer_add_pass(rr, rl, channels, passtype, viewname) == NULL) { \ + if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id) == NULL) { \ render_result_free(rr); \ return NULL; \ } \ } while (false) /* a renderlayer should always have a Combined pass*/ - render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); + render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA"); if (srl->passflag & SCE_PASS_Z) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_Z, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_Z, view, "Z"); if (srl->passflag & SCE_PASS_VECTOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_VECTOR, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_VECTOR, view, "XYZW"); if (srl->passflag & SCE_PASS_NORMAL) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_NORMAL, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_NORMAL, view, "XYZ"); if (srl->passflag & SCE_PASS_UV) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_UV, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA"); if (srl->passflag & SCE_PASS_RGBA) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_RGBA, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RGBA, view, "RGBA"); if (srl->passflag & SCE_PASS_EMIT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_EMIT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_EMIT, view, "RGB"); if (srl->passflag & SCE_PASS_DIFFUSE) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE, view, "RGB"); if (srl->passflag & SCE_PASS_SPEC) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SPEC, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SPEC, view, "RGB"); if (srl->passflag & SCE_PASS_AO) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_AO, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB"); if (srl->passflag & SCE_PASS_ENVIRONMENT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_ENVIRONMENT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_ENVIRONMENT, view, "RGB"); if (srl->passflag & SCE_PASS_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_SHADOW) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SHADOW, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SHADOW, view, "RGB"); if (srl->passflag & SCE_PASS_REFLECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_REFLECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFLECT, view, "RGB"); if (srl->passflag & SCE_PASS_REFRACT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_REFRACT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_REFRACT, view, "RGB"); if (srl->passflag & SCE_PASS_INDEXOB) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_INDEXOB, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXOB, view, "X"); if (srl->passflag & SCE_PASS_INDEXMA) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_INDEXMA, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_INDEXMA, view, "X"); if (srl->passflag & SCE_PASS_MIST) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, SCE_PASS_MIST, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 1, RE_PASSNAME_MIST, view, "Z"); if (rl->passflag & SCE_PASS_RAYHITS) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, SCE_PASS_RAYHITS, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 4, RE_PASSNAME_RAYHITS, view, "RGB"); if (srl->passflag & SCE_PASS_DIFFUSE_DIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_DIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_DIFFUSE_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_DIFFUSE_COLOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_DIFFUSE_COLOR, view, "RGB"); if (srl->passflag & SCE_PASS_GLOSSY_DIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_DIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_GLOSSY_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_GLOSSY_COLOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_GLOSSY_COLOR, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_GLOSSY_COLOR, view, "RGB"); if (srl->passflag & SCE_PASS_TRANSM_DIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_DIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_DIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_TRANSM_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_TRANSM_COLOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_TRANSM_COLOR, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_TRANSM_COLOR, view, "RGB"); if (srl->passflag & SCE_PASS_SUBSURFACE_DIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_DIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_DIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_SUBSURFACE_INDIRECT) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_INDIRECT, view); + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_INDIRECT, view, "RGB"); if (srl->passflag & SCE_PASS_SUBSURFACE_COLOR) - RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, SCE_PASS_SUBSURFACE_COLOR, view); - -#ifdef WITH_CYCLES_DEBUG - if (BKE_scene_use_new_shading_nodes(re->scene)) { - if (render_layer_add_debug_pass(rr, rl, SCE_PASS_DEBUG, - re->r.debug_pass_type, view) == NULL) - { - render_result_free(rr); - return NULL; - } - } -#endif - + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB"); #undef RENDER_LAYER_ADD_PASS_SAFE } } @@ -794,7 +443,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf IMB_exr_add_view(rl->exrhandle, view); /* a renderlayer should always have a Combined pass */ - render_layer_add_pass(rr, rl, 4, SCE_PASS_COMBINED, view); + render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA"); } /* note, this has to be in sync with scene.c */ @@ -813,6 +462,60 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf return rr; } +void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname) +{ + RenderLayer *rl; + RenderPass *main_rp; + + for (rl = rr->layers.first; rl; rl = rl->next) { + RenderLayer *main_rl = BLI_findstring(&re->result->layers, rl->name, offsetof(RenderLayer, name)); + if (!main_rl) { + continue; + } + + for (main_rp = main_rl->passes.first; main_rp; main_rp = main_rp->next) { + if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) { + continue; + } + + /* Compare fullname to make sure that the view also is equal. */ + RenderPass *rp = BLI_findstring(&rl->passes, main_rp->fullname, offsetof(RenderPass, fullname)); + if (!rp) { + render_layer_add_pass(rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id); + } + } + } +} + +void render_result_add_pass(RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname) +{ + RenderLayer *rl; + RenderPass *rp; + RenderView *rv; + + for (rl = rr->layers.first; rl; rl = rl->next) { + if (layername && layername[0] && !STREQ(rl->name, layername)) { + continue; + } + + for (rv = rr->views.first; rv; rv = rv->next) { + const char *view = rv->name; + + if (viewname && viewname[0] && !STREQ(view, viewname)) continue; + + /* Ensure that the pass doesn't exist yet. */ + for (rp = rl->passes.first; rp; rp = rp->next) { + if (!STREQ(rp->name, name)) continue; + if (!STREQ(rp->view, view)) continue; + } + + if (!rp) { + render_layer_add_pass(rr, rl, channels, name, view, chan_id); + } + } + } +} + /* allocate osa new results for samples */ RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers, const char *viewname) { @@ -830,6 +533,50 @@ RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *part return lb->first; } +static int passtype_from_name(const char *name) +{ + const char delim[] = {'.', '\0'}; + const char *sep, *suf; + int len = BLI_str_partition(name, delim, &sep, &suf); + +#define CHECK_PASS(NAME) if (STREQLEN(name, RE_PASSNAME_ ## NAME, len)) return SCE_PASS_ ## NAME + + CHECK_PASS(COMBINED); + CHECK_PASS(Z); + CHECK_PASS(VECTOR); + CHECK_PASS(NORMAL); + CHECK_PASS(UV); + CHECK_PASS(RGBA); + CHECK_PASS(EMIT); + CHECK_PASS(DIFFUSE); + CHECK_PASS(SPEC); + CHECK_PASS(SHADOW); + CHECK_PASS(AO); + CHECK_PASS(ENVIRONMENT); + CHECK_PASS(INDIRECT); + CHECK_PASS(REFLECT); + CHECK_PASS(REFRACT); + CHECK_PASS(INDEXOB); + CHECK_PASS(INDEXMA); + CHECK_PASS(MIST); + CHECK_PASS(RAYHITS); + CHECK_PASS(DIFFUSE_DIRECT); + CHECK_PASS(DIFFUSE_INDIRECT); + CHECK_PASS(DIFFUSE_COLOR); + CHECK_PASS(GLOSSY_DIRECT); + CHECK_PASS(GLOSSY_INDIRECT); + CHECK_PASS(GLOSSY_COLOR); + CHECK_PASS(TRANSM_DIRECT); + CHECK_PASS(TRANSM_INDIRECT); + CHECK_PASS(TRANSM_COLOR); + CHECK_PASS(SUBSURFACE_DIRECT); + CHECK_PASS(SUBSURFACE_INDIRECT); + CHECK_PASS(SUBSURFACE_COLOR); + +#undef CHECK_PASS + return 0; +} + /* callbacks for render_result_new_from_exr */ static void *ml_addlayer_cb(void *base, const char *str) { @@ -843,36 +590,30 @@ static void *ml_addlayer_cb(void *base, const char *str) return rl; } -static void ml_addpass_cb(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view) +static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view) { RenderResult *rr = base; RenderLayer *rl = lay; RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass"); - int a; - + BLI_addtail(&rl->passes, rpass); rpass->channels = totchan; - rpass->passtype = passtype_from_name(str, rl->passflag); - if (rpass->passtype == 0) - printf("unknown pass %s\n", str); - rl->passflag |= rpass->passtype; - + rl->passflag |= passtype_from_name(name); + /* channel id chars */ - for (a = 0; a < totchan; a++) - rpass->chan_id[a] = chan_id[a]; + BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id)); rpass->rect = rect; + BLI_strncpy(rpass->name, name, EXR_PASS_MAXNAME); + BLI_strncpy(rpass->view, view, sizeof(rpass->view)); + set_pass_full_name(rpass->fullname, name, -1, view, rpass->chan_id); + if (view[0] != '\0') { - BLI_snprintf(rpass->name, sizeof(rpass->name), "%s.%s", str, view); rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name)); } else { - BLI_strncpy(rpass->name, str, sizeof(rpass->name)); rpass->view_id = 0; } - - BLI_strncpy(rpass->view, view, sizeof(rpass->view)); - BLI_strncpy(rpass->internal_name, str, sizeof(rpass->internal_name)); } static void *ml_addview_cb(void *base, const char *str) @@ -912,12 +653,30 @@ static int order_render_passes(const void *a, const void *b) // 1 if a is after b RenderPass *rpa = (RenderPass *) a; RenderPass *rpb = (RenderPass *) b; + unsigned int passtype_a = passtype_from_name(rpa->name); + unsigned int passtype_b = passtype_from_name(rpb->name); - if (rpa->passtype > rpb->passtype) + /* Render passes with default type always go first. */ + if (passtype_b && !passtype_a) return 1; - else if (rpa->passtype < rpb->passtype) + if (passtype_a && !passtype_b) return 0; + if (passtype_a && passtype_b) { + if (passtype_a > passtype_b) + return 1; + else if (passtype_a < passtype_b) + return 0; + } + else { + int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME); + if (cmp > 0) + return 1; + if (cmp < 0) + return 0; + } + + /* they have the same type */ /* left first */ if (STREQ(rpa->view, STEREO_LEFT_NAME)) @@ -1049,7 +808,7 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) rpass = rpass->next) { /* renderresult have all passes, renderpart only the active view's passes */ - if (strcmp(rpassp->name, rpass->name) != 0) + if (strcmp(rpassp->fullname, rpass->fullname) != 0) continue; do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels); @@ -1061,21 +820,6 @@ void render_result_merge(RenderResult *rr, RenderResult *rrpart) } } -/* for passes read from files, these have names stored */ -static char *make_pass_name(RenderPass *rpass, int chan) -{ - static char name[EXR_PASS_MAXNAME]; - int len; - - BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME); - len = strlen(name); - name[len] = '.'; - name[len + 1] = rpass->chan_id[chan]; - name[len + 2] = 0; - - return name; -} - /* called from within UI and render pipeline, saves both rendered result as a file-read result * if multiview is true saves all views in a multiview exr * else if view is not NULL saves single view @@ -1136,8 +880,10 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil IMB_exr_add_view(exrhandle, rview->name); if (rview->rectf) { + char passname[EXR_PASS_MAXNAME]; for (a = 0; a < 4; a++) { - IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a), + set_pass_name(passname, RE_PASSNAME_COMBINED, a, "RGBA"); + IMB_exr_add_channel(exrhandle, RE_PASSNAME_COMBINED, passname, chan_view, 4, 4 * width, rview->rectf + a, use_half_float); } @@ -1150,6 +896,7 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil /* passes are allocated in sync */ for (rpass = rl->passes.first; rpass; rpass = rpass->next) { const int xstride = rpass->channels; + char passname[EXR_PASS_MAXNAME]; if (is_mono) { if (!STREQ(view, rpass->view)) { @@ -1163,16 +910,10 @@ bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *fil } for (a = 0; a < xstride; a++) { - if (rpass->passtype) { - IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view, - xstride, xstride * width, rpass->rect + a, - rpass->passtype == SCE_PASS_Z ? false : use_half_float); - } - else { - IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view, - xstride, xstride * width, rpass->rect + a, - use_half_float); - } + set_pass_name(passname, rpass->name, a, rpass->chan_id); + IMB_exr_add_channel(exrhandle, rl->name, passname, chan_view, + xstride, xstride * width, rpass->rect + a, + STREQ(rpass->name, RE_PASSNAME_Z) ? false : use_half_float); } } } @@ -1281,12 +1022,12 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) { const int xstride = rpassp->channels; int a; - char passname[EXR_PASS_MAXNAME]; + char fullname[EXR_PASS_MAXNAME]; for (a = 0; a < xstride; a++) { - set_pass_name(passname, rpassp->passtype, a, rpassp->view); + set_pass_full_name(fullname, rpassp->name, a, viewname, rpassp->chan_id); - IMB_exr_set_channel(rl->exrhandle, rlp->name, passname, + IMB_exr_set_channel(rl->exrhandle, rlp->name, fullname, xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs); } } @@ -1449,15 +1190,15 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c for (rpass = rl->passes.first; rpass; rpass = rpass->next) { const int xstride = rpass->channels; int a; - char passname[EXR_PASS_MAXNAME]; + char fullname[EXR_PASS_MAXNAME]; for (a = 0; a < xstride; a++) { - set_pass_name(passname, rpass->passtype, a, rpass->view); - IMB_exr_set_channel(exrhandle, rl->name, passname, + set_pass_full_name(fullname, rpass->name, a, rpass->view, rpass->chan_id); + IMB_exr_set_channel(exrhandle, rl->name, fullname, xstride, xstride * rectx, rpass->rect + a); } - set_pass_name(rpass->name, rpass->passtype, -1, rpass->view); + set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id); } } diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 42e4d4f27f6..22dc2b28900 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1495,6 +1495,7 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa case MTEX_SUB: fact= -fact; + ATTR_FALLTHROUGH; case MTEX_ADD: fact*= facg; in[0]= (fact*tex[0] + out[0]); @@ -1609,6 +1610,7 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen case MTEX_SUB: fact= -fact; + ATTR_FALLTHROUGH; case MTEX_ADD: in= fact*tex + out; break; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 910ea16607e..77f399d08d1 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -180,11 +180,12 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in flarec= 0; if (fullsample) { - for (sample=0; sample<totsample; sample++) + for (sample=0; sample<totsample; sample++) { if (ps->mask & (1 << sample)) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); addalphaAddfacFloat(pass + od*4, col, har->add); } + } } else { fac= ((float)amountm)/(float)R.osa; @@ -215,11 +216,12 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in } if (fullsample) { - for (sample=0; sample<totsample; sample++) + for (sample=0; sample<totsample; sample++) { if (!(mask & (1 << sample))) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); addalphaAddfacFloat(pass + od*4, col, har->add); } + } } else { col[0]= accol[0]; @@ -228,7 +230,7 @@ static void halo_pixelstruct(HaloRen *har, RenderLayer **rlpp, int totsample, in col[3]= accol[3]; for (sample=0; sample<totsample; sample++) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); addalphaAddfacFloat(pass + od*4, col, har->add); } } @@ -312,7 +314,7 @@ static void halo_tile(RenderPart *pa, RenderLayer *rl) if ((zz> har->zs) || (har->mat && (har->mat->mode & MA_HALO_SOFT))) { if (shadeHaloFloat(har, col, zz, dist, xn, yn, har->flarec)) { for (sample=0; sample<totsample; sample++) { - float * rect= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float * rect= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); addalphaAddfacFloat(rect + od*4, col, har->add); } } @@ -367,7 +369,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) if (fullsample) { for (sample=0; sample<totsample; sample++) { if (ps->mask & (1 << sample)) { - pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; @@ -379,7 +381,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) } else { fac= ((float)count)/(float)R.osa; - pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= fac*col[0]; pass[1]+= fac*col[1]; @@ -401,7 +403,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) for (sample=0; sample<totsample; sample++) { if (!(mask & (1 << sample))) { - pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; @@ -413,7 +415,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) } else { fac= ((float)R.osa-totsamp)/(float)R.osa; - pass = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= fac*col[0]; pass[1]+= fac*col[1]; @@ -433,7 +435,7 @@ static void lamphalo_tile(RenderPart *pa, RenderLayer *rl) renderspothalo(&shi, col, 1.0f); for (sample=0; sample<totsample; sample++) { - pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); pass += od * 4; pass[0]+= col[0]; pass[1]+= col[1]; @@ -462,101 +464,96 @@ static void add_filt_passes(RenderLayer *rl, int curmask, int rectx, int offset, float *fp, *col= NULL; int pixsize= 3; - switch (rpass->passtype) { - case SCE_PASS_COMBINED: - add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx); - break; - case SCE_PASS_Z: - fp= rpass->rect + offset; - *fp= shr->z; - break; - case SCE_PASS_RGBA: - col= shr->col; - pixsize= 4; - break; - case SCE_PASS_EMIT: - col= shr->emit; - break; - case SCE_PASS_DIFFUSE: - col= shr->diff; - break; - case SCE_PASS_SPEC: - col= shr->spec; - break; - case SCE_PASS_SHADOW: - col= shr->shad; - break; - case SCE_PASS_AO: - col= shr->ao; - break; - case SCE_PASS_ENVIRONMENT: - col= shr->env; - break; - case SCE_PASS_INDIRECT: - col= shr->indirect; - break; - case SCE_PASS_REFLECT: - col= shr->refl; - break; - case SCE_PASS_REFRACT: - col= shr->refr; - break; - case SCE_PASS_NORMAL: - col= shr->nor; - break; - case SCE_PASS_UV: - /* box filter only, gauss will screwup UV too much */ - if (shi->totuv) { - float mult= (float)count_mask(curmask)/(float)R.osa; - fp= rpass->rect + 3*offset; - fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]); - fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]); - fp[2]+= mult; - } - break; - case SCE_PASS_INDEXOB: - /* no filter */ - if (shi->vlr) { - fp= rpass->rect + offset; + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { + add_filt_fmask(curmask, shr->combined, rpass->rect + 4*offset, rectx); + } + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { + fp = rpass->rect + offset; + *fp = shr->z; + } + else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { + col = shr->col; + pixsize = 4; + } + else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { + col = shr->emit; + } + else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { + col = shr->diff; + } + else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { + col = shr->spec; + } + else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { + col = shr->shad; + } + else if (STREQ(rpass->name, RE_PASSNAME_AO)) { + col = shr->ao; + } + else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { + col = shr->env; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { + col = shr->indirect; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { + col = shr->refl; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { + col = shr->refr; + } + else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { + col = shr->nor; + } + else if (STREQ(rpass->name, RE_PASSNAME_UV)) { + /* box filter only, gauss will screwup UV too much */ + if (shi->totuv) { + float mult = (float)count_mask(curmask)/(float)R.osa; + fp = rpass->rect + 3*offset; + fp[0]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[0]); + fp[1]+= mult*(0.5f + 0.5f*shi->uv[shi->actuv].uv[1]); + fp[2]+= mult; + } + } + else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { + /* no filter */ + if (shi->vlr) { + fp = rpass->rect + offset; + if (*fp==0.0f) + *fp = (float)shi->obr->ob->index; + } + } + else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { + /* no filter */ + if (shi->vlr) { + fp = rpass->rect + offset; if (*fp==0.0f) - *fp= (float)shi->obr->ob->index; - } - break; - case SCE_PASS_INDEXMA: - /* no filter */ - if (shi->vlr) { - fp= rpass->rect + offset; - if (*fp==0.0f) - *fp= (float)shi->mat->index; - } - break; - case SCE_PASS_MIST: - /* */ - col= &shr->mist; - pixsize= 1; - break; - - case SCE_PASS_VECTOR: - { - /* add minimum speed in pixel, no filter */ - fp= rpass->rect + 4*offset; - if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { - fp[0]= shr->winspeed[0]; - fp[1]= shr->winspeed[1]; - } - if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { - fp[2]= shr->winspeed[2]; - fp[3]= shr->winspeed[3]; - } - - break; + *fp = (float)shi->mat->index; + } + } + else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { + /* */ + col = &shr->mist; + pixsize = 1; + } + else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { + /* add minimum speed in pixel, no filter */ + fp = rpass->rect + 4*offset; + if ( (ABS(shr->winspeed[0]) + ABS(shr->winspeed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { + fp[0] = shr->winspeed[0]; + fp[1] = shr->winspeed[1]; + } + if ( (ABS(shr->winspeed[2]) + ABS(shr->winspeed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { + fp[2] = shr->winspeed[2]; + fp[3] = shr->winspeed[3]; } - case SCE_PASS_RAYHITS: - /* */ - col= shr->rayhits; - pixsize= 4; - break; } + else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) { + /* */ + col = shr->rayhits; + pixsize= 4; + } + if (col) { fp= rpass->rect + pixsize*offset; add_filt_fmask_pixsize(curmask, col, fp, rectx, pixsize); @@ -574,86 +571,85 @@ static void add_passes(RenderLayer *rl, int offset, ShadeInput *shi, ShadeResult float *col= NULL, uvcol[3]; int a, pixsize= 3; - switch (rpass->passtype) { - case SCE_PASS_COMBINED: - /* copy combined to use for preview */ - copy_v4_v4(rpass->rect + 4*offset, shr->combined); - break; - case SCE_PASS_Z: - fp= rpass->rect + offset; - *fp= shr->z; - break; - case SCE_PASS_RGBA: - col= shr->col; - pixsize= 4; - break; - case SCE_PASS_EMIT: - col= shr->emit; - break; - case SCE_PASS_DIFFUSE: - col= shr->diff; - break; - case SCE_PASS_SPEC: - col= shr->spec; - break; - case SCE_PASS_SHADOW: - col= shr->shad; - break; - case SCE_PASS_AO: - col= shr->ao; - break; - case SCE_PASS_ENVIRONMENT: - col= shr->env; - break; - case SCE_PASS_INDIRECT: - col= shr->indirect; - break; - case SCE_PASS_REFLECT: - col= shr->refl; - break; - case SCE_PASS_REFRACT: - col= shr->refr; - break; - case SCE_PASS_NORMAL: - col= shr->nor; - break; - case SCE_PASS_UV: - if (shi->totuv) { - uvcol[0]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[0]; - uvcol[1]= 0.5f + 0.5f*shi->uv[shi->actuv].uv[1]; - uvcol[2]= 1.0f; - col= uvcol; - } - break; - case SCE_PASS_VECTOR: - col= shr->winspeed; - pixsize= 4; - break; - case SCE_PASS_INDEXOB: - if (shi->vlr) { - fp= rpass->rect + offset; - *fp= (float)shi->obr->ob->index; - } - break; - case SCE_PASS_INDEXMA: - if (shi->vlr) { - fp= rpass->rect + offset; - *fp= (float)shi->mat->index; - } - break; - case SCE_PASS_MIST: - fp= rpass->rect + offset; - *fp= shr->mist; - break; - case SCE_PASS_RAYHITS: - col= shr->rayhits; - pixsize= 4; - break; + if (STREQ(rpass->name, RE_PASSNAME_COMBINED)) { + /* copy combined to use for preview */ + copy_v4_v4(rpass->rect + 4*offset, shr->combined); + } + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { + fp = rpass->rect + offset; + *fp = shr->z; + } + else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { + col = shr->col; + pixsize = 4; + } + else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { + col = shr->emit; + } + else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { + col = shr->diff; + } + else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { + col = shr->spec; + } + else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { + col = shr->shad; + } + else if (STREQ(rpass->name, RE_PASSNAME_AO)) { + col = shr->ao; + } + else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { + col = shr->env; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { + col = shr->indirect; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { + col = shr->refl; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { + col = shr->refr; + } + else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { + col = shr->nor; + } + else if (STREQ(rpass->name, RE_PASSNAME_UV)) { + if (shi->totuv) { + uvcol[0] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[0]; + uvcol[1] = 0.5f + 0.5f*shi->uv[shi->actuv].uv[1]; + uvcol[2] = 1.0f; + col = uvcol; + } + } + else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { + col = shr->winspeed; + pixsize = 4; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { + if (shi->vlr) { + fp = rpass->rect + offset; + *fp = (float)shi->obr->ob->index; + } + } + else if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { + if (shi->vlr) { + fp = rpass->rect + offset; + *fp = (float)shi->mat->index; + } + } + else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { + fp = rpass->rect + offset; + *fp = shr->mist; + } + else if (STREQ(rpass->name, RE_PASSNAME_RAYHITS)) { + col = shr->rayhits; + pixsize = 4; } + if (col) { - fp= rpass->rect + pixsize*offset; + fp = rpass->rect + pixsize*offset; for (a=0; a<pixsize; a++) - fp[a]= col[a]; + fp[a] = col[a]; } } } @@ -696,7 +692,7 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl) bool done = false; for (sample= 0; sample<totsample; sample++) { - float *pass = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *pass = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); pass += od; if (pass[3]<1.0f) { @@ -737,7 +733,7 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) /* check that z pass is enabled */ if (pa->rectz==NULL) return; for (zpass= rl->passes.first; zpass; zpass= zpass->next) - if (zpass->passtype==SCE_PASS_Z) + if (STREQ(zpass->name, RE_PASSNAME_Z)) break; if (zpass==NULL) return; @@ -758,8 +754,8 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) int sample; for (sample=0; sample<totsample; sample++) { - const float *zrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_Z, R.viewname) + od; - float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname) + 4*od; + const float *zrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_Z, R.viewname) + od; + float *rgbrect = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname) + 4*od; float rgb[3] = {0}; bool done = false; @@ -994,7 +990,7 @@ static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl) return; for (sample= 0; sample<totsample; sample++) { - float *rectf = RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_COMBINED, R.viewname); + float *rectf = RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_COMBINED, R.viewname); for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { rectf[0] = MAX2(rectf[0], 0.0f); @@ -1076,7 +1072,7 @@ static void reset_sky_speed(RenderPart *pa, RenderLayer *rl) totsample= get_sample_layers(pa, rl, rlpp); for (sample= 0; sample<totsample; sample++) { - fp= RE_RenderLayerGetPass(rlpp[sample], SCE_PASS_VECTOR, R.viewname); + fp= RE_RenderLayerGetPass(rlpp[sample], RE_PASSNAME_VECTOR, R.viewname); if (fp==NULL) break; for (a= 4*pa->rectx*pa->recty - 1; a>=0; a--) @@ -1187,7 +1183,7 @@ void zbufshadeDA_tile(RenderPart *pa) pa->rectp= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectp"); pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); for (rl= rr->layers.first; rl; rl= rl->next) { - float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); @@ -1339,7 +1335,7 @@ void zbufshade_tile(RenderPart *pa) pa->rectz= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectz"); for (rl= rr->layers.first; rl; rl= rl->next) { - float *rect= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + float *rect= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); if ((rl->layflag & SCE_LAY_ZMASK) && (rl->layflag & SCE_LAY_NEG_ZMASK)) pa->rectmask= MEM_mallocN(sizeof(int)*pa->rectx*pa->recty, "rectmask"); @@ -1676,7 +1672,7 @@ void zbufshade_sss_tile(RenderPart *pa) return; } - fcol= RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + fcol= RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); co= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSCo"); color= MEM_mallocN(sizeof(float)*3*handle.totps, "SSSColor"); @@ -1969,7 +1965,7 @@ void add_halo_flare(Render *re) if ((rl->layflag & SCE_LAY_HALO) == 0) continue; - rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, re->viewname); + rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, re->viewname); if (rect==NULL) continue; @@ -1998,3 +1994,37 @@ void add_halo_flare(Render *re) } } +void render_internal_update_passes(RenderEngine *engine, Scene *scene, SceneRenderLayer *srl) +{ + int type; + + RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); + +#define CHECK_PASS(name, channels, chanid) \ + if (srl->passflag & (SCE_PASS_ ## name)) { \ + if (channels == 4) type = SOCK_RGBA; \ + else if (channels == 3) type = SOCK_VECTOR; \ + else type = SOCK_FLOAT; \ + RE_engine_register_pass(engine, scene, srl, RE_PASSNAME_ ## name, channels, chanid, type); \ + } + + CHECK_PASS(Z, 1, "Z"); + CHECK_PASS(VECTOR, 4, "XYZW"); + CHECK_PASS(NORMAL, 3, "XYZ"); + CHECK_PASS(UV, 3, "UVA"); + CHECK_PASS(RGBA, 4, "RGBA"); + CHECK_PASS(EMIT, 3, "RGB"); + CHECK_PASS(DIFFUSE, 3, "RGB"); + CHECK_PASS(SPEC, 3, "RGB"); + CHECK_PASS(AO, 3, "RGB"); + CHECK_PASS(ENVIRONMENT, 3, "RGB"); + CHECK_PASS(INDIRECT, 3, "RGB"); + CHECK_PASS(SHADOW, 3, "RGB"); + CHECK_PASS(REFLECT, 3, "RGB"); + CHECK_PASS(REFRACT, 3, "RGB"); + CHECK_PASS(INDEXOB, 1, "X"); + CHECK_PASS(INDEXMA, 1, "X"); + CHECK_PASS(MIST, 1, "Z"); + +#undef CHECK_PASS +} diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 76e6ca8d467..199322795f3 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -66,6 +66,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_hash.h" #include "DNA_material_types.h" #include "DNA_meshdata_types.h" @@ -1458,6 +1459,14 @@ ObjectInstanceRen *RE_addRenderInstance( } } + /* Fill object info */ + if (dob) { + obi->random_id = dob->random_id; + } + else { + obi->random_id = BLI_hash_int_2d(BLI_hash_string(obi->ob->id.name + 2), 0); + } + RE_updateRenderInstance(re, obi, RE_OBJECT_INSTANCES_UPDATE_OBMAT | RE_OBJECT_INSTANCES_UPDATE_VIEW); if (mat) { diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index a8fb72fb7f8..8dea0930b9e 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -2141,6 +2141,16 @@ const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int m return NULL; } +float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi) +{ + return obi->ob->index; +} + +float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi) +{ + return obi->random_id; +} + const float (*RE_render_current_get_matrix(int matrix_id))[4] { switch (matrix_id) { diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c index d4e53eb7305..f0cf29e98ca 100644 --- a/source/blender/render/intern/source/sunsky.c +++ b/source/blender/render/intern/source/sunsky.c @@ -398,7 +398,7 @@ void InitAtmosphere(struct SunSky *sunSky, float sun_intens, float mief, float r vLambda2[0] = fLambda2[0]; vLambda2[1] = fLambda2[1]; vLambda2[2] = fLambda2[2]; - + vLambda4[0] = fLambda4[0]; vLambda4[1] = fLambda4[1]; vLambda4[2] = fLambda4[2]; diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 610e86caa13..7fe52328781 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -275,10 +275,12 @@ static float metadensity(Object *ob, const float co[3]) break; case MB_CUBE: tp[2] = (tp[2] > ml->expz) ? (tp[2] - ml->expz) : ((tp[2] < -ml->expz) ? (tp[2] + ml->expz) : 0.f); - /* no break, xy as plane */ + /* no break, xy as plane */ + ATTR_FALLTHROUGH; case MB_PLANE: tp[1] = (tp[1] > ml->expy) ? (tp[1] - ml->expy) : ((tp[1] < -ml->expy) ? (tp[1] + ml->expy) : 0.f); - /* no break, x as tube */ + /* no break, x as tube */ + ATTR_FALLTHROUGH; case MB_TUBE: tp[0] = (tp[0] > ml->expx) ? (tp[0] - ml->expx) : ((tp[0] < -ml->expx) ? (tp[0] + ml->expx) : 0.f); } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 9f777631e52..68707f163af 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -1601,7 +1601,6 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float * * Note: uses globals. * \param v1 start coordinate s * \param v2 target coordinate t - * \param b1 * \param b2 * \param b3 * \param a index for coordinate (x, y, or z) @@ -3494,7 +3493,7 @@ static void add_transp_speed(RenderLayer *rl, int offset, float speed[4], float RenderPass *rpass; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (rpass->passtype==SCE_PASS_VECTOR) { + if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { float *fp= rpass->rect + 4*offset; if (speed==NULL) { @@ -3528,7 +3527,7 @@ static void add_transp_obindex(RenderLayer *rl, int offset, Object *ob) RenderPass *rpass; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (rpass->passtype == SCE_PASS_INDEXOB) { + if (STREQ(rpass->name, RE_PASSNAME_INDEXOB)) { float *fp= rpass->rect + offset; *fp= (float)ob->index; break; @@ -3541,7 +3540,7 @@ static void add_transp_material_index(RenderLayer *rl, int offset, Material *mat RenderPass *rpass; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - if (rpass->passtype == SCE_PASS_INDEXMA) { + if (STREQ(rpass->name, RE_PASSNAME_INDEXMA)) { float *fp= rpass->rect + offset; *fp= (float)mat->index; break; @@ -3558,78 +3557,74 @@ static void merge_transp_passes(RenderLayer *rl, ShadeResult *shr) int delta= sizeof(ShadeResult)/4; for (rpass= rl->passes.first; rpass; rpass= rpass->next) { - float *col= NULL; - int pixsize= 3; + float *col = NULL; + int pixsize = 3; - switch (rpass->passtype) { - case SCE_PASS_RGBA: - col= shr->col; - pixsize= 4; - break; - case SCE_PASS_EMIT: - col= shr->emit; - break; - case SCE_PASS_DIFFUSE: - col= shr->diff; - break; - case SCE_PASS_SPEC: - col= shr->spec; - break; - case SCE_PASS_SHADOW: - col= shr->shad; - break; - case SCE_PASS_AO: - col= shr->ao; - break; - case SCE_PASS_ENVIRONMENT: - col= shr->env; - break; - case SCE_PASS_INDIRECT: - col= shr->indirect; - break; - case SCE_PASS_REFLECT: - col= shr->refl; - break; - case SCE_PASS_REFRACT: - col= shr->refr; - break; - case SCE_PASS_NORMAL: - col= shr->nor; - break; - case SCE_PASS_MIST: - col= &shr->mist; - pixsize= 1; - break; - case SCE_PASS_Z: - col= &shr->z; - pixsize= 1; - break; - case SCE_PASS_VECTOR: + if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { + col = shr->col; + pixsize = 4; + } + else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { + col = shr->emit; + } + else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { + col = shr->diff; + } + else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { + col = shr->spec; + } + else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { + col = shr->shad; + } + else if (STREQ(rpass->name, RE_PASSNAME_AO)) { + col = shr->ao; + } + else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { + col = shr->env; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { + col = shr->indirect; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { + col = shr->refl; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { + col = shr->refr; + } + else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { + col = shr->nor; + } + else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { + col = &shr->mist; + pixsize = 1; + } + else if (STREQ(rpass->name, RE_PASSNAME_Z)) { + col = &shr->z; + pixsize = 1; + } + else if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) { + ShadeResult *shr_t = shr+1; + float *fp = shr->winspeed; /* was initialized */ + int samp; + + /* add minimum speed in pixel */ + for (samp = 1; samp<R.osa; samp++, shr_t++) { - { - ShadeResult *shr_t= shr+1; - float *fp= shr->winspeed; /* was initialized */ - int samp; + if (shr_t->combined[3] > 0.0f) { + const float *speed = shr_t->winspeed; - /* add minimum speed in pixel */ - for (samp= 1; samp<R.osa; samp++, shr_t++) { - - if (shr_t->combined[3] > 0.0f) { - const float *speed= shr_t->winspeed; - - if ( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { - fp[0]= speed[0]; - fp[1]= speed[1]; - } - if ( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { - fp[2]= speed[2]; - fp[3]= speed[3]; - } - } + if ( (ABS(speed[0]) + ABS(speed[1]))< (ABS(fp[0]) + ABS(fp[1])) ) { + fp[0] = speed[0]; + fp[1] = speed[1]; + } + if ( (ABS(speed[2]) + ABS(speed[3]))< (ABS(fp[2]) + ABS(fp[3])) ) { + fp[2] = speed[2]; + fp[3] = speed[3]; } } - break; + } } + if (col) { const float *fp= col+delta; int samp; @@ -3661,53 +3656,51 @@ static void add_transp_passes(RenderLayer *rl, int offset, ShadeResult *shr, flo float *fp, *col= NULL; int pixsize= 3; - switch (rpass->passtype) { - case SCE_PASS_Z: - fp= rpass->rect + offset; - if (shr->z < *fp) - *fp= shr->z; - break; - case SCE_PASS_RGBA: - fp= rpass->rect + 4*offset; - addAlphaOverFloat(fp, shr->col); - break; - case SCE_PASS_EMIT: - col= shr->emit; - break; - case SCE_PASS_DIFFUSE: - col= shr->diff; - break; - case SCE_PASS_SPEC: - col= shr->spec; - break; - case SCE_PASS_SHADOW: - col= shr->shad; - break; - case SCE_PASS_AO: - col= shr->ao; - break; - case SCE_PASS_ENVIRONMENT: - col= shr->env; - break; - case SCE_PASS_INDIRECT: - col= shr->indirect; - break; - case SCE_PASS_REFLECT: - col= shr->refl; - break; - case SCE_PASS_REFRACT: - col= shr->refr; - break; - case SCE_PASS_NORMAL: - col= shr->nor; - break; - case SCE_PASS_MIST: - col= &shr->mist; - pixsize= 1; - break; + if (STREQ(rpass->name, RE_PASSNAME_Z)) { + fp = rpass->rect + offset; + if (shr->z < *fp) + *fp = shr->z; + } + else if (STREQ(rpass->name, RE_PASSNAME_RGBA)) { + fp = rpass->rect + 4*offset; + addAlphaOverFloat(fp, shr->col); + } + else if (STREQ(rpass->name, RE_PASSNAME_EMIT)) { + col = shr->emit; + } + else if (STREQ(rpass->name, RE_PASSNAME_DIFFUSE)) { + col = shr->diff; + } + else if (STREQ(rpass->name, RE_PASSNAME_SPEC)) { + col = shr->spec; + } + else if (STREQ(rpass->name, RE_PASSNAME_SHADOW)) { + col = shr->shad; + } + else if (STREQ(rpass->name, RE_PASSNAME_AO)) { + col = shr->ao; + } + else if (STREQ(rpass->name, RE_PASSNAME_ENVIRONMENT)) { + col = shr->env; + } + else if (STREQ(rpass->name, RE_PASSNAME_INDIRECT)) { + col = shr->indirect; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFLECT)) { + col = shr->refl; + } + else if (STREQ(rpass->name, RE_PASSNAME_REFRACT)) { + col = shr->refr; + } + else if (STREQ(rpass->name, RE_PASSNAME_NORMAL)) { + col = shr->nor; + } + else if (STREQ(rpass->name, RE_PASSNAME_MIST)) { + col = &shr->mist; + pixsize = 1; } - if (col) { + if (col) { fp= rpass->rect + pixsize*offset; fp[0]= col[0] + (1.0f-alpha)*fp[0]; if (pixsize==3) { @@ -3964,7 +3957,7 @@ static void reset_sky_speedvectors(RenderPart *pa, RenderLayer *rl, float *rectf float *fp, *col; int a; - fp = RE_RenderLayerGetPass(rl, SCE_PASS_VECTOR, R.viewname); + fp = RE_RenderLayerGetPass(rl, RE_PASSNAME_VECTOR, R.viewname); if (fp==NULL) return; col= rectf+3; @@ -4058,7 +4051,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas /* zero alpha pixels get speed vector max again */ if (addpassflag & SCE_PASS_VECTOR) if (rl->layflag & SCE_LAY_SOLID) { - float *rect = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, R.viewname); + float *rect = RE_RenderLayerGetPass(rl, RE_PASSNAME_COMBINED, R.viewname); reset_sky_speedvectors(pa, rl, rl->acolrect ? rl->acolrect : rect); /* if acolrect is set we use it */ } /* filtered render, for now we assume only 1 filter size */ @@ -4246,7 +4239,7 @@ unsigned short *zbuffer_transp_shade(RenderPart *pa, RenderLayer *rl, float *pas if (alpha != 0.0f) { RenderLayer *rl_other = ssamp.rlpp[a]; - float *rect = RE_RenderLayerGetPass(rl_other , SCE_PASS_COMBINED, R.viewname); + float *rect = RE_RenderLayerGetPass(rl_other , RE_PASSNAME_COMBINED, R.viewname); addAlphaOverFloat(rect + 4 * od, samp_shr[a].combined); add_transp_passes(rl_other , od, &samp_shr[a], alpha); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 1cfd20defe0..a91c30c2807 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -102,7 +102,8 @@ enum { }; struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect); -struct wmWindow *WM_window_open_temp(struct bContext *C, const struct rcti *rect_init, int type); +struct wmWindow *WM_window_open_temp(struct bContext *C, int x, int y, int sizex, int sizey, int type); +void WM_window_set_dpi(wmWindow *win); /* returns true if draw method is triple buffer */ bool WM_is_draw_triple(struct wmWindow *win); @@ -186,8 +187,9 @@ struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase /* mouse */ void WM_event_add_mousemove(struct bContext *C); -bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event); +bool WM_event_is_modal_tweak_exit(const struct wmEvent *event, int tweak_event); bool WM_event_is_absolute(const struct wmEvent *event); +bool WM_event_is_last_mousemove(const struct wmEvent *event); #ifdef WITH_INPUT_NDOF /* 3D mouse */ diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 4351cd22b18..67e961b9cd0 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -483,13 +483,12 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) void wm_close_and_free_all(bContext *C, ListBase *wmlist) { - Main *bmain = CTX_data_main(C); wmWindowManager *wm; - + while ((wm = wmlist->first)) { wm_close_and_free(C, wm); BLI_remlink(wmlist, wm); - BKE_libblock_free_data(bmain, &wm->id); + BKE_libblock_free_data(&wm->id, true); MEM_freeN(wm); } } diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 77ffa46b990..25c6980f58e 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -926,15 +926,14 @@ void wm_draw_update(bContext *C) for (win = wm->windows.first; win; win = win->next) { #ifdef WIN32 - if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { - GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin); - - if (state == GHOST_kWindowStateMinimized) { - /* do not update minimized windows, it gives issues on intel drivers (see [#33223]) - * anyway, it seems logical to skip update for invisible windows - */ - continue; - } + GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin); + + if (state == GHOST_kWindowStateMinimized) { + /* do not update minimized windows, gives issues on Intel (see T33223) + * and AMD (see T50856). it seems logical to skip update for invisible + * window anyway. + */ + continue; } #endif if (win->drawmethod != U.wmdrawmethod) { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index f26ee0e73ec..32f978ae891 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -615,6 +615,16 @@ bool WM_event_is_absolute(const wmEvent *event) return (event->tablet_data != NULL); } +bool WM_event_is_last_mousemove(const wmEvent *event) +{ + while ((event = event->next)) { + if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + return false; + } + } + return true; +} + #ifdef WITH_INPUT_NDOF void WM_ndof_deadzone_set(float deadzone) { @@ -2852,7 +2862,7 @@ void WM_event_add_mousemove(bContext *C) /* for modal callbacks, check configuration for how to interpret exit with tweaks */ -bool WM_modal_tweak_exit(const wmEvent *event, int tweak_event) +bool WM_event_is_modal_tweak_exit(const wmEvent *event, int tweak_event) { /* if the release-confirm userpref setting is enabled, * tweak events can be canceled when mouse is released diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 028355f9af3..b4a6366fb4e 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -316,7 +316,7 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) } /* in case UserDef was read, we re-initialize all, and do versioning */ -static void wm_init_userdef(bContext *C, const bool use_factory_settings) +static void wm_init_userdef(bContext *C, const bool read_userdef_from_memory) { Main *bmain = CTX_data_main(C); @@ -336,14 +336,12 @@ static void wm_init_userdef(bContext *C, const bool use_factory_settings) } /* avoid re-saving for every small change to our prefs, allow overrides */ - if (use_factory_settings) { + if (read_userdef_from_memory) { BLO_update_defaults_userpref_blend(); } /* update tempdir from user preferences */ BKE_tempdir_init(U.tempdir); - - BKE_blender_userdef_refresh(); } @@ -667,7 +665,7 @@ int wm_homefile_read( * * And in this case versioning code is to be run. */ - bool read_userdef_from_memory = true; + bool read_userdef_from_memory = false; eBLOReadSkip skip_flags = 0; /* options exclude eachother */ @@ -713,7 +711,6 @@ int wm_homefile_read( BKE_blender_userdef_set_data(userdef); MEM_freeN(userdef); - read_userdef_from_memory = false; skip_flags |= BLO_READ_SKIP_USERDEF; printf("Read prefs: %s\n", filepath_userdef); } @@ -724,7 +721,7 @@ int wm_homefile_read( if (filepath_startup_override != NULL) { /* pass */ } - else if (app_template_override) { + else if (app_template_override && app_template_override[0]) { app_template = app_template_override; } else if (!use_factory_settings && U.app_template[0]) { @@ -775,6 +772,9 @@ int wm_homefile_read( success = BKE_blendfile_read_from_memory( C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, skip_flags, true); + if (success && !(skip_flags & BLO_READ_SKIP_USERDEF)) { + read_userdef_from_memory = true; + } if (BLI_listbase_is_empty(&wmbase)) { wm_clear_default_size(C); } @@ -810,6 +810,7 @@ int wm_homefile_read( /* we need to have preferences load to overwrite preferences from previous template */ userdef_template = BKE_blendfile_userdef_read_from_memory( datatoc_startup_blend, datatoc_startup_blend_size, NULL); + read_userdef_from_memory = true; } if (userdef_template) { BKE_blender_userdef_set_app_template(userdef_template); @@ -1093,7 +1094,7 @@ static int wm_file_write(bContext *C, const char *filepath, int fileflags, Repor BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath); return ret; } - + /* note: used to replace the file extension (to ensure '.blend'), * no need to now because the operator ensures, * its handy for scripts to save to a predefined name without blender editing it */ diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index 3b733f9558c..f19c999a4f1 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -608,7 +608,8 @@ static void lib_relocate_do( } /* Note that in reload case, we also want to replace indirect usages. */ - const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE); + const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE | + (do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE); for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) { WMLinkAppendDataItem *item = itemlink->link; ID *old_id = item->customdata; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 9bafe72d805..00a9976e8be 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -181,7 +181,7 @@ void WM_init(bContext *C, int argc, const char **argv) ED_file_init(); /* for fsmenu */ ED_node_init_butfuncs(); - BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */ + BLF_init(); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */ BLT_lang_init(); /* Enforce loading the UI for the initial homefile */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index d827ccafda8..d3ebd3e4d2c 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1799,13 +1799,13 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar if (version_suffix != NULL && version_suffix[0]) { /* placed after the version number in the image, * placing y is tricky to match baseline */ - int x = 260 - (2 * UI_DPI_WINDOW_FAC); - int y = 242 + (4 * UI_DPI_WINDOW_FAC); - int w = 240; + int x = 260 * U.pixelsize - (2 * UI_DPI_FAC); + int y = 242 * U.pixelsize + (4 * UI_DPI_FAC); + int w = 240 * U.pixelsize; /* hack to have text draw 'text_sel' */ UI_block_emboss_set(block, UI_EMBOSS_NONE); - but = uiDefBut(block, UI_BTYPE_LABEL, 0, version_suffix, x * U.pixelsize, y * U.pixelsize, w * U.pixelsize, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + but = uiDefBut(block, UI_BTYPE_LABEL, 0, version_suffix, x, y, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); /* XXX, set internal flag - UI_SELECT */ UI_but_flag_enable(but, 1); UI_block_emboss_set(block, UI_EMBOSS); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 6bf7bcc2934..77378cf8e0c 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -1256,7 +1256,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv) //GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); /* initialize the font */ - BLF_init(11, 72); + BLF_init(); ps.fontid = BLF_load_mem("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); BLF_size(ps.fontid, 11, 72); @@ -1428,8 +1428,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv) ps.next_frame = ps.direction; - - while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0)) || ps.wait2) { + while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, ps.wait2))) { if (hasevent) { GHOST_DispatchEvents(g_WS.ghost_system); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index aaf77946412..e7a1643a1ff 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -375,10 +375,15 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) } } -static void wm_window_set_dpi(wmWindow *win) +void WM_window_set_dpi(wmWindow *win) { int auto_dpi = GHOST_GetDPIHint(win->ghostwin); + /* Clamp auto DPI to 96, since our font/interface drawing does not work well + * with lower sizes. The main case we are interested in supporting is higher + * DPI. If a smaller UI is desired it is still possible to adjust UI scale. */ + auto_dpi = MAX2(auto_dpi, 96); + /* Lazily init UI scale size, preserving backwards compatibility by * computing UI scale from ratio of previous DPI and auto DPI */ if (U.ui_scale == 0) { @@ -406,8 +411,10 @@ static void wm_window_set_dpi(wmWindow *win) U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin) * pixelsize; U.dpi = dpi / pixelsize; U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE; + U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72; - BKE_blender_userdef_refresh(); + /* update font drawing */ + BLF_default_dpi(U.pixelsize * U.dpi); } /* belongs to below */ @@ -483,7 +490,7 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm } /* needed here, because it's used before it reads userdef */ - wm_window_set_dpi(win); + WM_window_set_dpi(win); wm_window_swap_buffers(win); @@ -642,14 +649,27 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect) * \param type: WM_WINDOW_RENDER, WM_WINDOW_USERPREFS... * \return the window or NULL. */ -wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type) +wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, int type) { wmWindow *win_prev = CTX_wm_window(C); wmWindow *win; ScrArea *sa; Scene *scene = CTX_data_scene(C); const char *title; - rcti rect = *rect_init; + + /* convert to native OS window coordinates */ + const float native_pixel_size = GHOST_GetNativePixelSize(win_prev->ghostwin); + x /= native_pixel_size; + y /= native_pixel_size; + sizex /= native_pixel_size; + sizey /= native_pixel_size; + + /* calculate postition */ + rcti rect; + rect.xmin = x + win_prev->posx - sizex / 2; + rect.ymin = y + win_prev->posy - sizey / 2; + rect.xmax = rect.xmin + sizex; + rect.ymax = rect.ymin + sizey; /* changes rect to fit within desktop */ wm_window_check_position(&rect); @@ -857,7 +877,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) GHOST_ActivateWindowDrawingContext(win->ghostwin); /* this can change per window */ - wm_window_set_dpi(win); + WM_window_set_dpi(win); } } @@ -1057,7 +1077,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr WM_jobs_stop(wm, win->screen, NULL); } - wm_window_set_dpi(win); + WM_window_set_dpi(win); /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { @@ -1144,11 +1164,10 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr case GHOST_kEventWindowDPIHintChanged: { - wm_window_set_dpi(win); + WM_window_set_dpi(win); /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ BLF_cache_clear(); - BKE_blender_userdef_refresh(); WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ break; @@ -1234,7 +1253,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr { // only update if the actual pixel size changes float prev_pixelsize = U.pixelsize; - wm_window_set_dpi(win); + WM_window_set_dpi(win); if (U.pixelsize != prev_pixelsize) { // close all popups since they are positioned with the pixel |