diff options
author | Phil Gosch <phil@saphirestudio.at> | 2017-07-11 20:51:35 +0300 |
---|---|---|
committer | Phil Gosch <phil@saphirestudio.at> | 2017-07-11 20:51:35 +0300 |
commit | 99c3d1106e3ff73e2111781d8e38307b2164d57c (patch) | |
tree | a40f7ddf5c7bc1ee531f05df70cce5a994bccf1a /source | |
parent | 2dae9a1596d93f0ed8e782f0c5152db231ed1abe (diff) | |
parent | bb0e8f1c552adfb67f34551f061f2b901e1f2d90 (diff) |
Merge remote-tracking branch 'origin/master' into soc-2016-uv_tools
Diffstat (limited to 'source')
681 files changed, 16156 insertions, 10881 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 90a99469389..4fe65b96f36 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -66,13 +66,14 @@ using Alembic::Abc::OBox3dProperty; ExportSettings::ExportSettings() : scene(NULL) + , logger() , selected_only(false) , visible_layers_only(false) , 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) @@ -82,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) @@ -105,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: @@ -114,6 +117,7 @@ static bool object_is_shape(Object *ob) } return true; + case OB_EMPTY: case OB_CURVE: case OB_SURF: case OB_CAMERA: @@ -123,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)) { @@ -153,11 +174,13 @@ AbcExporter::AbcExporter(Scene *scene, const char *filename, ExportSettings &set AbcExporter::~AbcExporter() { - std::map<std::string, AbcTransformWriter*>::iterator it, e; - for (it = m_xforms.begin(), e = m_xforms.end(); it != e; ++it) { - delete it->second; + /* Free xforms map */ + m_xforms_type::iterator it_x, e_x; + for (it_x = m_xforms.begin(), e_x = m_xforms.end(); it_x != e_x; ++it_x) { + delete it_x->second; } + /* Free shapes vector */ for (int i = 0, e = m_shapes.size(); i != e; ++i) { delete m_shapes[i]; } @@ -165,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]); } } @@ -250,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()); @@ -310,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) { @@ -322,7 +334,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) continue; } - std::map<std::string, AbcTransformWriter *>::iterator xit, xe; + m_xforms_type::iterator xit, xe; for (xit = m_xforms.begin(), xe = m_xforms.end(); xit != xe; ++xit) { xit->second->write(); } @@ -346,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; - } -} + 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; -void AbcExporter::createTransformWritersFlat() -{ - Base *base = static_cast<Base *>(m_scene->base.first); - - 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; @@ -382,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); } @@ -394,68 +393,91 @@ 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; } } free_object_duplilist(lb); } -void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupliObParent) +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); - /* check if we have already created a transform writer for this object */ - if (getXForm(name) != NULL){ - std::cerr << "xform " << name << " already exists\n"; - return; + std::string name; + if (m_settings.flatten_hierarchy) { + name = get_id_name(ob); + } + else { + name = get_object_dag_path_name(ob, dupliObParent); } - AbcTransformWriter *parent_xform = NULL; + /* check if we have already created a transform writer for this object */ + AbcTransformWriter *my_writer = getXForm(name); + if (my_writer != NULL) { + return my_writer; + } - if (parent) { - const std::string parentname = get_object_dag_path_name(parent, dupliObParent); - parent_xform = getXForm(parentname); + AbcTransformWriter *parent_writer = NULL; + Alembic::Abc::OObject alembic_parent; - if (!parent_xform) { - if (parent->parent) { - createTransformWriter(parent, parent->parent, dupliObParent); + 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) { + 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) { - createTransformWriter(parent, NULL, NULL); - } - else { - createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent); - } + } + else if (parent == dupliObParent) { + if (dupliObParent->parent == NULL) { + parent_writer = createTransformWriter(parent, NULL, NULL); } else { - createTransformWriter(parent, dupliObParent, dupliObParent); + parent_writer = createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent); } - - parent_xform = getXForm(parentname); } - } + else { + parent_writer = createTransformWriter(parent, dupliObParent, dupliObParent); + } - if (parent_xform) { - m_xforms[name] = new AbcTransformWriter(ob, parent_xform->alembicXform(), parent_xform, m_trans_sampling_index, m_settings); - m_xforms[name]->setParent(parent); + BLI_assert(parent_writer); + alembic_parent = parent_writer->alembicXform(); } - else { - m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), NULL, m_trans_sampling_index, m_settings); + + 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; } void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx) @@ -472,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; } @@ -513,32 +563,18 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent) AbcTransformWriter *xform = getXForm(name); if (!xform) { - std::cerr << __func__ << ": xform " << name << " is NULL\n"; + ABC_LOG(m_settings.logger) << __func__ << ": xform " << name << " is NULL\n"; return; } - ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first); + createParticleSystemsWriters(ob, xform); - 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)); - } - } - - switch(ob->type) { + 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 b0eb8e185d6..f763922a73b 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -28,6 +28,8 @@ #include <set> #include <vector> +#include "abc_util.h" + class AbcObjectWriter; class AbcTransformWriter; class ArchiveWriter; @@ -41,14 +43,15 @@ struct ExportSettings { ExportSettings(); Scene *scene; + SimpleLogger logger; bool selected_only; bool visible_layers_only; 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; @@ -60,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; @@ -86,7 +91,10 @@ class AbcExporter { ArchiveWriter *m_writer; - std::map<std::string, AbcTransformWriter *> m_xforms; + /* mapping from name to transform writer */ + typedef std::map<std::string, AbcTransformWriter *> m_xforms_type; + m_xforms_type m_xforms; + std::vector<AbcObjectWriter *> m_shapes; public: @@ -95,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(); - void createTransformWriter(Object *ob, Object *parent, Object *dupliObParent); + 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 a5b8af542fc..04f6da48711 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -91,7 +91,7 @@ Imath::Box3d AbcObjectWriter::bounds() if (!bb) { if (this->m_object->type != OB_CAMERA) { - std::cerr << "Boundbox is null!\n"; + ABC_LOG(m_settings.logger) << "Bounding box is null!\n"; } return Imath::Box3d(); @@ -127,6 +127,7 @@ AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings , m_min_time(std::numeric_limits<chrono_t>::max()) , m_max_time(std::numeric_limits<chrono_t>::min()) , m_refcount(0) + , parent_reader(NULL) { m_name = object.getFullName(); std::vector<std::string> parts; @@ -214,7 +215,15 @@ Imath::M44d get_matrix(const IXformSchema &schema, const float time) return s0.getMatrix(); } -void AbcObjectReader::readObjectMatrix(const float time) +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; @@ -236,49 +245,88 @@ void AbcObjectReader::readObjectMatrix(const float time) } } -void AbcObjectReader::read_matrix(float mat[4][4], const float time, const float scale, bool &is_constant) +Alembic::AbcGeom::IXform AbcObjectReader::xform() { - IXform ixform; - bool has_alembic_parent = false; - /* Check that we have an empty object (locator, bone head/tail...). */ if (IXform::matches(m_iobject.getMetaData())) { - ixform = IXform(m_iobject, Alembic::AbcGeom::kWrapExisting); - - /* See comment below. */ - has_alembic_parent = m_iobject.getParent().getParent().valid(); + return IXform(m_iobject, Alembic::AbcGeom::kWrapExisting); } - /* Check that we have an object with actual data. */ - else if (IXform::matches(m_iobject.getParent().getMetaData())) { - ixform = IXform(m_iobject.getParent(), Alembic::AbcGeom::kWrapExisting); - - /* This is a bit hackish, but we need to make sure that extra - * transformations added to the matrix (rotation/scale) are only applied - * to root objects. The way objects and their hierarchy are created will - * need to be revisited at some point but for now this seems to do the - * trick. - * - * Explanation of the trick: - * The first getParent() will return this object's transformation matrix. - * The second getParent() will get the parent of the transform, but this - * might be the archive root ('/') which is valid, so we go passed it to - * make sure that there is no parent. - */ - has_alembic_parent = m_iobject.getParent().getParent().getParent().valid(); + + /* Check that we have an object with actual data, in which case the + * parent Alembic object should contain the transform. */ + IObject abc_parent = m_iobject.getParent(); + + /* The archive's top object can be recognised by not having a parent. */ + if (abc_parent.getParent() + && IXform::matches(abc_parent.getMetaData())) { + return IXform(abc_parent, Alembic::AbcGeom::kWrapExisting); } + /* Should not happen. */ - else { + std::cerr << "AbcObjectReader::xform(): " + << "unable to find IXform for Alembic object '" + << m_iobject.getFullName() << "'\n"; + BLI_assert(false); + + return IXform(); +} + +void AbcObjectReader::read_matrix(float r_mat[4][4], const float time, + const float scale, bool &is_constant) +{ + IXform ixform = xform(); + if (!ixform) { return; } - const IXformSchema &schema(ixform.getSchema()); - + const IXformSchema & schema(ixform.getSchema()); if (!schema.valid()) { + std::cerr << "Alembic object " << ixform.getFullName() + << " has an invalid schema." << std::endl; 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, mat, scale, has_alembic_parent); + convert_matrix(matrix, m_object, r_mat); + + if (has_alembic_parent) { + /* 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 + * parent object is already updated for the current timekey, and use its + * world matrix. */ + BLI_assert(m_object->parent); + mul_m4_m4m4(r_mat, m_object->parent->obmat, r_mat); + } + else { + /* Only apply scaling to root objects, parenting will propagate it. */ + float scale_mat[4][4]; + scale_m4_fl(scale_mat, scale); + scale_mat[3][3] = scale; /* scale translations too */ + mul_m4_m4m4(r_mat, r_mat, scale_mat); + } is_constant = schema.isConstant(); } @@ -322,4 +370,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 0f733e67d3f..1462f93a422 100644 --- a/source/blender/alembic/intern/abc_object.h +++ b/source/blender/alembic/intern/abc_object.h @@ -117,15 +117,7 @@ struct ImportSettings { template <typename Schema> static bool has_animations(Schema &schema, ImportSettings *settings) { - if (settings->is_sequence) { - return true; - } - - if (!schema.isConstant()) { - return true; - } - - return false; + return settings->is_sequence || !schema.isConstant(); } /* ************************************************************************** */ @@ -152,28 +144,44 @@ protected: int m_refcount; public: + AbcObjectReader *parent_reader; + +public: explicit AbcObjectReader(const Alembic::Abc::IObject &object, ImportSettings &settings); virtual ~AbcObjectReader(); const Alembic::Abc::IObject &iobject() const; + typedef std::vector<AbcObjectReader *> ptr_vector; + + /** + * Returns the transform of this object. This can be the Alembic object + * itself (in case of an Empty) or it can be the parent Alembic object. + */ + virtual Alembic::AbcGeom::IXform xform(); + Object *object() const; void object(Object *ob); + 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; } + 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); - void readObjectMatrix(const float time); + /** Reads the object matrix and sets up an object transform if animated. */ + void setupObjectTransform(const float time); void addCacheModifier(); @@ -184,7 +192,8 @@ public: void incref(); void decref(); - void read_matrix(float mat[4][4], const float time, const float scale, bool &is_constant); + void read_matrix(float r_mat[4][4], const float time, + const float scale, bool &is_constant); }; 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 2c6ef09326c..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,9 +63,9 @@ 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); - m_parent = NULL; if (!m_is_animated) { time_sampling = 0; @@ -72,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,27 +90,30 @@ void AbcTransformWriter::do_write() return; } - float mat[4][4]; - create_transform_matrix(m_object, mat); + float yup_mat[4][4]; + 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(mat, mat, rot_mat); + 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. */ float scale_mat[4][4]; scale_m4_fl(scale_mat, m_settings.global_scale); - mul_m4_m4m4(mat, mat, scale_mat); - mul_v3_fl(mat[3], 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(mat); - + m_matrix = convert_matrix(yup_mat); m_sample.setMatrix(m_matrix); + m_sample.setInheritsXforms(m_inherits_xform); m_schema.set(m_sample); } @@ -133,6 +140,10 @@ bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const AbcEmptyReader::AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings) : AbcObjectReader(object, settings) { + /* Empties have no data. It makes the import of Alembic files easier to + * understand when we name the empty after its name in Alembic. */ + m_object_name = object.getName(); + Alembic::AbcGeom::IXform xform(object, Alembic::AbcGeom::kWrapExisting); m_schema = xform.getSchema(); @@ -144,8 +155,26 @@ 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_data_name.c_str()); + m_object = BKE_object_add_only_object(bmain, OB_EMPTY, + m_object_name.c_str()); m_object->data = NULL; } diff --git a/source/blender/alembic/intern/abc_transform.h b/source/blender/alembic/intern/abc_transform.h index 6a3aae216f2..753a4247e9f 100644 --- a/source/blender/alembic/intern/abc_transform.h +++ b/source/blender/alembic/intern/abc_transform.h @@ -37,8 +37,11 @@ class AbcTransformWriter : public AbcObjectWriter { Alembic::Abc::M44d m_matrix; bool m_is_animated; - Object *m_parent; bool m_visible; + bool m_inherits_xform; + +public: + Object *m_proxy_from; public: AbcTransformWriter(Object *ob, @@ -49,7 +52,6 @@ public: Alembic::AbcGeom::OXform &alembicXform() { return m_xform;} virtual Imath::Box3d bounds(); - void setParent(Object *p) { m_parent = p; } private: virtual void do_write(); @@ -66,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 50fa43a3491..26eb7620fb1 100644 --- a/source/blender/alembic/intern/abc_util.cc +++ b/source/blender/alembic/intern/abc_util.cc @@ -41,7 +41,7 @@ extern "C" { #include "PIL_time.h" } -std::string get_id_name(Object *ob) +std::string get_id_name(const Object * const ob) { if (!ob) { return ""; @@ -50,7 +50,7 @@ std::string get_id_name(Object *ob) return get_id_name(&ob->id); } -std::string get_id_name(ID *id) +std::string get_id_name(const ID * const id) { std::string name(id->name + 2); std::replace(name.begin(), name.end(), ' ', '_'); @@ -60,7 +60,7 @@ std::string get_id_name(ID *id) return name; } -std::string get_object_dag_path_name(Object *ob, Object *dupli_parent) +std::string get_object_dag_path_name(const Object * const ob, Object *dupli_parent) { std::string name = get_id_name(ob); @@ -132,15 +132,28 @@ void split(const std::string &s, const char delim, std::vector<std::string> &tok } } -/* Create a rotation matrix for each axis from euler angles. - * Euler angles are swaped to change coordinate system. */ -static void create_rotation_matrix( +void create_swapped_rotation_matrix( float rot_x_mat[3][3], float rot_y_mat[3][3], - float rot_z_mat[3][3], const float euler[3], const bool to_yup) + float rot_z_mat[3][3], const float euler[3], + AbcAxisSwapMode mode) { const float rx = euler[0]; - const float ry = (to_yup) ? euler[2] : -euler[2]; - const float rz = (to_yup) ? -euler[1] : euler[1]; + float ry; + float rz; + + /* Apply transformation */ + switch (mode) { + case ABC_ZUP_FROM_YUP: + ry = -euler[2]; + rz = euler[1]; + break; + case ABC_YUP_FROM_ZUP: + ry = euler[2]; + rz = -euler[1]; + break; + default: + BLI_assert(false); + } unit_m3(rot_x_mat); unit_m3(rot_y_mat); @@ -162,58 +175,70 @@ static void create_rotation_matrix( rot_z_mat[1][1] = cos(rz); } -/* Recompute transform matrix of object in new coordinate system - * (from Y-Up to Z-Up). */ -void create_transform_matrix(float r_mat[4][4]) +/* Convert matrix from Z=up to Y=up or vice versa. Use yup_mat = zup_mat for in-place conversion. */ +void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode) { - float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], transform_mat[4][4]; + float dst_rot[3][3], src_rot[3][3], dst_scale_mat[4][4]; float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3]; - float loc[3], scale[3], euler[3]; + float src_trans[3], dst_scale[3], src_scale[3], euler[3]; - zero_v3(loc); - zero_v3(scale); + zero_v3(src_trans); + zero_v3(dst_scale); + zero_v3(src_scale); zero_v3(euler); - unit_m3(rot); - unit_m3(rot_mat); - unit_m4(scale_mat); - unit_m4(transform_mat); - unit_m4(invmat); + unit_m3(src_rot); + unit_m3(dst_rot); + unit_m4(dst_scale_mat); - /* Compute rotation matrix. */ + /* We assume there is no sheer component and no homogeneous scaling component. */ + BLI_assert(fabs(src_mat[0][3]) < 2 * FLT_EPSILON); + BLI_assert(fabs(src_mat[1][3]) < 2 * FLT_EPSILON); + BLI_assert(fabs(src_mat[2][3]) < 2 * FLT_EPSILON); + BLI_assert(fabs(src_mat[3][3] - 1.0f) < 2 * FLT_EPSILON); - /* Extract location, rotation, and scale from matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, r_mat); + /* Extract translation, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(src_trans, src_rot, src_scale, src_mat); /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_XYZ, rot); + mat3_to_eulO(euler, ROT_MODE_XZY, src_rot); /* Create X, Y, Z rotation matrices from euler angles. */ - create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, false); + create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, mode); /* Concatenate rotation matrices. */ - mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); + mul_m3_m3m3(dst_rot, dst_rot, rot_z_mat); + mul_m3_m3m3(dst_rot, dst_rot, rot_y_mat); + mul_m3_m3m3(dst_rot, dst_rot, rot_x_mat); - /* Add rotation matrix to transformation matrix. */ - copy_m4_m3(transform_mat, rot_mat); + mat3_to_eulO(euler, ROT_MODE_XZY, dst_rot); - /* Add translation to transformation matrix. */ - copy_zup_from_yup(transform_mat[3], loc); + /* Start construction of dst_mat from rotation matrix */ + unit_m4(dst_mat); + copy_m4_m3(dst_mat, dst_rot); - /* Create scale matrix. */ - scale_mat[0][0] = scale[0]; - scale_mat[1][1] = scale[2]; - scale_mat[2][2] = scale[1]; + /* Apply translation */ + switch (mode) { + case ABC_ZUP_FROM_YUP: + copy_zup_from_yup(dst_mat[3], src_trans); + break; + case ABC_YUP_FROM_ZUP: + copy_yup_from_zup(dst_mat[3], src_trans); + break; + default: + BLI_assert(false); + } - /* Add scale to transformation matrix. */ - mul_m4_m4m4(transform_mat, transform_mat, scale_mat); + /* Apply scale matrix. Swaps y and z, but does not + * negate like translation does. */ + dst_scale[0] = src_scale[0]; + dst_scale[1] = src_scale[2]; + dst_scale[2] = src_scale[1]; - copy_m4_m4(r_mat, transform_mat); + size_to_mat4(dst_scale_mat, dst_scale); + mul_m4_m4m4(dst_mat, dst_mat, dst_scale_mat); } -void convert_matrix(const Imath::M44d &xform, Object *ob, - float r_mat[4][4], float scale, bool has_alembic_parent) +void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4]) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { @@ -227,207 +252,32 @@ void convert_matrix(const Imath::M44d &xform, Object *ob, mul_m4_m4m4(r_mat, r_mat, cam_to_yup); } - create_transform_matrix(r_mat); - - if (ob->parent) { - mul_m4_m4m4(r_mat, ob->parent->obmat, r_mat); - } - /* TODO(kevin) */ - else if (!has_alembic_parent) { - /* Only apply scaling to root objects, parenting will propagate it. */ - float scale_mat[4][4]; - scale_m4_fl(scale_mat, scale); - mul_m4_m4m4(r_mat, r_mat, scale_mat); - mul_v3_fl(r_mat[3], scale); - } + copy_m44_axis_swap(r_mat, r_mat, ABC_ZUP_FROM_YUP); } -/* Recompute transform matrix of object in new coordinate system (from Z-Up to Y-Up). */ -void create_transform_matrix(Object *obj, float transform_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], AbcMatrixMode mode, + Object *proxy_from) { - float rot_mat[3][3], rot[3][3], scale_mat[4][4], invmat[4][4], mat[4][4]; - float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3]; - float loc[3], scale[3], euler[3]; - - zero_v3(loc); - zero_v3(scale); - zero_v3(euler); - unit_m3(rot); - unit_m3(rot_mat); - unit_m4(scale_mat); - unit_m4(transform_mat); - unit_m4(invmat); - unit_m4(mat); - - /* get local matrix. */ - if (obj->parent) { - invert_m4_m4(invmat, obj->parent->obmat); - mul_m4_m4m4(mat, invmat, obj->obmat); + float zup_mat[4][4]; + + /* 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); } else { - copy_m4_m4(mat, obj->obmat); + copy_m4_m4(zup_mat, obj->obmat); } - /* Compute rotation matrix. */ - switch (obj->rotmode) { - case ROT_MODE_AXISANGLE: - { - /* Get euler angles from axis angle rotation. */ - axis_angle_to_eulO(euler, ROT_MODE_XYZ, obj->rotAxis, obj->rotAngle); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); - - /* Extract location and scale from matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, mat); - - break; - } - case ROT_MODE_QUAT: - { - float q[4]; - copy_v4_v4(q, obj->quat); - - /* Swap axis. */ - q[2] = obj->quat[3]; - q[3] = -obj->quat[2]; - - /* Compute rotation matrix from quaternion. */ - quat_to_mat3(rot_mat, q); - - /* Extract location and scale from matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, mat); - - break; - } - case ROT_MODE_XYZ: - { - /* Extract location, rotation, and scale form matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, mat); - - /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_XYZ, rot); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); - - break; - } - case ROT_MODE_XZY: - { - /* Extract location, rotation, and scale form matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, mat); - - /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_XZY, rot); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); - - break; - } - case ROT_MODE_YXZ: - { - /* Extract location, rotation, and scale form matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, mat); - - /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_YXZ, rot); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); - - break; - } - case ROT_MODE_YZX: - { - /* Extract location, rotation, and scale form matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, mat); - - /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_YZX, rot); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); - - break; - } - case ROT_MODE_ZXY: - { - /* Extract location, rotation, and scale form matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, mat); - - /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_ZXY, rot); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); - - break; - } - case ROT_MODE_ZYX: - { - /* Extract location, rotation, and scale form matrix. */ - mat4_to_loc_rot_size(loc, rot, scale, mat); - - /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_ZYX, rot); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, true); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(rot_mat, rot_mat, rot_x_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_z_mat); - mul_m3_m3m3(rot_mat, rot_mat, rot_y_mat); - - break; - } + if (proxy_from) { + mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat); } - /* Add rotation matrix to transformation matrix. */ - copy_m4_m3(transform_mat, rot_mat); - - /* Add translation to transformation matrix. */ - copy_yup_from_zup(transform_mat[3], loc); - - /* Create scale matrix. */ - scale_mat[0][0] = scale[0]; - scale_mat[1][1] = scale[2]; - scale_mat[2][2] = scale[1]; - - /* Add scale to transformation matrix. */ - mul_m4_m4m4(transform_mat, transform_mat, scale_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) @@ -520,7 +370,10 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe reader = new AbcCurveReader(object, settings); } else { - assert(false); + std::cerr << "Alembic: unknown how to handle objects of schema " + << md.get("schemaObjTitle") + << ", skipping object " + << object.getFullName() << std::endl; } return reader; @@ -537,3 +390,32 @@ ScopeTimer::~ScopeTimer() { fprintf(stderr, "%s: %fs\n", m_message, PIL_check_seconds_timer() - m_start); } + +/* ********************** */ + +bool SimpleLogger::empty() +{ + return ((size_t)m_stream.tellp()) == 0ul; +} + +std::string SimpleLogger::str() const +{ + return m_stream.str(); +} + +void SimpleLogger::clear() +{ + m_stream.clear(); + m_stream.str(""); +} + +std::ostringstream &SimpleLogger::stream() +{ + return m_stream; +} + +std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger) +{ + os << logger.str(); + return os; +} diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h index 85ba4d5c9c7..2526958111a 100644 --- a/source/blender/alembic/intern/abc_util.h +++ b/source/blender/alembic/intern/abc_util.h @@ -32,6 +32,11 @@ # define ABC_INLINE static inline #endif +/** + * \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). + */ struct CacheReader { int unused; }; @@ -44,16 +49,21 @@ struct ImportSettings; struct ID; struct Object; -std::string get_id_name(ID *id); -std::string get_id_name(Object *ob); -std::string get_object_dag_path_name(Object *ob, Object *dupli_parent); +std::string get_id_name(const ID * const id); +std::string get_id_name(const Object * const ob); +std::string get_object_dag_path_name(const Object * const ob, Object *dupli_parent); bool object_selected(Object *ob); bool parent_selected(Object *ob); Imath::M44d convert_matrix(float mat[4][4]); -void create_transform_matrix(float r_mat[4][4]); -void create_transform_matrix(Object *obj, float 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); @@ -64,8 +74,7 @@ bool begins_with(const TContainer &input, const TContainer &match) && std::equal(match.begin(), match.end(), input.begin()); } -void convert_matrix(const Imath::M44d &xform, Object *ob, - float r_mat[4][4], float scale, bool has_alembic_parent = false); +void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4]); template <typename Schema> void get_min_max_time_ex(const Schema &schema, chrono_t &min, chrono_t &max) @@ -118,34 +127,54 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3]) { + const float old_yup1 = yup[1]; /* in case zup == yup */ zup[0] = yup[0]; zup[1] = -yup[2]; - zup[2] = yup[1]; + zup[2] = old_yup1; } ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3]) { + const short old_yup1 = yup[1]; /* in case zup == yup */ zup[0] = yup[0]; zup[1] = -yup[2]; - zup[2] = yup[1]; + zup[2] = old_yup1; } /* Copy from Z-up to Y-up. */ ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3]) { + const float old_zup1 = zup[1]; /* in case yup == zup */ yup[0] = zup[0]; yup[1] = zup[2]; - yup[2] = -zup[1]; + yup[2] = -old_zup1; } ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3]) { + const short old_zup1 = zup[1]; /* in case yup == zup */ yup[0] = zup[0]; yup[1] = zup[2]; - yup[2] = -zup[1]; + yup[2] = -old_zup1; } +/* Names are given in (dst, src) order, just like + * the parameters of copy_m44_axis_swap() */ +typedef enum { + ABC_ZUP_FROM_YUP = 1, + ABC_YUP_FROM_ZUP = 2, +} AbcAxisSwapMode; + +/* Create a rotation matrix for each axis from euler angles. + * Euler angles are swaped to change coordinate system. */ +void create_swapped_rotation_matrix( + float rot_x_mat[3][3], float rot_y_mat[3][3], + float rot_z_mat[3][3], const float euler[3], + AbcAxisSwapMode mode); + +void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode); + /* *************************** */ #undef ABC_DEBUG_TIME @@ -165,4 +194,48 @@ public: # define SCOPE_TIMER(message) #endif +/* *************************** */ + +/** + * Utility class whose purpose is to more easily log related informations. An + * instance of the SimpleLogger can be created in any context, and will hold a + * copy of all the strings passed to its output stream. + * + * Different instances of the class may be accessed from different threads, + * although accessing the same instance from different threads will lead to race + * conditions. + */ +class SimpleLogger { + std::ostringstream m_stream; + +public: + /** + * Check whether or not the SimpleLogger's stream is empty. + */ + bool empty(); + + /** + * Return a copy of the string contained in the SimpleLogger's stream. + */ + std::string str() const; + + /** + * Remove the bits set on the SimpleLogger's stream and clear its string. + */ + void clear(); + + /** + * Return a reference to the SimpleLogger's stream, in order to e.g. push + * content into it. + */ + std::ostringstream &stream(); +}; + +#define ABC_LOG(logger) logger.stream() + +/** + * Pass the content of the logger's stream to the specified std::ostream. + */ +std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger); + #endif /* __ABC_UTIL_H__ */ diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index dc5146a26e0..be454050098 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -21,6 +21,7 @@ */ #include "../ABC_alembic.h" +#include <boost/foreach.hpp> #include <Alembic/AbcMaterial/IMaterial.h> @@ -120,91 +121,62 @@ ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveReader *archive) /* NOTE: this function is similar to visit_objects below, need to keep them in * sync. */ -static void gather_objects_paths(const IObject &object, ListBase *object_paths) +static bool gather_objects_paths(const IObject &object, ListBase *object_paths) { if (!object.valid()) { - return; + return false; } - for (int i = 0; i < object.getNumChildren(); ++i) { - IObject child = object.getChild(i); - if (!child.valid()) { - continue; - } + size_t children_claiming_this_object = 0; + size_t num_children = object.getNumChildren(); - bool get_path = false; + for (size_t i = 0; i < num_children; ++i) { + bool child_claims_this_object = gather_objects_paths(object.getChild(i), object_paths); + children_claiming_this_object += child_claims_this_object ? 1 : 0; + } - const MetaData &md = child.getMetaData(); + const MetaData &md = object.getMetaData(); + bool get_path = false; + bool parent_is_part_of_this_object = false; - if (IXform::matches(md)) { - /* Check whether or not this object is a Maya locator, which is - * similar to empties used as parent object in Blender. */ - if (has_property(child.getProperties(), "locator")) { - get_path = true; - } - else { - /* Avoid creating an empty object if the child of this transform - * is not a transform (that is an empty). */ - if (child.getNumChildren() == 1) { - if (IXform::matches(child.getChild(0).getMetaData())) { - get_path = true; - } -#if 0 - else { - std::cerr << "Skipping " << child.getFullName() << '\n'; - } -#endif - } - else { - get_path = true; - } - } - } - else if (IPolyMesh::matches(md)) { - get_path = true; - } - else if (ISubD::matches(md)) { - get_path = true; - } - else if (INuPatch::matches(md)) { -#ifdef USE_NURBS - get_path = true; -#endif - } - else if (ICamera::matches(md)) { - get_path = true; - } - else if (IPoints::matches(md)) { - get_path = true; - } - else if (IMaterial::matches(md)) { - /* Pass for now. */ - } - else if (ILight::matches(md)) { - /* Pass for now. */ - } - else if (IFaceSet::matches(md)) { - /* Pass, those are handled in the mesh reader. */ - } - else if (ICurves::matches(md)) { + if (!object.getParent()) { + /* The root itself is not an object we should import. */ + } + else if (IXform::matches(md)) { + if (has_property(object.getProperties(), "locator")) { get_path = true; } else { - assert(false); + get_path = children_claiming_this_object == 0; } - if (get_path) { - AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>( - MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath")); - - BLI_strncpy(abc_path->path, child.getFullName().c_str(), PATH_MAX); + /* Transforms are never "data" for their parent. */ + parent_is_part_of_this_object = false; + } + else { + /* These types are "data" for their parent. */ + get_path = + IPolyMesh::matches(md) || + ISubD::matches(md) || +#ifdef USE_NURBS + INuPatch::matches(md) || +#endif + ICamera::matches(md) || + IPoints::matches(md) || + ICurves::matches(md); + parent_is_part_of_this_object = get_path; + } - BLI_addtail(object_paths, abc_path); - } + if (get_path) { + void *abc_path_void = MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath"); + AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(abc_path_void); - gather_objects_paths(child, object_paths); + BLI_strncpy(abc_path->path, object.getFullName().c_str(), sizeof(abc_path->path)); + BLI_addtail(object_paths, abc_path); } + + return parent_is_part_of_this_object; } AbcArchiveHandle *ABC_create_handle(const char *filename, ListBase *object_paths) @@ -266,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) @@ -299,12 +272,14 @@ 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) { - std::cerr << "Abc Export error: " << e.what() << '\n'; + ABC_LOG(data->settings.logger) << "Abc Export error: " << e.what() << '\n'; } catch (...) { - std::cerr << "Abc Export error\n"; + ABC_LOG(data->settings.logger) << "Abc Export: unknown error...\n"; } } @@ -316,26 +291,49 @@ static void export_endjob(void *customdata) BLI_delete(data->filename, false, false); } + if (!data->settings.logger.empty()) { + std::cerr << data->settings.logger; + WM_report(RPT_ERROR, "Errors occured during the export, look in the console to know more..."); + } + G.is_rendering = false; 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.... + * + * ExportJobData contains an ExportSettings containing a SimpleLogger. + * + * Since ExportJobData is a C-style struct dynamically allocated with + * MEM_mallocN (see above), its construtor is never called, therefore the + * ExportSettings constructor is not called which implies that the + * SimpleLogger one is not called either. SimpleLogger in turn does not call + * the constructor of its data members which ultimately means that its + * std::ostringstream member has a NULL pointer. To be able to properly use + * the stream's operator<<, the pointer needs to be set, therefore we have + * to properly construct everything. And this is done using the placement + * new operator as here below. It seems hackish, but I'm too lazy to + * do bigger refactor and maybe there is a better way which does not involve + * hardcore refactoring. */ + new (&job->settings) ExportSettings(); 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; @@ -343,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; @@ -359,136 +359,248 @@ 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 ********************** */ -static void visit_object(const IObject &object, - std::vector<AbcObjectReader *> &readers, - GHash *parent_map, - ImportSettings &settings) +/** + * Generates an AbcObjectReader for this Alembic object and its children. + * + * \param object The Alembic IObject to visit. + * \param readers The created AbcObjectReader * will be appended to this vector. + * \param settings Import settings, not used directly but passed to the + * AbcObjectReader subclass constructors. + * \param r_assign_as_parent Return parameter, contains a list of reader + * pointers, whose parent pointer should still be set. + * This is filled when this call to visit_object() didn't create + * a reader that should be the parent. + * \return A pair of boolean and reader pointer. The boolean indicates whether + * this IObject claims its parent as part of the same object + * (for example an IPolyMesh object would claim its parent, as the mesh + * is interpreted as the object's data, and the parent IXform as its + * Blender object). The pointer is the AbcObjectReader that represents + * the IObject parameter. + * + * NOTE: this function is similar to gather_object_paths above, need to keep + * them in sync. */ +static std::pair<bool, AbcObjectReader *> visit_object( + const IObject &object, + AbcObjectReader::ptr_vector &readers, + ImportSettings &settings, + AbcObjectReader::ptr_vector &r_assign_as_parent) { + const std::string & full_name = object.getFullName(); + if (!object.valid()) { - return; + std::cerr << " - " + << full_name + << ": object is invalid, skipping it and all its children.\n"; + return std::make_pair(false, static_cast<AbcObjectReader *>(NULL)); } - for (int i = 0; i < object.getNumChildren(); ++i) { - IObject child = object.getChild(i); - - if (!child.valid()) { - continue; - } - - AbcObjectReader *reader = NULL; + /* The interpretation of data by the children determine the role of this + * object. This is especially important for Xform objects, as they can be + * either part of a Blender object or a Blender object (Empty) themselves. + */ + size_t children_claiming_this_object = 0; + size_t num_children = object.getNumChildren(); + AbcObjectReader::ptr_vector claiming_child_readers; + AbcObjectReader::ptr_vector nonclaiming_child_readers; + AbcObjectReader::ptr_vector assign_as_parent; + for (size_t i = 0; i < num_children; ++i) { + const IObject ichild = object.getChild(i); - const MetaData &md = child.getMetaData(); + /* TODO: When we only support C++11, use std::tie() instead. */ + std::pair<bool, AbcObjectReader *> child_result; + child_result = visit_object(ichild, readers, settings, assign_as_parent); - if (IXform::matches(md)) { - bool create_xform = false; + bool child_claims_this_object = child_result.first; + AbcObjectReader *child_reader = child_result.second; - /* Check whether or not this object is a Maya locator, which is - * similar to empties used as parent object in Blender. */ - if (has_property(child.getProperties(), "locator")) { - create_xform = true; + if (child_reader == NULL) { + BLI_assert(!child_claims_this_object); + } + else { + if (child_claims_this_object) { + claiming_child_readers.push_back(child_reader); } else { - /* Avoid creating an empty object if the child of this transform - * is not a transform (that is an empty). */ - if (child.getNumChildren() == 1) { - if (IXform::matches(child.getChild(0).getMetaData())) { - create_xform = true; - } -#if 0 - else { - std::cerr << "Skipping " << child.getFullName() << '\n'; - } -#endif - } - else { - create_xform = true; - } + nonclaiming_child_readers.push_back(child_reader); } + } - if (create_xform) { - reader = new AbcEmptyReader(child, settings); - } + children_claiming_this_object += child_claims_this_object ? 1 : 0; + } + BLI_assert(children_claiming_this_object == claiming_child_readers.size()); + + AbcObjectReader *reader = NULL; + const MetaData &md = object.getMetaData(); + bool parent_is_part_of_this_object = false; + + if (!object.getParent()) { + /* The root itself is not an object we should import. */ + } + else if (IXform::matches(md)) { + bool create_empty; + + /* An xform can either be a Blender Object (if it contains a mesh, for + * example), but it can also be an Empty. Its correct translation to + * Blender's data model depends on its children. */ + + /* Check whether or not this object is a Maya locator, which is + * similar to empties used as parent object in Blender. */ + if (has_property(object.getProperties(), "locator")) { + create_empty = true; } - else if (IPolyMesh::matches(md)) { - reader = new AbcMeshReader(child, settings); + else { + create_empty = claiming_child_readers.empty(); } - else if (ISubD::matches(md)) { - reader = new AbcSubDReader(child, settings); + + if (create_empty) { + reader = new AbcEmptyReader(object, settings); } - else if (INuPatch::matches(md)) { + } + else if (IPolyMesh::matches(md)) { + reader = new AbcMeshReader(object, settings); + parent_is_part_of_this_object = true; + } + else if (ISubD::matches(md)) { + reader = new AbcSubDReader(object, settings); + parent_is_part_of_this_object = true; + } + else if (INuPatch::matches(md)) { #ifdef USE_NURBS - /* TODO(kevin): importing cyclic NURBS from other software crashes - * at the moment. This is due to the fact that NURBS in other - * software have duplicated points which causes buffer overflows in - * Blender. Need to figure out exactly how these points are - * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV). - * Until this is fixed, disabling NURBS reading. */ - reader = new AbcNurbsReader(child, settings); + /* TODO(kevin): importing cyclic NURBS from other software crashes + * at the moment. This is due to the fact that NURBS in other + * software have duplicated points which causes buffer overflows in + * Blender. Need to figure out exactly how these points are + * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV). + * Until this is fixed, disabling NURBS reading. */ + reader = new AbcNurbsReader(object, settings); + parent_is_part_of_this_object = true; #endif + } + else if (ICamera::matches(md)) { + reader = new AbcCameraReader(object, settings); + parent_is_part_of_this_object = true; + } + else if (IPoints::matches(md)) { + reader = new AbcPointsReader(object, settings); + parent_is_part_of_this_object = true; + } + else if (IMaterial::matches(md)) { + /* Pass for now. */ + } + else if (ILight::matches(md)) { + /* Pass for now. */ + } + else if (IFaceSet::matches(md)) { + /* Pass, those are handled in the mesh reader. */ + } + else if (ICurves::matches(md)) { + reader = new AbcCurveReader(object, settings); + parent_is_part_of_this_object = true; + } + else { + std::cerr << "Alembic object " << full_name + << " is of unsupported schema type '" + << object.getMetaData().get("schemaObjTitle") << "'" + << std::endl; + } + + if (reader) { + /* We have created a reader, which should imply that this object is + * not claimed as part of any child Alembic object. */ + BLI_assert(claiming_child_readers.empty()); + + readers.push_back(reader); + reader->incref(); + + AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>( + MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath")); + 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. */ + if (nonclaiming_child_readers.size() + assign_as_parent.size() > 0) { + /* TODO: When we only support C++11, use for (a: b) instead. */ + BOOST_FOREACH(AbcObjectReader *child_reader, nonclaiming_child_readers) { + child_reader->parent_reader = reader; + } + BOOST_FOREACH(AbcObjectReader *child_reader, assign_as_parent) { + child_reader->parent_reader = reader; + } } - else if (ICamera::matches(md)) { - reader = new AbcCameraReader(child, settings); - } - else if (IPoints::matches(md)) { - reader = new AbcPointsReader(child, settings); - } - else if (IMaterial::matches(md)) { - /* Pass for now. */ - } - else if (ILight::matches(md)) { - /* Pass for now. */ - } - else if (IFaceSet::matches(md)) { - /* Pass, those are handled in the mesh reader. */ - } - else if (ICurves::matches(md)) { - reader = new AbcCurveReader(child, settings); + } + else if (object.getParent()) { + if (claiming_child_readers.size() > 0) { + /* The first claiming child will serve just fine as parent to + * our non-claiming children. Since all claiming children share + * the same XForm, it doesn't really matter which one we pick. */ + AbcObjectReader *claiming_child = claiming_child_readers[0]; + BOOST_FOREACH(AbcObjectReader *child_reader, nonclaiming_child_readers) { + child_reader->parent_reader = claiming_child; + } + BOOST_FOREACH(AbcObjectReader *child_reader, assign_as_parent) { + child_reader->parent_reader = claiming_child; + } + /* Claiming children should have our parent set as their parent. */ + BOOST_FOREACH(AbcObjectReader *child_reader, claiming_child_readers) { + r_assign_as_parent.push_back(child_reader); + } } else { - assert(false); - } - - if (reader) { - readers.push_back(reader); - reader->incref(); - - AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>( - MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath")); - - BLI_strncpy(abc_path->path, child.getFullName().c_str(), PATH_MAX); - - BLI_addtail(&settings.cache_file->object_paths, abc_path); - - /* Cast to `void *` explicitly to avoid compiler errors because it - * is a `const char *` which the compiler cast to `const void *` - * instead of the expected `void *`. */ - BLI_ghash_insert(parent_map, (void *)child.getFullName().c_str(), reader); + /* This object isn't claimed by any child, and didn't produce + * a reader. Odd situation, could be the top Alembic object, or + * an unsupported Alembic schema. Delegate to our parent. */ + BOOST_FOREACH(AbcObjectReader *child_reader, claiming_child_readers) { + r_assign_as_parent.push_back(child_reader); + } + BOOST_FOREACH(AbcObjectReader *child_reader, nonclaiming_child_readers) { + r_assign_as_parent.push_back(child_reader); + } + BOOST_FOREACH(AbcObjectReader *child_reader, assign_as_parent) { + r_assign_as_parent.push_back(child_reader); + } } - - visit_object(child, readers, parent_map, settings); } + + return std::make_pair(parent_is_part_of_this_object, reader); } enum { ABC_NO_ERROR = 0, ABC_ARCHIVE_FAIL, + ABC_UNSUPPORTED_HDF5, }; struct ImportJobData { @@ -498,7 +610,6 @@ struct ImportJobData { char filename[1024]; ImportSettings settings; - GHash *parent_map; std::vector<AbcObjectReader *> readers; short *stop; @@ -507,6 +618,7 @@ struct ImportJobData { char error_code; bool was_cancelled; + bool import_ok; }; ABC_INLINE bool is_mesh_and_strands(const IObject &object) @@ -553,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; } @@ -575,11 +691,12 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa *data->do_update = true; *data->progress = 0.05f; - data->parent_map = BLI_ghash_str_new("alembic parent ghash"); - /* Parse Alembic Archive. */ + AbcObjectReader::ptr_vector assign_as_parent; + visit_object(archive->getTop(), data->readers, data->settings, assign_as_parent); - visit_object(archive->getTop(), data->readers, data->parent_map, data->settings); + /* There shouldn't be any orphans. */ + BLI_assert(assign_as_parent.size() == 0); if (G.is_break) { data->was_cancelled = true; @@ -597,19 +714,23 @@ 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->readObjectMatrix(0.0f); + reader->readObjectData(data->bmain, sample_sel); min_time = std::min(min_time, reader->minTime()); max_time = std::max(max_time, reader->maxTime()); } + else { + std::cerr << "Object " << reader->name() << " in Alembic file " + << data->filename << " is invalid.\n"; + } - *data->progress = 0.1f + 0.6f * (++i / size); + *data->progress = 0.1f + 0.3f * (++i / size); *data->do_update = true; if (G.is_break) { @@ -627,45 +748,31 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa 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; } } - /* Setup parentship. */ - - i = 0; + /* Setup parenthood. */ for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { const AbcObjectReader *reader = *iter; - const AbcObjectReader *parent_reader = NULL; - const IObject &iobject = reader->iobject(); - - IObject parent = iobject.getParent(); - - if (!IXform::matches(iobject.getHeader())) { - /* In the case of an non XForm node, the parent is the transform - * matrix of the data itself, so we get the its grand parent. - */ + const AbcObjectReader *parent_reader = reader->parent_reader; + Object *ob = reader->object(); - /* Special case with object only containing a mesh and some strands, - * we want both objects to be parented to the same object. */ - if (!is_mesh_and_strands(parent)) { - parent = parent.getParent(); - } + if (parent_reader == NULL) { + ob->parent = NULL; } - - parent_reader = reinterpret_cast<AbcObjectReader *>( - BLI_ghash_lookup(data->parent_map, parent.getFullName().c_str())); - - if (parent_reader) { - Object *parent = parent_reader->object(); - - if (parent != NULL && reader->object() != parent) { - Object *ob = reader->object(); - ob->parent = parent; - } + else { + ob->parent = parent_reader->object(); } + } + + /* Setup transformations and constraints. */ + i = 0; + for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { + AbcObjectReader *reader = *iter; + reader->setupObjectTransform(0.0f); *data->progress = 0.7f + 0.3f * (++i / size); *data->do_update = true; @@ -690,23 +797,25 @@ static void import_endjob(void *user_data) for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) { Object *ob = (*iter)->object(); - if (ob->data) { - BKE_libblock_free_us(data->bmain, ob->data); - ob->data = NULL; - } + /* It's possible that cancellation occured between the creation of + * the reader and the creation of the Blender object. */ + if (ob == NULL) continue; BKE_libblock_free_us(data->bmain, ob); } } 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); } @@ -723,17 +832,17 @@ static void import_endjob(void *user_data) } } - if (data->parent_map) { - BLI_ghash_free(data->parent_map, NULL, NULL); - } - 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); @@ -745,13 +854,16 @@ 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; @@ -760,25 +872,40 @@ void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence job->settings.sequence_len = sequence_len; job->settings.offset = offset; job->settings.validate_meshes = validate_meshes; - job->parent_map = NULL; 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); + + 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; - /* 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); + import_freejob(job); + } - WM_jobs_start(CTX_wm_manager(C), wm_job); + return import_ok; } /* ************************************************************************** */ @@ -813,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); } /* ************************************************************************** */ @@ -863,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/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_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_appdir.h b/source/blender/blenkernel/BKE_appdir.h index 077fe2a629c..ac8f861fa56 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -27,11 +27,15 @@ /* note on naming: typical _get() suffix is omitted here, * since its the main purpose of the API. */ const char *BKE_appdir_folder_default(void); +const char *BKE_appdir_folder_id_ex(const int folder_id, const char *subfolder, char *path, size_t path_len); const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder); const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder); const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder); const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check); +bool BKE_appdir_app_template_any(void); +bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len); + /* Initialize path to program executable */ void BKE_appdir_program_path_init(const char *argv0); 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 d2d9c763031..d55926ffb1e 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -38,14 +38,22 @@ extern "C" { #endif +struct UserDef; + void BKE_blender_free(void); void BKE_blender_globals_init(void); void BKE_blender_globals_clear(void); +void BKE_blender_version_string( + char *version_str, size_t maxncpy, + short version, short subversion, bool v_prefix, bool include_subversion); -void BKE_blender_userdef_free(void); +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); + /* set this callback when a UI is running */ void BKE_blender_callback_test_break_set(void (*func)(void)); int BKE_blender_test_break(void); 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_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index 6767fce3abd..ac58451e412 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -33,8 +33,7 @@ struct ID; struct Main; struct MemFile; struct ReportList; - -int BKE_blendfile_read(struct bContext *C, const char *filepath, struct ReportList *reports); +struct UserDef; enum { BKE_BLENDFILE_READ_FAIL = 0, /* no load */ @@ -42,15 +41,24 @@ enum { BKE_BLENDFILE_READ_OK_USERPREFS = 2, /* OK, and with new user settings */ }; +int BKE_blendfile_read( + struct bContext *C, const char *filepath, + struct ReportList *reports, int skip_flag); bool BKE_blendfile_read_from_memory( - struct bContext *C, const void *filebuf, - int filelength, struct ReportList *reports, bool update_defaults); + struct bContext *C, const void *filebuf, int filelength, + struct ReportList *reports, int skip_flag, bool update_defaults); bool BKE_blendfile_read_from_memfile( struct bContext *C, struct MemFile *memfile, + struct ReportList *reports, int skip_flag); +void BKE_blendfile_read_make_empty(struct bContext *C); + +struct UserDef *BKE_blendfile_userdef_read( + const char *filepath, struct ReportList *reports); +struct UserDef *BKE_blendfile_userdef_read_from_memory( + const void *filebuf, int filelength, struct ReportList *reports); -int BKE_blendfile_read_userdef(const char *filepath, struct ReportList *reports); -int BKE_blendfile_write_userdef(const char *filepath, struct ReportList *reports); +int BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports); /* partial blend file writing */ 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_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 36330242f18..6c517bd02df 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -136,9 +136,6 @@ typedef struct ClothSpring { float restlen; /* The original length of the spring. */ int type; /* types defined in BKE_cloth.h ("springType") */ int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ - float dfdx[3][3]; - float dfdv[3][3]; - float f[3]; float stiffness; /* stiffness factor from the vertex groups */ float editrestlen; @@ -240,9 +237,6 @@ void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving); // needed for button_object.c void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float framenr ); -// needed for cloth.c -int cloth_add_spring (struct ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type); - void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]); //////////////////////////////////////////////// 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..0d382c8a49c 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); 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 546f0d97c2b..d5279c5b0ce 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -49,7 +49,7 @@ #include "RNA_types.h" /* not very important, but the stack solver likes to know a maximum */ -#define MAX_SOCKET 64 +#define MAX_SOCKET 512 struct bContext; struct bNode; @@ -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 89adbc4338f..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); @@ -200,6 +196,11 @@ void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); +void BKE_object_eval_cloth(struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *object); + + void BKE_object_handle_data_update(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..f9948ba500a 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); 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 160adcc3988..eba5814d897 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. */ @@ -2912,9 +2916,6 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em, CustomDa /* get derived mesh from an object, using editbmesh if available. */ DerivedMesh *object_get_derived_final(Object *ob, const bool for_render) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_btmesh; - if (for_render) { /* TODO(sergey): use proper derived render here in the future. */ return ob->derivedFinal; @@ -2922,9 +2923,13 @@ DerivedMesh *object_get_derived_final(Object *ob, const bool for_render) /* only return the editmesh if its from this object because * we don't a mesh from another object's modifier stack: T43122 */ - if (em && (em->ob == ob)) { - DerivedMesh *dm = em->derivedFinal; - return dm; + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + if (em && (em->ob == ob)) { + DerivedMesh *dm = em->derivedFinal; + return dm; + } } return ob->derivedFinal; @@ -3317,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, char *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); @@ -3455,7 +3461,7 @@ 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); 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..bcc0d1aeacb 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 ------------------------------------------- */ /** diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index f2f0a92d8b3..43fd47981b1 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -114,18 +114,26 @@ static char *blender_version_decimal(const int ver) * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath, * returning true if result points to a directory. */ -static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) +static bool test_path( + char *targetpath, size_t targetpath_len, + const char *path_base, const char *path_sep, const char *folder_name) { char tmppath[FILE_MAX]; - if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); - else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); + if (path_sep) { + BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); + } + else { + BLI_strncpy(tmppath, path_base, sizeof(tmppath)); + } /* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */ - if (folder_name) - BLI_make_file_string("/", targetpath, tmppath, folder_name); - else - BLI_strncpy(targetpath, tmppath, sizeof(tmppath)); + if (folder_name) { + BLI_join_dirfile(targetpath, targetpath_len, tmppath, folder_name); + } + else { + BLI_strncpy(targetpath, tmppath, targetpath_len); + } /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile) * if folder_name is specified but not otherwise? */ @@ -179,7 +187,9 @@ static bool test_env_path(char *path, const char *envvar) * \param ver To construct name of version-specific directory within bprogdir * \return true if such a directory exists. */ -static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver) +static bool get_path_local( + char *targetpath, size_t targetpath_len, + const char *folder_name, const char *subfolder_name, const int ver) { char relfolder[FILE_MAX]; @@ -201,11 +211,12 @@ static bool get_path_local(char *targetpath, const char *folder_name, const char /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */ #ifdef __APPLE__ - static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */ + /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */ + static char osx_resourses[FILE_MAX]; sprintf(osx_resourses, "%s../Resources", bprogdir); - return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder); + return test_path(targetpath, targetpath_len, osx_resourses, blender_version_decimal(ver), relfolder); #else - return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder); + return test_path(targetpath, targetpath_len, bprogdir, blender_version_decimal(ver), relfolder); #endif } @@ -219,7 +230,7 @@ static bool is_portable_install(void) const int ver = BLENDER_VERSION; char path[FILE_MAX]; - return get_path_local(path, "config", NULL, ver); + return get_path_local(path, sizeof(path), "config", NULL, ver); } /** @@ -233,20 +244,22 @@ static bool is_portable_install(void) * \param ver Blender version, used to construct a subdirectory name * \return true if it was able to construct such a path. */ -static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) +static bool get_path_user( + char *targetpath, size_t targetpath_len, const char *folder_name, const char *subfolder_name, + const char *envvar, const int ver) { char user_path[FILE_MAX]; const char *user_base_path; /* for portable install, user path is always local */ - if (is_portable_install()) - return get_path_local(targetpath, folder_name, subfolder_name, ver); - + if (is_portable_install()) { + return get_path_local(targetpath, targetpath_len, folder_name, subfolder_name, ver); + } user_path[0] = '\0'; if (test_env_path(user_path, envvar)) { if (subfolder_name) { - return test_path(targetpath, user_path, NULL, subfolder_name); + return test_path(targetpath, targetpath_len, user_path, NULL, subfolder_name); } else { BLI_strncpy(targetpath, user_path, FILE_MAX); @@ -266,10 +279,10 @@ static bool get_path_user(char *targetpath, const char *folder_name, const char #endif if (subfolder_name) { - return test_path(targetpath, user_path, folder_name, subfolder_name); + return test_path(targetpath, targetpath_len, user_path, folder_name, subfolder_name); } else { - return test_path(targetpath, user_path, NULL, folder_name); + return test_path(targetpath, targetpath_len, user_path, NULL, folder_name); } } @@ -283,7 +296,9 @@ static bool get_path_user(char *targetpath, const char *folder_name, const char * \param ver Blender version, used to construct a subdirectory name * \return true if it was able to construct such a path. */ -static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) +static bool get_path_system( + char *targetpath, size_t targetpath_len, const char *folder_name, const char *subfolder_name, + const char *envvar, const int ver) { char system_path[FILE_MAX]; const char *system_base_path; @@ -307,13 +322,13 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha /* try CWD/release/folder_name */ if (BLI_current_working_dir(cwd, sizeof(cwd))) { - if (test_path(targetpath, cwd, "release", relfolder)) { + if (test_path(targetpath, targetpath_len, cwd, "release", relfolder)) { return true; } } /* try EXECUTABLE_DIR/release/folder_name */ - if (test_path(targetpath, bprogdir, "release", relfolder)) + if (test_path(targetpath, targetpath_len, bprogdir, "release", relfolder)) return true; /* end developer overrides */ @@ -324,7 +339,7 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha if (test_env_path(system_path, envvar)) { if (subfolder_name) { - return test_path(targetpath, system_path, NULL, subfolder_name); + return test_path(targetpath, targetpath_len, system_path, NULL, subfolder_name); } else { BLI_strncpy(targetpath, system_path, FILE_MAX); @@ -345,57 +360,63 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha if (subfolder_name) { /* try $BLENDERPATH/folder_name/subfolder_name */ - return test_path(targetpath, system_path, folder_name, subfolder_name); + return test_path(targetpath, targetpath_len, system_path, folder_name, subfolder_name); } else { /* try $BLENDERPATH/folder_name */ - return test_path(targetpath, system_path, NULL, folder_name); + return test_path(targetpath, targetpath_len, system_path, NULL, folder_name); } } -/* get a folder out of the 'folder_id' presets for paths */ -/* returns the path if found, NULL string if not */ -const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder) +/** + * Get a folder out of the 'folder_id' presets for paths. + * returns the path if found, NULL string if not + * + * \param subfolder: The name of a directory to check for, + * this may contain path separators but must resolve to a directory, checked with #BLI_is_dir. + */ +const char *BKE_appdir_folder_id_ex( + const int folder_id, const char *subfolder, + char *path, size_t path_len) { const int ver = BLENDER_VERSION; - static char path[FILE_MAX] = ""; - + switch (folder_id) { case BLENDER_DATAFILES: /* general case */ - if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; - if (get_path_local(path, "datafiles", subfolder, ver)) break; - if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; + if (get_path_user(path, path_len, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + if (get_path_local(path, path_len, "datafiles", subfolder, ver)) break; + if (get_path_system(path, path_len, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; return NULL; case BLENDER_USER_DATAFILES: - if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + if (get_path_user(path, path_len, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; return NULL; case BLENDER_SYSTEM_DATAFILES: - if (get_path_local(path, "datafiles", subfolder, ver)) break; - if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; + if (get_path_local(path, path_len, "datafiles", subfolder, ver)) break; + if (get_path_system(path, path_len, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; return NULL; case BLENDER_USER_AUTOSAVE: - if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + if (get_path_user(path, path_len, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break; return NULL; case BLENDER_USER_CONFIG: - if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break; + if (get_path_user(path, path_len, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break; return NULL; case BLENDER_USER_SCRIPTS: - if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break; + if (get_path_user(path, path_len, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break; return NULL; case BLENDER_SYSTEM_SCRIPTS: - if (get_path_local(path, "scripts", subfolder, ver)) break; - if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break; + if (get_path_local(path, path_len, "scripts", subfolder, ver)) break; + if (get_path_system(path, path_len, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break; return NULL; case BLENDER_SYSTEM_PYTHON: - if (get_path_local(path, "python", subfolder, ver)) break; - if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break; + if (get_path_local(path, path_len, "python", subfolder, ver)) break; + if (get_path_system(path, path_len, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break; return NULL; default: @@ -406,6 +427,13 @@ const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder) return path; } +const char *BKE_appdir_folder_id( + const int folder_id, const char *subfolder) +{ + static char path[FILE_MAX] = ""; + return BKE_appdir_folder_id_ex(folder_id, subfolder, path, sizeof(path)); +} + /** * Returns the path to a folder in the user area without checking that it actually exists first. */ @@ -416,16 +444,16 @@ const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *su switch (folder_id) { case BLENDER_USER_DATAFILES: - get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver); + get_path_user(path, sizeof(path), "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver); break; case BLENDER_USER_CONFIG: - get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver); + get_path_user(path, sizeof(path), "config", subfolder, "BLENDER_USER_CONFIG", ver); break; case BLENDER_USER_AUTOSAVE: - get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver); + get_path_user(path, sizeof(path), "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver); break; case BLENDER_USER_SCRIPTS: - get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver); + get_path_user(path, sizeof(path), "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver); break; default: BLI_assert(0); @@ -469,13 +497,13 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con bool ok; switch (folder_id) { case BLENDER_RESOURCE_PATH_USER: - ok = get_path_user(path, NULL, NULL, NULL, ver); + ok = get_path_user(path, sizeof(path), NULL, NULL, NULL, ver); break; case BLENDER_RESOURCE_PATH_LOCAL: - ok = get_path_local(path, NULL, NULL, ver); + ok = get_path_local(path, sizeof(path), NULL, NULL, ver); break; case BLENDER_RESOURCE_PATH_SYSTEM: - ok = get_path_system(path, NULL, NULL, NULL, ver); + ok = get_path_system(path, sizeof(path), NULL, NULL, NULL, ver); break; default: path[0] = '\0'; /* in case do_check is false */ @@ -655,6 +683,48 @@ bool BKE_appdir_program_python_search( return is_found; } +static const char *app_template_directory_search[2] = { + "startup" SEP_STR "bl_app_templates_user", + "startup" SEP_STR "bl_app_templates_system", +}; + +static const int app_template_directory_id[2] = { + BLENDER_USER_SCRIPTS, + BLENDER_SYSTEM_SCRIPTS, +}; + +/** + * Return true if templates exist + */ +bool BKE_appdir_app_template_any(void) +{ + char temp_dir[FILE_MAX]; + for (int i = 0; i < 2; i++) { + if (BKE_appdir_folder_id_ex( + app_template_directory_id[i], app_template_directory_search[i], + temp_dir, sizeof(temp_dir))) + { + return true; + } + } + return false; +} + +bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len) +{ + for (int i = 0; i < 2; i++) { + char subdir[FILE_MAX]; + BLI_join_dirfile(subdir, sizeof(subdir), app_template_directory_search[i], app_template); + if (BKE_appdir_folder_id_ex( + app_template_directory_id[i], subdir, + path, path_len)) + { + return true; + } + } + return false; +} + /** * Gets the temp directory when blender first runs. * If the default path is not found, use try $TEMP @@ -713,7 +783,8 @@ static void where_is_temp(char *fullname, char *basename, const size_t maxlen, c BLI_add_slash(fullname); #ifdef WIN32 if (userdir && userdir != fullname) { - BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ + /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ + BLI_strncpy(userdir, fullname, maxlen); } #endif } 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 afd60102453..ceb641073e0 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -100,6 +100,18 @@ void BKE_blender_free(void) free_nodesystem(); } +void BKE_blender_version_string(char *version_str, size_t maxncpy, short version, short subversion, bool v_prefix, bool include_subversion) +{ + const char *prefix = v_prefix ? "v" : ""; + + if (include_subversion && subversion > 0) { + BLI_snprintf(version_str, maxncpy, "%s%d.%02d.%d", prefix, version / 100, version % 100, subversion); + } + else { + BLI_snprintf(version_str, maxncpy, "%s%d.%02d", prefix, version / 100, version % 100); + } +} + void BKE_blender_globals_init(void) { memset(&G, 0, sizeof(Global)); @@ -110,10 +122,7 @@ void BKE_blender_globals_init(void) strcpy(G.ima, "//"); - if (BLENDER_SUBVERSION) - BLI_snprintf(versionstr, sizeof(versionstr), "v%d.%02d.%d", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION); - else - BLI_snprintf(versionstr, sizeof(versionstr), "v%d.%02d", BLENDER_VERSION / 100, BLENDER_VERSION % 100); + BKE_blender_version_string(versionstr, sizeof(versionstr), BLENDER_VERSION, BLENDER_SUBVERSION, true, true); #ifndef WITH_PYTHON_SECURITY /* default */ G.f |= G_SCRIPT_AUTOEXEC; @@ -141,20 +150,18 @@ static void keymap_item_free(wmKeyMapItem *kmi) MEM_freeN(kmi->ptr); } -/** - * When loading a new userdef from file, - * or when exiting Blender. - */ -void BKE_blender_userdef_free(void) +void BKE_blender_userdef_set_data(UserDef *userdef) { - wmKeyMap *km; - wmKeyMapItem *kmi; - wmKeyMapDiffItem *kmdi; - bAddon *addon, *addon_next; - uiFont *font; - - for (km = U.user_keymaps.first; km; km = km->next) { - for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { + /* only here free userdef themes... */ + BKE_blender_userdef_free_data(&U); + U = *userdef; +} + +static void userdef_free_keymaps(UserDef *userdef) +{ + for (wmKeyMap *km = userdef->user_keymaps.first, *km_next; km; km = km_next) { + km_next = km->next; + for (wmKeyMapDiffItem *kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { if (kmdi->add_item) { keymap_item_free(kmdi->add_item); MEM_freeN(kmdi->add_item); @@ -165,14 +172,21 @@ void BKE_blender_userdef_free(void) } } - for (kmi = km->items.first; kmi; kmi = kmi->next) + for (wmKeyMapItem *kmi = km->items.first; kmi; kmi = kmi->next) { keymap_item_free(kmi); + } BLI_freelistN(&km->diff_items); BLI_freelistN(&km->items); + + MEM_freeN(km); } - - for (addon = U.addons.first; addon; addon = addon_next) { + BLI_listbase_clear(&userdef->user_keymaps); +} + +static void userdef_free_addons(UserDef *userdef) +{ + for (bAddon *addon = userdef->addons.first, *addon_next; addon; addon = addon_next) { addon_next = addon->next; if (addon->prop) { IDP_FreeProperty(addon->prop); @@ -180,19 +194,35 @@ void BKE_blender_userdef_free(void) } MEM_freeN(addon); } + BLI_listbase_clear(&userdef->addons); +} - for (font = U.uifonts.first; font; font = font->next) { +/** + * When loading a new userdef from file, + * or when exiting Blender. + */ +void BKE_blender_userdef_free_data(UserDef *userdef) +{ +#define U _invalid_access_ /* ensure no accidental global access */ +#ifdef U /* quiet warning */ +#endif + + userdef_free_keymaps(userdef); + userdef_free_addons(userdef); + + for (uiFont *font = userdef->uifonts.first; font; font = font->next) { BLF_unload_id(font->blf_id); } BLF_default_set(-1); - BLI_freelistN(&U.autoexec_paths); + BLI_freelistN(&userdef->autoexec_paths); + + BLI_freelistN(&userdef->uistyles); + BLI_freelistN(&userdef->uifonts); + BLI_freelistN(&userdef->themes); - BLI_freelistN(&U.uistyles); - BLI_freelistN(&U.uifonts); - BLI_freelistN(&U.themes); - BLI_freelistN(&U.user_keymaps); +#undef U } /** @@ -208,6 +238,44 @@ void BKE_blender_userdef_refresh(void) } +/** + * Write U from userdef. + * This function defines which settings a template will override for the user preferences. + */ +void BKE_blender_userdef_set_app_template(UserDef *userdef) +{ + /* TODO: + * - keymaps + * - various minor settings (add as needed). + */ + +#define LIST_OVERRIDE(id) { \ + BLI_freelistN(&U.id); \ + BLI_movelisttolist(&U.id, &userdef->id); \ +} ((void)0) + +#define MEMCPY_OVERRIDE(id) \ + memcpy(U.id, userdef->id, sizeof(U.id)); + + /* for some types we need custom free functions */ + userdef_free_addons(&U); + userdef_free_keymaps(&U); + + LIST_OVERRIDE(uistyles); + LIST_OVERRIDE(uifonts); + LIST_OVERRIDE(themes); + LIST_OVERRIDE(addons); + LIST_OVERRIDE(user_keymaps); + + MEMCPY_OVERRIDE(light); + + MEMCPY_OVERRIDE(font_path_ui); + MEMCPY_OVERRIDE(font_path_ui_mono); + +#undef LIST_OVERRIDE +#undef MEMCPY_OVERRIDE +} + /* ***************** testing for break ************* */ static void (*blender_test_break_cb)(void) = NULL; diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c index bc98d6f6805..e3a5edb2049 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -108,9 +108,9 @@ static int read_undosave(bContext *C, UndoElem *uel) G.fileflags |= G_FILE_NO_UI; if (UNDO_DISK) - success = (BKE_blendfile_read(C, uel->str, NULL) != BKE_BLENDFILE_READ_FAIL); + success = (BKE_blendfile_read(C, uel->str, NULL, 0) != BKE_BLENDFILE_READ_FAIL); else - success = BKE_blendfile_read_from_memfile(C, &uel->memfile, NULL); + success = BKE_blendfile_read_from_memfile(C, &uel->memfile, NULL, 0); /* restore */ BLI_strncpy(G.main->name, mainstr, sizeof(G.main->name)); /* restore */ @@ -389,7 +389,7 @@ bool BKE_undo_save_file(const char *filename) Main *BKE_undo_get_main(Scene **r_scene) { Main *mainp = NULL; - BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL); + BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL, BLO_READ_SKIP_NONE); if (bfd) { mainp = bfd->main; diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 54f709a1e5b..05ea7983b8e 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -227,7 +227,7 @@ static void setup_app_data( if (bfd->user) { /* only here free userdef themes... */ - BKE_blender_userdef_free(); + BKE_blender_userdef_free_data(&U); U = *bfd->user; @@ -349,17 +349,23 @@ static int handle_subversion_warning(Main *main, ReportList *reports) return 1; } -int BKE_blendfile_read(bContext *C, const char *filepath, ReportList *reports) +int BKE_blendfile_read( + bContext *C, const char *filepath, + ReportList *reports, int skip_flags) { BlendFileData *bfd; int retval = BKE_BLENDFILE_READ_OK; - if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) /* don't print user-pref loading */ - printf("read blend: %s\n", filepath); + /* don't print user-pref loading */ + if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) { + printf("Read blend: %s\n", filepath); + } - bfd = BLO_read_from_file(filepath, reports); + bfd = BLO_read_from_file(filepath, reports, skip_flags); if (bfd) { - if (bfd->user) retval = BKE_BLENDFILE_READ_OK_USERPREFS; + if (bfd->user) { + retval = BKE_BLENDFILE_READ_OK_USERPREFS; + } if (0 == handle_subversion_warning(bfd->main, reports)) { BKE_main_free(bfd->main); @@ -379,11 +385,11 @@ int BKE_blendfile_read(bContext *C, const char *filepath, ReportList *reports) bool BKE_blendfile_read_from_memory( bContext *C, const void *filebuf, int filelength, - ReportList *reports, bool update_defaults) + ReportList *reports, int skip_flags, bool update_defaults) { BlendFileData *bfd; - bfd = BLO_read_from_memory(filebuf, filelength, reports); + bfd = BLO_read_from_memory(filebuf, filelength, reports, skip_flags); if (bfd) { if (update_defaults) BLO_update_defaults_startup_blend(bfd->main); @@ -399,17 +405,17 @@ bool BKE_blendfile_read_from_memory( /* memfile is the undo buffer */ bool BKE_blendfile_read_from_memfile( bContext *C, struct MemFile *memfile, - ReportList *reports) + ReportList *reports, int skip_flags) { BlendFileData *bfd; - bfd = BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports); + bfd = BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports, skip_flags); 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); } @@ -420,32 +426,76 @@ bool BKE_blendfile_read_from_memfile( return (bfd != NULL); } +/** + * Utility to make a file 'empty' used for startup to optionally give an empty file. + * Handy for tests. + */ +void BKE_blendfile_read_make_empty(bContext *C) +{ + Main *bmain = CTX_data_main(C); + + ListBase *lbarray[MAX_LIBARRAY]; + ID *id; + int a; + + a = set_listbasepointers(bmain, lbarray); + while (a--) { + id = lbarray[a]->first; + if (id != NULL) { + if (ELEM(GS(id->name), ID_SCE, ID_SCR, ID_WM)) { + continue; + } + while ((id = lbarray[a]->first)) { + BKE_libblock_delete(bmain, id); + } + } + } +} + /* only read the userdef from a .blend */ -int BKE_blendfile_read_userdef(const char *filepath, ReportList *reports) +UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports) { BlendFileData *bfd; - int retval = BKE_BLENDFILE_READ_FAIL; + UserDef *userdef = NULL; - bfd = BLO_read_from_file(filepath, reports); + bfd = BLO_read_from_file(filepath, reports, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF); if (bfd) { if (bfd->user) { - retval = BKE_BLENDFILE_READ_OK_USERPREFS; + userdef = bfd->user; + } + BKE_main_free(bfd->main); + MEM_freeN(bfd); + } - /* only here free userdef themes... */ - BKE_blender_userdef_free(); + return userdef; +} - U = *bfd->user; - MEM_freeN(bfd->user); + +UserDef *BKE_blendfile_userdef_read_from_memory( + const void *filebuf, int filelength, + ReportList *reports) +{ + BlendFileData *bfd; + UserDef *userdef = NULL; + + bfd = BLO_read_from_memory(filebuf, filelength, reports, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF); + if (bfd) { + if (bfd->user) { + userdef = bfd->user; } BKE_main_free(bfd->main); MEM_freeN(bfd); } + else { + BKE_reports_prepend(reports, "Loading failed: "); + } - return retval; + return userdef; } + /* only write the userdef in a .blend */ -int BKE_blendfile_write_userdef(const char *filepath, ReportList *reports) +int BKE_blendfile_userdef_write(const char *filepath, ReportList *reports) { Main *mainb = MEM_callocN(sizeof(Main), "empty main"); int retval = 0; 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..17d482a5d1b 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); @@ -220,7 +221,6 @@ void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file) } #endif mcmd->reader = NULL; - mcmd->object_path[0] = '\0'; } } @@ -238,7 +238,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/cloth.c b/source/blender/blenkernel/intern/cloth.c index 28ef3f6f248..ee0fde1ea61 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -869,12 +869,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d return 0; } - for ( i = 0; i < dm->getNumVerts(dm); i++) { - if ((!(cloth->verts[i].flags & CLOTH_VERT_FLAG_PINNED)) && (cloth->verts[i].goal > ALMOST_ZERO)) { - cloth_add_spring (clmd, i, i, 0.0, CLOTH_SPRING_TYPE_GOAL); - } - } - // init our solver BPH_cloth_solver_init(ob, clmd); @@ -944,37 +938,6 @@ BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1) } } -// be careful: implicit solver has to be resettet when using this one! -// --> only for implicit handling of this spring! -int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) -{ - Cloth *cloth = clmd->clothObject; - ClothSpring *spring = NULL; - - if (cloth) { - // TODO: look if this spring is already there - - spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); - - if (!spring) - return 0; - - spring->ij = indexA; - spring->kl = indexB; - spring->restlen = restlength; - spring->type = spring_type; - spring->flags = 0; - spring->stiffness = 0; - - cloth->numsprings++; - - BLI_linklist_prepend ( &cloth->springs, spring ); - - return 1; - } - return 0; -} - static void cloth_free_edgelist(LinkNodePair *edgelist, unsigned int mvert_num) { if (edgelist) { 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 439abb1d593..8b32109cf2b 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; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index c9f0b8ec9ca..0939d35ed8d 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -33,14 +33,10 @@ /** \file blender/blenkernel/intern/customdata.c * \ingroup bke */ - - -#include <math.h> -#include <string.h> -#include <assert.h> #include "MEM_guardedalloc.h" +#include "DNA_customdata_types.h" #include "DNA_meshdata_types.h" #include "DNA_ID.h" @@ -62,20 +58,16 @@ #include "BKE_mesh_remap.h" #include "BKE_multires.h" -#include "data_transfer_intern.h" - #include "bmesh.h" -#include <math.h> -#include <string.h> +/* only for customdata_data_transfer_interp_normal_normals */ +#include "data_transfer_intern.h" /* number of layers to add when growing a CustomData object */ #define CUSTOMDATA_GROW 5 /* ensure typemap size is ok */ -BLI_STATIC_ASSERT(sizeof(((CustomData *)NULL)->typemap) / - sizeof(((CustomData *)NULL)->typemap[0]) == CD_NUMTYPES, - "size mismatch"); +BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)NULL)->typemap) == CD_NUMTYPES, "size mismatch"); /********************* Layer type information **********************/ @@ -805,18 +797,15 @@ static void layerInterp_mloopcol( const float *sub_weights, int count, void *dest) { MLoopCol *mc = dest; - int i; - const float *sub_weight; struct { float a; float r; float g; float b; - } col; - col.a = col.r = col.g = col.b = 0; + } col = {0}; - sub_weight = sub_weights; - for (i = 0; i < count; ++i) { + const float *sub_weight = sub_weights; + for (int i = 0; i < count; ++i) { float weight = weights ? weights[i] : 1; const MLoopCol *src = sources[i]; if (sub_weights) { @@ -833,19 +822,16 @@ static void layerInterp_mloopcol( col.a += src->a * weight; } } - + + /* Subdivide smooth or fractal can cause problems without clamping * although weights should also not cause this situation */ - CLAMP(col.a, 0.0f, 255.0f); - CLAMP(col.r, 0.0f, 255.0f); - CLAMP(col.g, 0.0f, 255.0f); - CLAMP(col.b, 0.0f, 255.0f); - /* delay writing to the destination incase dest is in sources */ - mc->r = (int)col.r; - mc->g = (int)col.g; - mc->b = (int)col.b; - mc->a = (int)col.a; + /* also delay writing to the destination incase dest is in sources */ + mc->r = CLAMPIS(iroundf(col.r), 0, 255); + mc->g = CLAMPIS(iroundf(col.g), 0, 255); + mc->b = CLAMPIS(iroundf(col.b), 0, 255); + mc->a = CLAMPIS(iroundf(col.a), 0, 255); } static int layerMaxNum_mloopcol(void) @@ -1068,15 +1054,10 @@ static void layerInterp_mcol( /* Subdivide smooth or fractal can cause problems without clamping * although weights should also not cause this situation */ - CLAMP(col[j].a, 0.0f, 255.0f); - CLAMP(col[j].r, 0.0f, 255.0f); - CLAMP(col[j].g, 0.0f, 255.0f); - CLAMP(col[j].b, 0.0f, 255.0f); - - mc[j].a = (int)col[j].a; - mc[j].r = (int)col[j].r; - mc[j].g = (int)col[j].g; - mc[j].b = (int)col[j].b; + mc[j].a = CLAMPIS(iroundf(col[j].a), 0, 255); + mc[j].r = CLAMPIS(iroundf(col[j].r), 0, 255); + mc[j].g = CLAMPIS(iroundf(col[j].g), 0, 255); + mc[j].b = CLAMPIS(iroundf(col[j].b), 0, 255); } } @@ -1963,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); @@ -2012,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 678dc92a5f2..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); } - 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..4a45bf1534c 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); } @@ -2053,20 +2055,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 (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 (index != -1) { + 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); 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 b2641b110f8..e98181be444 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -117,31 +117,35 @@ 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); } -/*shallow copies item*/ +/* shallow copies item */ void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item) { IDProperty *old; BLI_assert(prop->type == IDP_IDPARRAY); + if (index >= prop->len || index < 0) + return; + old = GETPROP(prop, index); - if (index >= prop->len || index < 0) return; - if (item != old) IDP_FreeProperty(old); - - memcpy(GETPROP(prop, index), item, sizeof(IDProperty)); + if (item != old) { + IDP_FreeProperty(old); + + memcpy(old, item, sizeof(IDProperty)); + } } IDProperty *IDP_GetIndexArray(IDProperty *prop, int index) @@ -433,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; } + /** \} */ @@ -499,14 +505,9 @@ void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src) break; default: { - IDProperty *tmp = other; - IDProperty *copy = IDP_CopyProperty(prop); - - BLI_insertlinkafter(&dest->data.group, other, copy); - BLI_remlink(&dest->data.group, tmp); - - IDP_FreeProperty(tmp); - MEM_freeN(tmp); + BLI_insertlinkreplace(&dest->data.group, other, IDP_CopyProperty(prop)); + IDP_FreeProperty(other); + MEM_freeN(other); break; } } @@ -526,11 +527,9 @@ void IDP_SyncGroupTypes(IDProperty *dst, const IDProperty *src, const bool do_ar if ((prop_dst->type != prop_src->type || prop_dst->subtype != prop_src->subtype) || (do_arraylen && ELEM(prop_dst->type, IDP_ARRAY, IDP_IDPARRAY) && (prop_src->len != prop_dst->len))) { - IDP_FreeFromGroup(dst, prop_dst); - prop_dst = IDP_CopyProperty(prop_src); - - dst->len++; - BLI_insertlinkbefore(&dst->data.group, prop_dst_next, prop_dst); + BLI_insertlinkreplace(&dst->data.group, prop_dst, IDP_CopyProperty(prop_src)); + IDP_FreeProperty(prop_dst); + MEM_freeN(prop_dst); } else if (prop_dst->type == IDP_GROUP) { IDP_SyncGroupTypes(prop_dst, prop_src, do_arraylen); @@ -555,11 +554,7 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src) for (prop = src->data.group.first; prop; prop = prop->next) { for (loop = dest->data.group.first; loop; loop = loop->next) { if (STREQ(loop->name, prop->name)) { - IDProperty *copy = IDP_CopyProperty(prop); - - BLI_insertlinkafter(&dest->data.group, loop, copy); - - BLI_remlink(&dest->data.group, loop); + BLI_insertlinkreplace(&dest->data.group, loop, IDP_CopyProperty(prop)); IDP_FreeProperty(loop); MEM_freeN(loop); break; @@ -586,9 +581,7 @@ void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop BLI_assert(prop_exist == IDP_GetPropertyFromGroup(group, prop->name)); if ((prop_exist = IDP_GetPropertyFromGroup(group, prop->name))) { - BLI_insertlinkafter(&group->data.group, prop_exist, prop); - - BLI_remlink(&group->data.group, prop_exist); + BLI_insertlinkreplace(&group->data.group, prop_exist, prop); IDP_FreeProperty(prop_exist); MEM_freeN(prop_exist); } @@ -719,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); } @@ -742,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 @@ -844,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); @@ -867,17 +901,19 @@ bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) * The union is simple to use; see the top of this header file for its definition. * An example of using this function: * - * IDPropertyTemplate val; - * IDProperty *group, *idgroup, *color; - * group = IDP_New(IDP_GROUP, val, "group1"); //groups don't need a template. + * \code{.c} + * IDPropertyTemplate val; + * IDProperty *group, *idgroup, *color; + * group = IDP_New(IDP_GROUP, val, "group1"); //groups don't need a template. * - * val.array.len = 4 - * val.array.type = IDP_FLOAT; - * color = IDP_New(IDP_ARRAY, val, "color1"); + * val.array.len = 4 + * val.array.type = IDP_FLOAT; + * color = IDP_New(IDP_ARRAY, val, "color1"); * - * idgroup = IDP_GetProperties(some_id, 1); - * IDP_AddToGroup(idgroup, color); - * IDP_AddToGroup(idgroup, group); + * idgroup = IDP_GetProperties(some_id, 1); + * IDP_AddToGroup(idgroup, color); + * IDP_AddToGroup(idgroup, group); + * \endcode * * Note that you MUST either attach the id property to an id property group with * IDP_AddToGroup or MEM_freeN the property, doing anything else might result in @@ -897,7 +933,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char * *(float *)&prop->data.val = val->f; break; case IDP_DOUBLE: - prop = MEM_callocN(sizeof(IDProperty), "IDProperty float"); + prop = MEM_callocN(sizeof(IDProperty), "IDProperty double"); *(double *)&prop->data.val = val->d; break; case IDP_ARRAY: @@ -917,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: @@ -963,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"); @@ -977,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: @@ -991,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); @@ -1006,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/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 b0671f33094..c9d7dddf25a 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -67,7 +67,7 @@ #include "BKE_deform.h" -/* Workaround for cyclic depenndnecy with curves. +/* Workaround for cyclic dependency with curves. * In such case curve_cache might not be ready yet, */ #define CYCLIC_DEPENDENCY_WORKAROUND @@ -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 befe1a4d70e..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 { @@ -2145,6 +2146,8 @@ static int split_faces_prepare_new_verts( /* If vert is already used by another smooth fan, we need a new vert for this one. */ const int new_vert_idx = vert_used ? num_verts++ : vert_idx; + BLI_assert(*lnor_space); + if ((*lnor_space)->loops) { for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) { const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link); @@ -2377,19 +2380,24 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) * loops' vertex and edge indices to new, to-be-created split ones). */ const int num_new_edges = split_faces_prepare_new_edges(mesh, &new_edges, memarena); - BLI_assert(num_new_edges > 0); + /* We can have to split a vertex without having to add a single new edge... */ + const bool do_edges = (num_new_edges > 0); /* Reallocate all vert and edge related data. */ mesh->totvert += num_new_verts; mesh->totedge += num_new_edges; CustomData_realloc(&mesh->vdata, mesh->totvert); - CustomData_realloc(&mesh->edata, mesh->totedge); + if (do_edges) { + CustomData_realloc(&mesh->edata, mesh->totedge); + } /* Update pointers to a newly allocated memory. */ BKE_mesh_update_customdata_pointers(mesh, false); /* Perform actual split of vertices and edges. */ split_faces_split_new_verts(mesh, new_verts, num_new_verts); - split_faces_split_new_edges(mesh, new_edges, num_new_edges); + if (do_edges) { + split_faces_split_new_edges(mesh, new_edges, num_new_edges); + } } /* Note: after this point mesh is expected to be valid again. */ @@ -2479,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; @@ -2515,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); @@ -2570,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 e96a434194c..5dfcef9f9bf 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -304,13 +304,13 @@ void BKE_mesh_calc_normals_poly( void BKE_mesh_calc_normals(Mesh *mesh) { #ifdef DEBUG_TIME - TIMEIT_START(BKE_mesh_calc_normals); + TIMEIT_START_AVERAGED(BKE_mesh_calc_normals); #endif BKE_mesh_calc_normals_poly(mesh->mvert, NULL, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, false); #ifdef DEBUG_TIME - TIMEIT_END(BKE_mesh_calc_normals); + TIMEIT_END_AVERAGED(BKE_mesh_calc_normals); #endif } @@ -630,7 +630,6 @@ typedef struct LoopSplitTaskDataCommon { * Note we do not need to protect it, though, since two different tasks will *always* affect different * elements in the arrays. */ MLoopNorSpaceArray *lnors_spacearr; - BLI_bitmap *sharp_verts; float (*loopnors)[3]; short (*clnors_data)[2]; @@ -643,11 +642,8 @@ typedef struct LoopSplitTaskDataCommon { const int *loop_to_poly; const float (*polynors)[3]; + int numLoops; int numPolys; - - /* ***** Workers communication. ***** */ - ThreadQueue *task_queue; - } LoopSplitTaskDataCommon; #define INDEX_UNSET INT_MIN @@ -655,6 +651,50 @@ typedef struct LoopSplitTaskDataCommon { /* See comment about edge_to_loops below. */ #define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID)) +static void loop_manifold_fan_around_vert_next( + const MLoop *mloops, const MPoly *mpolys, + const int *loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index, + const MLoop **r_mlfan_curr, int *r_mlfan_curr_index, int *r_mlfan_vert_index, int *r_mpfan_curr_index) +{ + const MLoop *mlfan_next; + const MPoly *mpfan_next; + + /* Warning! This is rather complex! + * We have to find our next edge around the vertex (fan mode). + * First we find the next loop, which is either previous or next to mlfan_curr_index, depending + * whether both loops using current edge are in the same direction or not, and whether + * mlfan_curr_index actually uses the vertex we are fanning around! + * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one + * (i.e. not the future mlfan_curr)... + */ + *r_mlfan_curr_index = (e2lfan_curr[0] == *r_mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0]; + *r_mpfan_curr_index = loop_to_poly[*r_mlfan_curr_index]; + + BLI_assert(*r_mlfan_curr_index >= 0); + BLI_assert(*r_mpfan_curr_index >= 0); + + mlfan_next = &mloops[*r_mlfan_curr_index]; + mpfan_next = &mpolys[*r_mpfan_curr_index]; + if (((*r_mlfan_curr)->v == mlfan_next->v && (*r_mlfan_curr)->v == mv_pivot_index) || + ((*r_mlfan_curr)->v != mlfan_next->v && (*r_mlfan_curr)->v != mv_pivot_index)) + { + /* We need the previous loop, but current one is our vertex's loop. */ + *r_mlfan_vert_index = *r_mlfan_curr_index; + if (--(*r_mlfan_curr_index) < mpfan_next->loopstart) { + *r_mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1; + } + } + else { + /* We need the next loop, which is also our vertex's loop. */ + if (++(*r_mlfan_curr_index) >= mpfan_next->loopstart + mpfan_next->totloop) { + *r_mlfan_curr_index = mpfan_next->loopstart; + } + *r_mlfan_vert_index = *r_mlfan_curr_index; + } + *r_mlfan_curr = &mloops[*r_mlfan_curr_index]; + /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */ +} + static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data) { MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; @@ -680,7 +720,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS */ copy_v3_v3(*lnor, polynors[mp_index]); - /* printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", ml_curr_index, ml_curr->e, ml_curr->v, mp_index); */ +// printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", ml_curr_index, ml_curr->e, ml_curr->v, mp_index); /* If needed, generate this (simple!) lnor space. */ if (lnors_spacearr) { @@ -747,8 +787,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli const MEdge *me_org = &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */ const int *e2lfan_curr; float vec_curr[3], vec_prev[3], vec_org[3]; - const MLoop *mlfan_curr, *mlfan_next; - const MPoly *mpfan_next; + const MLoop *mlfan_curr; float lnor[3] = {0.0f, 0.0f, 0.0f}; /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */ int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index; @@ -787,7 +826,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli } } - /* printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e); */ +// printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e); while (true) { const MEdge *me_curr = &medges[mlfan_curr->e]; @@ -803,7 +842,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli normalize_v3(vec_curr); } - /* printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index); */ +// printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index); { /* Code similar to accumulate_vertex_normals_poly. */ @@ -845,46 +884,16 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli /* Current edge is sharp and we have finished with this fan of faces around this vert, * or this vert is smooth, and we have completed a full turn around it. */ - /* printf("FAN: Finished!\n"); */ +// printf("FAN: Finished!\n"); break; } copy_v3_v3(vec_prev, vec_curr); - /* Warning! This is rather complex! - * We have to find our next edge around the vertex (fan mode). - * First we find the next loop, which is either previous or next to mlfan_curr_index, depending - * whether both loops using current edge are in the same direction or not, and whether - * mlfan_curr_index actually uses the vertex we are fanning around! - * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one - * (i.e. not the future mlfan_curr)... - */ - mlfan_curr_index = (e2lfan_curr[0] == mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0]; - mpfan_curr_index = loop_to_poly[mlfan_curr_index]; - - BLI_assert(mlfan_curr_index >= 0); - BLI_assert(mpfan_curr_index >= 0); - - mlfan_next = &mloops[mlfan_curr_index]; - mpfan_next = &mpolys[mpfan_curr_index]; - if ((mlfan_curr->v == mlfan_next->v && mlfan_curr->v == mv_pivot_index) || - (mlfan_curr->v != mlfan_next->v && mlfan_curr->v != mv_pivot_index)) - { - /* We need the previous loop, but current one is our vertex's loop. */ - mlfan_vert_index = mlfan_curr_index; - if (--mlfan_curr_index < mpfan_next->loopstart) { - mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1; - } - } - else { - /* We need the next loop, which is also our vertex's loop. */ - if (++mlfan_curr_index >= mpfan_next->loopstart + mpfan_next->totloop) { - mlfan_curr_index = mpfan_next->loopstart; - } - mlfan_vert_index = mlfan_curr_index; - } - mlfan_curr = &mloops[mlfan_curr_index]; - /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */ + /* Find next loop of the smooth fan. */ + loop_manifold_fan_around_vert_next( + mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index, + &mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index); e2lfan_curr = edge_to_loops[mlfan_curr->e]; } @@ -955,31 +964,25 @@ static void loop_split_worker_do( } } -static void loop_split_worker(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) +static void loop_split_worker(TaskPool * __restrict pool, void *taskdata, int UNUSED(threadid)) { - LoopSplitTaskDataCommon *common_data = taskdata; - LoopSplitTaskData *data_buff; + LoopSplitTaskDataCommon *common_data = BLI_task_pool_userdata(pool); + LoopSplitTaskData *data = taskdata; /* Temp edge vectors stack, only used when computing lnor spacearr. */ BLI_Stack *edge_vectors = common_data->lnors_spacearr ? BLI_stack_new(sizeof(float[3]), __func__) : NULL; #ifdef DEBUG_TIME - TIMEIT_START(loop_split_worker); + TIMEIT_START_AVERAGED(loop_split_worker); #endif - while ((data_buff = BLI_thread_queue_pop(common_data->task_queue))) { - LoopSplitTaskData *data = data_buff; - int i; - - for (i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) { - /* A NULL ml_curr is used to tag ended data! */ - if (data->ml_curr == NULL) { - break; - } - loop_split_worker_do(common_data, data, edge_vectors); + for (int i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) { + /* A NULL ml_curr is used to tag ended data! */ + if (data->ml_curr == NULL) { + break; } - MEM_freeN(data_buff); + loop_split_worker_do(common_data, data, edge_vectors); } if (edge_vectors) { @@ -987,38 +990,104 @@ static void loop_split_worker(TaskPool * __restrict UNUSED(pool), void *taskdata } #ifdef DEBUG_TIME - TIMEIT_END(loop_split_worker); + TIMEIT_END_AVERAGED(loop_split_worker); #endif } -static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const bool threaded) +/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not. + * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */ +static bool loop_split_generator_check_cyclic_smooth_fan( + const MLoop *mloops, const MPoly *mpolys, + const int (*edge_to_loops)[2], const int *loop_to_poly, const int *e2l_prev, BLI_bitmap *skip_loops, + const MLoop *ml_curr, const MLoop *ml_prev, const int ml_curr_index, const int ml_prev_index, + const int mp_curr_index) +{ + const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */ + const int *e2lfan_curr; + const MLoop *mlfan_curr; + /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */ + int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index; + + e2lfan_curr = e2l_prev; + if (IS_EDGE_SHARP(e2lfan_curr)) { + /* Sharp loop, so not a cyclic smooth fan... */ + return false; + } + + mlfan_curr = ml_prev; + mlfan_curr_index = ml_prev_index; + mlfan_vert_index = ml_curr_index; + mpfan_curr_index = mp_curr_index; + + BLI_assert(mlfan_curr_index >= 0); + BLI_assert(mlfan_vert_index >= 0); + BLI_assert(mpfan_curr_index >= 0); + + BLI_assert(!BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)); + BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index); + + 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, + &mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index); + + e2lfan_curr = edge_to_loops[mlfan_curr->e]; + + if (IS_EDGE_SHARP(e2lfan_curr)) { + /* Sharp loop/edge, so not a cyclic smooth fan... */ + return false; + } + /* Smooth loop/edge... */ + else if (BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)) { + if (mlfan_vert_index == ml_curr_index) { + /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can + * use initial ml_curr/ml_prev edge as start for this smooth fan. */ + return true; + } + /* ... already checked in some previous looping, we can abort. */ + return false; + } + else { + /* ... we can skip it in future, and keep checking the smooth fan. */ + BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index); + } + } +} + +static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common_data) { MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; - BLI_bitmap *sharp_verts = common_data->sharp_verts; float (*loopnors)[3] = common_data->loopnors; const MLoop *mloops = common_data->mloops; const MPoly *mpolys = common_data->mpolys; + const int *loop_to_poly = common_data->loop_to_poly; const int (*edge_to_loops)[2] = common_data->edge_to_loops; + const int numLoops = common_data->numLoops; const int numPolys = common_data->numPolys; const MPoly *mp; int mp_index; - LoopSplitTaskData *data, *data_buff = NULL, data_mem; + const MLoop *ml_curr; + const MLoop *ml_prev; + int ml_curr_index; + int ml_prev_index; + + BLI_bitmap *skip_loops = BLI_BITMAP_NEW(numLoops, __func__); + + LoopSplitTaskData *data_buff = NULL; int data_idx = 0; /* Temp edge vectors stack, only used when computing lnor spacearr (and we are not multi-threading). */ BLI_Stack *edge_vectors = NULL; #ifdef DEBUG_TIME - TIMEIT_START(loop_split_generator); + TIMEIT_START_AVERAGED(loop_split_generator); #endif - if (!threaded) { - memset(&data_mem, 0, sizeof(data_mem)); - data = &data_mem; - + if (!pool) { if (lnors_spacearr) { edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); } @@ -1028,11 +1097,10 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const * Now, time to generate the normals. */ for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) { - const MLoop *ml_curr, *ml_prev; float (*lnors)[3]; const int ml_last_index = (mp->loopstart + mp->totloop) - 1; - int ml_curr_index = mp->loopstart; - int ml_prev_index = ml_last_index; + ml_curr_index = mp->loopstart; + ml_prev_index = ml_last_index; ml_curr = &mloops[ml_curr_index]; ml_prev = &mloops[ml_prev_index]; @@ -1042,23 +1110,40 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const const int *e2l_curr = edge_to_loops[ml_curr->e]; const int *e2l_prev = edge_to_loops[ml_prev->e]; - if (!IS_EDGE_SHARP(e2l_curr) && (!lnors_spacearr || BLI_BITMAP_TEST_BOOL(sharp_verts, ml_curr->v))) { - /* A smooth edge, and we are not generating lnor_spacearr, or the related vertex is sharp. - * We skip it because it is either: - * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit - * one of its ends, i.e. one of its two sharp edges), or... - * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex - * are just fine (or it has already be handled in a previous loop in case of needed lnors spacearr)! - */ - /* printf("Skipping loop %d / edge %d / vert %d(%d)\n", ml_curr_index, ml_curr->e, ml_curr->v, sharp_verts[ml_curr->v]); */ +// printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)...", +// ml_curr_index, ml_curr->e, ml_curr->v, IS_EDGE_SHARP(e2l_curr), BLI_BITMAP_TEST_BOOL(skip_loops, ml_curr_index)); + + /* A smooth edge, we have to check for cyclic smooth fan case. + * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as + * 'entry point', otherwise we can skip it. */ + /* Note: In theory, we could make loop_split_generator_check_cyclic_smooth_fan() store + * mlfan_vert_index'es and edge indexes in two stacks, to avoid having to fan again around the vert during + * actual computation of clnor & clnorspace. However, this would complicate the code, add more memory usage, + * and despite its logical complexity, loop_manifold_fan_around_vert_next() is quite cheap in term of + * CPU cycles, so really think it's not worth it. */ + if (!IS_EDGE_SHARP(e2l_curr) && + (BLI_BITMAP_TEST(skip_loops, ml_curr_index) || + !loop_split_generator_check_cyclic_smooth_fan( + mloops, mpolys, edge_to_loops, loop_to_poly, e2l_prev, skip_loops, + ml_curr, ml_prev, ml_curr_index, ml_prev_index, mp_index))) + { +// printf("SKIPPING!\n"); } else { - if (threaded) { + LoopSplitTaskData *data, data_local; + +// printf("PROCESSING!\n"); + + if (pool) { if (data_idx == 0) { data_buff = MEM_callocN(sizeof(*data_buff) * LOOP_SPLIT_TASK_BLOCK_SIZE, __func__); } data = &data_buff[data_idx]; } + else { + data = &data_local; + memset(data, 0, sizeof(*data)); + } if (IS_EDGE_SHARP(e2l_curr) && IS_EDGE_SHARP(e2l_prev)) { data->lnor = lnors; @@ -1094,22 +1179,18 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const data->mp_index = mp_index; if (lnors_spacearr) { data->lnor_space = BKE_lnor_space_create(lnors_spacearr); - /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one). - * This *has* to be done outside of workers tasks! */ - BLI_BITMAP_ENABLE(sharp_verts, ml_curr->v); } } - if (threaded) { + if (pool) { data_idx++; if (data_idx == LOOP_SPLIT_TASK_BLOCK_SIZE) { - BLI_thread_queue_push(common_data->task_queue, data_buff); + BLI_task_pool_push(pool, loop_split_worker, data_buff, true, TASK_PRIORITY_LOW); data_idx = 0; } } else { loop_split_worker_do(common_data, data, edge_vectors); - memset(data, 0, sizeof(data_mem)); } } @@ -1118,38 +1199,27 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const } } - if (threaded) { - /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, everything is fine. */ - if (LIKELY(data_idx)) { - BLI_thread_queue_push(common_data->task_queue, data_buff); - } - - /* This will signal all other worker threads to wake up and finish! */ - BLI_thread_queue_nowait(common_data->task_queue); + /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, everything is fine. */ + if (pool && data_idx) { + BLI_task_pool_push(pool, loop_split_worker, data_buff, true, TASK_PRIORITY_LOW); } if (edge_vectors) { BLI_stack_free(edge_vectors); } + MEM_freeN(skip_loops); #ifdef DEBUG_TIME - TIMEIT_END(loop_split_generator); + TIMEIT_END_AVERAGED(loop_split_generator); #endif } -static void loop_split_generator(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) -{ - LoopSplitTaskDataCommon *common_data = taskdata; - - loop_split_generator_do(common_data, true); -} - /** * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals'). * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges). */ void BKE_mesh_normals_loop_split( - const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges, + const MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges, MLoop *mloops, float (*r_loopnors)[3], const int numLoops, MPoly *mpolys, const float (*polynors)[3], const int numPolys, const bool use_split_normals, float split_angle, @@ -1187,8 +1257,6 @@ void BKE_mesh_normals_loop_split( return; } - { - /* Mapping edge -> loops. * If that edge is used by more than two loops (polys), it is always sharp (and tagged as such, see below). * We also use the second loop index as a kind of flag: smooth edge: > 0, @@ -1198,33 +1266,25 @@ void BKE_mesh_normals_loop_split( * store the negated value of loop index instead of INDEX_INVALID to retrieve the real value later in code). * Note also that lose edges always have both values set to 0! */ - int (*edge_to_loops)[2] = MEM_callocN(sizeof(int[2]) * (size_t)numEdges, __func__); + int (*edge_to_loops)[2] = MEM_callocN(sizeof(*edge_to_loops) * (size_t)numEdges, __func__); /* Simple mapping from a loop to its polygon index. */ - int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__); + int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_mallocN(sizeof(*loop_to_poly) * (size_t)numLoops, __func__); MPoly *mp; - int mp_index, me_index; - bool check_angle = (split_angle < (float)M_PI); - int i; + int mp_index; - BLI_bitmap *sharp_verts = NULL; - MLoopNorSpaceArray _lnors_spacearr = {NULL}; + /* When using custom loop normals, disable the angle feature! */ + const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL); - LoopSplitTaskDataCommon common_data = {NULL}; + MLoopNorSpaceArray _lnors_spacearr = {NULL}; #ifdef DEBUG_TIME - TIMEIT_START(BKE_mesh_normals_loop_split); + TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split); #endif if (check_angle) { - /* When using custom loop normals, disable the angle feature! */ - if (clnors_data) { - check_angle = false; - } - else { - split_angle = cosf(split_angle); - } + split_angle = cosf(split_angle); } if (!r_lnors_spacearr && clnors_data) { @@ -1233,7 +1293,6 @@ void BKE_mesh_normals_loop_split( } if (r_lnors_spacearr) { BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops); - sharp_verts = BLI_BITMAP_NEW((size_t)numVerts, __func__); } /* This first loop check which edges are actually smooth, and compute edge vectors. */ @@ -1287,60 +1346,38 @@ void BKE_mesh_normals_loop_split( } } - if (r_lnors_spacearr) { - /* Tag vertices that have at least one sharp edge as 'sharp' (used for the lnor spacearr computation). - * XXX This third loop over edges is a bit disappointing, could not find any other way yet. - * Not really performance-critical anyway. - */ - for (me_index = 0; me_index < numEdges; me_index++) { - const int *e2l = edge_to_loops[me_index]; - const MEdge *me = &medges[me_index]; - if (IS_EDGE_SHARP(e2l)) { - BLI_BITMAP_ENABLE(sharp_verts, me->v1); - BLI_BITMAP_ENABLE(sharp_verts, me->v2); - } - } - } - /* Init data common to all tasks. */ - common_data.lnors_spacearr = r_lnors_spacearr; - common_data.loopnors = r_loopnors; - common_data.clnors_data = clnors_data; - - common_data.mverts = mverts; - common_data.medges = medges; - common_data.mloops = mloops; - common_data.mpolys = mpolys; - common_data.sharp_verts = sharp_verts; - common_data.edge_to_loops = (const int(*)[2])edge_to_loops; - common_data.loop_to_poly = loop_to_poly; - common_data.polynors = polynors; - common_data.numPolys = numPolys; + LoopSplitTaskDataCommon common_data = { + .lnors_spacearr = r_lnors_spacearr, + .loopnors = r_loopnors, + .clnors_data = clnors_data, + .mverts = mverts, + .medges = medges, + .mloops = mloops, + .mpolys = mpolys, + .edge_to_loops = (const int(*)[2])edge_to_loops, + .loop_to_poly = loop_to_poly, + .polynors = polynors, + .numLoops = numLoops, + .numPolys = numPolys, + }; if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) { /* Not enough loops to be worth the whole threading overhead... */ - loop_split_generator_do(&common_data, false); + loop_split_generator(NULL, &common_data); } else { TaskScheduler *task_scheduler; TaskPool *task_pool; - int nbr_workers; - - common_data.task_queue = BLI_thread_queue_init(); task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create(task_scheduler, NULL); + task_pool = BLI_task_pool_create(task_scheduler, &common_data); + + loop_split_generator(task_pool, &common_data); - nbr_workers = max_ii(2, BLI_task_scheduler_num_threads(task_scheduler)); - for (i = 1; i < nbr_workers; i++) { - BLI_task_pool_push(task_pool, loop_split_worker, &common_data, false, TASK_PRIORITY_HIGH); - } - BLI_task_pool_push(task_pool, loop_split_generator, &common_data, false, TASK_PRIORITY_HIGH); BLI_task_pool_work_and_wait(task_pool); BLI_task_pool_free(task_pool); - - BLI_thread_queue_free(common_data.task_queue); } MEM_freeN(edge_to_loops); @@ -1349,17 +1386,14 @@ void BKE_mesh_normals_loop_split( } if (r_lnors_spacearr) { - MEM_freeN(sharp_verts); if (r_lnors_spacearr == &_lnors_spacearr) { BKE_lnor_spacearr_free(r_lnors_spacearr); } } #ifdef DEBUG_TIME - TIMEIT_END(BKE_mesh_normals_loop_split); + TIMEIT_END_AVERAGED(BKE_mesh_normals_loop_split); #endif - - } } #undef INDEX_UNSET @@ -1595,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, @@ -1959,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 */ @@ -2109,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..dd28a534d22 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); } @@ -1828,7 +1830,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); } } @@ -3568,6 +3570,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..e9ebd397df0 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; } diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 5cb704e4737..e03af585cf2 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -54,6 +54,7 @@ #include "BKE_editmesh.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_material.h" #include "BKE_image.h" @@ -144,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) @@ -347,3 +336,9 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME); } + +void BKE_object_eval_cloth(EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *object) +{ + DEBUG_PRINT("%s on %s\n", __func__, object->id.name); + BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH); +} 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..fe7138f6774 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -590,7 +590,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); @@ -3326,7 +3326,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; @@ -3466,7 +3466,8 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti case TEXCO_UV: if (fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec)) 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; @@ -3538,7 +3539,8 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex case TEXCO_UV: if (get_particle_uv(sim->psmd->dm_final, pa, 0, pa->fuv, mtex->uvname, texvec)) 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); 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..6603521c42f 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -1092,7 +1092,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..3f9a92a5577 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; 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..390e6dedc3f 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); @@ -1622,8 +1622,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..44b71416bf0 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -233,6 +233,9 @@ 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) { @@ -416,11 +419,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 +2070,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 +2137,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..dbdffa54d29 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; } @@ -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/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index b14ed2d67ad..7094d5a3547 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -588,13 +588,8 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM DerivedMesh *ss_mesh = NULL; ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData; - /* remove loop dependencies on derived meshes (TODO should this be done elsewhere?) - * This also ensure the target is of type OBJ_MESH avoiding crash in `object_get_derived_final` (see T50899). */ - if (smd->target) { - if (smd->target->type != OB_MESH || smd->target == ob) { - smd->target = NULL; - } - } + /* remove loop dependencies on derived meshes (TODO should this be done elsewhere?) */ + if (smd->target == ob) smd->target = NULL; if (smd->auxTarget == ob) smd->auxTarget = NULL; 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 722fc89a75f..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, @@ -755,7 +755,8 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_ if (ok) { r_ref_pos[0] /= weight_sum; r_ref_pos[1] /= weight_sum; - } else { + } + else { /* No usable tracking data on any track on this frame. * Use data from neighbouring frames to extrapolate... */ @@ -784,7 +785,8 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_ * Also default to this frame when we're in a gap */ average_marker_positions(ctx, next_lower, r_ref_pos); - } else if (next_higher < MAXFRAME) { + } + else if (next_higher < MAXFRAME) { average_marker_positions(ctx, next_higher, r_ref_pos); } use_values_from_fcurves(ctx, false); 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/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 9994d479ce7..156b74f5c3d 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -568,7 +568,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int if (context->ffmpeg_crf >= 0) { ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf); - } else { + } + else { c->bit_rate = context->ffmpeg_video_bitrate * 1000; c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000; c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000; @@ -576,8 +577,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int } if (context->ffmpeg_preset) { - char const * preset_name; - switch(context->ffmpeg_preset) { + char const *preset_name; + switch (context->ffmpeg_preset) { case FFM_PRESET_ULTRAFAST: preset_name = "ultrafast"; break; case FFM_PRESET_SUPERFAST: preset_name = "superfast"; break; case FFM_PRESET_VERYFAST: preset_name = "veryfast"; break; 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 96349a7b066..b06944e4985 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -67,6 +67,7 @@ void *BLI_poptail(ListBase *listbase) ATTR_NONNULL(1); void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1); void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1); void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1); +void BLI_insertlinkreplace(ListBase *listbase, void *v_l_src, void *v_l_dst) ATTR_NONNULL(1, 2, 3); void BLI_listbase_sort(struct ListBase *listbase, int (*cmp)(const void *, const void *)) ATTR_NONNULL(1, 2); void BLI_listbase_sort_r(ListBase *listbase, int (*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1, 2); bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL(); @@ -124,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 baa1f792018..b59e7f99d59 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -39,20 +39,12 @@ extern "C" { struct ListBase; -#ifdef WIN32 -#define SEP '\\' -#define ALTSEP '/' -#else -#define SEP '/' -#define ALTSEP '\\' -#endif - void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1); 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); @@ -60,7 +52,13 @@ void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file) ATTR_NONNULL(); void BLI_join_dirfile(char *__restrict string, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL(); +size_t BLI_path_join( + char *__restrict dst, const size_t dst_len, + const char *path_first, ...) ATTR_NONNULL(1, 3) ATTR_SENTINEL(0); const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +bool BLI_path_name_at_index( + const char *__restrict path, const int index, + int *__restrict r_offset, int *__restrict r_len) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; #if 0 typedef enum bli_rebase_state { @@ -83,7 +81,6 @@ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen); #endif bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name); -void BLI_getlastdir(const char *dir, char *last, const size_t maxlen); bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; bool BLI_testextensie_n(const char *str, ...) ATTR_NONNULL(1) ATTR_SENTINEL(0); bool BLI_testextensie_array(const char *str, const char **ext_array) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; @@ -143,6 +140,18 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char # define FILE_MAX 1024 #endif +#ifdef WIN32 +# define SEP '\\' +# define ALTSEP '/' +# define SEP_STR "\\" +# define ALTSEP_STR "/" +#else +# define SEP '/' +# define ALTSEP '\\' +# define SEP_STR "/" +# define ALTSEP_STR "\\" +#endif + /* Parent and current dir helpers. */ #define FILENAME_PARENT ".." #define FILENAME_CURRENT "." 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 c9bf4976ae8..46dcee48eda 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -342,6 +342,40 @@ void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) } } + +/** + * Insert a link in place of another, without changing it's position in the list. + * + * Puts `vnewlink` in the position of `vreplacelink`, removing `vreplacelink`. + * - `vreplacelink` *must* be in the list. + * - `vnewlink` *must not* be in the list. + */ +void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlink) +{ + Link *l_old = vreplacelink; + Link *l_new = vnewlink; + + /* update adjacent links */ + if (l_old->next != NULL) { + l_old->next->prev = l_new; + } + if (l_old->prev != NULL) { + l_old->prev->next = l_new; + } + + /* set direct links */ + l_new->next = l_old->next; + l_new->prev = l_old->prev; + + /* update list */ + if (listbase->first == l_old) { + listbase->first = l_new; + } + if (listbase->last == l_old) { + listbase->last = l_new; + } +} + /** * Reinsert \a vlink relative to its current position but offset by \a step. Doesn't move * item if new position would exceed list (could optionally move to head/tail). @@ -630,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 4e20872cb51..630eaed05db 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)); } @@ -2851,6 +2851,9 @@ bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[ /** * \note: using #cross_tri_v2 means locations outside the triangle are correctly weighted + * + * \note This is *exactly* the same calculation as #resolve_tri_uv_v2, + * although it has double precision and is used for texture baking, so keep both. */ void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]) { @@ -2890,9 +2893,11 @@ void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const fl } } -/* same as #barycentric_weights_v2 but works with a quad, +/** + * same as #barycentric_weights_v2 but works with a quad, * note: untested for values outside the quad's bounds - * this is #interp_weights_poly_v2 expanded for quads only */ + * this is #interp_weights_poly_v2 expanded for quads only + */ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const float v3[2], const float v4[2], const float co[2], float w[4]) { @@ -3345,6 +3350,8 @@ void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3 * Barycentric reverse * * Compute coordinates (u, v) for point \a st with respect to triangle (\a st0, \a st1, \a st2) + * + * \note same basic result as #barycentric_weights_v2, see it's comment for details. */ void resolve_tri_uv_v2(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]) 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/path_util.c b/source/blender/blenlib/intern/path_util.c index 6644e6605a1..4b3a74d02ae 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1167,52 +1167,16 @@ bool BLI_path_program_search( } /** - * Copies into *last the part of *dir following the second-last slash. - */ -void BLI_getlastdir(const char *dir, char *last, const size_t maxlen) -{ - const char *s = dir; - const char *lslash = NULL; - const char *prevslash = NULL; - while (*s) { - if ((*s == '\\') || (*s == '/')) { - prevslash = lslash; - lslash = s; - } - s++; - } - if (prevslash) { - BLI_strncpy(last, prevslash + 1, maxlen); - } - else { - BLI_strncpy(last, dir, maxlen); - } -} - - -/** * Sets the specified environment variable to the specified value, * and clears it if val == NULL. */ 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) @@ -1258,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); } /** @@ -1615,6 +1581,90 @@ void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__r } /** + * Join multiple strings into a path, ensuring only a single path separator between each, + * and trailing slash is kept. + * + * \note If you want a trailing slash, add ``SEP_STR`` as the last path argument, + * duplicate slashes will be cleaned up. + */ +size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...) +{ + if (UNLIKELY(dst_len == 0)) { + return 0; + } + const size_t dst_last = dst_len - 1; + size_t ofs = BLI_strncpy_rlen(dst, path, dst_len); + + if (ofs == dst_last) { + return ofs; + } + + /* remove trailing slashes, unless there are _only_ trailing slashes + * (allow "//" as the first argument). */ + bool has_trailing_slash = false; + if (ofs != 0) { + size_t len = ofs; + while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { + len -= 1; + } + if (len != 0) { + ofs = len; + } + has_trailing_slash = (path[len] != '\0'); + } + + va_list args; + va_start(args, path); + while ((path = (const char *) va_arg(args, const char *))) { + has_trailing_slash = false; + const char *path_init = path; + while (ELEM(path[0], SEP, ALTSEP)) { + path++; + } + size_t len = strlen(path); + if (len != 0) { + while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { + len -= 1; + } + + if (len != 0) { + /* the very first path may have a slash at the end */ + if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) { + dst[ofs++] = SEP; + if (ofs == dst_last) { + break; + } + } + has_trailing_slash = (path[len] != '\0'); + if (ofs + len >= dst_last) { + len = dst_last - ofs; + } + memcpy(&dst[ofs], path, len); + ofs += len; + if (ofs == dst_last) { + break; + } + } + } + else { + has_trailing_slash = (path_init != path); + } + } + va_end(args); + + if (has_trailing_slash) { + if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) { + dst[ofs++] = SEP; + } + } + + BLI_assert(ofs <= dst_last); + dst[ofs] = '\0'; + + return ofs; +} + +/** * like pythons os.path.basename() * * \return The pointer into \a path string immediately after last slash, @@ -1626,6 +1676,71 @@ const char *BLI_path_basename(const char *path) return filename ? filename + 1 : path; } +/** + * Get an element of the path at an index, eg: + * "/some/path/file.txt" where an index of... + * - 0 or -3: "some" + * - 1 or -2: "path" + * - 2 or -1: "file.txt" + * + * Ignores multiple slashes at any point in the path (including start/end). + */ +bool BLI_path_name_at_index(const char *path, const int index, int *r_offset, int *r_len) +{ + if (index >= 0) { + int index_step = 0; + int prev = -1; + int i = 0; + while (true) { + const char c = path[i]; + if (ELEM(c, SEP, ALTSEP, '\0')) { + if (prev + 1 != i) { + prev += 1; + if (index_step == index) { + *r_offset = prev; + *r_len = i - prev; + /* printf("!!! %d %d\n", start, end); */ + return true; + } + index_step += 1; + } + if (c == '\0') { + break; + } + prev = i; + } + i += 1; + } + return false; + } + else { + /* negative number, reverse where -1 is the last element */ + int index_step = -1; + int prev = strlen(path); + int i = prev - 1; + while (true) { + const char c = i >= 0 ? path[i] : '\0'; + if (ELEM(c, SEP, ALTSEP, '\0')) { + if (prev - 1 != i) { + i += 1; + if (index_step == index) { + *r_offset = i; + *r_len = prev - i; + return true; + } + index_step -= 1; + } + if (c == '\0') { + break; + } + prev = i; + } + i -= 1; + } + return false; + } +} + /* UNUSED */ #if 0 /** 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 17e20f8fa18..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); } @@ -743,9 +854,7 @@ void BLI_task_pool_work_and_wait(TaskPool *pool) BLI_condition_notify_all(&scheduler->queue_cond); BLI_mutex_unlock(&scheduler->queue_mutex); - } - pool->is_suspended = false; } pool->do_work = true; @@ -779,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); @@ -834,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 */ /** @@ -992,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/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index c85cf128643..e6fc4703248 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -71,11 +71,25 @@ typedef struct BlendFileData { BlenFileType type; } BlendFileData; -BlendFileData *BLO_read_from_file(const char *filepath, struct ReportList *reports); -BlendFileData *BLO_read_from_memory(const void *mem, int memsize, struct ReportList *reports); + +/* skip reading some data-block types (may want to skip screen data too). */ +typedef enum eBLOReadSkip { + BLO_READ_SKIP_NONE = 0, + BLO_READ_SKIP_USERDEF = (1 << 0), + BLO_READ_SKIP_DATA = (1 << 1), +} eBLOReadSkip; +#define BLO_READ_SKIP_ALL \ + (BLO_READ_SKIP_USERDEF | BLO_READ_SKIP_DATA) + +BlendFileData *BLO_read_from_file( + const char *filepath, + struct ReportList *reports, eBLOReadSkip skip_flag); +BlendFileData *BLO_read_from_memory( + const void *mem, int memsize, + struct ReportList *reports, eBLOReadSkip skip_flag); BlendFileData *BLO_read_from_memfile( struct Main *oldmain, const char *filename, struct MemFile *memfile, - struct ReportList *reports); + struct ReportList *reports, eBLOReadSkip skip_flag); void BLO_blendfiledata_free(BlendFileData *bfd); diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 8cb9ef837b2..3d2e8a306de 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -69,6 +69,12 @@ if(WITH_BUILDINFO) add_definitions(-DWITH_BUILDINFO) endif() +if(WITH_PYTHON) + if(WITH_PYTHON_SECURITY) + add_definitions(-DWITH_PYTHON_SECURITY) + endif() +endif() + if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index be893177b3b..73109413271 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -317,7 +317,9 @@ void BLO_blendhandle_close(BlendHandle *bh) * \param reports If the return value is NULL, errors indicating the cause of the failure. * \return The data of the file. */ -BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports) +BlendFileData *BLO_read_from_file( + const char *filepath, + ReportList *reports, eBLOReadSkip skip_flags) { BlendFileData *bfd = NULL; FileData *fd; @@ -325,6 +327,7 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports) fd = blo_openblenderfile(filepath, reports); if (fd) { fd->reports = reports; + fd->skip_flags = skip_flags; bfd = blo_read_file_internal(fd, filepath); blo_freefiledata(fd); } @@ -341,7 +344,9 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports) * \param reports If the return value is NULL, errors indicating the cause of the failure. * \return The data of the file. */ -BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *reports) +BlendFileData *BLO_read_from_memory( + const void *mem, int memsize, + ReportList *reports, eBLOReadSkip skip_flags) { BlendFileData *bfd = NULL; FileData *fd; @@ -349,6 +354,7 @@ BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *re fd = blo_openblendermemory(mem, memsize, reports); if (fd) { fd->reports = reports; + fd->skip_flags = skip_flags; bfd = blo_read_file_internal(fd, ""); blo_freefiledata(fd); } @@ -362,7 +368,9 @@ BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *re * \param oldmain old main, from which we will keep libraries and other datablocks that should not have changed. * \param filename current file, only for retrieving library data. */ -BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFile *memfile, ReportList *reports) +BlendFileData *BLO_read_from_memfile( + Main *oldmain, const char *filename, MemFile *memfile, + ReportList *reports, eBLOReadSkip skip_flags) { BlendFileData *bfd = NULL; FileData *fd; @@ -371,6 +379,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil fd = blo_openblendermemfile(memfile, reports); if (fd) { fd->reports = reports; + fd->skip_flags = skip_flags; BLI_strncpy(fd->relabase, filename, sizeof(fd->relabase)); /* clear ob->proxy_from pointers in old main */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 638f877c841..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 *************** */ @@ -2192,19 +2233,19 @@ static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap) /* library brush linking after fileread */ static void lib_link_brush(FileData *fd, Main *main) { - Brush *brush; - /* only link ID pointers */ - for (brush = main->brush.first; brush; brush = brush->id.next) { + for (Brush *brush = main->brush.first; brush; brush = brush->id.next) { if (brush->id.tag & LIB_TAG_NEED_LINK) { - brush->id.tag &= ~LIB_TAG_NEED_LINK; - + 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); brush->mask_mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mask_mtex.tex); brush->clone.image = newlibadr(fd, brush->id.lib, brush->clone.image); brush->toggle_brush = newlibadr(fd, brush->id.lib, brush->toggle_brush); brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve); + + brush->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -2227,13 +2268,13 @@ static void direct_link_brush(FileData *fd, Brush *brush) } /* ************ READ Palette *************** */ -static void lib_link_palette(FileData *UNUSED(fd), Main *main) +static void lib_link_palette(FileData *fd, Main *main) { - Palette *palette; - /* only link ID pointers */ - for (palette = main->palettes.first; palette; palette = palette->id.next) { + 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); + palette->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -2245,13 +2286,13 @@ static void direct_link_palette(FileData *fd, Palette *palette) link_list(fd, &palette->colors); } -static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main) +static void lib_link_paint_curve(FileData *fd, Main *main) { - PaintCurve *pc; - /* only link ID pointers */ - for (pc = main->paintcurves.first; pc; pc = pc->id.next) { + 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); + pc->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -2503,15 +2544,12 @@ static void direct_link_fcurves(FileData *fd, ListBase *list) static void lib_link_action(FileData *fd, Main *main) { - bAction *act; - bActionChannel *chan; - - for (act = main->action.first; act; act = act->id.next) { + for (bAction *act = main->action.first; act; act = act->id.next) { if (act->id.tag & LIB_TAG_NEED_LINK) { - act->id.tag &= ~LIB_TAG_NEED_LINK; + IDP_LibLinkProperty(act->id.properties, fd); // XXX deprecated - old animation system <<< - for (chan=act->chanbase.first; chan; chan=chan->next) { + for (bActionChannel *chan = act->chanbase.first; chan; chan = chan->next) { chan->ipo = newlibadr_us(fd, act->id.lib, chan->ipo); lib_link_constraint_channels(fd, &act->id, &chan->constraintChannels); } @@ -2524,6 +2562,8 @@ static void lib_link_action(FileData *fd, Main *main) marker->camera = newlibadr(fd, act->id.lib, marker->camera); } } + + act->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -2710,26 +2750,20 @@ static void direct_link_animdata(FileData *fd, AnimData *adt) static void lib_link_cachefiles(FileData *fd, Main *bmain) { - CacheFile *cache_file; - /* only link ID pointers */ - for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) { + for (CacheFile *cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) { if (cache_file->id.tag & LIB_TAG_NEED_LINK) { - cache_file->id.tag &= ~LIB_TAG_NEED_LINK; - } - - BLI_listbase_clear(&cache_file->object_paths); - cache_file->handle = NULL; - cache_file->handle_mutex = NULL; - - if (cache_file->adt) { + 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; } } } static void direct_link_cachefile(FileData *fd, CacheFile *cache_file) { + BLI_listbase_clear(&cache_file->object_paths); cache_file->handle = NULL; cache_file->handle_mutex = NULL; @@ -2753,19 +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); lib_link_animdata(fd, &ntree->id, ntree->adt); ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd); @@ -2773,32 +2801,35 @@ 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); + node->id = newlibadr_us(fd, id->lib, node->id); - for (sock = node->inputs.first; sock; sock = sock->next) - lib_link_node_socket(fd, id, sock); - for (sock = node->outputs.first; sock; sock = sock->next) - lib_link_node_socket(fd, id, sock); + for (sock = node->inputs.first; sock; sock = sock->next) { + IDP_LibLinkProperty(sock->prop, fd); + } + for (sock = node->outputs.first; sock; sock = sock->next) { + IDP_LibLinkProperty(sock->prop, fd); + } } - for (sock = ntree->inputs.first; sock; sock = sock->next) - lib_link_node_socket(fd, id, sock); - for (sock = ntree->outputs.first; sock; sock = sock->next) - lib_link_node_socket(fd, id, sock); + for (sock = ntree->inputs.first; sock; sock = sock->next) { + IDP_LibLinkProperty(sock->prop, fd); + } + for (sock = ntree->outputs.first; sock; sock = sock->next) { + IDP_LibLinkProperty(sock->prop, fd); + } } /* library ntree linking after fileread */ static void lib_link_nodetree(FileData *fd, Main *main) { - bNodeTree *ntree; - /* only link ID pointers */ - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { + for (bNodeTree *ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { if (ntree->id.tag & LIB_TAG_NEED_LINK) { - ntree->id.tag &= ~LIB_TAG_NEED_LINK; lib_link_ntree(fd, &ntree->id, ntree); + + ntree->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -3089,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) { @@ -3291,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; @@ -3311,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) { - bArmature *arm; - - for (arm = main->armature.first; arm; arm = arm->id.next) { + 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); 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; } } @@ -3362,14 +3408,13 @@ static void direct_link_armature(FileData *fd, bArmature *arm) static void lib_link_camera(FileData *fd, Main *main) { - Camera *ca; - - for (ca = main->camera.first; ca; ca = ca->id.next) { + 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); lib_link_animdata(fd, &ca->id, ca->adt); ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX deprecated - old animation system - + ca->dof_ob = newlibadr(fd, ca->id.lib, ca->dof_ob); ca->id.tag &= ~LIB_TAG_NEED_LINK; @@ -3388,16 +3433,13 @@ static void direct_link_camera(FileData *fd, Camera *ca) static void lib_link_lamp(FileData *fd, Main *main) { - Lamp *la; - MTex *mtex; - int a; - - for (la = main->lamp.first; la; la = la->id.next) { + 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); lib_link_animdata(fd, &la->id, la->adt); - for (a = 0; a < MAX_MTEX; a++) { - mtex = la->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = la->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, la->id.lib, mtex->tex); mtex->object = newlibadr(fd, la->id.lib, mtex->object); @@ -3454,17 +3496,11 @@ void blo_do_versions_key_uidgen(Key *key) static void lib_link_key(FileData *fd, Main *main) { - Key *key; - - for (key = main->key.first; key; key = key->id.next) { - /*check if we need to generate unique ids for the shapekeys*/ - if (!key->uidgen) { - blo_do_versions_key_uidgen(key); - } - + for (Key *key = main->key.first; key; key = key->id.next) { BLI_assert((key->id.tag & LIB_TAG_EXTERN) == 0); if (key->id.tag & LIB_TAG_NEED_LINK) { + 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 @@ -3527,15 +3563,14 @@ static void direct_link_key(FileData *fd, Key *key) static void lib_link_mball(FileData *fd, Main *main) { - MetaBall *mb; - int a; - - for (mb = main->mball.first; mb; mb = mb->id.next) { + 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); lib_link_animdata(fd, &mb->id, mb->adt); - for (a = 0; a < mb->totcol; a++) + for (int a = 0; a < mb->totcol; a++) { mb->mat[a] = newlibadr_us(fd, mb->id.lib, mb->mat[a]); + } mb->ipo = newlibadr_us(fd, mb->id.lib, mb->ipo); // XXX deprecated - old animation system @@ -3564,18 +3599,15 @@ static void direct_link_mball(FileData *fd, MetaBall *mb) static void lib_link_world(FileData *fd, Main *main) { - World *wrld; - MTex *mtex; - int a; - - for (wrld = main->world.first; wrld; wrld = wrld->id.next) { + 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); lib_link_animdata(fd, &wrld->id, wrld->adt); wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX deprecated - old animation system - for (a=0; a < MAX_MTEX; a++) { - mtex = wrld->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = wrld->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, wrld->id.lib, mtex->tex); mtex->object = newlibadr(fd, wrld->id.lib, mtex->object); @@ -3616,12 +3648,12 @@ static void direct_link_world(FileData *fd, World *wrld) /* ************ READ VFONT ***************** */ -static void lib_link_vfont(FileData *UNUSED(fd), Main *main) +static void lib_link_vfont(FileData *fd, Main *main) { - VFont *vf; - - for (vf = main->vfont.first; vf; vf = vf->id.next) { + 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); + vf->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -3636,12 +3668,12 @@ static void direct_link_vfont(FileData *fd, VFont *vf) /* ************ READ TEXT ****************** */ -static void lib_link_text(FileData *UNUSED(fd), Main *main) +static void lib_link_text(FileData *fd, Main *main) { - Text *text; - - for (text = main->text.first; text; text = text->id.next) { + 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); + text->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -3690,11 +3722,9 @@ static void direct_link_text(FileData *fd, Text *text) static void lib_link_image(FileData *fd, Main *main) { - Image *ima; - - for (ima = main->image.first; ima; ima = ima->id.next) { + 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; } @@ -3759,15 +3789,14 @@ static void direct_link_image(FileData *fd, Image *ima) static void lib_link_curve(FileData *fd, Main *main) { - Curve *cu; - int a; - - for (cu = main->curve.first; cu; cu = cu->id.next) { + 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); lib_link_animdata(fd, &cu->id, cu->adt); - for (a = 0; a < cu->totcol; a++) + for (int a = 0; a < cu->totcol; a++) { cu->mat[a] = newlibadr_us(fd, cu->id.lib, cu->mat[a]); + } cu->bevobj = newlibadr(fd, cu->id.lib, cu->bevobj); cu->taperobj = newlibadr(fd, cu->id.lib, cu->taperobj); @@ -3852,10 +3881,9 @@ static void direct_link_curve(FileData *fd, Curve *cu) static void lib_link_texture(FileData *fd, Main *main) { - Tex *tex; - - for (tex = main->tex.first; tex; tex = tex->id.next) { + 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); lib_link_animdata(fd, &tex->id, tex->adt); tex->ima = newlibadr_us(fd, tex->id.lib, tex->ima); @@ -3931,23 +3959,20 @@ static void direct_link_texture(FileData *fd, Tex *tex) static void lib_link_material(FileData *fd, Main *main) { - Material *ma; - MTex *mtex; - int a; - - for (ma = main->mat.first; ma; ma = ma->id.next) { + 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); 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); - for (a = 0; a < MAX_MTEX; a++) { - mtex = ma->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = ma->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, ma->id.lib, mtex->tex); mtex->object = newlibadr(fd, ma->id.lib, mtex->object); @@ -4078,14 +4103,11 @@ static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd) static void lib_link_particlesettings(FileData *fd, Main *main) { - ParticleSettings *part; - ParticleDupliWeight *dw; - MTex *mtex; - int a; - - for (part = main->particle.first; part; part = part->id.next) { + 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); lib_link_animdata(fd, &part->id, part->adt); + part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX deprecated - old animation system part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob); @@ -4105,6 +4127,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main) } if (part->dupliweights.first && part->dup_group) { + ParticleDupliWeight *dw; int index_ok = 0; /* check for old files without indices (all indexes 0) */ if (BLI_listbase_is_single(&part->dupliweights)) { @@ -4169,8 +4192,8 @@ static void lib_link_particlesettings(FileData *fd, Main *main) } } - for (a = 0; a < MAX_MTEX; a++) { - mtex= part->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex= part->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, part->id.lib, mtex->tex); mtex->object = newlibadr(fd, part->id.lib, mtex->object); @@ -4404,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 */ @@ -4677,10 +4700,9 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) static void lib_link_latt(FileData *fd, Main *main) { - Lattice *lt; - - for (lt = main->latt.first; lt; lt = lt->id.next) { + 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); lib_link_animdata(fd, <->id, lt->adt); lt->ipo = newlibadr_us(fd, lt->id.lib, lt->ipo); // XXX deprecated - old animation system @@ -4724,17 +4746,13 @@ static void lib_link_modifiers(FileData *fd, Object *ob) static void lib_link_object(FileData *fd, Main *main) { - Object *ob; - PartEff *paf; - bSensor *sens; - bController *cont; - bActuator *act; - void *poin; - int warn=0, a; - - for (ob = main->object.first; ob; ob = ob->id.next) { + bool warn = false; + + for (Object *ob = main->object.first; ob; ob = ob->id.next) { if (ob->id.tag & LIB_TAG_NEED_LINK) { - IDP_LibLinkProperty(ob->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + int a; + + IDP_LibLinkProperty(ob->id.properties, fd); lib_link_animdata(fd, &ob->id, ob->adt); // XXX deprecated - old animation system <<< @@ -4766,17 +4784,17 @@ static void lib_link_object(FileData *fd, Main *main) } ob->proxy_group = newlibadr(fd, ob->id.lib, ob->proxy_group); - poin = ob->data; + void *poin = ob->data; ob->data = newlibadr_us(fd, ob->id.lib, ob->data); - if (ob->data==NULL && poin!=NULL) { + if (ob->data == NULL && poin != NULL) { if (ob->id.lib) printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->name); else printf("Object %s lost data.\n", ob->id.name + 2); ob->type = OB_EMPTY; - warn = 1; + warn = true; if (ob->pose) { /* we can't call #BKE_pose_free() here because of library linking @@ -4822,13 +4840,13 @@ static void lib_link_object(FileData *fd, Main *main) lib_link_nlastrips(fd, &ob->id, &ob->nlastrips); // >>> XXX deprecated - old animation system - for (paf = ob->effect.first; paf; paf = paf->next) { + for (PartEff *paf = ob->effect.first; paf; paf = paf->next) { if (paf->type == EFF_PARTICLE) { paf->group = newlibadr_us(fd, ob->id.lib, paf->group); } } - for (sens = ob->sensors.first; sens; sens = sens->next) { + for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) { for (a = 0; a < sens->totlinks; a++) sens->links[a] = newglobadr(fd, sens->links[a]); @@ -4839,7 +4857,7 @@ static void lib_link_object(FileData *fd, Main *main) } } - for (cont = ob->controllers.first; cont; cont = cont->next) { + for (bController *cont = ob->controllers.first; cont; cont = cont->next) { for (a=0; a < cont->totlinks; a++) cont->links[a] = newglobadr(fd, cont->links[a]); @@ -4851,86 +4869,117 @@ static void lib_link_object(FileData *fd, Main *main) cont->totslinks = 0; } - for (act = ob->actuators.first; act; act = act->next) { - if (act->type == ACT_SOUND) { - bSoundActuator *sa = act->data; - sa->sound= newlibadr_us(fd, ob->id.lib, sa->sound); - } - else if (act->type == ACT_GAME) { - /* bGameActuator *ga= act->data; */ - } - else if (act->type == ACT_CAMERA) { - bCameraActuator *ca = act->data; - ca->ob= newlibadr(fd, ob->id.lib, ca->ob); - } - /* leave this one, it's obsolete but necessary to read for conversion */ - else if (act->type == ACT_ADD_OBJECT) { - bAddObjectActuator *eoa = act->data; - if (eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob); - } - else if (act->type == ACT_OBJECT) { - bObjectActuator *oa = act->data; - if (oa == NULL) { - init_actuator(act); + for (bActuator *act = ob->actuators.first; act; act = act->next) { + switch (act->type) { + case ACT_SOUND: + { + bSoundActuator *sa = act->data; + sa->sound = newlibadr_us(fd, ob->id.lib, sa->sound); + break; } - else { - oa->reference = newlibadr(fd, ob->id.lib, oa->reference); + case ACT_GAME: + /* bGameActuator *ga= act->data; */ + break; + case ACT_CAMERA: + { + bCameraActuator *ca = act->data; + ca->ob = newlibadr(fd, ob->id.lib, ca->ob); + break; } - } - else if (act->type == ACT_EDIT_OBJECT) { - bEditObjectActuator *eoa = act->data; - if (eoa == NULL) { - init_actuator(act); + /* leave this one, it's obsolete but necessary to read for conversion */ + case ACT_ADD_OBJECT: + { + bAddObjectActuator *eoa = act->data; + if (eoa) + eoa->ob = newlibadr(fd, ob->id.lib, eoa->ob); + break; } - else { - eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob); - eoa->me= newlibadr(fd, ob->id.lib, eoa->me); + case ACT_OBJECT: + { + bObjectActuator *oa = act->data; + if (oa == NULL) { + init_actuator(act); + } + else { + oa->reference = newlibadr(fd, ob->id.lib, oa->reference); + } + break; } - } - else if (act->type == ACT_SCENE) { - bSceneActuator *sa = act->data; - sa->camera= newlibadr(fd, ob->id.lib, sa->camera); - sa->scene= newlibadr(fd, ob->id.lib, sa->scene); - } - else if (act->type == ACT_ACTION) { - bActionActuator *aa = act->data; - aa->act= newlibadr_us(fd, ob->id.lib, aa->act); - } - else if (act->type == ACT_SHAPEACTION) { - bActionActuator *aa = act->data; - aa->act= newlibadr_us(fd, ob->id.lib, aa->act); - } - else if (act->type == ACT_PROPERTY) { - bPropertyActuator *pa = act->data; - pa->ob= newlibadr(fd, ob->id.lib, pa->ob); - } - else if (act->type == ACT_MESSAGE) { - bMessageActuator *ma = act->data; - ma->toObject= newlibadr(fd, ob->id.lib, ma->toObject); - } - else if (act->type == ACT_2DFILTER) { - bTwoDFilterActuator *_2dfa = act->data; - _2dfa->text= newlibadr(fd, ob->id.lib, _2dfa->text); - } - else if (act->type == ACT_PARENT) { - bParentActuator *parenta = act->data; - parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob); - } - else if (act->type == ACT_STATE) { - /* bStateActuator *statea = act->data; */ - } - else if (act->type == ACT_ARMATURE) { - bArmatureActuator *arma= act->data; - arma->target= newlibadr(fd, ob->id.lib, arma->target); - arma->subtarget= newlibadr(fd, ob->id.lib, arma->subtarget); - } - else if (act->type == ACT_STEERING) { - bSteeringActuator *steeringa = act->data; - steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target); - steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh); - } - else if (act->type == ACT_MOUSE) { - /* bMouseActuator *moa= act->data; */ + case ACT_EDIT_OBJECT: + { + bEditObjectActuator *eoa = act->data; + if (eoa == NULL) { + init_actuator(act); + } + else { + eoa->ob = newlibadr(fd, ob->id.lib, eoa->ob); + eoa->me = newlibadr(fd, ob->id.lib, eoa->me); + } + break; + } + case ACT_SCENE: + { + bSceneActuator *sa = act->data; + sa->camera = newlibadr(fd, ob->id.lib, sa->camera); + sa->scene = newlibadr(fd, ob->id.lib, sa->scene); + break; + } + case ACT_ACTION: + { + bActionActuator *aa = act->data; + aa->act = newlibadr_us(fd, ob->id.lib, aa->act); + break; + } + case ACT_SHAPEACTION: + { + bActionActuator *aa = act->data; + aa->act = newlibadr_us(fd, ob->id.lib, aa->act); + break; + } + case ACT_PROPERTY: + { + bPropertyActuator *pa = act->data; + pa->ob = newlibadr(fd, ob->id.lib, pa->ob); + break; + } + case ACT_MESSAGE: + { + bMessageActuator *ma = act->data; + ma->toObject = newlibadr(fd, ob->id.lib, ma->toObject); + break; + } + case ACT_2DFILTER: + { + bTwoDFilterActuator *_2dfa = act->data; + _2dfa->text = newlibadr(fd, ob->id.lib, _2dfa->text); + break; + } + case ACT_PARENT: + { + bParentActuator *parenta = act->data; + parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob); + break; + } + case ACT_STATE: + /* bStateActuator *statea = act->data; */ + break; + case ACT_ARMATURE: + { + bArmatureActuator *arma= act->data; + arma->target = newlibadr(fd, ob->id.lib, arma->target); + arma->subtarget = newlibadr(fd, ob->id.lib, arma->subtarget); + break; + } + case ACT_STEERING: + { + bSteeringActuator *steeringa = act->data; + steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target); + steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh); + break; + } + case ACT_MOUSE: + /* bMouseActuator *moa = act->data; */ + break; } } @@ -5662,23 +5711,16 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene) static void lib_link_scene(FileData *fd, Main *main) { - Scene *sce; - Base *base, *next; - Sequence *seq; - SceneRenderLayer *srl; - FreestyleModuleConfig *fmc; - FreestyleLineSet *fls; - #ifdef USE_SETSCENE_CHECK bool need_check_set = false; int totscene = 0; #endif - for (sce = main->scene.first; sce; sce = sce->id.next) { + for (Scene *sce = main->scene.first; sce; sce = sce->id.next) { 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); @@ -5714,7 +5756,7 @@ static void lib_link_scene(FileData *fd, Main *main) sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object); - for (base = sce->base.first; base; base = next) { + for (Base *next, *base = sce->base.first; base; base = next) { next = base->next; base->object = newlibadr_us(fd, sce->id.lib, base->object); @@ -5728,8 +5770,11 @@ 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) { @@ -5793,13 +5838,13 @@ static void lib_link_scene(FileData *fd, Main *main) composite_patch(sce->nodetree, sce); } - for (srl = sce->r.layers.first; srl; srl = srl->next) { + for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) { srl->mat_override = newlibadr_us(fd, sce->id.lib, srl->mat_override); srl->light_override = newlibadr_us(fd, sce->id.lib, srl->light_override); - for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { + for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { fmc->script = newlibadr(fd, sce->id.lib, fmc->script); } - for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { + for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle); fls->group = newlibadr_us(fd, sce->id.lib, fls->group); } @@ -5833,7 +5878,7 @@ static void lib_link_scene(FileData *fd, Main *main) #ifdef USE_SETSCENE_CHECK if (need_check_set) { - for (sce = main->scene.first; sce; sce = sce->id.next) { + for (Scene *sce = main->scene.first; sce; sce = sce->id.next) { if (sce->id.tag & LIB_TAG_NEED_LINK) { sce->id.tag &= ~LIB_TAG_NEED_LINK; if (!scene_validate_setscene__liblink(sce, totscene)) { @@ -6051,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; @@ -6128,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)); } @@ -6243,8 +6297,10 @@ static void lib_link_windowmanager(FileData *fd, Main *main) for (wm = main->wm.first; wm; wm = wm->id.next) { if (wm->id.tag & LIB_TAG_NEED_LINK) { - for (win = wm->windows.first; win; win = win->next) + /* Note: WM IDProperties are never written to file, hence no need to read/link them here. */ + for (win = wm->windows.first; win; win = win->next) { win->screen = newlibadr(fd, NULL, win->screen); + } wm->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -6256,13 +6312,12 @@ static void lib_link_windowmanager(FileData *fd, Main *main) /* relink's grease pencil data's refs */ static void lib_link_gpencil(FileData *fd, Main *main) { - bGPdata *gpd; - - for (gpd = main->gpencil.first; gpd; gpd = gpd->id.next) { + for (bGPdata *gpd = main->gpencil.first; gpd; gpd = gpd->id.next) { if (gpd->id.tag & LIB_TAG_NEED_LINK) { - gpd->id.tag &= ~LIB_TAG_NEED_LINK; - + IDP_LibLinkProperty(gpd->id.properties, fd); lib_link_animdata(fd, &gpd->id, gpd->adt); + + gpd->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -6324,12 +6379,11 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd) * check lib pointers in call below */ static void lib_link_screen(FileData *fd, Main *main) { - bScreen *sc; - ScrArea *sa; - - for (sc = main->screen.first; sc; sc = sc->id.next) { + 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); id_us_ensure_real(&sc->id); + sc->scene = newlibadr(fd, sc->id.lib, sc->scene); /* this should not happen, but apparently it does somehow. Until we figure out the cause, @@ -6340,177 +6394,204 @@ static void lib_link_screen(FileData *fd, Main *main) sc->animtimer = NULL; /* saved in rare cases */ sc->scrubbing = false; - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { sa->full = newlibadr(fd, sc->id.lib, sa->full); - for (sl = sa->spacedata.first; sl; sl= sl->next) { - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D*) sl; - BGpic *bgpic = NULL; - - v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera); - v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre); - - /* should be do_versions but not easy adding into the listbase */ - if (v3d->bgpic) { - v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic); - BLI_addtail(&v3d->bgpicbase, bgpic); - v3d->bgpic = NULL; + for (SpaceLink *sl = sa->spacedata.first; sl; sl= sl->next) { + switch (sl->spacetype) { + case SPACE_VIEW3D: + { + View3D *v3d = (View3D*) sl; + BGpic *bgpic = NULL; + + v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera); + v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre); + + /* should be do_versions but not easy adding into the listbase */ + if (v3d->bgpic) { + v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic); + BLI_addtail(&v3d->bgpicbase, bgpic); + v3d->bgpic = NULL; + } + + for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { + bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima); + bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip); + } + if (v3d->localvd) { + v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera); + } + break; } - - for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima); - bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip); + case SPACE_IPO: + { + SpaceIpo *sipo = (SpaceIpo *)sl; + bDopeSheet *ads = sipo->ads; + + if (ads) { + ads->source = newlibadr(fd, sc->id.lib, ads->source); + ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + } + break; } - if (v3d->localvd) { - v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera); + case SPACE_BUTS: + { + SpaceButs *sbuts = (SpaceButs *)sl; + sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid); + if (sbuts->pinid == NULL) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } + break; } - } - else if (sl->spacetype == SPACE_IPO) { - SpaceIpo *sipo = (SpaceIpo *)sl; - bDopeSheet *ads = sipo->ads; - - if (ads) { - ads->source = newlibadr(fd, sc->id.lib, ads->source); - ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + case SPACE_FILE: + break; + case SPACE_ACTION: + { + SpaceAction *saction = (SpaceAction *)sl; + bDopeSheet *ads = &saction->ads; + + if (ads) { + ads->source = newlibadr(fd, sc->id.lib, ads->source); + ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + } + + saction->action = newlibadr(fd, sc->id.lib, saction->action); + break; } - } - else if (sl->spacetype == SPACE_BUTS) { - SpaceButs *sbuts = (SpaceButs *)sl; - sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid); - if (sbuts->pinid == NULL) { - sbuts->flag &= ~SB_PIN_CONTEXT; + case SPACE_IMAGE: + { + SpaceImage *sima = (SpaceImage *)sl; + + sima->image = newlibadr_real_us(fd, sc->id.lib, sima->image); + sima->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sima->mask_info.mask); + + /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data + * so fingers crossed this works fine! + */ + sima->gpd = newlibadr_us(fd, sc->id.lib, sima->gpd); + break; } - } - else if (sl->spacetype == SPACE_FILE) { - ; - } - else if (sl->spacetype == SPACE_ACTION) { - SpaceAction *saction = (SpaceAction *)sl; - bDopeSheet *ads = &saction->ads; - - if (ads) { - ads->source = newlibadr(fd, sc->id.lib, ads->source); - ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + case SPACE_SEQ: + { + SpaceSeq *sseq = (SpaceSeq *)sl; + + /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data + * so fingers crossed this works fine! + */ + sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd); + break; } - - saction->action = newlibadr(fd, sc->id.lib, saction->action); - } - else if (sl->spacetype == SPACE_IMAGE) { - SpaceImage *sima = (SpaceImage *)sl; - - sima->image = newlibadr_real_us(fd, sc->id.lib, sima->image); - sima->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sima->mask_info.mask); - - /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data - * so fingers crossed this works fine! - */ - sima->gpd = newlibadr_us(fd, sc->id.lib, sima->gpd); - } - else if (sl->spacetype == SPACE_SEQ) { - SpaceSeq *sseq = (SpaceSeq *)sl; - - /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data - * so fingers crossed this works fine! - */ - sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd); + case SPACE_NLA: + { + SpaceNla *snla= (SpaceNla *)sl; + bDopeSheet *ads= snla->ads; + + if (ads) { + ads->source = newlibadr(fd, sc->id.lib, ads->source); + ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + } + break; + } + case SPACE_TEXT: + { + SpaceText *st= (SpaceText *)sl; - } - else if (sl->spacetype == SPACE_NLA) { - SpaceNla *snla= (SpaceNla *)sl; - bDopeSheet *ads= snla->ads; - - if (ads) { - ads->source = newlibadr(fd, sc->id.lib, ads->source); - ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + st->text= newlibadr(fd, sc->id.lib, st->text); + break; } - } - else if (sl->spacetype == SPACE_TEXT) { - SpaceText *st= (SpaceText *)sl; - - st->text= newlibadr(fd, sc->id.lib, st->text); - } - else if (sl->spacetype == SPACE_SCRIPT) { - SpaceScript *scpt = (SpaceScript *)sl; - /*scpt->script = NULL; - 2.45 set to null, better re-run the script */ - if (scpt->script) { - scpt->script = newlibadr(fd, sc->id.lib, scpt->script); + case SPACE_SCRIPT: + { + SpaceScript *scpt = (SpaceScript *)sl; + /*scpt->script = NULL; - 2.45 set to null, better re-run the script */ if (scpt->script) { - SCRIPT_SET_NULL(scpt->script); + scpt->script = newlibadr(fd, sc->id.lib, scpt->script); + if (scpt->script) { + SCRIPT_SET_NULL(scpt->script); + } } + break; } - } - else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOops *so= (SpaceOops *)sl; - so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id); - - if (so->treestore) { - TreeStoreElem *tselem; - BLI_mempool_iter iter; + case SPACE_OUTLINER: + { + SpaceOops *so= (SpaceOops *)sl; + so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id); + + if (so->treestore) { + TreeStoreElem *tselem; + BLI_mempool_iter iter; + + BLI_mempool_iternew(so->treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + tselem->id = newlibadr(fd, NULL, tselem->id); + } + if (so->treehash) { + /* rebuild hash table, because it depends on ids too */ + so->storeflag |= SO_TREESTORE_REBUILD; + } + } + break; + } + case SPACE_NODE: + { + SpaceNode *snode = (SpaceNode *)sl; + bNodeTreePath *path, *path_next; + bNodeTree *ntree; + + /* node tree can be stored locally in id too, link this first */ + snode->id = newlibadr(fd, sc->id.lib, snode->id); + snode->from = newlibadr(fd, sc->id.lib, snode->from); + + ntree = snode->id ? ntreeFromID(snode->id) : NULL; + snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree); + + for (path = snode->treepath.first; path; path = path->next) { + if (path == snode->treepath.first) { + /* first nodetree in path is same as snode->nodetree */ + path->nodetree = snode->nodetree; + } + else + path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree); - BLI_mempool_iternew(so->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - tselem->id = newlibadr(fd, NULL, tselem->id); + if (!path->nodetree) + break; } - if (so->treehash) { - /* rebuild hash table, because it depends on ids too */ - so->storeflag |= SO_TREESTORE_REBUILD; + + /* remaining path entries are invalid, remove */ + for (; path; path = path_next) { + path_next = path->next; + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); } - } - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - bNodeTreePath *path, *path_next; - bNodeTree *ntree; - - /* node tree can be stored locally in id too, link this first */ - snode->id = newlibadr(fd, sc->id.lib, snode->id); - snode->from = newlibadr(fd, sc->id.lib, snode->from); - - ntree = snode->id ? ntreeFromID(snode->id) : NULL; - snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree); - - for (path = snode->treepath.first; path; path = path->next) { - if (path == snode->treepath.first) { - /* first nodetree in path is same as snode->nodetree */ - path->nodetree = snode->nodetree; + + /* edittree is just the last in the path, + * set this directly since the path may have been shortened above */ + if (snode->treepath.last) { + path = snode->treepath.last; + snode->edittree = path->nodetree; } - else - path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree); - - if (!path->nodetree) - break; + else { + snode->edittree = NULL; + } + break; } - - /* remaining path entries are invalid, remove */ - for (; path; path = path_next) { - path_next = path->next; - - BLI_remlink(&snode->treepath, path); - MEM_freeN(path); + case SPACE_CLIP: + { + SpaceClip *sclip = (SpaceClip *)sl; + + sclip->clip = newlibadr_real_us(fd, sc->id.lib, sclip->clip); + sclip->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sclip->mask_info.mask); + break; } - - /* edittree is just the last in the path, - * set this directly since the path may have been shortened above */ - if (snode->treepath.last) { - path = snode->treepath.last; - snode->edittree = path->nodetree; + case SPACE_LOGIC: + { + SpaceLogic *slogic = (SpaceLogic *)sl; + + slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd); + break; } - else - snode->edittree = NULL; - } - else if (sl->spacetype == SPACE_CLIP) { - SpaceClip *sclip = (SpaceClip *)sl; - - sclip->clip = newlibadr_real_us(fd, sc->id.lib, sclip->clip); - sclip->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sclip->mask_info.mask); - } - else if (sl->spacetype == SPACE_LOGIC) { - SpaceLogic *slogic = (SpaceLogic *)sl; - - slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd); + default: + break; } } } @@ -7384,13 +7465,13 @@ static void fix_relpaths_library(const char *basepath, Main *main) static void lib_link_speaker(FileData *fd, Main *main) { - Speaker *spk; - - for (spk = main->speaker.first; spk; spk = spk->id.next) { + 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); lib_link_animdata(fd, &spk->id, spk->adt); spk->sound = newlibadr_us(fd, spk->id.lib, spk->sound); + spk->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -7440,14 +7521,15 @@ static void direct_link_sound(FileData *fd, bSound *sound) static void lib_link_sound(FileData *fd, Main *main) { - bSound *sound; - - for (sound = main->sound.first; sound; sound = sound->id.next) { + for (bSound *sound = main->sound.first; sound; sound = sound->id.next) { if (sound->id.tag & LIB_TAG_NEED_LINK) { - sound->id.tag &= ~LIB_TAG_NEED_LINK; + IDP_LibLinkProperty(sound->id.properties, fd); + sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system BKE_sound_load(main, sound); + + sound->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -7462,17 +7544,13 @@ static void direct_link_group(FileData *fd, Group *group) static void lib_link_group(FileData *fd, Main *main) { - Group *group; - GroupObject *go; - bool add_us; - - for (group = main->group.first; group; group = group->id.next) { + for (Group *group = main->group.first; group; group = group->id.next) { if (group->id.tag & LIB_TAG_NEED_LINK) { - group->id.tag &= ~LIB_TAG_NEED_LINK; + IDP_LibLinkProperty(group->id.properties, fd); - add_us = false; + bool add_us = false; - for (go = group->gobject.first; go; go = go->next) { + for (GroupObject *go = group->gobject.first; go; go = go->next) { go->ob = newlibadr_real_us(fd, group->id.lib, go->ob); if (go->ob) { go->ob->flag |= OB_FROMGROUP; @@ -7484,6 +7562,8 @@ static void lib_link_group(FileData *fd, Main *main) id_us_ensure_real(&group->id); } BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */ + + group->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -7588,13 +7668,11 @@ static void lib_link_moviePlaneTracks(FileData *fd, MovieClip *clip, ListBase *t static void lib_link_movieclip(FileData *fd, Main *main) { - MovieClip *clip; - - for (clip = main->movieclip.first; clip; clip = clip->id.next) { + for (MovieClip *clip = main->movieclip.first; clip; clip = clip->id.next) { if (clip->id.tag & LIB_TAG_NEED_LINK) { MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *object; + IDP_LibLinkProperty(clip->id.properties, fd); lib_link_animdata(fd, &clip->id, clip->adt); clip->gpd = newlibadr_us(fd, clip->id.lib, clip->gpd); @@ -7602,7 +7680,7 @@ static void lib_link_movieclip(FileData *fd, Main *main) lib_link_movieTracks(fd, clip, &tracking->tracks); lib_link_moviePlaneTracks(fd, clip, &tracking->plane_tracks); - for (object = tracking->objects.first; object; object = object->next) { + for (MovieTrackingObject *object = tracking->objects.first; object; object = object->next) { lib_link_movieTracks(fd, clip, &object->tracks); lib_link_moviePlaneTracks(fd, clip, &object->plane_tracks); } @@ -7679,16 +7757,12 @@ static void lib_link_mask_parent(FileData *fd, Mask *mask, MaskParent *parent) static void lib_link_mask(FileData *fd, Main *main) { - Mask *mask; - - mask = main->mask.first; - while (mask) { + for (Mask *mask = main->mask.first; mask; mask = mask->id.next) { if (mask->id.tag & LIB_TAG_NEED_LINK) { - MaskLayer *masklay; - + IDP_LibLinkProperty(mask->id.properties, fd); lib_link_animdata(fd, &mask->id, mask->adt); - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + for (MaskLayer *masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; spline = masklay->splines.first; @@ -7709,7 +7783,6 @@ static void lib_link_mask(FileData *fd, Main *main) mask->id.tag &= ~LIB_TAG_NEED_LINK; } - mask = mask->id.next; } } @@ -7717,18 +7790,13 @@ static void lib_link_mask(FileData *fd, Main *main) static void lib_link_linestyle(FileData *fd, Main *main) { - FreestyleLineStyle *linestyle; - LineStyleModifier *m; - MTex *mtex; - int a; - - linestyle = main->linestyle.first; - while (linestyle) { + for (FreestyleLineStyle *linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) { if (linestyle->id.tag & LIB_TAG_NEED_LINK) { - 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) { switch (m->type) { case LS_MODIFIER_DISTANCE_FROM_OBJECT: @@ -7759,8 +7827,8 @@ static void lib_link_linestyle(FileData *fd, Main *main) break; } } - for (a=0; a < MAX_MTEX; a++) { - mtex = linestyle->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = linestyle->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, linestyle->id.lib, mtex->tex); mtex->object = newlibadr(fd, linestyle->id.lib, mtex->object); @@ -7770,8 +7838,9 @@ static void lib_link_linestyle(FileData *fd, Main *main) lib_link_ntree(fd, &linestyle->id, linestyle->nodetree); linestyle->nodetree->id.lib = linestyle->id.lib; } + + linestyle->id.tag &= ~LIB_TAG_NEED_LINK; } - linestyle = linestyle->id.next; } } @@ -8442,12 +8511,13 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_screen(fd, main); lib_link_scene(fd, main); lib_link_object(fd, main); + lib_link_mesh(fd, main); lib_link_curve(fd, main); lib_link_mball(fd, main); lib_link_material(fd, main); lib_link_texture(fd, main); lib_link_image(fd, main); - lib_link_ipo(fd, main); // XXX deprecated... still needs to be maintained for version patches still + lib_link_ipo(fd, main); /* XXX deprecated... still needs to be maintained for version patches still */ lib_link_key(fd, main); lib_link_world(fd, main); lib_link_lamp(fd, main); @@ -8460,7 +8530,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_armature(fd, main); lib_link_action(fd, main); lib_link_vfont(fd, main); - lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */ + lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */ lib_link_brush(fd, main); lib_link_palette(fd, main); lib_link_paint_curve(fd, main); @@ -8471,9 +8541,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_gpencil(fd, main); lib_link_cachefiles(fd, main); - lib_link_mesh(fd, main); /* as last: tpage images with users at zero */ - - lib_link_library(fd, main); /* only init users */ + lib_link_library(fd, main); /* only init users */ } static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi) @@ -8597,7 +8665,12 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) bhead = read_global(bfd, fd, bhead); break; case USER: - bhead = read_userdef(bfd, fd, bhead); + if (fd->skip_flags & BLO_READ_SKIP_USERDEF) { + bhead = blo_nextbhead(fd, bhead); + } + else { + bhead = read_userdef(bfd, fd, bhead); + } break; case ENDB: bhead = NULL; @@ -8606,15 +8679,25 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) case ID_ID: /* Always adds to the most recently loaded ID_LI block, see direct_link_library. * This is part of the file format definition. */ - bhead = read_libblock(fd, mainlist.last, bhead, LIB_TAG_READ | LIB_TAG_EXTERN, NULL); + if (fd->skip_flags & BLO_READ_SKIP_DATA) { + bhead = blo_nextbhead(fd, bhead); + } + else { + bhead = read_libblock(fd, mainlist.last, bhead, LIB_TAG_READ | LIB_TAG_EXTERN, NULL); + } break; - /* 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: - bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, NULL); + if (fd->skip_flags & BLO_READ_SKIP_DATA) { + bhead = blo_nextbhead(fd, bhead); + } + else { + bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, NULL); + } } } @@ -8879,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; @@ -9064,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); @@ -9072,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) @@ -9293,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; @@ -9313,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( @@ -9558,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); @@ -9715,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); @@ -10041,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/readfile.h b/source/blender/blenloader/intern/readfile.h index d97bef13a78..62ce15a640e 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -81,6 +81,8 @@ typedef struct FileData { int id_name_offs; /* used to retrieve ID names from (bhead+1) */ int globalf, fileflags; /* for do_versions patching */ + eBLOReadSkip skip_flags; /* skip some data-blocks */ + struct OldNewMap *datamap; struct OldNewMap *globmap; struct OldNewMap *libmap; 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..d2f43a2d79e 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)) { @@ -1259,7 +1295,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 +1595,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 +1644,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 99d9e140481..e7e0054e7a1 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -68,6 +68,18 @@ void BLO_update_defaults_userpref_blend(void) * but take care since some hardware has driver bugs here (T46962). * Further hardware workarounds should be made in gpu_extensions.c */ U.glalphaclip = (1.0f / 255); + + /* default so DPI is detected automatically */ + U.dpi = 0; + U.ui_scale = 1.0f; + +#ifdef WITH_PYTHON_SECURITY + /* use alternative setting for security nuts + * otherwise we'd need to patch the binary blob - startup.blend.c */ + U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; +#else + U.flag &= ~USER_SCRIPT_AUTOEXEC_DISABLE; +#endif } /** @@ -230,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 01d07e0d774..ee9665dc834 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -797,26 +797,22 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) } } -static void write_actions(WriteData *wd, ListBase *idbase) +static void write_action(WriteData *wd, bAction *act) { - for (bAction *act = idbase->first; act; act = act->id.next) { - if (act->id.us > 0 || wd->current) { - writestruct(wd, ID_AC, bAction, 1, act); - write_iddata(wd, &act->id); + if (act->id.us > 0 || wd->current) { + writestruct(wd, ID_AC, bAction, 1, act); + write_iddata(wd, &act->id); - write_fcurves(wd, &act->curves); + write_fcurves(wd, &act->curves); - for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) { - writestruct(wd, DATA, bActionGroup, 1, grp); - } + for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) { + writestruct(wd, DATA, bActionGroup, 1, grp); + } - for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { - writestruct(wd, DATA, TimeMarker, 1, marker); - } + for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) { + writestruct(wd, DATA, TimeMarker, 1, marker); } } - - mywrite_flush(wd); } static void write_keyingsets(WriteData *wd, ListBase *list) @@ -965,7 +961,7 @@ static void write_node_socket_interface(WriteData *wd, bNodeTree *UNUSED(ntree), } } /* this is only direct data, tree itself should have been written */ -static void write_nodetree(WriteData *wd, bNodeTree *ntree) +static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree) { bNode *node; bNodeSocket *sock; @@ -1056,7 +1052,7 @@ static void write_nodetree(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); @@ -1293,60 +1289,60 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches) } } } -static void write_particlesettings(WriteData *wd, ListBase *idbase) + +static void write_particlesettings(WriteData *wd, ParticleSettings *part) { - for (ParticleSettings *part = idbase->first; part; part = part->id.next) { - if (part->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_PA, ParticleSettings, 1, part); - write_iddata(wd, &part->id); - - if (part->adt) { - write_animdata(wd, part->adt); - } - writestruct(wd, DATA, PartDeflect, 1, part->pd); - writestruct(wd, DATA, PartDeflect, 1, part->pd2); - writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights); + if (part->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_PA, ParticleSettings, 1, part); + write_iddata(wd, &part->id); - if (part->clumpcurve) { - write_curvemapping(wd, part->clumpcurve); - } - if (part->roughcurve) { - write_curvemapping(wd, part->roughcurve); - } + if (part->adt) { + write_animdata(wd, part->adt); + } + writestruct(wd, DATA, PartDeflect, 1, part->pd); + writestruct(wd, DATA, PartDeflect, 1, part->pd2); + writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights); - for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) { - /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ - if (dw->ob != NULL) { - dw->index = 0; - if (part->dup_group) { /* can be NULL if lining fails or set to None */ - for (GroupObject *go = part->dup_group->gobject.first; - go && go->ob != dw->ob; - go = go->next, dw->index++); - } + if (part->clumpcurve) { + write_curvemapping(wd, part->clumpcurve); + } + if (part->roughcurve) { + write_curvemapping(wd, part->roughcurve); + } + + for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) { + /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ + if (dw->ob != NULL) { + dw->index = 0; + if (part->dup_group) { /* can be NULL if lining fails or set to None */ + for (GroupObject *go = part->dup_group->gobject.first; + go && go->ob != dw->ob; + go = go->next, dw->index++); } - writestruct(wd, DATA, ParticleDupliWeight, 1, dw); } + writestruct(wd, DATA, ParticleDupliWeight, 1, dw); + } - if (part->boids && part->phystype == PART_PHYS_BOIDS) { - writestruct(wd, DATA, BoidSettings, 1, part->boids); + if (part->boids && part->phystype == PART_PHYS_BOIDS) { + writestruct(wd, DATA, BoidSettings, 1, part->boids); - for (BoidState *state = part->boids->states.first; state; state = state->next) { - write_boid_state(wd, state); - } - } - if (part->fluid && part->phystype == PART_PHYS_FLUID) { - writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid); + for (BoidState *state = part->boids->states.first; state; state = state->next) { + write_boid_state(wd, state); } + } + if (part->fluid && part->phystype == PART_PHYS_FLUID) { + writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid); + } - for (int a = 0; a < MAX_MTEX; a++) { - if (part->mtex[a]) { - writestruct(wd, DATA, MTex, 1, part->mtex[a]); - } + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + writestruct(wd, DATA, MTex, 1, part->mtex[a]); } } } } + static void write_particlesystems(WriteData *wd, ListBase *particles) { ParticleSystem *psys = particles->first; @@ -1866,198 +1862,178 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) } } -static void write_objects(WriteData *wd, ListBase *idbase) +static void write_object(WriteData *wd, Object *ob) { - for (Object *ob = idbase->first; ob; ob = ob->id.next) { - if (ob->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_OB, Object, 1, ob); - write_iddata(wd, &ob->id); - - if (ob->adt) { - write_animdata(wd, ob->adt); - } - - /* direct data */ - writedata(wd, DATA, sizeof(void *) * ob->totcol, ob->mat); - writedata(wd, DATA, sizeof(char) * ob->totcol, ob->matbits); - /* write_effects(wd, &ob->effect); */ /* not used anymore */ - write_properties(wd, &ob->prop); - write_sensors(wd, &ob->sensors); - write_controllers(wd, &ob->controllers); - write_actuators(wd, &ob->actuators); - - if (ob->type == OB_ARMATURE) { - bArmature *arm = ob->data; - if (arm && ob->pose && arm->act_bone) { - BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone)); - } - } + if (ob->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_OB, Object, 1, ob); + write_iddata(wd, &ob->id); - write_pose(wd, ob->pose); - write_defgroups(wd, &ob->defbase); - write_constraints(wd, &ob->constraints); - write_motionpath(wd, ob->mpath); + if (ob->adt) { + write_animdata(wd, ob->adt); + } - writestruct(wd, DATA, PartDeflect, 1, ob->pd); - writestruct(wd, DATA, SoftBody, 1, ob->soft); - if (ob->soft) { - write_pointcaches(wd, &ob->soft->ptcaches); - writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights); - } - writestruct(wd, DATA, BulletSoftBody, 1, ob->bsoft); + /* direct data */ + writedata(wd, DATA, sizeof(void *) * ob->totcol, ob->mat); + writedata(wd, DATA, sizeof(char) * ob->totcol, ob->matbits); + /* write_effects(wd, &ob->effect); */ /* not used anymore */ + write_properties(wd, &ob->prop); + write_sensors(wd, &ob->sensors); + write_controllers(wd, &ob->controllers); + write_actuators(wd, &ob->actuators); - if (ob->rigidbody_object) { - /* TODO: if any extra data is added to handle duplis, will need separate function then */ - writestruct(wd, DATA, RigidBodyOb, 1, ob->rigidbody_object); - } - if (ob->rigidbody_constraint) { - writestruct(wd, DATA, RigidBodyCon, 1, ob->rigidbody_constraint); + if (ob->type == OB_ARMATURE) { + bArmature *arm = ob->data; + if (arm && ob->pose && arm->act_bone) { + BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone)); } + } - if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) { - writestruct(wd, DATA, ImageUser, 1, ob->iuser); - } + write_pose(wd, ob->pose); + write_defgroups(wd, &ob->defbase); + write_constraints(wd, &ob->constraints); + write_motionpath(wd, ob->mpath); - write_particlesystems(wd, &ob->particlesystem); - write_modifiers(wd, &ob->modifiers); + writestruct(wd, DATA, PartDeflect, 1, ob->pd); + writestruct(wd, DATA, SoftBody, 1, ob->soft); + if (ob->soft) { + write_pointcaches(wd, &ob->soft->ptcaches); + writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights); + } + writestruct(wd, DATA, BulletSoftBody, 1, ob->bsoft); - writelist(wd, DATA, LinkData, &ob->pc_ids); - writelist(wd, DATA, LodLevel, &ob->lodlevels); + if (ob->rigidbody_object) { + /* TODO: if any extra data is added to handle duplis, will need separate function then */ + writestruct(wd, DATA, RigidBodyOb, 1, ob->rigidbody_object); + } + if (ob->rigidbody_constraint) { + writestruct(wd, DATA, RigidBodyCon, 1, ob->rigidbody_constraint); + } - write_previews(wd, ob->preview); + if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) { + writestruct(wd, DATA, ImageUser, 1, ob->iuser); } - } - mywrite_flush(wd); + write_particlesystems(wd, &ob->particlesystem); + write_modifiers(wd, &ob->modifiers); + + writelist(wd, DATA, LinkData, &ob->pc_ids); + writelist(wd, DATA, LodLevel, &ob->lodlevels); + + write_previews(wd, ob->preview); + } } -static void write_vfonts(WriteData *wd, ListBase *idbase) +static void write_vfont(WriteData *wd, VFont *vf) { - for (VFont *vf = idbase->first; vf; vf = vf->id.next) { - if (vf->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_VF, VFont, 1, vf); - write_iddata(wd, &vf->id); + if (vf->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_VF, VFont, 1, vf); + write_iddata(wd, &vf->id); - /* direct data */ - if (vf->packedfile) { - PackedFile *pf = vf->packedfile; - writestruct(wd, DATA, PackedFile, 1, pf); - writedata(wd, DATA, pf->size, pf->data); - } + /* direct data */ + if (vf->packedfile) { + PackedFile *pf = vf->packedfile; + writestruct(wd, DATA, PackedFile, 1, pf); + writedata(wd, DATA, pf->size, pf->data); } } - - mywrite_flush(wd); } -static void write_keys(WriteData *wd, ListBase *idbase) +static void write_key(WriteData *wd, Key *key) { - for (Key *key = idbase->first; key; key = key->id.next) { - if (key->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_KE, Key, 1, key); - write_iddata(wd, &key->id); - - if (key->adt) { - write_animdata(wd, key->adt); - } + if (key->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_KE, Key, 1, key); + write_iddata(wd, &key->id); - /* direct data */ - for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { - writestruct(wd, DATA, KeyBlock, 1, kb); - if (kb->data) { - writedata(wd, DATA, kb->totelem * key->elemsize, kb->data); - } + if (key->adt) { + write_animdata(wd, key->adt); + } + + /* direct data */ + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + writestruct(wd, DATA, KeyBlock, 1, kb); + if (kb->data) { + writedata(wd, DATA, kb->totelem * key->elemsize, kb->data); } } } - - mywrite_flush(wd); } -static void write_cameras(WriteData *wd, ListBase *idbase) +static void write_camera(WriteData *wd, Camera *cam) { - for (Camera *cam = idbase->first; cam; cam = cam->id.next) { - if (cam->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_CA, Camera, 1, cam); - write_iddata(wd, &cam->id); - - if (cam->adt) { - write_animdata(wd, cam->adt); - } + if (cam->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_CA, Camera, 1, cam); + write_iddata(wd, &cam->id); + + if (cam->adt) { + write_animdata(wd, cam->adt); } } } -static void write_mballs(WriteData *wd, ListBase *idbase) +static void write_mball(WriteData *wd, MetaBall *mb) { - for (MetaBall *mb = idbase->first; mb; mb = mb->id.next) { - if (mb->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_MB, MetaBall, 1, mb); - write_iddata(wd, &mb->id); + if (mb->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_MB, MetaBall, 1, mb); + write_iddata(wd, &mb->id); - /* direct data */ - writedata(wd, DATA, sizeof(void *) * mb->totcol, mb->mat); - if (mb->adt) { - write_animdata(wd, mb->adt); - } + /* direct data */ + writedata(wd, DATA, sizeof(void *) * mb->totcol, mb->mat); + if (mb->adt) { + write_animdata(wd, mb->adt); + } - for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) { - writestruct(wd, DATA, MetaElem, 1, ml); - } + for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) { + writestruct(wd, DATA, MetaElem, 1, ml); } } } -static void write_curves(WriteData *wd, ListBase *idbase) +static void write_curve(WriteData *wd, Curve *cu) { - for (Curve *cu = idbase->first; cu; cu = cu->id.next) { - if (cu->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_CU, Curve, 1, cu); - write_iddata(wd, &cu->id); + if (cu->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_CU, Curve, 1, cu); + write_iddata(wd, &cu->id); - /* direct data */ - writedata(wd, DATA, sizeof(void *) * cu->totcol, cu->mat); - if (cu->adt) { - write_animdata(wd, cu->adt); - } + /* direct data */ + writedata(wd, DATA, sizeof(void *) * cu->totcol, cu->mat); + if (cu->adt) { + write_animdata(wd, cu->adt); + } - if (cu->vfont) { - writedata(wd, DATA, cu->len + 1, cu->str); - writestruct(wd, DATA, CharInfo, cu->len_wchar + 1, cu->strinfo); - writestruct(wd, DATA, TextBox, cu->totbox, cu->tb); + if (cu->vfont) { + writedata(wd, DATA, cu->len + 1, cu->str); + writestruct(wd, DATA, CharInfo, cu->len_wchar + 1, cu->strinfo); + writestruct(wd, DATA, TextBox, cu->totbox, cu->tb); + } + else { + /* is also the order of reading */ + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + writestruct(wd, DATA, Nurb, 1, nu); } - else { - /* is also the order of reading */ - for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { - writestruct(wd, DATA, Nurb, 1, nu); + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt); } - for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt); + else { + writestruct(wd, DATA, BPoint, nu->pntsu * nu->pntsv, nu->bp); + if (nu->knotsu) { + writedata(wd, DATA, KNOTSU(nu) * sizeof(float), nu->knotsu); } - else { - writestruct(wd, DATA, BPoint, nu->pntsu * nu->pntsv, nu->bp); - if (nu->knotsu) { - writedata(wd, DATA, KNOTSU(nu) * sizeof(float), nu->knotsu); - } - if (nu->knotsv) { - writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv); - } + if (nu->knotsv) { + writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv); } } } } } - - mywrite_flush(wd); } static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist) @@ -2174,7 +2150,7 @@ static void write_customdata( } } -static void write_meshes(WriteData *wd, ListBase *idbase) +static void write_mesh(WriteData *wd, Mesh *mesh) { #ifdef USE_BMESH_SAVE_AS_COMPAT const bool save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */ @@ -2182,365 +2158,342 @@ static void write_meshes(WriteData *wd, ListBase *idbase) const bool save_for_old_blender = false; #endif - for (Mesh *mesh = idbase->first; mesh; mesh = mesh->id.next) { - CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE]; - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - - if (mesh->id.us > 0 || wd->current) { - /* write LibData */ - if (!save_for_old_blender) { - /* write a copy of the mesh, don't modify in place because it is - * not thread safe for threaded renders that are reading this */ - Mesh *old_mesh = mesh; - Mesh copy_mesh = *mesh; - mesh = ©_mesh; + CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE]; + CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; + + if (mesh->id.us > 0 || wd->current) { + /* write LibData */ + if (!save_for_old_blender) { + /* write a copy of the mesh, don't modify in place because it is + * not thread safe for threaded renders that are reading this */ + Mesh *old_mesh = mesh; + Mesh copy_mesh = *mesh; + mesh = ©_mesh; #ifdef USE_BMESH_SAVE_WITHOUT_MFACE - /* cache only - don't write */ - mesh->mface = NULL; - mesh->totface = 0; - memset(&mesh->fdata, 0, sizeof(mesh->fdata)); + /* cache only - don't write */ + mesh->mface = NULL; + mesh->totface = 0; + memset(&mesh->fdata, 0, sizeof(mesh->fdata)); #endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ - /** - * Those calls: - * - Reduce mesh->xdata.totlayer to number of layers to write. - * - Fill xlayers with those layers to be written. - * Note that mesh->xdata is from now on invalid for Blender, but this is why the whole mesh is - * a temp local copy! - */ - CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff)); - CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff)); + /** + * Those calls: + * - Reduce mesh->xdata.totlayer to number of layers to write. + * - Fill xlayers with those layers to be written. + * Note that mesh->xdata is from now on invalid for Blender, but this is why the whole mesh is + * a temp local copy! + */ + CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff)); + CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff)); #ifndef USE_BMESH_SAVE_WITHOUT_MFACE /* Do not copy org fdata in this case!!! */ - CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff)); + CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff)); #else - flayers = flayers_buff; + flayers = flayers_buff; #endif - CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff)); - CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); + CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff)); + CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); - writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh); - write_iddata(wd, &mesh->id); + writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh); + write_iddata(wd, &mesh->id); - /* direct data */ - if (mesh->adt) { - write_animdata(wd, mesh->adt); - } + /* direct data */ + if (mesh->adt) { + write_animdata(wd, mesh->adt); + } - writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat); - writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); + writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat); + writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); - write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0); - write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0); - /* fdata is really a dummy - written so slots align */ - write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0); - write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0); - write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0); + write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0); + write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0); + /* fdata is really a dummy - written so slots align */ + write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0); + write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0); + write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0); - /* restore pointer */ - mesh = old_mesh; - } - else { + /* restore pointer */ + mesh = old_mesh; + } + else { #ifdef USE_BMESH_SAVE_AS_COMPAT - /* write a copy of the mesh, don't modify in place because it is - * not thread safe for threaded renders that are reading this */ - Mesh *old_mesh = mesh; - Mesh copy_mesh = *mesh; - mesh = ©_mesh; - - mesh->mpoly = NULL; - mesh->mface = NULL; - mesh->totface = 0; - mesh->totpoly = 0; - mesh->totloop = 0; - CustomData_reset(&mesh->fdata); - CustomData_reset(&mesh->pdata); - CustomData_reset(&mesh->ldata); - mesh->edit_btmesh = NULL; - - /* now fill in polys to mfaces */ - /* XXX This breaks writing design, by using temp allocated memory, which will likely generate - * duplicates in stored 'old' addresses. - * This is very bad, but do not see easy way to avoid this, aside from generating those data - * 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); + /* write a copy of the mesh, don't modify in place because it is + * not thread safe for threaded renders that are reading this */ + Mesh *old_mesh = mesh; + Mesh copy_mesh = *mesh; + mesh = ©_mesh; + + mesh->mpoly = NULL; + mesh->mface = NULL; + mesh->totface = 0; + mesh->totpoly = 0; + mesh->totloop = 0; + CustomData_reset(&mesh->fdata); + CustomData_reset(&mesh->pdata); + CustomData_reset(&mesh->ldata); + mesh->edit_btmesh = NULL; + + /* now fill in polys to mfaces */ + /* XXX This breaks writing design, by using temp allocated memory, which will likely generate + * duplicates in stored 'old' addresses. + * This is very bad, but do not see easy way to avoid this, aside from generating those data + * 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); - BKE_mesh_update_customdata_pointers(mesh, false); + BKE_mesh_update_customdata_pointers(mesh, false); - CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff)); - CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff)); - CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff)); + CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff)); + CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff)); + CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff)); #if 0 - CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff)); - CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); + CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff)); + CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff)); #endif - writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh); - write_iddata(wd, &mesh->id); + writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh); + write_iddata(wd, &mesh->id); - /* direct data */ - if (mesh->adt) { - write_animdata(wd, mesh->adt); - } + /* direct data */ + if (mesh->adt) { + write_animdata(wd, mesh->adt); + } - writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat); - /* writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); */ /* pre-bmesh NULL's */ + writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat); + /* writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); */ /* pre-bmesh NULL's */ - write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0); - write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0); - write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0); - /* harmless for older blender versioins but _not_ writing these keeps file size down */ + write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0); + write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0); + write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0); + /* harmless for older blender versioins but _not_ writing these keeps file size down */ #if 0 - write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0); - write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0); + write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0); + write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0); #endif - CustomData_free(&mesh->fdata, mesh->totface); - flayers = NULL; + CustomData_free(&mesh->fdata, mesh->totface); + flayers = NULL; - /* restore pointer */ - mesh = old_mesh; + /* restore pointer */ + mesh = old_mesh; #endif /* USE_BMESH_SAVE_AS_COMPAT */ - } - } - - if (vlayers && vlayers != vlayers_buff) { - MEM_freeN(vlayers); - } - if (elayers && elayers != elayers_buff) { - MEM_freeN(elayers); - } - if (flayers && flayers != flayers_buff) { - MEM_freeN(flayers); - } - if (llayers && llayers != llayers_buff) { - MEM_freeN(llayers); - } - if (players && players != players_buff) { - MEM_freeN(players); } } - mywrite_flush(wd); + if (vlayers && vlayers != vlayers_buff) { + MEM_freeN(vlayers); + } + if (elayers && elayers != elayers_buff) { + MEM_freeN(elayers); + } + if (flayers && flayers != flayers_buff) { + MEM_freeN(flayers); + } + if (llayers && llayers != llayers_buff) { + MEM_freeN(llayers); + } + if (players && players != players_buff) { + MEM_freeN(players); + } } -static void write_lattices(WriteData *wd, ListBase *idbase) +static void write_lattice(WriteData *wd, Lattice *lt) { - for (Lattice *lt = idbase->first; lt; lt = lt->id.next) { - if (lt->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_LT, Lattice, 1, lt); - write_iddata(wd, <->id); - - /* write animdata */ - if (lt->adt) { - write_animdata(wd, lt->adt); - } - - /* direct data */ - writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def); + if (lt->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_LT, Lattice, 1, lt); + write_iddata(wd, <->id); - write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert); + /* write animdata */ + if (lt->adt) { + write_animdata(wd, lt->adt); } - } - mywrite_flush(wd); + /* direct data */ + writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def); + + write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert); + } } -static void write_images(WriteData *wd, ListBase *idbase) +static void write_image(WriteData *wd, Image *ima) { - for (Image *ima = idbase->first; ima; ima = ima->id.next) { - if (ima->id.us > 0 || wd->current) { - ImagePackedFile *imapf; - - /* Some trickery to keep forward compatibility of packed images. */ - BLI_assert(ima->packedfile == NULL); - if (ima->packedfiles.first != NULL) { - imapf = ima->packedfiles.first; - ima->packedfile = imapf->packedfile; - } - - /* write LibData */ - writestruct(wd, ID_IM, Image, 1, ima); - write_iddata(wd, &ima->id); + if (ima->id.us > 0 || wd->current) { + ImagePackedFile *imapf; - for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { - writestruct(wd, DATA, ImagePackedFile, 1, imapf); - if (imapf->packedfile) { - PackedFile *pf = imapf->packedfile; - writestruct(wd, DATA, PackedFile, 1, pf); - writedata(wd, DATA, pf->size, pf->data); - } - } + /* Some trickery to keep forward compatibility of packed images. */ + BLI_assert(ima->packedfile == NULL); + if (ima->packedfiles.first != NULL) { + imapf = ima->packedfiles.first; + ima->packedfile = imapf->packedfile; + } - write_previews(wd, ima->preview); + /* write LibData */ + writestruct(wd, ID_IM, Image, 1, ima); + write_iddata(wd, &ima->id); - for (ImageView *iv = ima->views.first; iv; iv = iv->next) { - writestruct(wd, DATA, ImageView, 1, iv); + for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { + writestruct(wd, DATA, ImagePackedFile, 1, imapf); + if (imapf->packedfile) { + PackedFile *pf = imapf->packedfile; + writestruct(wd, DATA, PackedFile, 1, pf); + writedata(wd, DATA, pf->size, pf->data); } - writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format); + } + + write_previews(wd, ima->preview); - ima->packedfile = NULL; + for (ImageView *iv = ima->views.first; iv; iv = iv->next) { + writestruct(wd, DATA, ImageView, 1, iv); } - } + writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format); - mywrite_flush(wd); + ima->packedfile = NULL; + } } -static void write_textures(WriteData *wd, ListBase *idbase) +static void write_texture(WriteData *wd, Tex *tex) { - for (Tex *tex = idbase->first; tex; tex = tex->id.next) { - if (tex->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_TE, Tex, 1, tex); - write_iddata(wd, &tex->id); - - if (tex->adt) { - write_animdata(wd, tex->adt); - } + if (tex->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_TE, Tex, 1, tex); + write_iddata(wd, &tex->id); - /* direct data */ - if (tex->coba) { - writestruct(wd, DATA, ColorBand, 1, tex->coba); - } - if (tex->type == TEX_ENVMAP && tex->env) { - writestruct(wd, DATA, EnvMap, 1, tex->env); - } - if (tex->type == TEX_POINTDENSITY && tex->pd) { - writestruct(wd, DATA, PointDensity, 1, tex->pd); - if (tex->pd->coba) { - writestruct(wd, DATA, ColorBand, 1, tex->pd->coba); - } - if (tex->pd->falloff_curve) { - write_curvemapping(wd, tex->pd->falloff_curve); - } - } - if (tex->type == TEX_VOXELDATA) { - writestruct(wd, DATA, VoxelData, 1, tex->vd); - } - if (tex->type == TEX_OCEAN && tex->ot) { - writestruct(wd, DATA, OceanTex, 1, tex->ot); - } + if (tex->adt) { + write_animdata(wd, tex->adt); + } - /* nodetree is integral part of texture, no libdata */ - if (tex->nodetree) { - writestruct(wd, DATA, bNodeTree, 1, tex->nodetree); - write_nodetree(wd, tex->nodetree); + /* direct data */ + if (tex->coba) { + writestruct(wd, DATA, ColorBand, 1, tex->coba); + } + if (tex->type == TEX_ENVMAP && tex->env) { + writestruct(wd, DATA, EnvMap, 1, tex->env); + } + if (tex->type == TEX_POINTDENSITY && tex->pd) { + writestruct(wd, DATA, PointDensity, 1, tex->pd); + if (tex->pd->coba) { + writestruct(wd, DATA, ColorBand, 1, tex->pd->coba); } + if (tex->pd->falloff_curve) { + write_curvemapping(wd, tex->pd->falloff_curve); + } + } + if (tex->type == TEX_VOXELDATA) { + writestruct(wd, DATA, VoxelData, 1, tex->vd); + } + if (tex->type == TEX_OCEAN && tex->ot) { + writestruct(wd, DATA, OceanTex, 1, tex->ot); + } - write_previews(wd, tex->preview); + /* nodetree is integral part of texture, no libdata */ + if (tex->nodetree) { + writestruct(wd, DATA, bNodeTree, 1, tex->nodetree); + write_nodetree_nolib(wd, tex->nodetree); } - } - mywrite_flush(wd); + write_previews(wd, tex->preview); + } } -static void write_materials(WriteData *wd, ListBase *idbase) +static void write_material(WriteData *wd, Material *ma) { - for (Material *ma = idbase->first; ma; ma = ma->id.next) { - if (ma->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_MA, Material, 1, ma); - write_iddata(wd, &ma->id); - - if (ma->adt) { - write_animdata(wd, ma->adt); - } + if (ma->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_MA, Material, 1, ma); + write_iddata(wd, &ma->id); - for (int a = 0; a < MAX_MTEX; a++) { - if (ma->mtex[a]) { - writestruct(wd, DATA, MTex, 1, ma->mtex[a]); - } - } + if (ma->adt) { + write_animdata(wd, ma->adt); + } - if (ma->ramp_col) { - writestruct(wd, DATA, ColorBand, 1, ma->ramp_col); - } - if (ma->ramp_spec) { - writestruct(wd, DATA, ColorBand, 1, ma->ramp_spec); + for (int a = 0; a < MAX_MTEX; a++) { + if (ma->mtex[a]) { + writestruct(wd, DATA, MTex, 1, ma->mtex[a]); } + } - /* nodetree is integral part of material, no libdata */ - if (ma->nodetree) { - writestruct(wd, DATA, bNodeTree, 1, ma->nodetree); - write_nodetree(wd, ma->nodetree); - } + if (ma->ramp_col) { + writestruct(wd, DATA, ColorBand, 1, ma->ramp_col); + } + if (ma->ramp_spec) { + writestruct(wd, DATA, ColorBand, 1, ma->ramp_spec); + } - write_previews(wd, ma->preview); + /* nodetree is integral part of material, no libdata */ + if (ma->nodetree) { + writestruct(wd, DATA, bNodeTree, 1, ma->nodetree); + write_nodetree_nolib(wd, ma->nodetree); } + + write_previews(wd, ma->preview); } } -static void write_worlds(WriteData *wd, ListBase *idbase) +static void write_world(WriteData *wd, World *wrld) { - for (World *wrld = idbase->first; wrld; wrld = wrld->id.next) { - if (wrld->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_WO, World, 1, wrld); - write_iddata(wd, &wrld->id); - - if (wrld->adt) { - write_animdata(wd, wrld->adt); - } + if (wrld->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_WO, World, 1, wrld); + write_iddata(wd, &wrld->id); - for (int a = 0; a < MAX_MTEX; a++) { - if (wrld->mtex[a]) { - writestruct(wd, DATA, MTex, 1, wrld->mtex[a]); - } - } + if (wrld->adt) { + write_animdata(wd, wrld->adt); + } - /* nodetree is integral part of world, no libdata */ - if (wrld->nodetree) { - writestruct(wd, DATA, bNodeTree, 1, wrld->nodetree); - write_nodetree(wd, wrld->nodetree); + for (int a = 0; a < MAX_MTEX; a++) { + if (wrld->mtex[a]) { + writestruct(wd, DATA, MTex, 1, wrld->mtex[a]); } + } - write_previews(wd, wrld->preview); + /* nodetree is integral part of world, no libdata */ + if (wrld->nodetree) { + writestruct(wd, DATA, bNodeTree, 1, wrld->nodetree); + write_nodetree_nolib(wd, wrld->nodetree); } + + write_previews(wd, wrld->preview); } } -static void write_lamps(WriteData *wd, ListBase *idbase) +static void write_lamp(WriteData *wd, Lamp *la) { - for (Lamp *la = idbase->first; la; la = la->id.next) { - if (la->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_LA, Lamp, 1, la); - write_iddata(wd, &la->id); - - if (la->adt) { - write_animdata(wd, la->adt); - } + if (la->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_LA, Lamp, 1, la); + write_iddata(wd, &la->id); - /* direct data */ - for (int a = 0; a < MAX_MTEX; a++) { - if (la->mtex[a]) { - writestruct(wd, DATA, MTex, 1, la->mtex[a]); - } - } + if (la->adt) { + write_animdata(wd, la->adt); + } - if (la->curfalloff) { - write_curvemapping(wd, la->curfalloff); + /* direct data */ + for (int a = 0; a < MAX_MTEX; a++) { + if (la->mtex[a]) { + writestruct(wd, DATA, MTex, 1, la->mtex[a]); } + } - /* nodetree is integral part of lamps, no libdata */ - if (la->nodetree) { - writestruct(wd, DATA, bNodeTree, 1, la->nodetree); - write_nodetree(wd, la->nodetree); - } + if (la->curfalloff) { + write_curvemapping(wd, la->curfalloff); + } - write_previews(wd, la->preview); + /* nodetree is integral part of lamps, no libdata */ + if (la->nodetree) { + writestruct(wd, DATA, bNodeTree, 1, la->nodetree); + write_nodetree_nolib(wd, la->nodetree); } - } - mywrite_flush(wd); + write_previews(wd, la->preview); + } } static void write_sequence_modifiers(WriteData *wd, ListBase *modbase) @@ -2584,267 +2537,256 @@ static void write_paint(WriteData *wd, Paint *p) } } -static void write_scenes(WriteData *wd, ListBase *scebase) +static void write_scene(WriteData *wd, Scene *sce) { - for (Scene *sce = scebase->first; sce; sce = sce->id.next) { - /* write LibData */ - writestruct(wd, ID_SCE, Scene, 1, sce); - write_iddata(wd, &sce->id); + /* write LibData */ + writestruct(wd, ID_SCE, Scene, 1, sce); + write_iddata(wd, &sce->id); - if (sce->adt) { - write_animdata(wd, sce->adt); - } - write_keyingsets(wd, &sce->keyingsets); + if (sce->adt) { + write_animdata(wd, sce->adt); + } + write_keyingsets(wd, &sce->keyingsets); - /* direct data */ - for (Base *base = sce->base.first; base; base = base->next) { - writestruct(wd, DATA, Base, 1, base); - } + /* direct data */ + for (Base *base = sce->base.first; base; base = base->next) { + writestruct(wd, DATA, Base, 1, base); + } - ToolSettings *tos = sce->toolsettings; - writestruct(wd, DATA, ToolSettings, 1, tos); - if (tos->vpaint) { - writestruct(wd, DATA, VPaint, 1, tos->vpaint); - write_paint(wd, &tos->vpaint->paint); - } - if (tos->wpaint) { - writestruct(wd, DATA, VPaint, 1, tos->wpaint); - write_paint(wd, &tos->wpaint->paint); - } - if (tos->sculpt) { - writestruct(wd, DATA, Sculpt, 1, tos->sculpt); - write_paint(wd, &tos->sculpt->paint); - } - if (tos->uvsculpt) { - writestruct(wd, DATA, UvSculpt, 1, tos->uvsculpt); - write_paint(wd, &tos->uvsculpt->paint); + ToolSettings *tos = sce->toolsettings; + writestruct(wd, DATA, ToolSettings, 1, tos); + if (tos->vpaint) { + writestruct(wd, DATA, VPaint, 1, tos->vpaint); + write_paint(wd, &tos->vpaint->paint); + } + if (tos->wpaint) { + writestruct(wd, DATA, VPaint, 1, tos->wpaint); + write_paint(wd, &tos->wpaint->paint); + } + if (tos->sculpt) { + writestruct(wd, DATA, Sculpt, 1, tos->sculpt); + write_paint(wd, &tos->sculpt->paint); + } + if (tos->uvsculpt) { + writestruct(wd, DATA, UvSculpt, 1, tos->uvsculpt); + write_paint(wd, &tos->uvsculpt->paint); + } + /* write grease-pencil drawing brushes to file */ + writelist(wd, DATA, bGPDbrush, &tos->gp_brushes); + for (bGPDbrush *brush = tos->gp_brushes.first; brush; brush = brush->next) { + if (brush->cur_sensitivity) { + write_curvemapping(wd, brush->cur_sensitivity); } - /* write grease-pencil drawing brushes to file */ - writelist(wd, DATA, bGPDbrush, &tos->gp_brushes); - for (bGPDbrush *brush = tos->gp_brushes.first; brush; brush = brush->next) { - if (brush->cur_sensitivity) { - write_curvemapping(wd, brush->cur_sensitivity); - } - if (brush->cur_strength) { - write_curvemapping(wd, brush->cur_strength); - } - if (brush->cur_jitter) { - write_curvemapping(wd, brush->cur_jitter); - } + if (brush->cur_strength) { + write_curvemapping(wd, brush->cur_strength); } - /* write grease-pencil custom ipo curve to file */ - if (tos->gp_interpolate.custom_ipo) { - write_curvemapping(wd, tos->gp_interpolate.custom_ipo); + if (brush->cur_jitter) { + write_curvemapping(wd, brush->cur_jitter); } - + } + /* write grease-pencil custom ipo curve to file */ + if (tos->gp_interpolate.custom_ipo) { + write_curvemapping(wd, tos->gp_interpolate.custom_ipo); + } - write_paint(wd, &tos->imapaint.paint); - Editing *ed = sce->ed; - if (ed) { - Sequence *seq; + write_paint(wd, &tos->imapaint.paint); - writestruct(wd, DATA, Editing, 1, ed); + Editing *ed = sce->ed; + if (ed) { + Sequence *seq; - /* reset write flags too */ + writestruct(wd, DATA, Editing, 1, ed); - SEQ_BEGIN(ed, seq) - { - if (seq->strip) { - seq->strip->done = false; - } - writestruct(wd, DATA, Sequence, 1, seq); - } - SEQ_END + /* reset write flags too */ - SEQ_BEGIN(ed, seq) - { - if (seq->strip && seq->strip->done == 0) { - /* write strip with 'done' at 0 because readfile */ - - if (seq->effectdata) { - switch (seq->type) { - case SEQ_TYPE_COLOR: - writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata); - break; - case SEQ_TYPE_SPEED: - writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata); - break; - case SEQ_TYPE_WIPE: - writestruct(wd, DATA, WipeVars, 1, seq->effectdata); - break; - case SEQ_TYPE_GLOW: - writestruct(wd, DATA, GlowVars, 1, seq->effectdata); - break; - case SEQ_TYPE_TRANSFORM: - writestruct(wd, DATA, TransformVars, 1, seq->effectdata); - break; - case SEQ_TYPE_GAUSSIAN_BLUR: - writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata); - break; - case SEQ_TYPE_TEXT: - writestruct(wd, DATA, TextVars, 1, seq->effectdata); - break; - } - } + SEQ_BEGIN(ed, seq) + { + if (seq->strip) { + seq->strip->done = false; + } + writestruct(wd, DATA, Sequence, 1, seq); + } + SEQ_END - writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format); + SEQ_BEGIN(ed, seq) + { + if (seq->strip && seq->strip->done == 0) { + /* write strip with 'done' at 0 because readfile */ - Strip *strip = seq->strip; - writestruct(wd, DATA, Strip, 1, strip); - if (seq->flag & SEQ_USE_CROP && strip->crop) { - writestruct(wd, DATA, StripCrop, 1, strip->crop); - } - if (seq->flag & SEQ_USE_TRANSFORM && strip->transform) { - writestruct(wd, DATA, StripTransform, 1, strip->transform); - } - if (seq->flag & SEQ_USE_PROXY && strip->proxy) { - writestruct(wd, DATA, StripProxy, 1, strip->proxy); - } - if (seq->type == SEQ_TYPE_IMAGE) { - writestruct(wd, DATA, StripElem, - 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); + if (seq->effectdata) { + switch (seq->type) { + case SEQ_TYPE_COLOR: + writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata); + break; + case SEQ_TYPE_SPEED: + writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata); + break; + case SEQ_TYPE_WIPE: + writestruct(wd, DATA, WipeVars, 1, seq->effectdata); + break; + case SEQ_TYPE_GLOW: + writestruct(wd, DATA, GlowVars, 1, seq->effectdata); + break; + case SEQ_TYPE_TRANSFORM: + writestruct(wd, DATA, TransformVars, 1, seq->effectdata); + break; + case SEQ_TYPE_GAUSSIAN_BLUR: + writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata); + break; + case SEQ_TYPE_TEXT: + writestruct(wd, DATA, TextVars, 1, seq->effectdata); + break; } - - strip->done = true; } - if (seq->prop) { - IDP_WriteProperty(seq->prop, wd); + writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format); + + Strip *strip = seq->strip; + writestruct(wd, DATA, Strip, 1, strip); + if (seq->flag & SEQ_USE_CROP && strip->crop) { + writestruct(wd, DATA, StripCrop, 1, strip->crop); + } + if (seq->flag & SEQ_USE_TRANSFORM && strip->transform) { + writestruct(wd, DATA, StripTransform, 1, strip->transform); + } + if (seq->flag & SEQ_USE_PROXY && strip->proxy) { + writestruct(wd, DATA, StripProxy, 1, strip->proxy); + } + if (seq->type == SEQ_TYPE_IMAGE) { + writestruct(wd, DATA, StripElem, + 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); } - write_sequence_modifiers(wd, &seq->modifiers); + strip->done = true; } - SEQ_END - /* new; meta stack too, even when its nasty restore code */ - for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) { - writestruct(wd, DATA, MetaStack, 1, ms); + if (seq->prop) { + IDP_WriteProperty(seq->prop, wd); } + + write_sequence_modifiers(wd, &seq->modifiers); } + SEQ_END - if (sce->r.avicodecdata) { - writestruct(wd, DATA, AviCodecData, 1, sce->r.avicodecdata); - if (sce->r.avicodecdata->lpFormat) { - writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat); - } - if (sce->r.avicodecdata->lpParms) { - writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms); - } + /* new; meta stack too, even when its nasty restore code */ + for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) { + writestruct(wd, DATA, MetaStack, 1, ms); } + } - if (sce->r.qtcodecdata) { - writestruct(wd, DATA, QuicktimeCodecData, 1, sce->r.qtcodecdata); - if (sce->r.qtcodecdata->cdParms) { - writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms); - } + if (sce->r.avicodecdata) { + writestruct(wd, DATA, AviCodecData, 1, sce->r.avicodecdata); + if (sce->r.avicodecdata->lpFormat) { + writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat); } - if (sce->r.ffcodecdata.properties) { - IDP_WriteProperty(sce->r.ffcodecdata.properties, wd); + if (sce->r.avicodecdata->lpParms) { + writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms); } + } - /* writing dynamic list of TimeMarkers to the blend file */ - for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) { - writestruct(wd, DATA, TimeMarker, 1, marker); + if (sce->r.qtcodecdata) { + writestruct(wd, DATA, QuicktimeCodecData, 1, sce->r.qtcodecdata); + if (sce->r.qtcodecdata->cdParms) { + writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms); } + } + if (sce->r.ffcodecdata.properties) { + IDP_WriteProperty(sce->r.ffcodecdata.properties, wd); + } - /* writing dynamic list of TransformOrientations to the blend file */ - for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) { - writestruct(wd, DATA, TransformOrientation, 1, ts); - } + /* writing dynamic list of TimeMarkers to the blend file */ + for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) { + writestruct(wd, DATA, TimeMarker, 1, marker); + } - for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) { - writestruct(wd, DATA, SceneRenderLayer, 1, srl); - for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { - writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc); - } - for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { - writestruct(wd, DATA, FreestyleLineSet, 1, fls); - } - } + /* writing dynamic list of TransformOrientations to the blend file */ + for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) { + writestruct(wd, DATA, TransformOrientation, 1, ts); + } - /* writing MultiView to the blend file */ - for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) { - writestruct(wd, DATA, SceneRenderView, 1, srv); + 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); } - - if (sce->nodetree) { - writestruct(wd, DATA, bNodeTree, 1, sce->nodetree); - write_nodetree(wd, sce->nodetree); + for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { + writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc); + } + for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { + writestruct(wd, DATA, FreestyleLineSet, 1, fls); } + } - write_view_settings(wd, &sce->view_settings); + /* writing MultiView to the blend file */ + for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) { + writestruct(wd, DATA, SceneRenderView, 1, srv); + } - /* writing RigidBodyWorld data to the blend file */ - if (sce->rigidbody_world) { - writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world); - writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights); - write_pointcaches(wd, &(sce->rigidbody_world->ptcaches)); - } + if (sce->nodetree) { + writestruct(wd, DATA, bNodeTree, 1, sce->nodetree); + write_nodetree_nolib(wd, sce->nodetree); + } - write_previews(wd, sce->preview); - write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve); + write_view_settings(wd, &sce->view_settings); + + /* writing RigidBodyWorld data to the blend file */ + if (sce->rigidbody_world) { + writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world); + writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights); + write_pointcaches(wd, &(sce->rigidbody_world->ptcaches)); } - mywrite_flush(wd); + write_previews(wd, sce->preview); + write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve); } -static void write_gpencils(WriteData *wd, ListBase *lb) +static void write_gpencil(WriteData *wd, bGPdata *gpd) { - for (bGPdata *gpd = lb->first; gpd; gpd = gpd->id.next) { - if (gpd->id.us > 0 || wd->current) { - /* write gpd data block to file */ - writestruct(wd, ID_GD, bGPdata, 1, gpd); - write_iddata(wd, &gpd->id); - - if (gpd->adt) { - write_animdata(wd, gpd->adt); - } - - /* write grease-pencil layers to file */ - writelist(wd, DATA, bGPDlayer, &gpd->layers); - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - /* write this layer's frames to file */ - writelist(wd, DATA, bGPDframe, &gpl->frames); - for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { - /* write strokes */ - writelist(wd, DATA, bGPDstroke, &gpf->strokes); - for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { - writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points); - } + if (gpd->id.us > 0 || wd->current) { + /* write gpd data block to file */ + writestruct(wd, ID_GD, bGPdata, 1, gpd); + write_iddata(wd, &gpd->id); + + if (gpd->adt) { + write_animdata(wd, gpd->adt); + } + + /* write grease-pencil layers to file */ + writelist(wd, DATA, bGPDlayer, &gpd->layers); + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + /* write this layer's frames to file */ + writelist(wd, DATA, bGPDframe, &gpl->frames); + for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { + /* write strokes */ + writelist(wd, DATA, bGPDstroke, &gpf->strokes); + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { + writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points); } } + } - /* write grease-pencil palettes */ - writelist(wd, DATA, bGPDpalette, &gpd->palettes); - for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) { - writelist(wd, DATA, bGPDpalettecolor, &palette->colors); - } + /* write grease-pencil palettes */ + writelist(wd, DATA, bGPDpalette, &gpd->palettes); + for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) { + writelist(wd, DATA, bGPDpalettecolor, &palette->colors); } } - - mywrite_flush(wd); } -static void write_windowmanagers(WriteData *wd, ListBase *lb) +static void write_windowmanager(WriteData *wd, wmWindowManager *wm) { - for (wmWindowManager *wm = lb->first; wm; wm = wm->id.next) { - writestruct(wd, ID_WM, wmWindowManager, 1, wm); - write_iddata(wd, &wm->id); + writestruct(wd, ID_WM, wmWindowManager, 1, wm); + write_iddata(wd, &wm->id); - for (wmWindow *win = wm->windows.first; win; win = win->next) { - writestruct(wd, DATA, wmWindow, 1, win); - writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format); - } + for (wmWindow *win = wm->windows.first; win; win = win->next) { + writestruct(wd, DATA, wmWindow, 1, win); + writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format); } - - /* typically flushing wouldn't be needed however this data _always_ changes, - * so flush here for more efficient undo. */ - mywrite_flush(wd); } static void write_region(WriteData *wd, ARegion *ar, int spacetype) @@ -2927,172 +2869,168 @@ static void write_soops(WriteData *wd, SpaceOops *so) } } -static void write_screens(WriteData *wd, ListBase *scrbase) +static void write_screen(WriteData *wd, bScreen *sc) { - for (bScreen *sc = scrbase->first; sc; sc = sc->id.next) { - /* write LibData */ - /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ - writestruct(wd, ID_SCRN, bScreen, 1, sc); - write_iddata(wd, &sc->id); - - /* direct data */ - for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) { - writestruct(wd, DATA, ScrVert, 1, sv); - } + /* write LibData */ + /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */ + writestruct(wd, ID_SCRN, bScreen, 1, sc); + write_iddata(wd, &sc->id); - for (ScrEdge *se = sc->edgebase.first; se; se = se->next) { - writestruct(wd, DATA, ScrEdge, 1, se); - } - - for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - Panel *pa; - uiList *ui_list; - uiPreview *ui_preview; - PanelCategoryStack *pc_act; - ARegion *ar; - - writestruct(wd, DATA, ScrArea, 1, sa); + /* direct data */ + for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) { + writestruct(wd, DATA, ScrVert, 1, sv); + } - for (ar = sa->regionbase.first; ar; ar = ar->next) { - write_region(wd, ar, sa->spacetype); + for (ScrEdge *se = sc->edgebase.first; se; se = se->next) { + writestruct(wd, DATA, ScrEdge, 1, se); + } - for (pa = ar->panels.first; pa; pa = pa->next) { - writestruct(wd, DATA, Panel, 1, pa); - } + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + Panel *pa; + uiList *ui_list; + uiPreview *ui_preview; + PanelCategoryStack *pc_act; + ARegion *ar; - for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) { - writestruct(wd, DATA, PanelCategoryStack, 1, pc_act); - } + writestruct(wd, DATA, ScrArea, 1, sa); - for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) { - write_uilist(wd, ui_list); - } + for (ar = sa->regionbase.first; ar; ar = ar->next) { + write_region(wd, ar, sa->spacetype); - for (ui_preview = ar->ui_previews.first; ui_preview; ui_preview = ui_preview->next) { - writestruct(wd, DATA, uiPreview, 1, ui_preview); - } + for (pa = ar->panels.first; pa; pa = pa->next) { + writestruct(wd, DATA, Panel, 1, pa); } - for (sl = sa->spacedata.first; sl; sl = sl->next) { - for (ar = sl->regionbase.first; ar; ar = ar->next) { - write_region(wd, ar, sl->spacetype); - } - - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - BGpic *bgpic; - writestruct(wd, DATA, View3D, 1, v3d); - for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - writestruct(wd, DATA, BGpic, 1, bgpic); - } - if (v3d->localvd) { - writestruct(wd, DATA, View3D, 1, v3d->localvd); - } + for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) { + writestruct(wd, DATA, PanelCategoryStack, 1, pc_act); + } - if (v3d->fx_settings.ssao) { - writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao); - } - if (v3d->fx_settings.dof) { - writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof); - } - } - else if (sl->spacetype == SPACE_IPO) { - SpaceIpo *sipo = (SpaceIpo *)sl; - ListBase tmpGhosts = sipo->ghostCurves; + for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) { + write_uilist(wd, ui_list); + } - /* temporarily disable ghost curves when saving */ - sipo->ghostCurves.first = sipo->ghostCurves.last = NULL; + for (ui_preview = ar->ui_previews.first; ui_preview; ui_preview = ui_preview->next) { + writestruct(wd, DATA, uiPreview, 1, ui_preview); + } + } - writestruct(wd, DATA, SpaceIpo, 1, sl); - if (sipo->ads) { - writestruct(wd, DATA, bDopeSheet, 1, sipo->ads); - } + for (sl = sa->spacedata.first; sl; sl = sl->next) { + for (ar = sl->regionbase.first; ar; ar = ar->next) { + write_region(wd, ar, sl->spacetype); + } - /* reenable ghost curves */ - sipo->ghostCurves = tmpGhosts; + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + BGpic *bgpic; + writestruct(wd, DATA, View3D, 1, v3d); + for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { + writestruct(wd, DATA, BGpic, 1, bgpic); } - else if (sl->spacetype == SPACE_BUTS) { - writestruct(wd, DATA, SpaceButs, 1, sl); + if (v3d->localvd) { + writestruct(wd, DATA, View3D, 1, v3d->localvd); } - else if (sl->spacetype == SPACE_FILE) { - SpaceFile *sfile = (SpaceFile *)sl; - writestruct(wd, DATA, SpaceFile, 1, sl); - if (sfile->params) { - writestruct(wd, DATA, FileSelectParams, 1, sfile->params); - } - } - else if (sl->spacetype == SPACE_SEQ) { - writestruct(wd, DATA, SpaceSeq, 1, sl); - } - else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOops *so = (SpaceOops *)sl; - write_soops(wd, so); - } - else if (sl->spacetype == SPACE_IMAGE) { - writestruct(wd, DATA, SpaceImage, 1, sl); - } - else if (sl->spacetype == SPACE_TEXT) { - writestruct(wd, DATA, SpaceText, 1, sl); + if (v3d->fx_settings.ssao) { + writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao); } - else if (sl->spacetype == SPACE_SCRIPT) { - SpaceScript *scr = (SpaceScript *)sl; - scr->but_refs = NULL; - writestruct(wd, DATA, SpaceScript, 1, sl); + if (v3d->fx_settings.dof) { + writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof); } - else if (sl->spacetype == SPACE_ACTION) { - writestruct(wd, DATA, SpaceAction, 1, sl); - } - else if (sl->spacetype == SPACE_NLA) { - SpaceNla *snla = (SpaceNla *)sl; + } + else if (sl->spacetype == SPACE_IPO) { + SpaceIpo *sipo = (SpaceIpo *)sl; + ListBase tmpGhosts = sipo->ghostCurves; - writestruct(wd, DATA, SpaceNla, 1, snla); - if (snla->ads) { - writestruct(wd, DATA, bDopeSheet, 1, snla->ads); - } - } - else if (sl->spacetype == SPACE_TIME) { - writestruct(wd, DATA, SpaceTime, 1, sl); - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - bNodeTreePath *path; - writestruct(wd, DATA, SpaceNode, 1, snode); + /* temporarily disable ghost curves when saving */ + sipo->ghostCurves.first = sipo->ghostCurves.last = NULL; - for (path = snode->treepath.first; path; path = path->next) { - writestruct(wd, DATA, bNodeTreePath, 1, path); - } - } - else if (sl->spacetype == SPACE_LOGIC) { - writestruct(wd, DATA, SpaceLogic, 1, sl); + writestruct(wd, DATA, SpaceIpo, 1, sl); + if (sipo->ads) { + writestruct(wd, DATA, bDopeSheet, 1, sipo->ads); } - else if (sl->spacetype == SPACE_CONSOLE) { - SpaceConsole *con = (SpaceConsole *)sl; - ConsoleLine *cl; - - for (cl = con->history.first; cl; cl = cl->next) { - /* 'len_alloc' is invalid on write, set from 'len' on read */ - writestruct(wd, DATA, ConsoleLine, 1, cl); - writedata(wd, DATA, cl->len + 1, cl->line); - } - writestruct(wd, DATA, SpaceConsole, 1, sl); + /* reenable ghost curves */ + sipo->ghostCurves = tmpGhosts; + } + else if (sl->spacetype == SPACE_BUTS) { + writestruct(wd, DATA, SpaceButs, 1, sl); + } + else if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + + writestruct(wd, DATA, SpaceFile, 1, sl); + if (sfile->params) { + writestruct(wd, DATA, FileSelectParams, 1, sfile->params); } - else if (sl->spacetype == SPACE_USERPREF) { - writestruct(wd, DATA, SpaceUserPref, 1, sl); + } + else if (sl->spacetype == SPACE_SEQ) { + writestruct(wd, DATA, SpaceSeq, 1, sl); + } + else if (sl->spacetype == SPACE_OUTLINER) { + SpaceOops *so = (SpaceOops *)sl; + write_soops(wd, so); + } + else if (sl->spacetype == SPACE_IMAGE) { + writestruct(wd, DATA, SpaceImage, 1, sl); + } + else if (sl->spacetype == SPACE_TEXT) { + writestruct(wd, DATA, SpaceText, 1, sl); + } + else if (sl->spacetype == SPACE_SCRIPT) { + SpaceScript *scr = (SpaceScript *)sl; + scr->but_refs = NULL; + writestruct(wd, DATA, SpaceScript, 1, sl); + } + else if (sl->spacetype == SPACE_ACTION) { + writestruct(wd, DATA, SpaceAction, 1, sl); + } + else if (sl->spacetype == SPACE_NLA) { + SpaceNla *snla = (SpaceNla *)sl; + + writestruct(wd, DATA, SpaceNla, 1, snla); + if (snla->ads) { + writestruct(wd, DATA, bDopeSheet, 1, snla->ads); } - else if (sl->spacetype == SPACE_CLIP) { - writestruct(wd, DATA, SpaceClip, 1, sl); + } + else if (sl->spacetype == SPACE_TIME) { + writestruct(wd, DATA, SpaceTime, 1, sl); + } + else if (sl->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)sl; + bNodeTreePath *path; + writestruct(wd, DATA, SpaceNode, 1, snode); + + for (path = snode->treepath.first; path; path = path->next) { + writestruct(wd, DATA, bNodeTreePath, 1, path); } - else if (sl->spacetype == SPACE_INFO) { - writestruct(wd, DATA, SpaceInfo, 1, sl); + } + else if (sl->spacetype == SPACE_LOGIC) { + writestruct(wd, DATA, SpaceLogic, 1, sl); + } + else if (sl->spacetype == SPACE_CONSOLE) { + SpaceConsole *con = (SpaceConsole *)sl; + ConsoleLine *cl; + + for (cl = con->history.first; cl; cl = cl->next) { + /* 'len_alloc' is invalid on write, set from 'len' on read */ + writestruct(wd, DATA, ConsoleLine, 1, cl); + writedata(wd, DATA, cl->len + 1, cl->line); } + writestruct(wd, DATA, SpaceConsole, 1, sl); + + } + else if (sl->spacetype == SPACE_USERPREF) { + writestruct(wd, DATA, SpaceUserPref, 1, sl); + } + else if (sl->spacetype == SPACE_CLIP) { + writestruct(wd, DATA, SpaceClip, 1, sl); + } + else if (sl->spacetype == SPACE_INFO) { + writestruct(wd, DATA, SpaceInfo, 1, sl); } } } - - mywrite_flush(wd); } static void write_bone(WriteData *wd, Bone *bone) @@ -3115,121 +3053,101 @@ static void write_bone(WriteData *wd, Bone *bone) } } -static void write_armatures(WriteData *wd, ListBase *idbase) +static void write_armature(WriteData *wd, bArmature *arm) { - for (bArmature *arm = idbase->first; arm; arm = arm->id.next) { - if (arm->id.us > 0 || wd->current) { - writestruct(wd, ID_AR, bArmature, 1, arm); - write_iddata(wd, &arm->id); + if (arm->id.us > 0 || wd->current) { + writestruct(wd, ID_AR, bArmature, 1, arm); + write_iddata(wd, &arm->id); - if (arm->adt) { - write_animdata(wd, arm->adt); - } + if (arm->adt) { + write_animdata(wd, arm->adt); + } - /* Direct data */ - for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) { - write_bone(wd, bone); - } + /* Direct data */ + for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) { + write_bone(wd, bone); } } - - mywrite_flush(wd); } -static void write_texts(WriteData *wd, ListBase *idbase) +static void write_text(WriteData *wd, Text *text) { - for (Text *text = idbase->first; text; text = text->id.next) { - if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) { - text->flags &= ~TXT_ISEXT; - } + if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) { + text->flags &= ~TXT_ISEXT; + } - /* write LibData */ - writestruct(wd, ID_TXT, Text, 1, text); - write_iddata(wd, &text->id); + /* write LibData */ + writestruct(wd, ID_TXT, Text, 1, text); + write_iddata(wd, &text->id); - if (text->name) { - writedata(wd, DATA, strlen(text->name) + 1, text->name); - } + if (text->name) { + writedata(wd, DATA, strlen(text->name) + 1, text->name); + } - if (!(text->flags & TXT_ISEXT)) { - /* now write the text data, in two steps for optimization in the readfunction */ - for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) { - writestruct(wd, DATA, TextLine, 1, tmp); - } + if (!(text->flags & TXT_ISEXT)) { + /* now write the text data, in two steps for optimization in the readfunction */ + for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) { + writestruct(wd, DATA, TextLine, 1, tmp); + } - for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) { - writedata(wd, DATA, tmp->len + 1, tmp->line); - } + for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) { + writedata(wd, DATA, tmp->len + 1, tmp->line); } } - - mywrite_flush(wd); } -static void write_speakers(WriteData *wd, ListBase *idbase) +static void write_speaker(WriteData *wd, Speaker *spk) { - for (Speaker *spk = idbase->first; spk; spk = spk->id.next) { - if (spk->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_SPK, Speaker, 1, spk); - write_iddata(wd, &spk->id); - - if (spk->adt) { - write_animdata(wd, spk->adt); - } + if (spk->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_SPK, Speaker, 1, spk); + write_iddata(wd, &spk->id); + + if (spk->adt) { + write_animdata(wd, spk->adt); } } } -static void write_sounds(WriteData *wd, ListBase *idbase) +static void write_sound(WriteData *wd, bSound *sound) { - for (bSound *sound = idbase->first; sound; sound = sound->id.next) { - if (sound->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_SO, bSound, 1, sound); - write_iddata(wd, &sound->id); - - if (sound->packedfile) { - PackedFile *pf = sound->packedfile; - writestruct(wd, DATA, PackedFile, 1, pf); - writedata(wd, DATA, pf->size, pf->data); - } + if (sound->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_SO, bSound, 1, sound); + write_iddata(wd, &sound->id); + + if (sound->packedfile) { + PackedFile *pf = sound->packedfile; + writestruct(wd, DATA, PackedFile, 1, pf); + writedata(wd, DATA, pf->size, pf->data); } } - - mywrite_flush(wd); } -static void write_groups(WriteData *wd, ListBase *idbase) +static void write_group(WriteData *wd, Group *group) { - for (Group *group = idbase->first; group; group = group->id.next) { - if (group->id.us > 0 || wd->current) { - /* write LibData */ - writestruct(wd, ID_GR, Group, 1, group); - write_iddata(wd, &group->id); + if (group->id.us > 0 || wd->current) { + /* write LibData */ + writestruct(wd, ID_GR, Group, 1, group); + write_iddata(wd, &group->id); - write_previews(wd, group->preview); + write_previews(wd, group->preview); - for (GroupObject *go = group->gobject.first; go; go = go->next) { - writestruct(wd, DATA, GroupObject, 1, go); - } + for (GroupObject *go = group->gobject.first; go; go = go->next) { + writestruct(wd, DATA, GroupObject, 1, go); } } - - mywrite_flush(wd); } -static void write_nodetrees(WriteData *wd, ListBase *idbase) +static void write_nodetree(WriteData *wd, bNodeTree *ntree) { - for (bNodeTree *ntree = idbase->first; ntree; ntree = ntree->id.next) { - if (ntree->id.us > 0 || wd->current) { - writestruct(wd, ID_NT, bNodeTree, 1, ntree); - /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot - * be linked, etc., so we write actual id data here only, for 'real' ID trees. */ - write_iddata(wd, &ntree->id); + if (ntree->id.us > 0 || wd->current) { + writestruct(wd, ID_NT, bNodeTree, 1, ntree); + /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot + * be linked, etc., so we write actual id data here only, for 'real' ID trees. */ + write_iddata(wd, &ntree->id); - write_nodetree(wd, ntree); - } + write_nodetree_nolib(wd, ntree); } } @@ -3303,47 +3221,41 @@ static void customnodes_free_deprecated_data(Main *mainvar) } #endif -static void write_brushes(WriteData *wd, ListBase *idbase) +static void write_brush(WriteData *wd, Brush *brush) { - for (Brush *brush = idbase->first; brush; brush = brush->id.next) { - if (brush->id.us > 0 || wd->current) { - writestruct(wd, ID_BR, Brush, 1, brush); - write_iddata(wd, &brush->id); + if (brush->id.us > 0 || wd->current) { + writestruct(wd, ID_BR, Brush, 1, brush); + write_iddata(wd, &brush->id); - if (brush->curve) { - write_curvemapping(wd, brush->curve); - } - if (brush->gradient) { - writestruct(wd, DATA, ColorBand, 1, brush->gradient); - } + if (brush->curve) { + write_curvemapping(wd, brush->curve); + } + if (brush->gradient) { + writestruct(wd, DATA, ColorBand, 1, brush->gradient); } } } -static void write_palettes(WriteData *wd, ListBase *idbase) +static void write_palette(WriteData *wd, Palette *palette) { - for (Palette *palette = idbase->first; palette; palette = palette->id.next) { - if (palette->id.us > 0 || wd->current) { - PaletteColor *color; - writestruct(wd, ID_PAL, Palette, 1, palette); - write_iddata(wd, &palette->id); - - for (color = palette->colors.first; color; color = color->next) { - writestruct(wd, DATA, PaletteColor, 1, color); - } + if (palette->id.us > 0 || wd->current) { + PaletteColor *color; + writestruct(wd, ID_PAL, Palette, 1, palette); + write_iddata(wd, &palette->id); + + for (color = palette->colors.first; color; color = color->next) { + writestruct(wd, DATA, PaletteColor, 1, color); } } } -static void write_paintcurves(WriteData *wd, ListBase *idbase) +static void write_paintcurve(WriteData *wd, PaintCurve *pc) { - for (PaintCurve *pc = idbase->first; pc; pc = pc->id.next) { - if (pc->id.us > 0 || wd->current) { - writestruct(wd, ID_PC, PaintCurve, 1, pc); - write_iddata(wd, &pc->id); + if (pc->id.us > 0 || wd->current) { + writestruct(wd, ID_PC, PaintCurve, 1, pc); + write_iddata(wd, &pc->id); - writestruct(wd, DATA, PaintCurvePoint, pc->tot_points, pc->points); - } + writestruct(wd, DATA, PaintCurvePoint, pc->tot_points, pc->points); } } @@ -3385,93 +3297,85 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction } } -static void write_movieclips(WriteData *wd, ListBase *idbase) +static void write_movieclip(WriteData *wd, MovieClip *clip) { - for (MovieClip *clip = idbase->first; clip; clip = clip->id.next) { - if (clip->id.us > 0 || wd->current) { - MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *object; + if (clip->id.us > 0 || wd->current) { + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *object; - writestruct(wd, ID_MC, MovieClip, 1, clip); - write_iddata(wd, &clip->id); + writestruct(wd, ID_MC, MovieClip, 1, clip); + write_iddata(wd, &clip->id); - if (clip->adt) { - write_animdata(wd, clip->adt); - } + if (clip->adt) { + write_animdata(wd, clip->adt); + } - write_movieTracks(wd, &tracking->tracks); - write_moviePlaneTracks(wd, &tracking->plane_tracks); - write_movieReconstruction(wd, &tracking->reconstruction); + write_movieTracks(wd, &tracking->tracks); + write_moviePlaneTracks(wd, &tracking->plane_tracks); + write_movieReconstruction(wd, &tracking->reconstruction); - object = tracking->objects.first; - while (object) { - writestruct(wd, DATA, MovieTrackingObject, 1, object); + object = tracking->objects.first; + while (object) { + writestruct(wd, DATA, MovieTrackingObject, 1, object); - write_movieTracks(wd, &object->tracks); - write_moviePlaneTracks(wd, &object->plane_tracks); - write_movieReconstruction(wd, &object->reconstruction); + write_movieTracks(wd, &object->tracks); + write_moviePlaneTracks(wd, &object->plane_tracks); + write_movieReconstruction(wd, &object->reconstruction); - object = object->next; - } + object = object->next; } } - - mywrite_flush(wd); } -static void write_masks(WriteData *wd, ListBase *idbase) +static void write_mask(WriteData *wd, Mask *mask) { - for (Mask *mask = idbase->first; mask; mask = mask->id.next) { - if (mask->id.us > 0 || wd->current) { - MaskLayer *masklay; + if (mask->id.us > 0 || wd->current) { + MaskLayer *masklay; - writestruct(wd, ID_MSK, Mask, 1, mask); - write_iddata(wd, &mask->id); + writestruct(wd, ID_MSK, Mask, 1, mask); + write_iddata(wd, &mask->id); - if (mask->adt) { - write_animdata(wd, mask->adt); - } + if (mask->adt) { + write_animdata(wd, mask->adt); + } - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - MaskSpline *spline; - MaskLayerShape *masklay_shape; + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + MaskLayerShape *masklay_shape; - writestruct(wd, DATA, MaskLayer, 1, masklay); + writestruct(wd, DATA, MaskLayer, 1, masklay); - for (spline = masklay->splines.first; spline; spline = spline->next) { - int i; + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; - void *points_deform = spline->points_deform; - spline->points_deform = NULL; + void *points_deform = spline->points_deform; + spline->points_deform = NULL; - writestruct(wd, DATA, MaskSpline, 1, spline); - writestruct(wd, DATA, MaskSplinePoint, spline->tot_point, spline->points); + writestruct(wd, DATA, MaskSpline, 1, spline); + writestruct(wd, DATA, MaskSplinePoint, spline->tot_point, spline->points); - spline->points_deform = points_deform; + spline->points_deform = points_deform; - for (i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; - if (point->tot_uw) { - writestruct(wd, DATA, MaskSplinePointUW, point->tot_uw, point->uw); - } + if (point->tot_uw) { + writestruct(wd, DATA, MaskSplinePointUW, point->tot_uw, point->uw); } } + } - for (masklay_shape = masklay->splines_shapes.first; - 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); - } + for (masklay_shape = masklay->splines_shapes.first; + 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); } } } - - mywrite_flush(wd); } static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers) @@ -3728,43 +3632,39 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier } } -static void write_linestyles(WriteData *wd, ListBase *idbase) +static void write_linestyle(WriteData *wd, FreestyleLineStyle *linestyle) { - for (FreestyleLineStyle *linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) { - if (linestyle->id.us > 0 || wd->current) { - writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle); - write_iddata(wd, &linestyle->id); + if (linestyle->id.us > 0 || wd->current) { + writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle); + write_iddata(wd, &linestyle->id); - if (linestyle->adt) { - write_animdata(wd, linestyle->adt); - } + if (linestyle->adt) { + write_animdata(wd, linestyle->adt); + } - write_linestyle_color_modifiers(wd, &linestyle->color_modifiers); - write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers); - write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers); - write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers); - for (int a = 0; a < MAX_MTEX; a++) { - if (linestyle->mtex[a]) { - writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]); - } - } - if (linestyle->nodetree) { - writestruct(wd, DATA, bNodeTree, 1, linestyle->nodetree); - write_nodetree(wd, linestyle->nodetree); + write_linestyle_color_modifiers(wd, &linestyle->color_modifiers); + write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers); + write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers); + write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers); + for (int a = 0; a < MAX_MTEX; a++) { + if (linestyle->mtex[a]) { + writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]); } } + if (linestyle->nodetree) { + writestruct(wd, DATA, bNodeTree, 1, linestyle->nodetree); + write_nodetree_nolib(wd, linestyle->nodetree); + } } } -static void write_cachefiles(WriteData *wd, ListBase *idbase) +static void write_cachefile(WriteData *wd, CacheFile *cache_file) { - for (CacheFile *cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) { - if (cache_file->id.us > 0 || wd->current) { - writestruct(wd, ID_CF, CacheFile, 1, cache_file); + if (cache_file->id.us > 0 || wd->current) { + writestruct(wd, ID_CF, CacheFile, 1, cache_file); - if (cache_file->adt) { - write_animdata(wd, cache_file->adt); - } + if (cache_file->adt) { + write_animdata(wd, cache_file->adt); } } } @@ -3931,38 +3831,131 @@ static bool write_file_handle( * avoid thumbnail detecting changes because of this. */ mywrite_flush(wd); - write_windowmanagers(wd, &mainvar->wm); - write_screens(wd, &mainvar->screen); - write_movieclips(wd, &mainvar->movieclip); - write_masks(wd, &mainvar->mask); - write_scenes(wd, &mainvar->scene); - write_curves(wd, &mainvar->curve); - write_mballs(wd, &mainvar->mball); - write_images(wd, &mainvar->image); - write_cameras(wd, &mainvar->camera); - write_lamps(wd, &mainvar->lamp); - write_lattices(wd, &mainvar->latt); - write_vfonts(wd, &mainvar->vfont); - write_keys(wd, &mainvar->key); - write_worlds(wd, &mainvar->world); - write_texts(wd, &mainvar->text); - write_speakers(wd, &mainvar->speaker); - write_sounds(wd, &mainvar->sound); - write_groups(wd, &mainvar->group); - write_armatures(wd, &mainvar->armature); - write_actions(wd, &mainvar->action); - write_objects(wd, &mainvar->object); - write_materials(wd, &mainvar->mat); - write_textures(wd, &mainvar->tex); - write_meshes(wd, &mainvar->mesh); - write_particlesettings(wd, &mainvar->particle); - write_nodetrees(wd, &mainvar->nodetree); - write_brushes(wd, &mainvar->brush); - write_palettes(wd, &mainvar->palettes); - write_paintcurves(wd, &mainvar->paintcurves); - write_gpencils(wd, &mainvar->gpencil); - write_linestyles(wd, &mainvar->linestyle); - write_cachefiles(wd, &mainvar->cachefiles); + ListBase *lbarray[MAX_LIBARRAY]; + int a = set_listbasepointers(mainvar, lbarray); + while (a--) { + ID *id = lbarray[a]->first; + + if (id && GS(id->name) == ID_LI) { + continue; /* Libraries are handled separately below. */ + } + + for (; id; id = id->next) { + switch ((ID_Type)GS(id->name)) { + case ID_WM: + write_windowmanager(wd, (wmWindowManager *)id); + break; + case ID_SCR: + write_screen(wd, (bScreen *)id); + break; + case ID_MC: + write_movieclip(wd, (MovieClip *)id); + break; + case ID_MSK: + write_mask(wd, (Mask *)id); + break; + case ID_SCE: + write_scene(wd, (Scene *)id); + break; + case ID_CU: + write_curve(wd, (Curve *)id); + break; + case ID_MB: + write_mball(wd, (MetaBall *)id); + break; + case ID_IM: + write_image(wd, (Image *)id); + break; + case ID_CA: + write_camera(wd, (Camera *)id); + break; + case ID_LA: + write_lamp(wd, (Lamp *)id); + break; + case ID_LT: + write_lattice(wd, (Lattice *)id); + break; + case ID_VF: + write_vfont(wd, (VFont *)id); + break; + case ID_KE: + write_key(wd, (Key *)id); + break; + case ID_WO: + write_world(wd, (World *)id); + break; + case ID_TXT: + write_text(wd, (Text *)id); + break; + case ID_SPK: + write_speaker(wd, (Speaker *)id); + break; + case ID_SO: + write_sound(wd, (bSound *)id); + break; + case ID_GR: + write_group(wd, (Group *)id); + break; + case ID_AR: + write_armature(wd, (bArmature *)id); + break; + case ID_AC: + write_action(wd, (bAction *)id); + break; + case ID_OB: + write_object(wd, (Object *)id); + break; + case ID_MA: + write_material(wd, (Material *)id); + break; + case ID_TE: + write_texture(wd, (Tex *)id); + break; + case ID_ME: + write_mesh(wd, (Mesh *)id); + break; + case ID_PA: + write_particlesettings(wd, (ParticleSettings *)id); + break; + case ID_NT: + write_nodetree(wd, (bNodeTree *)id); + break; + case ID_BR: + write_brush(wd, (Brush *)id); + break; + case ID_PAL: + write_palette(wd, (Palette *)id); + break; + case ID_PC: + write_paintcurve(wd, (PaintCurve *)id); + break; + case ID_GD: + write_gpencil(wd, (bGPdata *)id); + break; + case ID_LS: + write_linestyle(wd, (FreestyleLineStyle *)id); + break; + case ID_CF: + write_cachefile(wd, (CacheFile *)id); + break; + case ID_LI: + /* Do nothing, handled below - and should never be reached. */ + BLI_assert(0); + break; + case ID_IP: + /* Do nothing, deprecated. */ + break; + default: + /* Should never be reached. */ + BLI_assert(0); + break; + } + } + + mywrite_flush(wd); + } + + /* Special handling, operating over split Mains... */ write_libraries(wd, mainvar->next); /* So changes above don't cause a 'DNA1' to be detected as changed on undo. */ 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.h b/source/blender/bmesh/bmesh.h index f29d280d071..b84a3d5e559 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -192,9 +192,10 @@ * * These conventions should be used throughout the bmesh module. * - * - ``BM_***()`` - High level BMesh API function for use anywhere. - * - ``bmesh_***()`` - Low level API function. + * - ``bmesh_kernel_*()`` - Low level API, for primitive functions that others are built ontop of. + * - ``bmesh_***()`` - Low level API function. * - ``bm_***()`` - 'static' functions, not apart of the API at all, but use prefix since they operate on BMesh data. + * - ``BM_***()`` - High level BMesh API function for use anywhere. * - ``BMO_***()`` - High level operator API function for use anywhere. * - ``bmo_***()`` - Low level / internal operator API functions. * - ``_bm_***()`` - Functions which are called via macros only. 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_core.c b/source/blender/bmesh/intern/bmesh_core.c index 68cacf55efe..4fe14fdf5c9 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1021,7 +1021,7 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l) * \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp, * (use when flipping normals, disable when mirroring, eg: symmetrize). */ -void bmesh_loop_reverse( +void bmesh_kernel_loop_reverse( BMesh *bm, BMFace *f, const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) { @@ -1438,7 +1438,7 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example) * * \return A BMFace pointer */ -BMFace *bmesh_sfme( +BMFace *bmesh_kernel_split_face_make_edge( BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2, BMLoop **r_l, #ifdef USE_BMESH_HOLES @@ -1584,7 +1584,7 @@ BMFace *bmesh_sfme( * * \return The newly created BMVert pointer. */ -BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) +BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) { BMLoop *l_next; BMEdge *e_new; @@ -1766,7 +1766,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) * faces with just 2 edges. It is up to the caller to decide what to do with * these faces. */ -BMEdge *bmesh_jekv( +BMEdge *bmesh_kernel_join_edge_kill_vert( BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool check_edge_double, const bool kill_degenerate_faces) @@ -1920,7 +1920,7 @@ BMEdge *bmesh_jekv( * * Collapse an edge, merging surrounding data. * - * Unlike #BM_vert_collapse_edge & #bmesh_jekv which only handle 2 valence verts, + * Unlike #BM_vert_collapse_edge & #bmesh_kernel_join_edge_kill_vert which only handle 2 valence verts, * this can handle any number of connected edges/faces. * * <pre> @@ -1932,7 +1932,7 @@ BMEdge *bmesh_jekv( * +-+-+-+ +-+-+-+ * </pre> */ -BMVert *bmesh_jvke( +BMVert *bmesh_kernel_join_vert_kill_edge( BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool check_edge_double, const bool kill_degenerate_faces) @@ -2035,7 +2035,7 @@ BMVert *bmesh_jvke( * In the example A, faces \a f1 and \a f2 are joined by a single edge, * and the euler can safely be used. * In example B however, \a f1 and \a f2 are joined by multiple edges and will produce an error. - * The caller in this case should call #bmesh_jekv on the extra edges + * The caller in this case should call #bmesh_kernel_join_edge_kill_vert on the extra edges * before attempting to fuse \a f1 and \a f2. * * \note The order of arguments decides whether or not certain per-face attributes are present @@ -2044,7 +2044,7 @@ BMVert *bmesh_jvke( * * \return A BMFace pointer */ -BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) +BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) { BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL; int newlen = 0, i, f1len = 0, f2len = 0; @@ -2249,7 +2249,7 @@ bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src) } -/** \name BM_vert_separate, bmesh_vert_separate and friends +/** \name BM_vert_separate, bmesh_kernel_vert_separate and friends * \{ */ /* BM_edge_face_count(e) >= 1 */ @@ -2269,7 +2269,7 @@ BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e) * * \return Success */ -void bmesh_vert_separate( +void bmesh_kernel_vert_separate( BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select) { @@ -2385,7 +2385,7 @@ void bmesh_vert_separate( * * Takes a list of edges, which have been split from their original. * - * Any edges which failed to split off in #bmesh_vert_separate will be merged back into the original edge. + * Any edges which failed to split off in #bmesh_kernel_vert_separate will be merged back into the original edge. * * \param edges_separate * A list-of-lists, each list is from a single original edge (the first edge is the original), @@ -2398,27 +2398,32 @@ void bmesh_vert_separate( * \note this function looks like it could become slow, * but in common cases its only going to iterate a few times. */ -static void bmesh_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate) +static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate) { do { LinkNode *n_orig = edges_separate->link; do { - BMEdge *e_orig = n_orig->link; + LinkNode *n_prev = n_orig; LinkNode *n_step = n_orig->next; + BMEdge *e_orig = n_orig->link; do { BMEdge *e = n_step->link; BLI_assert(e != e_orig); - if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2)) { - BM_edge_splice(bm, e_orig, e); + if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2) && + BM_edge_splice(bm, e_orig, e)) + { + /* don't visit again */ + n_prev->next = n_step->next; } - } while ((n_step = n_step->next)); + } while ((n_prev = n_step), + (n_step = n_step->next)); } while ((n_orig = n_orig->next) && n_orig->next); } while ((edges_separate = edges_separate->next)); } /** - * High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate + * High level function which wraps both #bmesh_kernel_vert_separate and #bmesh_kernel_edge_separate */ void BM_vert_separate( BMesh *bm, BMVert *v, @@ -2435,7 +2440,7 @@ void BM_vert_separate( LinkNode *edges_orig = NULL; do { BMLoop *l_sep = e->l; - bmesh_edge_separate(bm, e, l_sep, copy_select); + bmesh_kernel_edge_separate(bm, e, l_sep, copy_select); BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); BLI_assert(e != l_sep->e); } while (bm_edge_supports_separate(e)); @@ -2444,10 +2449,10 @@ void BM_vert_separate( } } - bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select); + bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select); if (edges_separate) { - bmesh_vert_separate__cleanup(bm, edges_separate); + bmesh_kernel_vert_separate__cleanup(bm, edges_separate); } } @@ -2472,7 +2477,7 @@ void BM_vert_separate_hflag( LinkNode *edges_orig = NULL; do { BMLoop *l_sep = e->l; - bmesh_edge_separate(bm, e, l_sep, copy_select); + bmesh_kernel_edge_separate(bm, e, l_sep, copy_select); /* trick to avoid looping over separated edges */ if (edges_separate == NULL && edges_orig == NULL) { e_first = l_sep->e; @@ -2486,10 +2491,10 @@ void BM_vert_separate_hflag( } } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); - bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select); + bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select); if (edges_separate) { - bmesh_vert_separate__cleanup(bm, edges_separate); + bmesh_kernel_vert_separate__cleanup(bm, edges_separate); } } @@ -2574,7 +2579,7 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src) * \note Does nothing if \a l_sep is already the only loop in the * edge radial. */ -void bmesh_edge_separate( +void bmesh_kernel_edge_separate( BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select) { @@ -2620,7 +2625,7 @@ void bmesh_edge_separate( * * \note Will be a no-op and return original vertex if only two edges at that vertex. */ -BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) +BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep) { BMVert *v_new = NULL; BMVert *v_sep = l_sep->v; @@ -2630,10 +2635,12 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) /* peel the face from the edge radials on both sides of the * loop vert, disconnecting the face from its fan */ - if (!BM_edge_is_boundary(l_sep->e)) - bmesh_edge_separate(bm, l_sep->e, l_sep, false); - if (!BM_edge_is_boundary(l_sep->prev->e)) - bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false); + if (!BM_edge_is_boundary(l_sep->e)) { + bmesh_kernel_edge_separate(bm, l_sep->e, l_sep, false); + } + if (!BM_edge_is_boundary(l_sep->prev->e)) { + bmesh_kernel_edge_separate(bm, l_sep->prev->e, l_sep->prev, false); + } /* do inline, below */ #if 0 @@ -2681,13 +2688,13 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) } /** - * A version of #bmesh_urmv_loop that disconnects multiple loops at once. + * A version of #bmesh_kernel_unglue_region_make_vert that disconnects multiple loops at once. * The loops must all share the same vertex, can be in any order * and are all moved to use a single new vertex - which is returned. * * This function handles the details of finding fans boundaries. */ -BMVert *bmesh_urmv_loop_multi( +BMVert *bmesh_kernel_unglue_region_make_vert_multi( BMesh *bm, BMLoop **larr, int larr_len) { BMVert *v_sep = larr[0]->v; @@ -2756,7 +2763,8 @@ BMVert *bmesh_urmv_loop_multi( } STACK_PUSH(edges, e_iter); - } else { + } + else { /* at least one edge attached isn't connected to our loops */ is_mixed_edge_any = true; } @@ -2870,9 +2878,9 @@ static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_ /** * This function assumes l_sep is apart of a larger fan which has already been - * isolated by calling bmesh_edge_separate to segregate it radially. + * isolated by calling #bmesh_kernel_edge_separate to segregate it radially. */ -BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep) +BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep) { BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP); /* passing either 'l_sep->e', 'l_sep->prev->e' will work */ @@ -2881,20 +2889,6 @@ BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep) return v_new; } - -/** - * \brief Unglue Region Make Vert (URMV) - * - * Disconnects f_sep from the vertex fan at \a v_sep - * - * \return The newly created BMVert - */ -BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep) -{ - BMLoop *l = BM_face_vert_share_loop(f_sep, v_sep); - return bmesh_urmv_loop(bm, l); -} - /** * Avoid calling this where possible, * low level function so both face pointers remain intact but point to swapped data. diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index f72e9d7b198..fb6b66809f3 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -64,21 +64,16 @@ void BM_face_kill(BMesh *bm, BMFace *f); void BM_edge_kill(BMesh *bm, BMEdge *e); void BM_vert_kill(BMesh *bm, BMVert *v); -void bmesh_edge_separate( - BMesh *bm, BMEdge *e, BMLoop *l_sep, - const bool copy_select); bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src); bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src); bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b); -void bmesh_vert_separate( - BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - const bool copy_select); - -void bmesh_loop_reverse( +void bmesh_kernel_loop_reverse( BMesh *bm, BMFace *f, const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip); +void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b); + BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del); void BM_vert_separate( BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select, @@ -90,34 +85,43 @@ void BM_vert_separate_wire_hflag( BMesh *bm, BMVert *v_dst, BMVert *v_src, const char hflag); -/* EULER API - For modifying structure */ -BMFace *bmesh_sfme( +/** + * BMesh Kernel: For modifying structure. + * + * Names are on the verbose side but these are only for low-level access. + */ +void bmesh_kernel_vert_separate( + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + const bool copy_select); +void bmesh_kernel_edge_separate( + BMesh *bm, BMEdge *e, BMLoop *l_sep, + const bool copy_select); + +BMFace *bmesh_kernel_split_face_make_edge( BMesh *bm, BMFace *f, BMLoop *l1, BMLoop *l2, BMLoop **r_l, #ifdef USE_BMESH_HOLES - ListBase *holes, + ListBase *holes, #endif - BMEdge *example, - const bool no_double - ); + BMEdge *example, + const bool no_double + ); -BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); -BMEdge *bmesh_jekv( +BMVert *bmesh_kernel_split_edge_make_vert( + BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); +BMEdge *bmesh_kernel_join_edge_kill_vert( BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool check_edge_splice, const bool kill_degenerate_faces); -BMVert *bmesh_jvke( +BMVert *bmesh_kernel_join_vert_kill_edge( BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool check_edge_double, const bool kill_degenerate_faces); -BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); -BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep); -BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep); -BMVert *bmesh_urmv_loop_multi( - BMesh *bm, BMLoop **larr, int larr_len); -BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep); +BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); -void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b); +BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep); +BMVert *bmesh_kernel_unglue_region_make_vert_multi(BMesh *bm, BMLoop **larr, int larr_len); +BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep); #endif /* __BMESH_CORE_H__ */ 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 57a6d8d2e1a..d5d9e4abe2c 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -486,8 +486,7 @@ static void bm_mesh_edges_sharp_tag( BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle, float (*r_lnos)[3]) { - BMIter eiter, viter; - BMVert *v; + BMIter eiter; BMEdge *e; int i; @@ -498,19 +497,13 @@ static void bm_mesh_edges_sharp_tag( } { - char htype = BM_LOOP; + char htype = BM_VERT | BM_LOOP; if (fnos) { htype |= BM_FACE; } BM_mesh_elem_index_ensure(bm, htype); } - /* Clear all vertices' tags (means they are all smooth for now). */ - BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { - BM_elem_index_set(v, i); /* set_inline */ - BM_elem_flag_disable(v, BM_ELEM_TAG); - } - /* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were * all smooth). */ @@ -551,20 +544,45 @@ static void bm_mesh_edges_sharp_tag( no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no; copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no); } - else { - /* Sharp edge, tag its verts as such. */ - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + } + } + + bm->elem_index_dirty &= ~BM_EDGE; +} + +/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not. + * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */ +static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr) +{ + BMLoop *lfan_pivot_next = l_curr; + BMEdge *e_next = l_curr->e; + + BLI_assert(!BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)); + BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG); + + while (true) { + /* Much simpler than in sibling code with basic Mesh data! */ + lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot_next, &e_next); + + if (!lfan_pivot_next || !BM_elem_flag_test(e_next, BM_ELEM_TAG)) { + /* Sharp loop/edge, so not a cyclic smooth fan... */ + return false; + } + /* Smooth loop/edge... */ + else if (BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)) { + if (lfan_pivot_next == l_curr) { + /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can + * use initial l_curr/l_prev edge as start for this smooth fan. */ + return true; } + /* ... already checked in some previous looping, we can abort. */ + return false; } else { - /* Sharp edge, tag its verts as such. */ - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + /* ... we can skip it in future, and keep checking the smooth fan. */ + BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG); } } - - bm->elem_index_dirty &= ~(BM_EDGE | BM_VERT); } /* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c @@ -587,13 +605,11 @@ static void bm_mesh_loops_calc_normals( BLI_Stack *edge_vectors = NULL; { - char htype = BM_LOOP; + char htype = 0; if (vcos) { htype |= BM_VERT; } - if (fnos) { - htype |= BM_FACE; - } + /* Face/Loop indices are set inline below. */ BM_mesh_elem_index_ensure(bm, htype); } @@ -606,6 +622,21 @@ static void bm_mesh_loops_calc_normals( edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); } + /* Clear all loops' tags (means none are to be skipped for now). */ + int index_face, index_loop = 0; + BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) { + BMLoop *l_curr, *l_first; + + BM_elem_index_set(f_curr, index_face); /* set_inline */ + + l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); + do { + BM_elem_index_set(l_curr, index_loop++); /* set_inline */ + 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); + /* 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. */ @@ -614,16 +645,16 @@ static void bm_mesh_loops_calc_normals( l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); do { + /* A smooth edge, we have to check for cyclic smooth fan case. + * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as + * 'entry point', otherwise we can skip it. */ + /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store mlfan_pivot's in a stack, + * to avoid having to fan again around the vert during actual computation of clnor & clnorspace. + * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop() + * is quite cheap in term of CPU cycles, so really think it's not worth it. */ if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && - (!r_lnors_spacearr || BM_elem_flag_test(l_curr->v, BM_ELEM_TAG))) + (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !bm_mesh_loop_check_cyclic_smooth_fan(l_curr))) { - /* A smooth edge, and we are not generating lnors_spacearr, or the related vertex is sharp. - * We skip it because it is either: - * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit - * one of its ends, i.e. one of its two sharp edges), or... - * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex - * are just fine! - */ } else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) @@ -1481,23 +1512,6 @@ int BM_mesh_elem_count(BMesh *bm, const char htype) } } -/** - * 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. - * - * \note ``ele_src`` Is a duplicate, so we don't need to worry about getting in a feedback loop. - * - * \note If there are other customdata layers which need this functionality, it should be generalized. - * However #BM_mesh_remap is currently the only place where this is done. - */ -static void bm_mesh_remap_cd_update( - BMHeader *ele_dst, BMHeader *ele_src, - const int cd_elem_pyptr) -{ - void **pyptr_dst_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_dst), cd_elem_pyptr); - void **pyptr_src_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_src), cd_elem_pyptr); - *pyptr_dst_p = *pyptr_src_p; -} /** * Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays @@ -1513,9 +1527,9 @@ static void bm_mesh_remap_cd_update( */ 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; @@ -1538,7 +1552,9 @@ 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); /* Init the old-to-new vert pointers mapping */ @@ -1547,9 +1563,14 @@ void BM_mesh_remap( /* Make a copy of all vertices. */ verts_pool = bm->vtable; verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy"); + void **pyptrs = (cd_vert_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totvert, __func__) : NULL; for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) { *ve = **vep; /* printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/ + if (cd_vert_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ve), cd_vert_pyptr); + pyptrs[i] = *pyptr; + } } /* Copy back verts to their new place, and update old2new pointers mapping. */ @@ -1562,20 +1583,26 @@ void BM_mesh_remap( /* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/ BLI_ghash_insert(vptr_map, *vep, new_vep); if (cd_vert_pyptr != -1) { - bm_mesh_remap_cd_update(&(*vep)->head, &new_vep->head, cd_vert_pyptr); + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_vep), cd_vert_pyptr); + *pyptr = pyptrs[*new_idx]; } } bm->elem_index_dirty |= BM_VERT; bm->elem_table_dirty |= BM_VERT; MEM_freeN(verts_copy); + if (pyptrs) { + MEM_freeN(pyptrs); + } } /* Remap Edges */ 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); /* Init the old-to-new vert pointers mapping */ @@ -1584,8 +1611,13 @@ void BM_mesh_remap( /* Make a copy of all vertices. */ edges_pool = bm->etable; edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy"); + void **pyptrs = (cd_edge_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totedge, __func__) : NULL; for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) { *ed = **edp; + if (cd_edge_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ed), cd_edge_pyptr); + pyptrs[i] = *pyptr; + } } /* Copy back verts to their new place, and update old2new pointers mapping. */ @@ -1598,20 +1630,26 @@ void BM_mesh_remap( BLI_ghash_insert(eptr_map, *edp, new_edp); /* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/ if (cd_edge_pyptr != -1) { - bm_mesh_remap_cd_update(&(*edp)->head, &new_edp->head, cd_edge_pyptr); + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_edp), cd_edge_pyptr); + *pyptr = pyptrs[*new_idx]; } } bm->elem_index_dirty |= BM_EDGE; bm->elem_table_dirty |= BM_EDGE; MEM_freeN(edges_copy); + if (pyptrs) { + MEM_freeN(pyptrs); + } } /* Remap Faces */ 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); /* Init the old-to-new vert pointers mapping */ @@ -1620,8 +1658,13 @@ void BM_mesh_remap( /* Make a copy of all vertices. */ faces_pool = bm->ftable; faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy"); + void **pyptrs = (cd_poly_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totface, __func__) : NULL; for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) { *fa = **fap; + if (cd_poly_pyptr != -1) { + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)fa), cd_poly_pyptr); + pyptrs[i] = *pyptr; + } } /* Copy back verts to their new place, and update old2new pointers mapping. */ @@ -1633,7 +1676,8 @@ void BM_mesh_remap( *new_fap = *fa; BLI_ghash_insert(fptr_map, *fap, new_fap); if (cd_poly_pyptr != -1) { - bm_mesh_remap_cd_update(&(*fap)->head, &new_fap->head, cd_poly_pyptr); + void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_fap), cd_poly_pyptr); + *pyptr = pyptrs[*new_idx]; } } @@ -1641,6 +1685,9 @@ void BM_mesh_remap( bm->elem_table_dirty |= BM_FACE; MEM_freeN(faces_copy); + if (pyptrs) { + MEM_freeN(pyptrs); + } } /* And now, fix all vertices/edges/faces/loops pointers! */ @@ -2008,4 +2055,4 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags) vpool_dst, epool_dst, NULL, fpool_dst); bm->use_toolflags = use_toolflags; -}
\ No newline at end of file +} 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_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 500da6b8788..1cd51528e06 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -234,7 +234,7 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_de if (l_a->v == l_b->v) { const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - bmesh_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true); + bmesh_kernel_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true); } BMFace *faces[2] = {l_a->f, l_b->f}; @@ -288,9 +288,9 @@ BMFace *BM_face_split( } #ifdef USE_BMESH_HOLES - f_new = bmesh_sfme(bm, f, l_a, l_b, r_l, NULL, example, no_double); + f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, NULL, example, no_double); #else - f_new = bmesh_sfme(bm, f, l_a, l_b, r_l, example, no_double); + f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, example, no_double); #endif if (f_new) { @@ -370,19 +370,19 @@ BMFace *BM_face_split_n( f_tmp = BM_face_copy(bm, bm, f, true, true); #ifdef USE_BMESH_HOLES - f_new = bmesh_sfme(bm, f, l_a, l_b, &l_new, NULL, example, false); + f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, NULL, example, false); #else - f_new = bmesh_sfme(bm, f, l_a, l_b, &l_new, example, false); + f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, example, false); #endif - /* bmesh_sfme returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'. + /* bmesh_kernel_split_face_make_edge returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'. * The radial_next is for 'f' and goes from 'v_b' to 'v_a' */ if (f_new) { e = l_new->e; for (i = 0; i < n; i++) { - v_new = bmesh_semv(bm, v_b, e, &e_new); + v_new = bmesh_kernel_split_edge_make_vert(bm, v_b, e, &e_new); BLI_assert(v_new != NULL); - /* bmesh_semv returns in 'e_new' the edge going from 'v_new' to 'v_b' */ + /* bmesh_kernel_split_edge_make_vert returns in 'e_new' the edge going from 'v_new' to 'v_b' */ copy_v3_v3(v_new->co, cos[i]); /* interpolate the loop data for the loops with (v == v_new), using orig face */ @@ -507,7 +507,7 @@ BMEdge *BM_vert_collapse_faces( /* single face or no faces */ /* same as BM_vert_collapse_edge() however we already * have vars to perform this operation so don't call. */ - e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); + e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */ } @@ -542,7 +542,7 @@ BMEdge *BM_vert_collapse_edge( BMVert *tv2 = BM_edge_other_vert(e2, v_kill); if (tv2) { /* only action, other calls here only get the edge to return */ - e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); + e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); } } } @@ -564,7 +564,7 @@ BMVert *BM_edge_collapse( BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces) { - return bmesh_jvke(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); + return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces); } /** @@ -616,7 +616,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac) } v_other = BM_edge_other_vert(e, v); - v_new = bmesh_semv(bm, v, e, &e_new); + v_new = bmesh_kernel_split_edge_make_vert(bm, v, e, &e_new); if (r_e != NULL) { *r_e = e_new; } @@ -1090,23 +1090,18 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f /** * \brief Rip a single face from a vertex fan */ -BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv) +BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep) { - return bmesh_urmv(bm, sf, sv); + return bmesh_kernel_unglue_region_make_vert(bm, l_sep); } -/** - * \brief Rip a single face from a vertex fan - * - * \note same as #BM_face_vert_separate but faster (avoids a loop lookup) - */ -BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl) +BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep) { - return bmesh_urmv_loop(bm, sl); + return bmesh_kernel_unglue_region_make_vert_multi_isolated(bm, l_sep); } -BMVert *BM_face_loop_separate_multi( - BMesh *bm, BMLoop **larr, int larr_len) +BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len) { - return bmesh_urmv_loop_multi(bm, larr, larr_len); + return bmesh_kernel_unglue_region_make_vert_multi(bm, larr, larr_len); } + diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index 5e95e9a2cc7..330a714418d 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -86,9 +86,8 @@ enum { }; -BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv); -BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl); -BMVert *BM_face_loop_separate_multi( - BMesh *bm, BMLoop **larr, int larr_len); +BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep); +BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep); +BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len); #endif /* __BMESH_MODS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 0d0fdda2c4c..200a31b1a57 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1284,7 +1284,7 @@ static BMOpDefine bmo_bisect_plane_def = { {"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */ {{'\0'}}, }, - {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output new geometry from the cut */ + {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output geometry aligned with the plane (new and existing) */ {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */ {{'\0'}}}, bmo_bisect_plane_exec, @@ -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 6acd790fc0c..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; @@ -844,7 +844,7 @@ void BM_face_normal_flip_ex( BMesh *bm, BMFace *f, const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) { - bmesh_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip); + bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip); negate_v3(f->no); } @@ -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..f5c14304ea3 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1515,16 +1515,30 @@ float BM_loop_calc_face_angle(const BMLoop *l) */ void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) { - if (normal_tri_v3(r_normal, - l->prev->v->co, - l->v->co, - l->next->v->co) != 0.0f) - { - /* pass */ +#define FEPSILON 1e-5f + + /* 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_manhattan_v3(v_tmp) > FEPSILON) { + /* Not co-linear, we can compute crossproduct and normalize it into normal. */ + cross_v3_v3v3(r_normal, v1, v2); + normalize_v3(r_normal); } else { copy_v3_v3(r_normal, l->f->no); } + +#undef FEPSILON } /** @@ -2326,7 +2340,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 +2409,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 +2567,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/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_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c index bed1ea5cb94..2c80ff651b8 100644 --- a/source/blender/bmesh/operators/bmo_bisect_plane.c +++ b/source/blender/bmesh/operators/bmo_bisect_plane.c @@ -38,7 +38,8 @@ #include "intern/bmesh_operators_private.h" /* own include */ #define ELE_NEW 1 -#define ELE_INPUT 2 +#define ELE_CUT 2 +#define ELE_INPUT 4 void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) { @@ -69,7 +70,7 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) BM_mesh_bisect_plane(bm, plane, use_snap_center, true, - ELE_NEW, dist); + ELE_CUT, ELE_NEW, dist); if (clear_outer || clear_inner) { @@ -108,5 +109,5 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW | ELE_INPUT); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_CUT); } 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_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 e2ff09669d7..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); @@ -663,7 +663,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) /* run the separate arg */ if (!BM_edge_is_boundary(es->e_old)) { - bmesh_edge_separate(bm, es->e_old, es->l, false); + bmesh_kernel_edge_separate(bm, es->e_old, es->l, false); } /* calc edge-split info */ @@ -742,7 +742,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) /* disable touching twice, this _will_ happen if the flags not disabled */ BM_elem_flag_disable(v, BM_ELEM_TAG); - bmesh_vert_separate(bm, v, &vout, &r_vout_len, false); + bmesh_kernel_vert_separate(bm, v, &vout, &r_vout_len, false); v = NULL; /* don't use again */ /* in some cases the edge doesn't split off */ 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_offset_edgeloops.c b/source/blender/bmesh/operators/bmo_offset_edgeloops.c index 7a6f779b34f..a9840a72fc9 100644 --- a/source/blender/bmesh/operators/bmo_offset_edgeloops.c +++ b/source/blender/bmesh/operators/bmo_offset_edgeloops.c @@ -270,7 +270,7 @@ void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op) v_other = BM_edge_other_vert(e, v); if (BM_elem_index_get(v_other) == -1) { if (BM_vert_is_edge_pair(v_other)) { - /* defer bmesh_jekv to avoid looping over data we're removing */ + /* defer bmesh_kernel_join_edge_kill_vert to avoid looping over data we're removing */ v_other->e = e; STACK_PUSH(varr, v_other); } @@ -278,7 +278,7 @@ void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op) } while ((v = STACK_POP(varr))) { - bmesh_jekv(bm, v->e, v, true, false, false); + bmesh_kernel_join_edge_kill_vert(bm, v->e, v, true, false, false); } } } diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index 723e0b168e0..cca0f7387cd 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; @@ -837,8 +841,6 @@ void BM_mesh_calc_uvs_grid(BMesh *bm, const unsigned int x_segments, const unsig float x = 0.0f; float y = 0.0f; - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - int loop_index; BLI_assert(cd_loop_uv_offset != -1); @@ -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; @@ -1566,7 +1576,7 @@ void BM_mesh_calc_uvs_cone( BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for ensuring the mesh has UVs */ - x = 0.0f; + x = 1.0f; y = 1.0f - uv_height; BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { @@ -1580,7 +1590,7 @@ void BM_mesh_calc_uvs_cone( switch (loop_index) { case 0: - x += uv_width; + /* Continue in the last position */ break; case 1: y += uv_height; @@ -1598,8 +1608,6 @@ void BM_mesh_calc_uvs_cone( luv->uv[0] = x; luv->uv[1] = y; } - - x += uv_width; } else { /* top or bottom face - so unwrap it by transforming back to a circle and using the X/Y coords */ @@ -1629,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}, @@ -1644,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 51b92a3c45e..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 @@ -110,10 +110,10 @@ 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) +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; @@ -154,10 +154,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con /* common case, just cut the face once */ BM_face_split(bm, f, l_a, l_b, &l_new, NULL, true); if (l_new) { - if (oflag_center) { - BMO_edge_flag_enable(bm, l_new->e, oflag_center); - BMO_face_flag_enable(bm, l_new->f, oflag_center); - BMO_face_flag_enable(bm, f, oflag_center); + if (oflag_center | oflag_new) { + BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new); + } + if (oflag_new) { + BMO_face_flag_enable(bm, l_new->f, oflag_new); } } } @@ -170,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; /* ---- */ @@ -245,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, @@ -269,10 +270,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con f_tmp = BM_face_split(bm, face_split_arr[j], l_a, l_b, &l_new, NULL, true); if (l_new) { - if (oflag_center) { - BMO_edge_flag_enable(bm, l_new->e, oflag_center); - BMO_face_flag_enable(bm, l_new->f, oflag_center); - BMO_face_flag_enable(bm, face_split_arr[j], oflag_center); + if (oflag_center | oflag_new) { + BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new); + } + if (oflag_new) { + BMO_face_flag_enable(bm, l_new->f, oflag_new); } } @@ -307,10 +309,10 @@ finally: void BM_mesh_bisect_plane( BMesh *bm, const float plane[4], const bool use_snap_center, const bool use_tag, - const short oflag_center, const float eps) + 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 *); @@ -343,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; @@ -390,7 +392,7 @@ void BM_mesh_bisect_plane( const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)}; if (side[0] && side[1] && (side[0] != side[1])) { - const float e_fac = fabsf(dist[0]) / fabsf(dist[0] - dist[1]); + const float e_fac = dist[0] / (dist[0] - dist[1]); BMVert *v_new; if (e->l) { @@ -404,10 +406,17 @@ void BM_mesh_bisect_plane( } while ((l_iter = l_iter->radial_next) != l_first); } - v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac); + { + BMEdge *e_new; + v_new = BM_edge_split(bm, e, e->v1, &e_new, e_fac); + if (oflag_new) { + BMO_edge_flag_enable(bm, e_new, oflag_new); + } + } + vert_is_center_enable(v_new); - if (oflag_center) { - BMO_vert_flag_enable(bm, v_new, oflag_center); + if (oflag_new | oflag_center) { + BMO_vert_flag_enable(bm, v_new, oflag_new | oflag_center); } BM_VERT_DIR(v_new) = 0; @@ -416,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) { @@ -448,7 +457,7 @@ void BM_mesh_bisect_plane( MEM_freeN(edges_arr); while ((f = BLI_LINKSTACK_POP(face_stack))) { - bm_face_bisect_verts(bm, f, plane, oflag_center); + bm_face_bisect_verts(bm, f, plane, oflag_center, oflag_new); } /* now we have all faces to split in the stack */ diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h index 7f3a97c4c79..fb99a1c8214 100644 --- a/source/blender/bmesh/tools/bmesh_bisect_plane.h +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h @@ -30,6 +30,6 @@ void BM_mesh_bisect_plane( BMesh *bm, const float plane[4], const bool use_snap_center, const bool use_tag, - const short oflag_center, const float eps); + const short oflag_center, const short oflag_new, const float eps); #endif /* __BMESH_BISECT_PLANE_H__ */ 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 04e03664956..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 { @@ -120,7 +120,7 @@ void BM_mesh_separate_faces( } /* Perform the split */ - bmesh_urmv_loop_multi(bm, loop_split.data, loop_split.count); + BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count); BLI_buffer_empty(&loop_split); } diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 3801c9300df..bd47ee0214d 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -1934,7 +1934,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No mul_m4_m4m4(mat, ipar, temp); } - TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size); + bc_decompose(mat, job->loc, NULL, job->quat, job->size); if (par_job) { job->parent = par_job; diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 9c26ba83b44..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; @@ -156,11 +159,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O } #endif -std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm) -{ - return get_joint_id(bone, ob_arm); -} - // parent_mat is armature-space void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se, @@ -261,47 +259,59 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW: //bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); float mat[4][4]; + float bone_rest_mat[4][4]; /* derived from bone->arm_mat */ + float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */ - if (bone->parent) { - // get bone-space matrix from parent pose - /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); - float invpar[4][4]; - invert_m4_m4(invpar, parchan->pose_mat); - mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/ - - float invpar[4][4]; - invert_m4_m4(invpar, bone->parent->arm_mat); - mul_m4_m4m4(mat, invpar, bone->arm_mat); + bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat); - } - else { + if (!has_restmat) { + + /* Have no restpose matrix stored, try old style <= Blender 2.78 */ - //copy_m4_m4(mat, pchan->pose_mat); - //pose mat is object space - //New change: export bone->arm_mat - copy_m4_m4(mat, bone->arm_mat); - } + bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true); - // OPEN_SIM_COMPATIBILITY - if (export_settings->open_sim) { - // Remove rotations vs armature from transform - // parent_rest_rot * mat * irest_rot - float temp[4][4]; - copy_m4_m4(temp, bone->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - invert_m4(temp); + if (bone->parent) { + // get bone-space matrix from parent pose + /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); + float invpar[4][4]; + invert_m4_m4(invpar, parchan->pose_mat); + mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/ + float invpar[4][4]; + bc_create_restpose_mat(this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true); - mul_m4_m4m4(mat, mat, temp); + invert_m4_m4(invpar, parent_rest_mat); + mul_m4_m4m4(mat, invpar, bone_rest_mat); - if (bone->parent) { - copy_m4_m4(temp, bone->parent->arm_mat); + } + else { + copy_m4_m4(mat, bone_rest_mat); + } + + // OPEN_SIM_COMPATIBILITY + if (export_settings->open_sim) { + // Remove rotations vs armature from transform + // parent_rest_rot * mat * irest_rot + float temp[4][4]; + copy_m4_m4(temp, bone_rest_mat); temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + invert_m4(temp); + + mul_m4_m4m4(mat, mat, temp); - mul_m4_m4m4(mat, temp, mat); + if (bone->parent) { + copy_m4_m4(temp, parent_rest_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + + mul_m4_m4m4(mat, temp, mat); + } } } + if (this->export_settings->limit_precision) + bc_sanitize_mat(mat, 6); + TransformWriter::add_node_transform(node, mat, NULL); + } std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob) diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index 883a6aca847..d271b505aa9 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -83,8 +83,6 @@ private: void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); #endif - std::string get_joint_sid(Bone *bone, Object *ob_arm); - // Scene, SceneExporter and the list of child_objects // are required for writing bone parented objects void add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se, diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 17334ca326c..0ea8324ed7c 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -32,6 +32,7 @@ #include "COLLADAFWUniqueId.h" +extern "C" { #include "BKE_action.h" #include "BKE_depsgraph.h" #include "BKE_object.h" @@ -39,7 +40,9 @@ #include "BLI_string.h" #include "BLI_listbase.h" #include "ED_armature.h" +} +#include "collada_utils.h" #include "ArmatureImporter.h" // use node name, or fall back to original id if not present (name is optional) @@ -91,6 +94,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon { float mat[4][4]; float joint_inv_bind_mat[4][4]; + float joint_bind_mat[4][4]; int chain_length = 0; //Checking if bone is already made. @@ -106,7 +110,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon */ std::map<COLLADAFW::UniqueId, SkinInfo>::iterator skin_it; - bool bone_is_not_skinned = true; + bool bone_is_skinned = false; for (skin_it = skin_by_data_uid.begin(); skin_it != skin_by_data_uid.end(); skin_it++) { SkinInfo *b = &skin_it->second; @@ -114,7 +118,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon // get original world-space matrix invert_m4_m4(mat, joint_inv_bind_mat); - + copy_m4_m4(joint_bind_mat, mat); // And make local to armature Object *ob_arm = skin->BKE_armature_from_object(); if (ob_arm) { @@ -123,24 +127,14 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon mul_m4_m4m4(mat, invmat, mat); } - bone_is_not_skinned = false; + bone_is_skinned = true; break; } } // create a bone even if there's no joint data for it (i.e. it has no influence) - if (bone_is_not_skinned) { - float obmat[4][4]; - // bone-space - get_node_mat(obmat, node, NULL, NULL); - - // get world-space - if (parent) { - mul_m4_m4m4(mat, parent_mat, obmat); - } - else { - copy_m4_m4(mat, obmat); - } + if (!bone_is_skinned) { + get_node_mat(mat, node, NULL, NULL, parent_mat); } if (parent) bone->parent = parent; @@ -156,10 +150,11 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon int use_connect = be.get_use_connect(); switch (use_connect) { - case 1: bone->flag |= BONE_CONNECTED; - break; - case 0: bone->flag &= ~BONE_CONNECTED; - case -1: break; // not defined + case 1: bone->flag |= BONE_CONNECTED; + break; + case -1:/* Connect type not specified */ + case 0: bone->flag &= ~BONE_CONNECTED; + break; } if (be.has_roll()) { @@ -172,6 +167,15 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon bone->roll = angle; } copy_v3_v3(bone->head, mat[3]); + + if (bone_is_skinned) + { + float rest_mat[4][4]; + get_node_mat(rest_mat, node, NULL, NULL, NULL); + bc_set_IDPropertyMatrix(bone, "bind_mat", joint_bind_mat); + bc_set_IDPropertyMatrix(bone, "rest_mat", rest_mat); + } + add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero /* find smallest bone length in armature (used later for leaf bone length) */ @@ -273,7 +277,6 @@ void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone) } - void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip) { BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); @@ -289,12 +292,13 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone for (; child; child = child->next) { BoneExtended *be = extended_bones[child->name]; if (be != NULL) { - if (be->get_chain_length() <= clip) { - if (be->get_chain_length() > maxlen) { + int chain_len = be->get_chain_length(); + if (chain_len <= clip) { + if (chain_len > maxlen) { dominant_child = be; - maxlen = be->get_chain_length(); + maxlen = chain_len; } - else if (be->get_chain_length() == maxlen) { + else if (chain_len == maxlen) { dominant_child = NULL; } } @@ -308,7 +312,6 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone EditBone *pebone = bc_get_edit_bone(armature, parentbone->name); EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name()); if (pebone && !(cebone->flag & BONE_CONNECTED)) { - float vec[3]; sub_v3_v3v3(vec, cebone->head, pebone->head); @@ -321,14 +324,16 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH) { - pebone->tail[0] = cebone->head[0]; - pebone->tail[1] = cebone->head[1]; - pebone->tail[2] = cebone->head[2]; - + copy_v3_v3(pebone->tail, cebone->head); + pbe->set_tail(pebone->tail); /* to make fix_leafbone happy ...*/ if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) { + + BoneExtended *cbe = extended_bones[cebone->name]; + cbe->set_use_connect(true); + cebone->flag |= BONE_CONNECTED; - printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name); pbe->set_leaf_bone(false); + printf("Connect Bone chain: parent (%s --> %s) child)\n", pebone->name, cebone->name); } } } diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 06e151c363b..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; @@ -157,11 +160,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O } #endif -std::string ControllerExporter::get_joint_sid(Bone *bone, Object *ob_arm) -{ - return get_joint_id(bone, ob_arm); -} - std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob) { return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX; @@ -468,81 +466,6 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defb return source_id; } -static float get_property(Bone *bone, const char *key, float def) -{ - float result = def; - if (bone->prop) { - IDProperty *property = IDP_GetPropertyFromGroup(bone->prop, key); - if (property) { - switch (property->type) { - case IDP_INT: - result = (float)(IDP_Int(property)); - break; - case IDP_FLOAT: - result = (float)(IDP_Float(property)); - break; - case IDP_DOUBLE: - result = (float)(IDP_Double(property)); - break; - default: - result = def; - } - } - } - return result; -} - -/** - * This function creates an arbitrary rest pose matrix from - * data provided as custom properties. This is a workaround - * for support of maya's restpose matrix which can be arbitrary - * in opposition to Blender where the Rest pose Matrix is always - * the Identity matrix. - * - * The custom properties are: - * - * restpose_scale_x - * restpose_scale_y - * restpose_scale_z - * - * restpose_rot_x - * restpose_rot_y - * restpose_rot_z - * - * restpose_loc_x - * restpose_loc_y - * restpose_loc_z - * - * The matrix is only setup if the scale AND the rot properties are defined. - * The presence of the loc properties is optional. - * - * This feature has been implemented to support Second Life "Fitted Mesh" - * TODO: Check if an arbitrary rest pose matrix makes sense within Blender. - * Eventually leverage the custom property data into an "official" - * Edit_bone Property - */ -static void create_restpose_mat(Bone *bone, float mat[4][4]) -{ - float loc[3] = { - get_property(bone, "restpose_loc_x", 0.0), - get_property(bone, "restpose_loc_y", 0.0), - get_property(bone, "restpose_loc_z", 0.0) - }; - - float rot[3] = { - DEG2RADF(get_property(bone, "restpose_rot_x", 0.0)), - DEG2RADF(get_property(bone, "restpose_rot_y", 0.0)), - DEG2RADF(get_property(bone, "restpose_rot_z", 0.0)) - }; - - float scale[3] = { - get_property(bone, "restpose_scale_x", 1.0), - get_property(bone, "restpose_scale_y", 1.0), - get_property(bone, "restpose_scale_z", 1.0) - }; - - loc_eulO_size_to_mat4(mat, loc, rot, scale, 6); -} std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) { @@ -585,30 +508,36 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas float world[4][4]; float inv_bind_mat[4][4]; + float bind_mat[4][4]; /* derived from bone->arm_mat */ + + bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat); - // SL/OPEN_SIM COMPATIBILITY - if (export_settings->open_sim) { - // Only translations, no rotation vs armature - float temp[4][4]; - unit_m4(temp); - copy_v3_v3(temp[3], pchan->bone->arm_mat[3]); - mul_m4_m4m4(world, ob_arm->obmat, temp); - - // Add Maya restpose matrix (if defined as properties) - float restpose_mat[4][4]; - create_restpose_mat(pchan->bone, restpose_mat); - mul_m4_m4m4(world, world, restpose_mat); + if (!has_bindmat) { - } - else { - // make world-space matrix, arm_mat is armature-space - mul_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat); + /* Have no bind matrix stored, try old style <= Blender 2.78 */ + + bc_create_restpose_mat(this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true); + + // SL/OPEN_SIM COMPATIBILITY + if (export_settings->open_sim) { + + float loc[3]; + float rot[3] = { 0, 0, 0 }; + float scale[3]; + bc_decompose(bind_mat, loc, NULL, NULL, scale); + + // Only translations, no rotation vs armature + loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6); + } } + // make world-space matrix (bind_mat is armature-space) + mul_m4_m4m4(world, ob_arm->obmat, bind_mat); invert_m4_m4(mat, world); converter.mat4_to_dae(inv_bind_mat, mat); - + if (this->export_settings->limit_precision) + bc_sanitize_mat(inv_bind_mat, 6); source.appendValues(inv_bind_mat); } } diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h index 0be51187f6f..80b858ca6dd 100644 --- a/source/blender/collada/ControllerExporter.h +++ b/source/blender/collada/ControllerExporter.h @@ -84,8 +84,6 @@ private: void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); #endif - std::string get_joint_sid(Bone *bone, Object *ob_arm); - std::string get_controller_id(Object *ob_arm, Object *ob); std::string get_controller_id(Key *key, Object *ob); 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 9451cac9dae..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; @@ -51,7 +49,10 @@ public: bool use_blender_profile; bool sort_by_name; BC_export_transformation_type export_transformation_type; + bool open_sim; + bool limit_precision; + bool keep_bind_info; char *filepath; LinkNode *export_set; 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/ImportSettings.h b/source/blender/collada/ImportSettings.h index 2c52d73e756..4a2d4e8046a 100644 --- a/source/blender/collada/ImportSettings.h +++ b/source/blender/collada/ImportSettings.h @@ -37,6 +37,7 @@ public: bool fix_orientation; int min_chain_length; char *filepath; + bool keep_bind_info; }; #endif 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/TransformReader.cpp b/source/blender/collada/TransformReader.cpp index f8f31304d28..7f742be7e30 100644 --- a/source/blender/collada/TransformReader.cpp +++ b/source/blender/collada/TransformReader.cpp @@ -34,7 +34,21 @@ TransformReader::TransformReader(UnitConverter *conv) : unit_converter(conv) /* pass */ } -void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob) +void TransformReader::get_node_mat( + float mat[4][4], + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Animation> *animation_map, + Object *ob) +{ + get_node_mat(mat, node, animation_map, ob, NULL); +} + +void TransformReader::get_node_mat( + float mat[4][4], + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Animation> *animation_map, + Object *ob, + float parent_mat[4][4]) { float cur[4][4]; float copy[4][4]; @@ -52,6 +66,9 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std:: // then this is considered as redundant information. // So if we find a Matrix we use that and return. dae_matrix_to_mat4(tm, mat); + if (parent_mat) { + mul_m4_m4m4(mat, parent_mat, mat); + } return; case COLLADAFW::Transformation::TRANSLATE: dae_translate_to_mat4(tm, cur); @@ -80,6 +97,10 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std:: (*animation_map)[anim_list_id] = anim; } } + + if (parent_mat) { + mul_m4_m4m4(mat, parent_mat, mat); + } } void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]) diff --git a/source/blender/collada/TransformReader.h b/source/blender/collada/TransformReader.h index ab974b9ba85..08bb17ccac1 100644 --- a/source/blender/collada/TransformReader.h +++ b/source/blender/collada/TransformReader.h @@ -43,7 +43,7 @@ //struct Object; -class TransformReader : public TransformBase +class TransformReader { protected: @@ -59,7 +59,8 @@ public: TransformReader(UnitConverter *conv); void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob); - + void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob, float parent_mat[4][4]); + void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index 908111ebae6..b7eeff3b074 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -27,11 +27,10 @@ #include "BKE_object.h" +#include "BLI_math.h" #include "TransformWriter.h" -#include "BLI_math.h" - void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]) { float loc[3], rot[3], scale[3]; @@ -51,7 +50,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], converter->mat4_to_dae_double(dmat, local); delete converter; - TransformBase::decompose(local, loc, rot, NULL, scale); + bc_decompose(local, loc, rot, NULL, scale); if (node.getType() == COLLADASW::Node::JOINT) { // XXX Why are joints handled differently ? @@ -116,7 +115,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B case BC_TRANSFORMATION_TYPE_TRANSROTLOC: { float loc[3], rot[3], scale[3]; - TransformBase::decompose(f_obmat, loc, rot, NULL, scale); + bc_decompose(f_obmat, loc, rot, NULL, scale); add_transform(node, loc, rot, scale); break; } diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h index 7f69a4b9c95..5bb13d4aac9 100644 --- a/source/blender/collada/TransformWriter.h +++ b/source/blender/collada/TransformWriter.h @@ -33,9 +33,10 @@ #include "DNA_object_types.h" #include "collada_internal.h" +#include "collada_utils.h" #include "collada.h" -class TransformWriter : protected TransformBase +class TransformWriter { protected: void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]); diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index fe8b1d2320a..024bc4a4a5c 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -48,7 +48,8 @@ int collada_import(bContext *C, int find_chains, int auto_connect, int fix_orientation, - int min_chain_length) + int min_chain_length, + int keep_bind_info) { ImportSettings import_settings; @@ -58,6 +59,7 @@ int collada_import(bContext *C, import_settings.find_chains = find_chains != 0; import_settings.fix_orientation = fix_orientation != 0; import_settings.min_chain_length = min_chain_length; + import_settings.keep_bind_info = keep_bind_info !=0; DocumentImporter imp(C, &import_settings); if (imp.import()) return 1; @@ -78,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, @@ -87,7 +88,9 @@ int collada_export(Scene *sce, int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim) + int open_sim, + int limit_precision, + int keep_bind_info) { ExportSettings export_settings; @@ -102,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; @@ -112,7 +114,8 @@ int collada_export(Scene *sce, export_settings.sort_by_name = sort_by_name != 0; export_settings.export_transformation_type = export_transformation_type; export_settings.open_sim = open_sim != 0; - + export_settings.limit_precision = limit_precision != 0; + export_settings.keep_bind_info = keep_bind_info !=0; int includeFilter = OB_REL_NONE; if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index a4416608584..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; @@ -58,7 +63,9 @@ int collada_import(struct bContext *C, int find_chains, int auto_connect, int fix_orientation, - int min_chain_length); + int min_chain_length, + + int keep_bind_info); int collada_export(struct Scene *sce, const char *filepath, @@ -72,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, @@ -81,9 +87,10 @@ int collada_export(struct Scene *sce, int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim); - + 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 e1a13559b08..8974acb3460 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -162,18 +162,6 @@ void UnitConverter::calculate_scale(Scene &sce) size_to_mat4(scale_mat4, rescale); } -void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size) -{ - mat4_to_size(size, mat); - if (eul) { - mat4_to_eul(eul, mat); - } - if (quat) { - mat4_to_quat(quat, mat); - } - copy_v3_v3(loc, mat[3]); -} - /** * Translation map. * Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be @@ -341,7 +329,12 @@ std::string get_light_id(Object *ob) std::string get_joint_id(Bone *bone, Object *ob_arm) { - return translate_id(/*id_name(ob_arm) + "_" +*/ bone->name); + return translate_id(id_name(ob_arm) + "_" + bone->name); +} + +std::string get_joint_sid(Bone *bone, Object *ob_arm) +{ + return translate_id(bone->name); } std::string get_camera_id(Object *ob) @@ -351,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 4aa637a6876..5f3fa34edc1 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -85,12 +85,6 @@ public: }; -class TransformBase -{ -public: - void decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size); -}; - extern void clear_global_id_map(); /** Look at documentation of translate_map */ extern std::string translate_id(const std::string &id); @@ -104,10 +98,12 @@ extern std::string get_geometry_id(Object *ob, bool use_instantiation); extern std::string get_light_id(Object *ob); extern std::string get_joint_id(Bone *bone, Object *ob_arm); +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 2efa8b21d81..b09732f9102 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -32,7 +32,7 @@ #include "COLLADAFWMeshPrimitive.h" #include "COLLADAFWMeshVertexData.h" -#include "collada_utils.h" +#include <set> extern "C" { #include "DNA_modifier_types.h" @@ -63,6 +63,9 @@ extern "C" { #include "bmesh_tools.h" } +#include "collada_utils.h" +#include "ExportSettings.h" + float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index) { if (index >= array.getValuesCount()) @@ -352,6 +355,28 @@ void bc_match_scale(std::vector<Object *> *objects_done, } } +/* + Convenience function to get only the needed components of a matrix +*/ +void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size) +{ + if (size) { + mat4_to_size(size, mat); + } + + if (eul) { + mat4_to_eul(eul, mat); + } + + if (quat) { + mat4_to_quat(quat, mat); + } + + if (loc) { + copy_v3_v3(loc, mat[3]); + } +} + void bc_triangulate_mesh(Mesh *me) { bool use_beauty = false; @@ -612,3 +637,356 @@ int BoneExtended::get_use_connect() { return this->use_connect; } + +/** +* Stores a 4*4 matrix as a custom bone property array of size 16 +*/ +void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]) +{ + IDProperty *idgroup = (IDProperty *)ebone->prop; + if (idgroup == NULL) + { + IDPropertyTemplate val = { 0 }; + idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); + ebone->prop = idgroup; + } + + IDPropertyTemplate val = { 0 }; + val.array.len = 16; + val.array.type = IDP_FLOAT; + + IDProperty *data = IDP_New(IDP_ARRAY, &val, key); + float *array = (float *)IDP_Array(data); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + array[4 * i + j] = mat[i][j]; + + IDP_AddToGroup(idgroup, data); +} + +#if 0 +/** +* Stores a Float value as a custom bone property +* +* Note: This function is currently not needed. Keep for future usage +*/ +static void bc_set_IDProperty(EditBone *ebone, const char *key, float value) +{ + if (ebone->prop == NULL) + { + IDPropertyTemplate val = { 0 }; + ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); + } + + IDProperty *pgroup = (IDProperty *)ebone->prop; + IDPropertyTemplate val = { 0 }; + IDProperty *prop = IDP_New(IDP_FLOAT, &val, key); + IDP_Float(prop) = value; + IDP_AddToGroup(pgroup, prop); + +} +#endif + +/* +* Get a custom property when it exists. +* This function is also used to check if a property exists. +*/ +IDProperty *bc_get_IDProperty(Bone *bone, std::string key) +{ + return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str()); +} + +/** +* Read a custom bone property and convert to float +* Return def if the property does not exist. +*/ +float bc_get_property(Bone *bone, std::string key, float def) +{ + float result = def; + IDProperty *property = bc_get_IDProperty(bone, key); + if (property) { + switch (property->type) { + case IDP_INT: + result = (float)(IDP_Int(property)); + break; + case IDP_FLOAT: + result = (float)(IDP_Float(property)); + break; + case IDP_DOUBLE: + result = (float)(IDP_Double(property)); + break; + default: + result = def; + } + } + return result; +} + +/** +* Read a custom bone property and convert to matrix +* Return true if conversion was succesfull +* +* Return false if: +* - the property does not exist +* - is not an array of size 16 +*/ +bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]) +{ + IDProperty *property = bc_get_IDProperty(bone, key); + if (property && property->type == IDP_ARRAY && property->len == 16) { + float *array = (float *)IDP_Array(property); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + mat[i][j] = array[4 * i + j]; + return true; + } + return false; +} + +/** +* get a vector that is stored in 3 custom properties (used in Blender <= 2.78) +*/ +void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]) +{ + val[0] = bc_get_property(bone, key + "_x", def[0]); + val[1] = bc_get_property(bone, key + "_y", def[1]); + val[2] = bc_get_property(bone, key + "_z", def[2]); +} + +/** +* Check if vector exist stored in 3 custom properties (used in Blender <= 2.78) +*/ +static bool has_custom_props(Bone *bone, bool enabled, std::string key) +{ + if (!enabled) + return false; + + return (bc_get_IDProperty(bone, key + "_x") + || bc_get_IDProperty(bone, key + "_y") + || bc_get_IDProperty(bone, key + "_z")); + +} + +/** +* Check if custom information about bind matrix exists and modify the from_mat +* accordingly. +* +* Note: This is old style for Blender <= 2.78 only kept for compatibility +*/ +void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space) +{ + float loc[3]; + float rot[3]; + float scale[3]; + static const float V0[3] = { 0, 0, 0 }; + + if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") && + !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") && + !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale")) + { + /* No need */ + copy_m4_m4(to_mat, from_mat); + return; + } + + bc_decompose(from_mat, loc, rot, NULL, scale); + loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); + + if (export_settings->keep_bind_info) { + bc_get_property_vector(bone, "restpose_loc", loc, loc); + + if (use_local_space && bone->parent) { + Bone *b = bone; + while (b->parent) { + b = b->parent; + float ploc[3]; + bc_get_property_vector(b, "restpose_loc", ploc, V0); + loc[0] += ploc[0]; + loc[1] += ploc[1]; + loc[2] += ploc[2]; + } + } + } + + if (export_settings->keep_bind_info) { + if (bc_get_IDProperty(bone, "restpose_rot_x")) + rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0)); + if (bc_get_IDProperty(bone, "restpose_rot_y")) + rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0)); + if (bc_get_IDProperty(bone, "restpose_rot_z")) + rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0)); + } + + if (export_settings->keep_bind_info) { + bc_get_property_vector(bone, "restpose_scale", scale, scale); + } + + loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); + +} + +/* + Make 4*4 matrices better readable +*/ +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 7fdbef3b6cb..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" { @@ -53,8 +54,10 @@ extern "C" { #include "BKE_object.h" #include "BKE_DerivedMesh.h" #include "BKE_scene.h" +#include "BKE_idprop.h" } +#include "ImportSettings.h" #include "ExportSettings.h" #include "collada_internal.h" @@ -78,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); @@ -88,11 +92,32 @@ extern std::string bc_url_encode(std::string data); extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene); extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene); +extern void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size); + extern void bc_triangulate_mesh(Mesh *me); extern bool bc_is_leaf_bone(Bone *bone); extern EditBone *bc_get_edit_bone(bArmature * armature, char *name); extern int bc_set_layer(int bitfield, int layer, bool enable); extern int bc_set_layer(int bitfield, int layer); +extern void bc_sanitize_mat(float mat[4][4], int precision); + +extern IDProperty *bc_get_IDProperty(Bone *bone, std::string key); +extern void bc_set_IDProperty(EditBone *ebone, const char *key, float value); +extern void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]); + +extern float bc_get_property(Bone *bone, std::string key, float def); +extern void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]); +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 { 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_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/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 cb2f057a090..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" @@ -52,14 +50,6 @@ namespace DEG { -string deg_fcurve_id_name(const FCurve *fcu) -{ - char index_buf[32]; - // TODO(sergey): Use int-to-string utility or so. - BLI_snprintf(index_buf, sizeof(index_buf), "[%d]", fcu->array_index); - return string(fcu->rna_path) + index_buf; -} - static bool check_object_needs_evaluation(Object *object) { if (object->recalc & OB_RECALC_ALL) { @@ -77,72 +67,79 @@ static bool check_object_needs_evaluation(Object *object) return false; } -void deg_graph_build_finalize(Depsgraph *graph) +void deg_graph_build_flush_layers(Depsgraph *graph) { - /* STEP 1: Make sure new invisible dependencies are ready for use. - * - * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice - * to do it ahead of a time and don't spend time on flushing updates on - * every frame change. - */ - GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash) - { - if (id_node->layers == 0) { - ID *id = id_node->id; - if (GS(id->name) == ID_OB) { - Object *object = (Object *)id; - if (check_object_needs_evaluation(object)) { - id_node->tag_update(graph); - } - } - } - } - GHASH_FOREACH_END(); - /* STEP 2: Flush visibility layers from children to parent. */ - 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) +{ + /* STEP 1: Make sure new invisible dependencies are ready for use. + * + * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice + * to do it ahead of a time and don't spend time on flushing updates on + * every frame change. + */ + GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash) + { + if (id_node->layers == 0) { + ID *id = id_node->id; + if (GS(id->name) == ID_OB) { + Object *object = (Object *)id; + if (check_object_needs_evaluation(object)) { + id_node->tag_update(graph); + } + } + } + } + GHASH_FOREACH_END(); + /* STEP 2: Flush visibility layers from children to parent. */ + deg_graph_build_flush_layers(graph); /* STEP 3: Re-tag IDs for update if it was tagged before the relations * update tag. */ @@ -154,7 +151,7 @@ void deg_graph_build_finalize(Depsgraph *graph) } GHASH_FOREACH_END(); - if ((id_node->layers & graph->layers) != 0) { + if ((id_node->layers & graph->layers) != 0 || graph->layers == 0) { ID *id = id_node->id; if ((id->tag & LIB_TAG_ID_RECALC_ALL) && (id->tag & LIB_TAG_DOIT)) diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h index bdc030e3810..b8ea8c8e599 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.h +++ b/source/blender/depsgraph/intern/builder/deg_builder.h @@ -38,9 +38,7 @@ namespace DEG { struct Depsgraph; -/* Get unique identifier for FCurves and Drivers */ -string deg_fcurve_id_name(const FCurve *fcu); - void deg_graph_build_finalize(struct Depsgraph *graph); +void deg_graph_build_flush_layers(struct Depsgraph *graph); } // namespace DEG 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 6b7fb5246ca..55f1f93be6a 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,12 +347,11 @@ 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); } /* Object data. */ - if (ob->data) { + if (ob->data != NULL) { /* type-specific data... */ switch (ob->type) { case OB_MESH: /* Geometry */ @@ -490,27 +409,41 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) build_animdata(&ob->id); /* particle systems */ - if (ob->particlesystem.first) { + if (ob->particlesystem.first != NULL) { build_particles(scene, ob); } - /* grease pencil */ - if (ob->gpd) { + /* Grease pencil. */ + if (ob->gpd != NULL) { build_gpencil(ob->gpd); } + + /* Object that this is a proxy for. */ + if (ob->proxy) { + ob->proxy->proxy_from = ob; + build_object(scene, base, ob->proxy); + } + + /* Object dupligroup. */ + if (ob->dup_group != NULL) { + build_group(scene, base, ob->dup_group); + } } 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); } @@ -526,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(); } /** @@ -556,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); } @@ -579,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 @@ -610,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); } @@ -642,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); @@ -682,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 @@ -709,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); } } @@ -734,7 +668,8 @@ 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); + ComponentDepsNode *psys_comp = + add_component_node(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES); /* particle systems */ LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) { @@ -747,11 +682,11 @@ 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), + function_bind(BKE_particle_system_eval, + _1, + scene, + ob, + psys), DEG_OPCODE_PSYS_EVAL, psys->name); } @@ -760,12 +695,25 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob) // TODO... } +void DepsgraphNodeBuilder::build_cloth(Scene *scene, Object *object) +{ + ComponentDepsNode *cache_comp = add_component_node(&object->id, + DEG_NODE_TYPE_CACHE); + add_operation_node(cache_comp, + function_bind(BKE_object_eval_cloth, + _1, + scene, + object), + DEG_OPCODE_PLACEHOLDER, + "Cloth Modifier"); +} + /* Shapekeys */ 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"); } @@ -774,18 +722,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. @@ -794,48 +743,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 */ @@ -864,14 +799,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; } @@ -883,14 +818,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; } @@ -901,20 +836,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), @@ -941,24 +875,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"); } @@ -974,15 +908,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"); } } @@ -998,10 +930,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 */ @@ -1020,12 +952,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) { @@ -1064,8 +998,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 */ @@ -1121,8 +1054,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"); @@ -1133,10 +1065,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); } @@ -1158,9 +1090,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 c5035f35f6e..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,14 +119,14 @@ 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); void build_animdata(ID *id); OperationDepsNode *build_driver(ID *id, FCurve *fcurve); void build_ik_pose(Scene *scene, 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 99e61692231..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 @@ -81,21 +81,7 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene) /* scene objects */ LINKLIST_FOREACH (Base *, base, &scene->base) { Object *ob = base->object; - - /* object itself */ build_object(scene, base, ob); - - /* object that this is a proxy for */ - // XXX: the way that proxies work needs to be completely reviewed! - if (ob->proxy) { - ob->proxy->proxy_from = ob; - build_object(scene, base, ob->proxy); - } - - /* Object dupligroup. */ - if (ob->dup_group) { - build_group(scene, base, ob->dup_group); - } } /* rigidbody */ 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 94cff521edc..dbe8a5f1984 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,39 +416,61 @@ 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) { + if (ob->parent != NULL) { /* parent relationship */ 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) { - OperationKey constraint_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS); + if (ob->constraints.first != NULL) { + OperationKey constraint_key(&ob->id, + DEG_NODE_TYPE_TRANSFORM, + DEG_OPCODE_TRANSFORM_CONSTRAINTS); /* constraint relations */ // TODO: provide base op // XXX: this is broken - build_constraints(scene, &ob->id, DEPSNODE_TYPE_TRANSFORM, "", &ob->constraints, NULL); + build_constraints(scene, + &ob->id, + 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" @@ -430,28 +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; @@ -492,44 +535,64 @@ 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"); } } - /* particle systems */ - if (ob->particlesystem.first) { + /* Particle systems. */ + if (ob->particlesystem.first != NULL) { build_particles(scene, ob); } - /* grease pencil */ - if (ob->gpd) { + /* Grease pencil. */ + if (ob->gpd != NULL) { build_gpencil(ob->gpd); } + + /* Object that this is a proxy for. */ + if (ob->proxy != NULL) { + ob->proxy->proxy_from = ob; + build_object(bmain, scene, ob->proxy); + /* 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, 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. */ + if (ob->dup_group != NULL) { + build_group(bmain, scene, ob, ob->dup_group); + } } void DepsgraphRelationBuilder::build_object_parent(Object *ob) { - /* XXX: for now, need to use the component key (not just direct to the parent op), or else the matrix doesn't get reset */ - // 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); + /* XXX: for now, need to use the component key (not just direct to the parent op), + * or else the matrix doesn't get reset/ + */ + // XXX: @sergey - it would be good if we got that backwards flushing working + // when tagging for updates. + //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); @@ -537,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; } @@ -566,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; } @@ -608,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) { @@ -631,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) { @@ -641,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) { @@ -675,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])) { @@ -695,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); @@ -719,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 */ @@ -736,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); } } @@ -762,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); } } @@ -781,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... @@ -797,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 */ @@ -821,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. */ @@ -837,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]"); } } } @@ -865,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) { @@ -893,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 */ @@ -920,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]"); } } } @@ -933,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]"); } } @@ -1007,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 @@ -1034,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 { @@ -1047,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 @@ -1061,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]"); } } @@ -1081,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) { @@ -1119,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) @@ -1136,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. @@ -1150,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"); } } @@ -1179,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"); } } } @@ -1197,7 +1237,7 @@ 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); /* particle systems */ @@ -1208,7 +1248,7 @@ 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)) @@ -1217,46 +1257,13 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob) /* 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(time_src_key, psys_key, "TimeSrc -> 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) { @@ -1280,19 +1287,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"); } } @@ -1302,20 +1306,32 @@ 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... } +void DepsgraphRelationBuilder::build_cloth(Scene * /*scene*/, + Object *object, + ModifierData * /*md*/) +{ + OperationKey cache_key(&object->id, + DEG_NODE_TYPE_CACHE, + DEG_OPCODE_PLACEHOLDER, + "Cloth Modifier"); + /* Cache component affects on modifier. */ + OperationKey modifier_key(&object->id, + 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); @@ -1323,8 +1339,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 */ @@ -1332,8 +1348,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"); } /** @@ -1361,34 +1377,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, @@ -1399,7 +1407,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) * @@ -1408,28 +1416,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"); } } - prev_mod_key = mod_key; + if (md->type == eModifierType_Cloth) { + build_cloth(scene, ob, md); + } } } /* 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"); } } } @@ -1445,15 +1448,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) { @@ -1462,9 +1458,9 @@ 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) { @@ -1478,10 +1474,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; } @@ -1494,20 +1490,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; @@ -1531,14 +1527,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"); } } @@ -1553,19 +1548,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"); } } @@ -1579,20 +1573,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 */ @@ -1609,7 +1601,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"); @@ -1629,19 +1621,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"); } } @@ -1664,15 +1654,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 054e4103290..02f8fc69070 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -58,6 +58,7 @@ struct Main; struct Mask; struct Material; struct MTex; +struct ModifierData; struct MovieClip; struct bNodeTree; struct Object; @@ -77,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(); @@ -176,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); @@ -205,6 +198,7 @@ struct DepsgraphRelationBuilder void build_world(World *world); void build_rigidbody(Scene *scene); void build_particles(Scene *scene, Object *ob); + void build_cloth(Scene *scene, Object *object, ModifierData *md); void build_ik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, @@ -235,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; @@ -248,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> @@ -288,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); @@ -296,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()); } } } @@ -324,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; @@ -343,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 8a3476cff45..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" @@ -76,26 +76,7 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) /* scene objects */ LINKLIST_FOREACH (Base *, base, &scene->base) { Object *ob = base->object; - - /* object itself */ build_object(bmain, scene, ob); - - /* object that this is a proxy for */ - if (ob->proxy) { - ob->proxy->proxy_from = ob; - build_object(bmain, scene, ob->proxy); - /* 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"); - } - - /* Object dupligroup. */ - if (ob->dup_group) { - build_group(bmain, scene, ob, ob->dup_group); - } } /* rigidbody */ 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 e8ed03666a6..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,12 +53,12 @@ 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" - #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.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); } @@ -346,6 +347,31 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene) GHASH_FOREACH_END(); } scene->lay_updated |= graph->layers; + /* Special trick to get local view to work. */ + LINKLIST_FOREACH (Base *, base, &scene->base) { + Object *object = base->object; + DEG::IDDepsNode *id_node = graph->find_id_node(&object->id); + id_node->layers = 0; + } + LINKLIST_FOREACH (Base *, base, &scene->base) { + 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) { + Object *object = base->object; + DEG::IDDepsNode *id_node = graph->find_id_node(&object->id); + GHASH_FOREACH_BEGIN(DEG::ComponentDepsNode *, comp, id_node->components) + { + id_node->layers |= comp->layers; + } + GHASH_FOREACH_END(); + } } void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time)) diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc index 39c189629f2..77454cd85ec 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,9 +116,6 @@ 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); diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h index effd34a0eb9..c1a42941a7d 100644 --- a/source/blender/depsgraph/intern/depsgraph_types.h +++ b/source/blender/depsgraph/intern/depsgraph_types.h @@ -44,9 +44,6 @@ #include <string> #include <vector> -using std::string; -using std::vector; - struct bAction; struct ChannelDriver; struct ModifierData; @@ -56,6 +53,9 @@ struct FCurve; namespace DEG { +using std::string; +using std::vector; + /* Evaluation Operation for atomic operation */ // XXX: move this to another header that can be exposed? typedef function<void(struct EvaluationContext *)> DepsEvalOperationCb; @@ -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 = 1, /* Time-Source */ - DEPSNODE_TYPE_TIMESOURCE = 2, + 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 = 3, - /* Isolated sub-graph - used for keeping instanced data separate from - * instances using them. - */ - DEPSNODE_TYPE_SUBGRAPH = 4, + DEG_NODE_TYPE_ID_REF, /* **** Outer Types **** */ /* Parameters Component - Default when nothing else fits * (i.e. just SDNA property setting). */ - DEPSNODE_TYPE_PARAMETERS = 11, - /* Generic "Proxy-Inherit" Component - * XXX: Also for instancing of subgraphs? - */ - DEPSNODE_TYPE_PROXY = 12, + DEG_NODE_TYPE_PARAMETERS, + /* Generic "Proxy-Inherit" Component. */ + DEG_NODE_TYPE_PROXY, /* Animation Component * * XXX: merge in with parameters? */ - DEPSNODE_TYPE_ANIMATION = 13, + DEG_NODE_TYPE_ANIMATION, /* Transform Component (Parenting/Constraints) */ - DEPSNODE_TYPE_TRANSFORM = 14, + DEG_NODE_TYPE_TRANSFORM, /* Geometry Component (DerivedMesh/Displist) */ - DEPSNODE_TYPE_GEOMETRY = 15, + DEG_NODE_TYPE_GEOMETRY, /* Sequencer Component (Scene Only) */ - DEPSNODE_TYPE_SEQUENCER = 16, + DEG_NODE_TYPE_SEQUENCER, /* **** Evaluation-Related Outer Types (with Subdata) **** */ /* Pose Component - Owner/Container of Bones Eval */ - DEPSNODE_TYPE_EVAL_POSE = 21, + DEG_NODE_TYPE_EVAL_POSE, /* Bone Component - Child/Subcomponent of Pose */ - DEPSNODE_TYPE_BONE = 22, + DEG_NODE_TYPE_BONE, /* Particle Systems Component */ - DEPSNODE_TYPE_EVAL_PARTICLES = 23, + DEG_NODE_TYPE_EVAL_PARTICLES, /* Material Shading Component */ - DEPSNODE_TYPE_SHADING = 24, + DEG_NODE_TYPE_SHADING, /* Cache Component */ - DEPSNODE_TYPE_CACHE = 25, + 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 * @@ -258,83 +236,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..aafd7ebb1f9 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -888,7 +888,8 @@ 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: 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_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 47f42ab5321..8a366ce6a81 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -4160,7 +4160,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; } @@ -5850,6 +5850,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); @@ -5860,7 +5861,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; @@ -6047,6 +6048,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 a542bf8fa11..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); @@ -701,24 +701,25 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness */ { bGPDspoint *pt1, *pt2; - float pm[2]; + float s0[2], s1[2]; /* segment 'center' points */ + float pm[2]; /* normal from previous segment. */ int i; float fpt[3]; glShadeModel(GL_FLAT); glBegin(GL_QUADS); - + + /* get x and y coordinates from first point */ + mul_v3_m4v3(fpt, diff_mat, &points->x); + gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s0); + for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) { - float s0[2], s1[2]; /* segment 'center' points */ float t0[2], t1[2]; /* tessellated coordinates */ float m1[2], m2[2]; /* gradient and normal */ float mt[2], sc[2]; /* gradient for thickness, point for end-cap */ float pthick; /* thickness at segment point */ - /* get x and y coordinates from points */ - mul_v3_m4v3(fpt, diff_mat, &pt1->x); - gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s0); - + /* get x and y coordinates from point2 (point1 has already been computed in previous iteration). */ mul_v3_m4v3(fpt, diff_mat, &pt2->x); gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1); @@ -846,6 +847,8 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness glVertex2fv(t0); } + /* store computed point2 coordinates as point1 ones of next segment. */ + copy_v2_v2(s0, s1); /* store stroke's 'natural' normal for next stroke to use */ copy_v2_v2(pm, m2); } diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index ec5a42c23a5..5332bec0c64 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 */ @@ -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 fa9acc36a2b..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; @@ -2126,10 +2222,10 @@ static int gp_count_subdivision_cuts(bGPDstroke *gps) int totnewpoints = 0; for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) { if (pt->flag & GP_SPOINT_SELECT) { - if (i + 1 < gps->totpoints){ + if (i + 1 < gps->totpoints) { if (gps->points[i + 1].flag & GP_SPOINT_SELECT) { ++totnewpoints; - }; + } } } } @@ -2184,7 +2280,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op) /* if next point is selected add a half way point */ if (pt->flag & GP_SPOINT_SELECT) { - if (i + 1 < oldtotpoints){ + if (i + 1 < oldtotpoints) { if (temp_points[i + 1].flag & GP_SPOINT_SELECT) { pt_final = &gps->points[i2]; /* Interpolate all values */ @@ -2196,7 +2292,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op) pt_final->time = interpf(pt->time, next->time, 0.5f); pt_final->flag |= GP_SPOINT_SELECT; ++i2; - }; + } } } } 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 297058168a0..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" @@ -86,13 +85,14 @@ /* Core/Shared Utilities */ /* Poll callback for interpolation operators */ -static int gpencil_interpolate_poll(bContext *C) +static int gpencil_view3d_poll(bContext *C) { bGPdata *gpd = CTX_data_gpencil_data(C); bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); /* only 3D view */ - if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) { + ScrArea *sa = CTX_wm_area(C); + if (sa && sa->spacetype != SPACE_VIEW3D) { return 0; } @@ -625,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; @@ -649,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... */ @@ -673,7 +675,7 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot) ot->invoke = gpencil_interpolate_invoke; ot->modal = gpencil_interpolate_modal; ot->cancel = gpencil_interpolate_cancel; - ot->poll = gpencil_interpolate_poll; + ot->poll = gpencil_view3d_poll; /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; @@ -1017,7 +1019,7 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) /* api callbacks */ ot->exec = gpencil_interpolate_seq_exec; - ot->poll = gpencil_interpolate_poll; + ot->poll = gpencil_view3d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1025,24 +1027,14 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) /* ******************** Remove Breakdowns ************************ */ -/* Same as gpencil_interpolate_poll(), - * except we ALSO need to have an active frame that is a breakdown - */ static int gpencil_interpolate_reverse_poll(bContext *C) { - bGPdata *gpd = CTX_data_gpencil_data(C); - bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); - - /* only 3D view */ - if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) { + if (!gpencil_view3d_poll(C)) { return 0; } - - /* need data to interpolate */ - if (ELEM(NULL, gpd, gpl)) { - return 0; - } - + + bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); + /* need to be on a breakdown frame */ if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) { CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown"); 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_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 9fbce7dd203..252c199d46c 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) @@ -421,7 +420,7 @@ typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1); void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg); void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext); -void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg); +void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, struct wmOperator *op); /* void uiPupBlockOperator(struct bContext *C, uiBlockCreateFunc func, struct wmOperator *op, int opcontext); */ /* UNUSED */ void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *block); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 682db20af55..bcb1e3e648a 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_floor(rect, &rectf); + BLI_rcti_rctf_copy_round(rect, &rectf); BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin); } @@ -2288,7 +2288,7 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size) #ifdef WITH_PYTHON -static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value) +static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *r_value) { char str_unit_convert[256]; const int unit_type = UI_but_unit_type_get(but); @@ -2300,13 +2300,13 @@ static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), but->drawstr, ui_get_but_scale_unit(but, 1.0), but->block->unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type)); - return BPY_execute_string_as_number(C, str_unit_convert, value, true); + return BPY_execute_string_as_number(C, str_unit_convert, true, r_value); } #endif /* WITH_PYTHON */ -bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *value) +bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *r_value) { bool ok = false; @@ -2315,13 +2315,13 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double if (str[0] != '\0') { bool is_unit_but = (ui_but_is_float(but) && ui_but_is_unit(but)); /* only enable verbose if we won't run again with units */ - if (BPY_execute_string_as_number(C, str, value, is_unit_but == false)) { + if (BPY_execute_string_as_number(C, str, is_unit_but == false, r_value)) { /* if the value parsed ok without unit conversion this button may still need a unit multiplier */ if (is_unit_but) { char str_new[128]; - BLI_snprintf(str_new, sizeof(str_new), "%f", *value); - ok = ui_set_but_string_eval_num_unit(C, but, str_new, value); + BLI_snprintf(str_new, sizeof(str_new), "%f", *r_value); + ok = ui_set_but_string_eval_num_unit(C, but, str_new, r_value); } else { ok = true; /* parse normal string via py (no unit conversion needed) */ @@ -2329,17 +2329,16 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double } else if (is_unit_but) { /* parse failed, this is a unit but so run replacements and parse again */ - ok = ui_set_but_string_eval_num_unit(C, but, str, value); + ok = ui_set_but_string_eval_num_unit(C, but, str, r_value); } } #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 +3167,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, @@ -3913,6 +3914,8 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int o uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip) { wmOperatorType *ot = WM_operatortype_find(opname, 0); + if (str && str[0] == '\0') + return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip); return uiDefIconTextButO_ptr(block, type, ot, opcontext, icon, str, x, y, width, height, tip); } diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 5da294302e9..a04360b3395 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -39,6 +39,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_nla.h" @@ -210,6 +211,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str) /* updates */ driver->flag |= DRIVER_FLAG_RECOMPILE; + DAG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL); ok = true; } 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 6e3c3c3674a..a3f0e29065d 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -87,6 +87,7 @@ #include "WM_api.h" #include "WM_types.h" +#include "wm_event_system.h" #ifdef WITH_INPUT_IME # include "wm_window.h" @@ -380,6 +381,7 @@ typedef struct uiAfterFunc { void *butm_func_arg; int a2; + wmOperator *popup_op; wmOperatorType *optype; int opcontext; PointerRNA *opptr; @@ -635,13 +637,24 @@ PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext, return ptr; } +static void popup_check(bContext *C, wmOperator *op) +{ + if (op && op->type->check && op->type->check(C, op)) { + /* check for popup and re-layout buttons */ + ARegion *ar_menu = CTX_wm_menu(C); + if (ar_menu) + ED_region_tag_refresh_ui(ar_menu); + } +} + /** * Check if a #uiAfterFunc is needed for this button. */ static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but) { return (but->func || but->funcN || but->rename_func || but->optype || but->rnaprop || block->handle_func || - (but->type == UI_BTYPE_BUT_MENU && block->butm_func)); + (but->type == UI_BTYPE_BUT_MENU && block->butm_func) || + (block->handle && block->handle->popup_op)); } static void ui_apply_but_func(bContext *C, uiBut *but) @@ -682,6 +695,9 @@ static void ui_apply_but_func(bContext *C, uiBut *but) after->butm_func_arg = block->butm_func_arg; after->a2 = but->a2; } + + if (block->handle) + after->popup_op = block->handle->popup_op; after->optype = but->optype; after->opcontext = but->opcontext; @@ -766,6 +782,9 @@ static void ui_apply_but_funcs_after(bContext *C) if (after.context) CTX_store_set(C, after.context); + if (after.popup_op) + popup_check(C, after.popup_op); + if (after.opptr) { /* free in advance to avoid leak on exit */ opptr = *after.opptr; @@ -3359,7 +3378,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); @@ -3377,7 +3396,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); @@ -6665,7 +6684,7 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but); + UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL); } /** @@ -6738,6 +6757,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}; @@ -6769,6 +6789,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); @@ -6984,7 +7010,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); } @@ -7005,20 +7035,17 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), ICON_URL, "WM_OT_doc_view_manual_ui_context"); - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); + ptr_props = uiItemFullO(layout, "WM_OT_doc_view", + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), + ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); /* XXX inactive option, not for public! */ #if 0 - WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit"); + ptr_props = uiItemFullO(layout, "WM_OT_doc_edit", + "Submit Description", ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr_props, "doc_id", buf); RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); - - uiItemFullO(layout, "WM_OT_doc_edit", - "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); #endif } } @@ -7034,6 +7061,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; @@ -8373,7 +8408,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); @@ -9167,23 +9202,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; @@ -9778,13 +9813,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); @@ -10182,6 +10217,25 @@ void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle * void UI_popup_handlers_remove(ListBase *handlers, uiPopupBlockHandle *popup) { + wmEventHandler *handler; + + for (handler = handlers->first; handler; handler = handler->next) { + if (handler->ui_handle == ui_popup_handler && + handler->ui_remove == ui_popup_handler_remove && + handler->ui_userdata == popup) + { + /* tag refresh parent popup */ + if (handler->next && + handler->next->ui_handle == ui_popup_handler && + handler->next->ui_remove == ui_popup_handler_remove) + { + uiPopupBlockHandle *parent_popup = handler->next->ui_userdata; + ED_region_tag_refresh_ui(parent_popup->region); + } + break; + } + } + WM_event_remove_ui_handler(handlers, ui_popup_handler, ui_popup_handler_remove, popup, false); } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index d8f9fdcbaae..067279777ba 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -556,6 +556,7 @@ struct uiPopupBlockHandle { struct uiKeyNavLock keynav_state; /* for operator popups */ + struct wmOperator *popup_op; struct wmOperatorType *optype; ScrArea *ctx_area; ARegion *ctx_region; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index f6347388cc4..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.5f * UI_UNIT_X; + if (index != RNA_ENUM_VALUE) + w += 0.6f * UI_UNIT_X; } else { w = ui_text_icon_width(layout, name, icon, 0); @@ -2171,7 +2172,17 @@ static void ui_litem_layout_row(uiLayout *litem) x += neww; - if ((neww < minw || itemw == minw || item->flag & UI_ITEM_MIN) && w != 0) { + bool min_flag = item->flag & UI_ITEM_MIN; + /* ignore min flag for rows with right or center alignment */ + if (item->type != ITEM_BUTTON && + ELEM(((uiLayout *)item)->alignment, UI_LAYOUT_ALIGN_RIGHT, UI_LAYOUT_ALIGN_CENTER) && + litem->alignment == UI_LAYOUT_ALIGN_EXPAND && + ((uiItem *)litem)->flag & UI_ITEM_MIN) + { + min_flag = false; + } + + if ((neww < minw || min_flag) && w != 0) { /* fixed size */ item->flag |= UI_ITEM_FIXED; if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) { @@ -2253,10 +2264,11 @@ static void ui_litem_layout_row(uiLayout *litem) } /* single-column layout */ -static void ui_litem_estimate_column(uiLayout *litem) +static void ui_litem_estimate_column(uiLayout *litem, bool is_box) { uiItem *item; int itemw, itemh; + bool min_size_flag = true; litem->w = 0; litem->h = 0; @@ -2264,15 +2276,21 @@ static void ui_litem_estimate_column(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); + litem->w = MAX2(litem->w, itemw); litem->h += itemh; - if (item->next) + if (item->next && (!is_box || item != litem->items.first)) litem->h += litem->space; } + + if (min_size_flag) { + litem->item.flag |= UI_ITEM_MIN; + } } -static void ui_litem_layout_column(uiLayout *litem) +static void ui_litem_layout_column(uiLayout *litem, bool is_box) { uiItem *item; int itemh, x, y; @@ -2286,7 +2304,7 @@ static void ui_litem_layout_column(uiLayout *litem) y -= itemh; ui_item_position(item, x, y, litem->w, itemh); - if (item->next) + if (item->next && (!is_box || item != litem->items.first)) y -= litem->space; } @@ -2378,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); @@ -2428,7 +2448,7 @@ static void ui_litem_layout_root(uiLayout *litem) else if (litem->root->type == UI_LAYOUT_PIEMENU) ui_litem_layout_root_radial(litem); else - ui_litem_layout_column(litem); + ui_litem_layout_column(litem, false); } /* box layout */ @@ -2436,9 +2456,10 @@ static void ui_litem_estimate_box(uiLayout *litem) { uiStyle *style = litem->root->style; - ui_litem_estimate_column(litem); + ui_litem_estimate_column(litem, true); + litem->item.flag &= ~UI_ITEM_MIN; litem->w += 2 * style->boxspace; - litem->h += style->boxspace; + litem->h += 2 * style->boxspace; } static void ui_litem_layout_box(uiLayout *litem) @@ -2452,17 +2473,18 @@ static void ui_litem_layout_box(uiLayout *litem) h = litem->h; litem->x += style->boxspace; + litem->y -= style->boxspace; if (w != 0) litem->w -= 2 * style->boxspace; if (h != 0) litem->h -= 2 * style->boxspace; - ui_litem_layout_column(litem); + ui_litem_layout_column(litem, true); litem->x -= style->boxspace; litem->y -= style->boxspace; if (w != 0) litem->w += 2 * style->boxspace; - if (h != 0) litem->h += style->boxspace; + if (h != 0) litem->h += 2 * style->boxspace; /* roundbox around the sublayout */ but = box->roundbox; @@ -3115,7 +3137,7 @@ static void ui_item_estimate(uiItem *item) switch (litem->item.type) { case ITEM_LAYOUT_COLUMN: - ui_litem_estimate_column(litem); + ui_litem_estimate_column(litem, false); break; case ITEM_LAYOUT_COLUMN_FLOW: ui_litem_estimate_column_flow(litem); @@ -3170,7 +3192,9 @@ static void ui_item_align(uiLayout *litem, short nr) } else if (item->type == ITEM_LAYOUT_BOX) { box = (uiLayoutItemBx *)item; - box->roundbox->alignnr = nr; + if (!box->roundbox->alignnr) { + box->roundbox->alignnr = nr; + } } else if (((uiLayout *)item)->align) { ui_item_align((uiLayout *)item, nr); @@ -3212,7 +3236,7 @@ static void ui_item_layout(uiItem *item) switch (litem->item.type) { case ITEM_LAYOUT_COLUMN: - ui_litem_layout_column(litem); + ui_litem_layout_column(litem, false); break; case ITEM_LAYOUT_COLUMN_FLOW: ui_litem_layout_column_flow(litem); @@ -3556,14 +3580,13 @@ void uiLayoutOperatorButs( row = uiLayoutRow(layout, true); uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE); - WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); + wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); + op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMIN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&op_ptr, "operator", op->type->idname); - uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); - WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); + op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMOUT, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&op_ptr, "operator", op->type->idname); RNA_boolean_set(&op_ptr, "remove_active", true); - uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); } if (op->type->ui) { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 466978272bc..534bd4278ca 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1692,6 +1692,28 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar) UI_block_draw(C, block); } +/** + * Use to refresh centered popups on screen resizing (for splash). + */ +static void ui_block_region_popup_window_listener( + bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn) +{ + switch (wmn->category) { + case NC_WINDOW: + { + switch (wmn->action) { + case NA_EDITED: + { + /* window resize */ + ED_region_tag_refresh_ui(ar); + break; + } + } + break; + } + } +} + static void ui_popup_block_clip(wmWindow *window, uiBlock *block) { uiBut *bt; @@ -2003,6 +2025,11 @@ uiPopupBlockHandle *ui_popup_block_create( block = ui_popup_block_refresh(C, handle, butregion, but); handle = block->handle; + /* keep centered on window resizing */ + if ((block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) && handle->can_refresh) { + type.listener = ui_block_region_popup_window_listener; + } + return handle; } @@ -3285,7 +3312,7 @@ void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg) UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT); } -void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg) +void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, wmOperator *op) { wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; @@ -3294,6 +3321,7 @@ void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc po handle->popup = true; handle->retvalue = 1; + handle->popup_op = op; handle->popup_arg = arg; handle->popup_func = popup_func; handle->cancel_func = cancel_func; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 62f12cd7967..131584dd405 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -430,7 +430,7 @@ static void template_ID( uiLayoutRow(layout, true); } else if (flag & UI_ID_BROWSE) { - but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.5, UI_UNIT_Y, + but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, TIP_(template_id_browse_tip(type))); ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); /* default dragging of icon for id browse buttons */ diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index df6f098ee81..636b7e4e9ce 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -127,12 +127,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind break; case PROP_POINTER: { - PointerRNA pptr; - - pptr = RNA_property_pointer_get(ptr, prop); - if (!pptr.type) - pptr.type = RNA_property_pointer_type(ptr, prop); - icon = RNA_struct_ui_icon(pptr.type); + if (icon == 0) { + PointerRNA pptr = RNA_property_pointer_get(ptr, prop); + icon = RNA_struct_ui_icon(pptr.type ? pptr.type : RNA_property_pointer_type(ptr, prop)); + } if (icon == ICON_DOT) icon = 0; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 4a2c13e395f..f7f2b422724 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -873,22 +873,19 @@ static void widget_draw_icon( if (icon && icon != ICON_BLANK1) { float ofs = 1.0f / aspect; - if (but->drawflag & UI_BUT_ICON_LEFT || ui_block_is_pie_menu(but->block)) { - if (but->block->flag & UI_BLOCK_LOOP) { - if (but->type == UI_BTYPE_SEARCH_MENU) - xs = rect->xmin + 4.0f * ofs; - else - xs = rect->xmin + 2.0f * ofs; - } - else { + if (but->drawflag & UI_BUT_ICON_LEFT) { + /* special case - icon_only pie buttons */ + if (ui_block_is_pie_menu(but->block) && but->type != UI_BTYPE_MENU && but->str && but->str[0] == '\0') xs = rect->xmin + 2.0f * ofs; - } - ys = (rect->ymin + rect->ymax - height) / 2.0f; + else if (but->dt == UI_EMBOSS_NONE || but->type == UI_BTYPE_LABEL) + xs = rect->xmin + 2.0f * ofs; + else + xs = rect->xmin + 4.0f * ofs; } else { xs = (rect->xmin + rect->xmax - height) / 2.0f; - ys = (rect->ymin + rect->ymax - height) / 2.0f; } + ys = (rect->ymin + rect->ymax - height) / 2.0f; /* force positions to integers, for zoom levels near 1. draws icons crisp. */ if (aspect > 0.95f && aspect < 1.05f) { diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 3f9eb33e239..fb20d9f3caa 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -102,12 +102,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 +122,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 +133,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; + } - return OPERATOR_FINISHED; + 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 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 +244,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 +304,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 +376,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, "", ""); } @@ -482,6 +516,7 @@ 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; @@ -490,9 +525,11 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op) sequence_len = get_sequence_len(filename, &offset); } - 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 +560,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..af6f55d7a64 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -143,7 +143,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 baae92f962e..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; @@ -97,7 +96,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int use_blender_profile; int sort_by_name; int export_transformation_type; + int open_sim; + int limit_precision; + int keep_bind_info; int export_count; @@ -136,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"); @@ -148,6 +149,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection"); open_sim = RNA_boolean_get(op->ptr, "open_sim"); + limit_precision = RNA_boolean_get(op->ptr, "limit_precision"); + keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info"); + /* get editmode results */ ED_object_editmode_load(CTX_data_edit_object(C)); @@ -163,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, @@ -172,7 +175,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) use_blender_profile, sort_by_name, export_transformation_type, - open_sim); + + open_sim, + limit_precision, + keep_bind_info + ); if (export_count == 0) { BKE_report(op->reports, RPT_WARNING, "No objects selected -- Created empty export file"); @@ -231,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); @@ -256,11 +260,11 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER); row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE); + uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE); row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "use_object_instantiation", 0, NULL, ICON_NONE); + uiItemR(row, imfptr, "use_object_instantiation", 1, NULL, ICON_NONE); row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "use_blender_profile", 0, NULL, ICON_NONE); + uiItemR(row, imfptr, "use_blender_profile", 1, NULL, ICON_NONE); row = uiLayoutRow(box, false); split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); @@ -270,6 +274,12 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE); + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "limit_precision", 0, NULL, ICON_NONE); + } static void wm_collada_export_draw(bContext *UNUSED(C), wmOperator *op) @@ -296,6 +306,8 @@ static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op) void WM_OT_collada_export(wmOperatorType *ot) { + struct StructRNA *func = ot->srna; + static EnumPropertyItem prop_bc_export_mesh_type[] = { {BC_MESH_TYPE_VIEW, "view", 0, "View", "Apply modifier's view settings"}, {BC_MESH_TYPE_RENDER, "render", 0, "Render", "Apply modifier's render settings"}, @@ -303,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"; @@ -325,65 +343,74 @@ void WM_OT_collada_export(wmOperatorType *ot) ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); - RNA_def_boolean(ot->srna, + RNA_def_boolean(func, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers to exported mesh (non destructive))"); - RNA_def_int(ot->srna, "export_mesh_type", 0, INT_MIN, INT_MAX, + RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX, "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX); - RNA_def_enum(ot->srna, "export_mesh_type_selection", prop_bc_export_mesh_type, 0, + RNA_def_enum(func, "export_mesh_type_selection", prop_bc_export_mesh_type, 0, "Resolution", "Modifier resolution for export"); - RNA_def_boolean(ot->srna, "selected", 0, "Selection Only", + RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements"); - RNA_def_boolean(ot->srna, "include_children", 0, "Include Children", + RNA_def_boolean(func, "include_children", 0, "Include Children", "Export all children of selected objects (even if not selected)"); - RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures", + RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)"); - RNA_def_boolean(ot->srna, "include_shapekeys", 1, "Include Shape Keys", + RNA_def_boolean(func, "include_shapekeys", 1, "Include Shape Keys", "Export all Shape Keys from Mesh Objects"); - RNA_def_boolean(ot->srna, "deform_bones_only", 0, "Deform Bones only", + RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures"); - - RNA_def_boolean(ot->srna, "active_uv_only", 0, "Only Selected UV Map", + RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map", "Export only the selected UV Map"); - RNA_def_boolean(ot->srna, "include_uv_textures", 0, "Include UV Textures", - "Export textures assigned to the object UV Maps"); - - RNA_def_boolean(ot->srna, "include_material_textures", 0, "Include Material Textures", - "Export textures assigned to the object Materials"); - - RNA_def_boolean(ot->srna, "use_texture_copies", 1, "Copy", + RNA_def_boolean(func, "use_texture_copies", 1, "Copy", "Copy textures to same folder where the .dae file is exported"); - RNA_def_boolean(ot->srna, "triangulate", 1, "Triangulate", + RNA_def_boolean(func, "triangulate", 1, "Triangulate", "Export Polygons (Quads & NGons) as Triangles"); - RNA_def_boolean(ot->srna, "use_object_instantiation", 1, "Use Object Instances", + RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data"); - RNA_def_boolean(ot->srna, "use_blender_profile", 1, "Use Blender Profile", + RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile", "Export additional Blender specific information (for material, shaders, bones, etc.)"); - RNA_def_boolean(ot->srna, "sort_by_name", 0, "Sort by Object name", + RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); - RNA_def_int(ot->srna, "export_transformation_type", 0, INT_MIN, INT_MAX, - "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); - RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0, - "Transform", "Transformation type for translation, scale and rotation"); + RNA_def_int(func, "export_transformation_type", 0, 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"); - RNA_def_boolean(ot->srna, "open_sim", 0, "Export to SL/OpenSim", + + 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"); + + RNA_def_boolean(func, "limit_precision", 0, + "Limit Precision", "Reduce the precision of the exported data to 6 digits"); + + RNA_def_boolean(func, "keep_bind_info", 0, + "Keep Bind Info", "Store Bindpose information in custom bone properties for later use during Collada export"); + } @@ -395,7 +422,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) int find_chains; int auto_connect; int fix_orientation; - int min_chain_length; + int min_chain_length; + + int keep_bind_info; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); @@ -407,6 +436,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) find_chains = RNA_boolean_get(op->ptr, "find_chains"); auto_connect = RNA_boolean_get(op->ptr, "auto_connect"); fix_orientation = RNA_boolean_get(op->ptr, "fix_orientation"); + + keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info"); + min_chain_length = RNA_int_get(op->ptr, "min_chain_length"); RNA_string_get(op->ptr, "filepath", filename); @@ -416,7 +448,8 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) find_chains, auto_connect, fix_orientation, - min_chain_length)) + min_chain_length, + keep_bind_info) ) { return OPERATOR_FINISHED; } @@ -453,6 +486,13 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, false); uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE); + + box = uiLayoutBox(layout); + row = uiLayoutRow(box, false); + + row = uiLayoutRow(box, false); + uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE); + } static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op) @@ -508,5 +548,9 @@ void WM_OT_collada_import(wmOperatorType *ot) 0, INT_MAX); + RNA_def_boolean(ot->srna, + "keep_bind_info", 0, "Keep Bind Info", + "Store Bindpose information in custom bone properties for later use during Collada export"); + } #endif 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..a478526dee0 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); } 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_rip.c b/source/blender/editors/mesh/editmesh_rip.c index e05ce727e22..1a2f9fdb62b 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -596,7 +596,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BMVert *v_new; BLI_assert(l_sep->v == v); - v_new = bmesh_urmv_loop_region(bm, l_sep); + v_new = BM_face_loop_separate_multi_isolated(bm, l_sep); BLI_assert(BM_vert_find_first_loop(v)); BM_vert_select_set(bm, v, false); @@ -665,7 +665,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BM_vert_select_set(bm, v, false); - bmesh_vert_separate(bm, v, &vout, &vout_len, true); + bmesh_kernel_vert_separate(bm, v, &vout, &vout_len, true); if (vout_len < 2) { MEM_freeN(vout); 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 ae458c722f9..a901560079a 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) { @@ -1626,7 +1640,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! */ @@ -1656,8 +1670,38 @@ static int convert_exec(bContext *C, wmOperator *op) } } - CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) + ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases"); + + /* Ensure we get all meshes calculated with a sufficient data-mask, + * needed since re-evaluating single modifiers causes bugs if they depend + * on other objects data masks too, see: T50950. */ { + 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) || 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); + } + + uint64_t customdata_mask_prev = scene->customdata_mask; + scene->customdata_mask |= CD_MASK_MESH; + BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene); + scene->customdata_mask = customdata_mask_prev; + } + + for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) { + Base *base = link->ptr.data; ob = base->object; if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) { @@ -1700,7 +1744,7 @@ static int convert_exec(bContext *C, wmOperator *op) ED_rigidbody_object_remove(bmain, scene, newob); } } - else if (ob->type == OB_MESH && ob->modifiers.first) { /* converting a mesh with no modifiers causes a segfault */ + else if (ob->type == OB_MESH) { ob->flag |= OB_DONE; if (keep_original) { @@ -1724,7 +1768,6 @@ static int convert_exec(bContext *C, wmOperator *op) * cases this doesnt give correct results (when MDEF is used for eg) */ dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH); - // dm = mesh_create_derived_no_deform(ob1, NULL); /* this was called original (instead of get_derived). man o man why! (ton) */ DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH, true); @@ -1889,7 +1932,7 @@ static int convert_exec(bContext *C, wmOperator *op) ((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */ } } - CTX_DATA_END; + BLI_freelistN(&selected_editable_bases); if (!keep_original) { if (mballConverted) { 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 d601f5c3b14..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 */ @@ -1484,7 +1484,6 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(ob); BMesh *bm = em->bm; - const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); BMVert *bm_vert; BMIter bm_iter; GSet *visited; @@ -1493,6 +1492,8 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) BKE_mesh_ensure_skin_customdata(ob->data); + const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); + BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) && BLI_gset_add(visited, bm_vert)) 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/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..43b1d033d23 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); 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 87c08dc6583..fa18b82507e 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -196,7 +196,7 @@ static Main *load_main_from_memory(const void *blend, int blend_size) BlendFileData *bfd; G.fileflags |= G_FILE_NO_UI; - bfd = BLO_read_from_memory(blend, blend_size, NULL); + bfd = BLO_read_from_memory(blend, blend_size, NULL, BLO_READ_SKIP_NONE); if (bfd) { bmain = bfd->main; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 837573ad175..0878636d0fa 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; 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/area.c b/source/blender/editors/screen/area.c index e6bb604d387..9cfaf3b4c1d 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1749,7 +1749,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco) RNA_pointer_create(&(scr->id), &RNA_Area, sa, &areaptr); - uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.5 * U.widget_unit, U.widget_unit, + uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.6 * U.widget_unit, U.widget_unit, &areaptr, "type", 0, 0.0f, 0.0f, 0.0f, 0.0f, ""); return xco + 1.7 * U.widget_unit; 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..18f02aff482 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) { @@ -1758,7 +1762,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 +1926,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 +2169,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 a7a0a240259..c99d9add432 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2808,7 +2808,7 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent bScreen *sc = CTX_wm_screen(C); uiPopupMenu *pup; uiLayout *layout; - PointerRNA ptr1, ptr2; + PointerRNA ptr; ScrEdge *actedge; const int winsize_x = WM_window_pixels_x(win); const int winsize_y = WM_window_pixels_y(win); @@ -2820,22 +2820,17 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE); layout = UI_popup_menu_layout(pup); - WM_operator_properties_create(&ptr1, "SCREEN_OT_area_join"); - - /* mouse cursor on edge, '4' can fail on wide edges... */ - RNA_int_set(&ptr1, "min_x", event->x + 4); - RNA_int_set(&ptr1, "min_y", event->y + 4); - RNA_int_set(&ptr1, "max_x", event->x - 4); - RNA_int_set(&ptr1, "max_y", event->y - 4); - - WM_operator_properties_create(&ptr2, "SCREEN_OT_area_split"); - + ptr = uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); /* store initial mouse cursor position */ - RNA_int_set(&ptr2, "mouse_x", event->x); - RNA_int_set(&ptr2, "mouse_y", event->y); - - uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, ptr2.data, WM_OP_INVOKE_DEFAULT, 0); - uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, ptr1.data, WM_OP_INVOKE_DEFAULT, 0); + RNA_int_set(&ptr, "mouse_x", event->x); + RNA_int_set(&ptr, "mouse_y", event->y); + + ptr = uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + /* mouse cursor on edge, '4' can fail on wide edges... */ + RNA_int_set(&ptr, "min_x", event->x + 4); + RNA_int_set(&ptr, "min_y", event->y + 4); + RNA_int_set(&ptr, "max_x", event->x - 4); + RNA_int_set(&ptr, "max_y", event->y - 4); UI_popup_menu_end(C, pup); @@ -2903,10 +2898,23 @@ static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot) static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op)) { - wmOperator *lastop = CTX_wm_manager(C)->operators.last; - - if (lastop) + wmWindowManager *wm = CTX_wm_manager(C); + wmOperator *lastop = wm->operators.last; + + /* Seek last registered operator */ + while (lastop) { + if (lastop->type->flag & OPTYPE_REGISTER) { + break; + } + else { + lastop = lastop->prev; + } + } + + if (lastop) { + WM_operator_free_all_after(wm, lastop); WM_operator_repeat(C, lastop); + } return OPERATOR_CANCELLED; } @@ -2941,8 +2949,9 @@ static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNU layout = UI_popup_menu_layout(pup); for (i = items - 1, lastop = wm->operators.last; lastop; lastop = lastop->prev, i--) - if (WM_operator_repeat_check(C, lastop)) + if ((lastop->type->flag & OPTYPE_REGISTER) && WM_operator_repeat_check(C, lastop)) { uiItemIntO(layout, RNA_struct_ui_name(lastop->type->srna), ICON_NONE, op->type->idname, "index", i); + } UI_popup_menu_end(C, pup); @@ -3747,7 +3756,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); @@ -3874,22 +3883,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/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_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/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 547c2fba66f..e901b9f8026 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -72,7 +72,7 @@ void clip_graph_tracking_values_iterate_track( BKE_movieclip_get_size(clip, &sc->user, &width, &height); for (coord = 0; coord < 2; coord++) { - int i, prevfra = 0; + int i, prevfra = track->markers[0].framenr; bool open = false; float prevval = 0.0f; @@ -179,6 +179,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); bool has_bundle = false; char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2]; + const bool used_for_stabilization = (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT)); if (track == act_track) tracking->act_track = NULL; @@ -200,7 +201,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); - if (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT)) { + if (used_for_stabilization) { WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } 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..6c33091ff01 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1964,7 +1964,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/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 631ff06a77a..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" @@ -169,12 +166,15 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path) static void fsmenu_entry_generate_name(struct FSMenuEntry *fsentry, char *name, size_t name_size) { - char temp[FILE_MAX]; + int offset = 0; + int len = name_size; - BLI_strncpy(temp, fsentry->path, FILE_MAX); - BLI_add_slash(temp); - BLI_getlastdir(temp, name, name_size); - BLI_del_slash(name); + if (BLI_path_name_at_index(fsentry->path, -1, &offset, &len)) { + /* use as size */ + len += 1; + } + + BLI_strncpy(name, &fsentry->path[offset], MIN2(len, name_size)); if (!name[0]) { name[0] = '/'; name[1] = '\0'; @@ -537,28 +537,22 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) /* Finally get user favorite places */ if (read_bookmarks) { UInt32 seed; - OSErr err = noErr; - CFArrayRef pathesArray; - LSSharedFileListRef list; - LSSharedFileListItemRef itemRef; - CFIndex i, pathesCount; - CFURLRef cfURL = NULL; - CFStringRef pathString = NULL; - list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL); - pathesArray = LSSharedFileListCopySnapshot(list, &seed); - pathesCount = CFArrayGetCount(pathesArray); + LSSharedFileListRef list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL); + CFArrayRef pathesArray = LSSharedFileListCopySnapshot(list, &seed); + CFIndex pathesCount = CFArrayGetCount(pathesArray); - for (i = 0; i < pathesCount; i++) { - itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(pathesArray, i); + for (CFIndex i = 0; i < pathesCount; i++) { + LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(pathesArray, i); - err = LSSharedFileListItemResolve(itemRef, - kLSSharedFileListNoUserInteraction | - kLSSharedFileListDoNotMountVolumes, - &cfURL, NULL); - if (err != noErr) + CFURLRef cfURL = NULL; + OSErr err = LSSharedFileListItemResolve(itemRef, + kLSSharedFileListNoUserInteraction | + kLSSharedFileListDoNotMountVolumes, + &cfURL, NULL); + if (err != noErr || !cfURL) continue; - pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle); + CFStringRef pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle); if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8)) continue; 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..501a5a35899 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,8 +1093,7 @@ 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) { @@ -1890,7 +1890,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 +2899,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 +2935,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_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 d31a475e45e..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: @@ -1320,9 +1321,6 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point PropertyRNA *prop; const char *layer_name; char scene_name[MAX_ID_NAME - 2]; - wmOperatorType *ot = WM_operatortype_find("RENDER_OT_render", 1); - - BLI_assert(ot != 0); uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL); @@ -1339,11 +1337,9 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point scn_ptr = RNA_pointer_get(ptr, "scene"); RNA_string_get(&scn_ptr, "name", scene_name); - WM_operator_properties_create_ptr(&op_ptr, ot); + op_ptr = uiItemFullO(row, "RENDER_OT_render", "", ICON_RENDER_STILL, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&op_ptr, "layer", layer_name); RNA_string_set(&op_ptr, "scene", scene_name); - uiItemFullO_ptr(row, ot, "", ICON_RENDER_STILL, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); - } @@ -1792,6 +1788,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi Scene *scene = CTX_data_scene(C); PointerRNA imfptr = RNA_pointer_get(ptr, "format"); PointerRNA active_input_ptr, op_ptr; + wmOperatorType *ot; uiLayout *row, *col; int active_index; const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER; @@ -1830,11 +1827,10 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi active_input_ptr.id.data = ptr->id.data; col = uiLayoutColumn(row, true); - op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "", - ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false); + op_ptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&op_ptr, "direction", 1); - op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "", - ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + op_ptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&op_ptr, "direction", 2); if (active_input_ptr.data) { @@ -2166,14 +2162,7 @@ static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr)) { - PointerRNA op_ptr; - wmOperatorType *ot = WM_operatortype_find("NODE_OT_switch_view_update", 1); - - BLI_assert(ot != 0); - - WM_operator_properties_create_ptr(&op_ptr, ot); - - uiItemFullO_ptr(layout, ot, "Update Views", ICON_FILE_REFRESH, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + uiItemFullO(layout, "NODE_OT_switch_view_update", "Update Views", ICON_FILE_REFRESH, NULL, WM_OP_INVOKE_DEFAULT, 0); } static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2489,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) { @@ -2716,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; } } @@ -3087,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; @@ -3436,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*/ @@ -3463,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++) { @@ -3483,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++) { @@ -3618,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) { @@ -3638,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 d49df2afbd4..dc6b06790e0 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -44,6 +44,8 @@ #include "BKE_main.h" #include "BKE_node.h" #include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_texture.h" #include "ED_node.h" /* own include */ #include "ED_screen.h" @@ -105,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; } @@ -312,7 +316,10 @@ static int node_add_file_exec(bContext *C, wmOperator *op) switch (snode->nodetree->type) { case NTREE_SHADER: - type = SH_NODE_TEX_IMAGE; + if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C))) + type = SH_NODE_TEX_IMAGE; + else + type = SH_NODE_TEXTURE; break; case NTREE_TEXTURE: type = TEX_NODE_IMAGE; @@ -333,7 +340,14 @@ static int node_add_file_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - node->id = (ID *)ima; + if (type == SH_NODE_TEXTURE) { + Tex *tex = BKE_texture_add(CTX_data_main(C), DATA_(ima->id.name)); + tex->ima = ima; + node->id = (ID *)tex; + WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, node->id); + } + else + node->id = (ID *)ima; /* When adding new image file via drag-drop we need to load imbuf in order * to get proper image source. diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index f0567924edd..925298451ce 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -133,6 +133,7 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa) int in_out; uiLayout *layout = pa->layout, *row, *split, *col; PointerRNA ptr, sockptr, opptr; + wmOperatorType *ot; if (!ntree) return; @@ -146,23 +147,25 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa) split = uiLayoutRow(row, true); col = uiLayoutColumn(split, true); + ot = WM_operatortype_find("NODE_OT_tree_socket_add", false); uiItemL(col, IFACE_("Inputs:"), ICON_NONE); uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input", NULL, 0, 0, 0, 0); - opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + opptr = uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "in_out", SOCK_IN); col = uiLayoutColumn(split, true); uiItemL(col, IFACE_("Outputs:"), ICON_NONE); uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output", NULL, 0, 0, 0, 0); - opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + opptr = uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "in_out", SOCK_OUT); + ot = WM_operatortype_find("NODE_OT_tree_socket_move", false); col = uiLayoutColumn(row, true); - opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + opptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "direction", 1); - opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); + opptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "direction", 2); if (sock) { 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..914f8ffbe10 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -92,9 +92,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 +112,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 ""; 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_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 684a1f9fd67..121fe812016 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1040,9 +1040,6 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto struct DrawIconArg arg; float aspect; - /* icons tiny bit away from text */ - x -= 0.15f * UI_UNIT_Y; - /* make function calls a bit compacter */ arg.block = block; arg.id = tselem->id; @@ -1053,8 +1050,10 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto /* placement of icons, copied from interface_widgets.c */ aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT; - arg.x = x = x + 4.0f * aspect; - arg.y = y = y + 0.1f * UI_UNIT_Y; + x += 2.0f * aspect; + y += 2.0f * aspect; + arg.x = x; + arg.y = y; if (tselem->type) { switch (tselem->type) { @@ -1389,9 +1388,9 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa UI_draw_roundbox_corner_set(UI_CNR_ALL); glColor4ub(255, 255, 255, 100); UI_draw_roundbox( - (float) *offsx - 1.0f * ufac, + (float) *offsx + 1.0f * ufac, (float)ys + 1.0f * ufac, - (float)*offsx + UI_UNIT_X - 2.0f * ufac, + (float)*offsx + UI_UNIT_X - 1.0f * ufac, (float)ys + UI_UNIT_Y - ufac, (float)UI_UNIT_Y / 2.0f - ufac); glEnable(GL_BLEND); /* roundbox disables */ @@ -1536,9 +1535,9 @@ static void outliner_draw_tree_element( if (active != OL_DRAWSEL_NONE) { UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox( - (float)startx + UI_UNIT_X, + (float)startx + UI_UNIT_X + 1.0f * ufac, (float)*starty + 1.0f * ufac, - (float)startx + 2.0f * UI_UNIT_X - 2.0f * ufac, + (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac, (float)*starty + UI_UNIT_Y - 1.0f * ufac, UI_UNIT_Y / 2.0f - 1.0f * ufac); glEnable(GL_BLEND); /* roundbox disables it */ @@ -1549,16 +1548,13 @@ static void outliner_draw_tree_element( /* open/close icon, only when sublevels, except for scene */ if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) { int icon_x; - if (tselem->type == 0 && ELEM(te->idcode, ID_OB, ID_SCE)) - icon_x = startx; - else - icon_x = startx + 5 * ufac; + icon_x = startx; // icons a bit higher if (TSELEM_OPEN(tselem, soops)) - UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_DOWN); + UI_icon_draw((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN); else - UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_RIGHT); + UI_icon_draw((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT); } offsx += UI_UNIT_X; @@ -1568,7 +1564,7 @@ static void outliner_draw_tree_element( tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, 1.0f); - offsx += UI_UNIT_X; + offsx += UI_UNIT_X + 2 * ufac; } else offsx += 2 * ufac; @@ -1576,16 +1572,16 @@ static void outliner_draw_tree_element( if (tselem->type == 0 && ID_IS_LINKED_DATABLOCK(tselem->id)) { glPixelTransferf(GL_ALPHA_SCALE, 0.5f); if (tselem->id->tag & LIB_TAG_MISSING) { - UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN); + UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN); } else if (tselem->id->tag & LIB_TAG_INDIRECT) { - UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT); + UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT); } else { - UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT); + UI_icon_draw((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT); } glPixelTransferf(GL_ALPHA_SCALE, 1.0f); - offsx += UI_UNIT_X; + offsx += UI_UNIT_X + 2 * ufac; } glDisable(GL_BLEND); @@ -1757,7 +1753,7 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio // gray hierarchy lines UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.4f); starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET; - startx = 6; + startx = UI_UNIT_X / 2 - 1.0f; outliner_draw_hierarchy(soops, &soops->tree, startx, &starty); // items themselves diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 345ac353c11..265a19b9e7e 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -309,9 +309,12 @@ static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeSto ID *id = tselem->id; BLI_assert(te->idcode != 0 && id != NULL); - BLI_assert(te->idcode != ID_LI || ((Library *)id)->parent == NULL); UNUSED_VARS_NDEBUG(te); + if (te->idcode == ID_LI && ((Library *)id)->parent != NULL) { + BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked library '%s'", id->name); + return; + } if (id->tag & LIB_TAG_INDIRECT) { BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked id '%s'", id->name); return; @@ -516,7 +519,8 @@ void OUTLINER_OT_id_remap(wmOperatorType *ot) ot->flag = 0; - RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", ""); + prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", ""); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace"); RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, outliner_id_itemf); @@ -1940,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..."); } @@ -1962,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; @@ -2068,74 +2073,62 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false); uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE); uiLayout *layout = UI_popup_menu_layout(pup); - PointerRNA ptr; - WM_operator_properties_create_ptr(&ptr, ot); + /* Cannot use uiItemEnumO()... have multiple properties to set. */ + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_OBJECT); - /* Cannot use uiItemEnumO()... have multiple properties to set. */ - uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - + /* par becomes parent, make the associated menus */ if (par->type == OB_ARMATURE) { - WM_operator_properties_create_ptr(&ptr, ot); + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_ARMATURE); - uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME); - uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE); - uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO); - uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_BONE); - uiItemFullO_ptr(layout, ot, IFACE_("Bone"), - 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); } else if (par->type == OB_CURVE) { - WM_operator_properties_create_ptr(&ptr, ot); + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_CURVE); - uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_FOLLOW); - uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create_ptr(&ptr, ot); + + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_PATH_CONST); - uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); } else if (par->type == OB_LATTICE) { - WM_operator_properties_create_ptr(&ptr, ot); + ptr = uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_string_set(&ptr, "parent", parname); RNA_string_set(&ptr, "child", childname); RNA_enum_set(&ptr, "type", PAR_LATTICE); - uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0); } UI_popup_menu_end(C, pup); diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 89df471990a..7e05c76b35b 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; } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 4eda7977622..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); @@ -1254,6 +1260,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) { if (idlevel > 0) { outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL); + ED_undo_push(C, "Delete"); } break; } @@ -1261,6 +1268,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op) { if (idlevel > 0) { outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); + ED_undo_push(C, "Remap"); } break; } @@ -1369,18 +1377,20 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op) outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL); WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL); - ED_undo_push(C, "Rename"); + ED_undo_push(C, "Rename Library"); break; } case OL_LIB_DELETE: { outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL); + ED_undo_push(C, "Delete Library"); break; } case OL_LIB_RELOCATE: { /* rename */ outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, lib_relocate_cb, NULL); + ED_undo_push(C, "Relocate Library"); break; } case OL_LIB_RELOAD: diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index ede6b7ce469..46f212e3679 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -38,6 +38,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "DNA_scene_types.h" #include "DNA_mask_types.h" @@ -445,6 +447,7 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot) sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", ""); RNA_def_enum_funcs(prop, RNA_movieclip_itemf); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP); RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); ot->prop = prop; } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 8ae89941bdb..3ae4a233353 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; 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 149144d969a..314b7bf3335 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1265,7 +1265,7 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl else { /* wire */ if (armflag & ARM_POSEMODE) { - if (constflag) { + if (constflag && ((G.f & G_PICKSEL) == 0)) { /* set constraint colors */ if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) { glEnable(GL_BLEND); @@ -1406,7 +1406,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag set_ebone_glColor(boneflag); } else if (armflag & ARM_POSEMODE) { - if (constflag) { + if (constflag && ((G.f & G_PICKSEL) == 0)) { /* draw constraint colors */ if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) { glEnable(GL_BLEND); @@ -2360,7 +2360,6 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt) /* Draw name */ if (arm->flag & ARM_DRAWNAMES) { mid_v3_v3v3(vec, eBone->head, eBone->tail); - glRasterPos3fv(vec); view3d_cached_text_draw_add(vec, eBone->name, strlen(eBone->name), 10, 0, col); } /* Draw additional axes */ diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index be2e4ab05e0..884bc6b83ba 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, @@ -1824,16 +1821,16 @@ static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], con glBegin(mode); glVertex3fv(near_plane[2]); - glVertex3fv(near_plane[1]); - glVertex3fv(far_plane[1]); glVertex3fv(far_plane[2]); + glVertex3fv(far_plane[3]); + glVertex3fv(near_plane[3]); glEnd(); glBegin(mode); - glVertex3fv(far_plane[0]); - glVertex3fv(near_plane[0]); - glVertex3fv(near_plane[3]); glVertex3fv(far_plane[3]); + glVertex3fv(near_plane[3]); + glVertex3fv(near_plane[0]); + glVertex3fv(far_plane[0]); glEnd(); } @@ -4212,7 +4209,6 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (is_obact && BKE_paint_select_vert_test(ob)) { const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0; - glColor3f(0.0f, 0.0f, 0.0f); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); if (!use_depth) glDisable(GL_DEPTH_TEST); @@ -5124,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: */ @@ -6420,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); @@ -6476,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); @@ -6529,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 @@ -7832,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); @@ -8007,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; @@ -8446,8 +8437,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_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 351c7ccec15..34e01405e7e 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -814,10 +814,6 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) if (dv && dv->totweight) { ToolSettings *ts = scene->toolsettings; - wmOperatorType *ot_weight_set_active = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true); - wmOperatorType *ot_weight_paste = WM_operatortype_find("OBJECT_OT_vertex_weight_paste", true); - wmOperatorType *ot_weight_delete = WM_operatortype_find("OBJECT_OT_vertex_weight_delete", true); - wmOperatorType *ot; PointerRNA op_ptr, tools_ptr; PointerRNA *but_ptr; @@ -856,7 +852,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) /* The Weight Group Name */ - ot = ot_weight_set_active; + ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true); but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, dg->name, xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, ""); but_ptr = UI_but_operator_ptr_get(but); @@ -882,23 +878,16 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa) xco += x; /* The weight group paste function */ - - ot = ot_weight_paste; - WM_operator_properties_create_ptr(&op_ptr, ot); - RNA_int_set(&op_ptr, "weight_group", i); icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN; - uiItemFullO_ptr(row, ot, "", icon, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + op_ptr = uiItemFullO(row, "OBJECT_OT_vertex_weight_paste", "", icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_int_set(&op_ptr, "weight_group", i); /* The weight entry delete function */ - - ot = ot_weight_delete; - WM_operator_properties_create_ptr(&op_ptr, ot); - RNA_int_set(&op_ptr, "weight_group", i); icon = (locked) ? ICON_LOCKED : ICON_X; - uiItemFullO_ptr(row, ot, "", icon, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + op_ptr = uiItemFullO(row, "OBJECT_OT_vertex_weight_delete", "", icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS); + RNA_int_set(&op_ptr, "weight_group", i); yco -= UI_UNIT_Y; - } } } 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 8230a0de6b9..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; @@ -1405,6 +1405,8 @@ static bool view3d_localview_init( } } + DAG_on_visible_update(bmain, false); + return ok; } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 7d9063c3285..4686ff0523e 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; @@ -4278,7 +4272,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 +4942,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 +4970,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 +4982,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 +5559,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 +5593,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..ba474e93b70 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -828,7 +828,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 +845,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); @@ -2004,9 +2008,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 +2280,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 +2402,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 +2469,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 = ( 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 0a984d90ae3..ec066ba91a4 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -143,21 +143,17 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags) } /* for pose mode */ -static void stats_pose(Scene *scene, RegionView3D *rv3d, bPoseChannel *pchan) +static void protectflag_to_drawflags_pchan(RegionView3D *rv3d, const bPoseChannel *pchan) { - Bone *bone = pchan->bone; - - if (bone) { - calc_tw_center(scene, pchan->pose_head); - protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag); - } + protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag); } /* for editmode*/ -static void stats_editbone(RegionView3D *rv3d, EditBone *ebo) +static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *ebo) { - if (ebo->flag & BONE_EDITMODE_LOCKED) + if (ebo->flag & BONE_EDITMODE_LOCKED) { protectflag_to_drawflags(OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE, &rv3d->twdrawflag); + } } /* could move into BLI_math however this is only useful for display/editing purposes */ @@ -192,73 +188,71 @@ static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], con } -static int test_rotmode_euler(short rotmode) +static bool test_rotmode_euler(short rotmode) { return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0 : 1; } bool gimbal_axis(Object *ob, float gmat[3][3]) { - if (ob) { - if (ob->mode & OB_MODE_POSE) { - bPoseChannel *pchan = BKE_pose_channel_active(ob); - - if (pchan) { - float mat[3][3], tmat[3][3], obmat[3][3]; - if (test_rotmode_euler(pchan->rotmode)) { - eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode); - } - else if (pchan->rotmode == ROT_MODE_AXISANGLE) { - axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle); - } - else { /* quat */ - return 0; - } - - - /* apply bone transformation */ - mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat); - - if (pchan->parent) { - float parent_mat[3][3]; + if (ob->mode & OB_MODE_POSE) { + bPoseChannel *pchan = BKE_pose_channel_active(ob); - copy_m3_m4(parent_mat, pchan->parent->pose_mat); - mul_m3_m3m3(mat, parent_mat, tmat); - - /* needed if object transformation isn't identity */ - copy_m3_m4(obmat, ob->obmat); - mul_m3_m3m3(gmat, obmat, mat); - } - else { - /* needed if object transformation isn't identity */ - copy_m3_m4(obmat, ob->obmat); - mul_m3_m3m3(gmat, obmat, tmat); - } - - normalize_m3(gmat); - return 1; - } - } - else { - if (test_rotmode_euler(ob->rotmode)) { - eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode); + if (pchan) { + float mat[3][3], tmat[3][3], obmat[3][3]; + if (test_rotmode_euler(pchan->rotmode)) { + eulO_to_gimbal_axis(mat, pchan->eul, pchan->rotmode); } - else if (ob->rotmode == ROT_MODE_AXISANGLE) { - axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle); + else if (pchan->rotmode == ROT_MODE_AXISANGLE) { + axis_angle_to_gimbal_axis(mat, pchan->rotAxis, pchan->rotAngle); } else { /* quat */ return 0; } - if (ob->parent) { + + /* apply bone transformation */ + mul_m3_m3m3(tmat, pchan->bone->bone_mat, mat); + + if (pchan->parent) { float parent_mat[3][3]; - copy_m3_m4(parent_mat, ob->parent->obmat); - normalize_m3(parent_mat); - mul_m3_m3m3(gmat, parent_mat, gmat); + + copy_m3_m4(parent_mat, pchan->parent->pose_mat); + mul_m3_m3m3(mat, parent_mat, tmat); + + /* needed if object transformation isn't identity */ + copy_m3_m4(obmat, ob->obmat); + mul_m3_m3m3(gmat, obmat, mat); } + else { + /* needed if object transformation isn't identity */ + copy_m3_m4(obmat, ob->obmat); + mul_m3_m3m3(gmat, obmat, tmat); + } + + normalize_m3(gmat); return 1; } } + else { + if (test_rotmode_euler(ob->rotmode)) { + eulO_to_gimbal_axis(gmat, ob->rot, ob->rotmode); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + axis_angle_to_gimbal_axis(gmat, ob->rotAxis, ob->rotAngle); + } + else { /* quat */ + return 0; + } + + if (ob->parent) { + float parent_mat[3][3]; + copy_m3_m4(parent_mat, ob->parent->obmat); + normalize_m3(parent_mat); + mul_m3_m3m3(gmat, parent_mat, gmat); + } + return 1; + } return 0; } @@ -385,7 +379,7 @@ static int calc_manipulator_stats(const bContext *C) calc_tw_center(scene, ebo->head); totsel++; } - stats_editbone(rv3d, ebo); + protectflag_to_drawflags_ebone(rv3d, ebo); } else { for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { @@ -405,7 +399,7 @@ static int calc_manipulator_stats(const bContext *C) totsel++; } if (ebo->flag & BONE_SELECTED) { - stats_editbone(rv3d, ebo); + protectflag_to_drawflags_ebone(rv3d, ebo); } } } @@ -530,7 +524,8 @@ static int calc_manipulator_stats(const bContext *C) /* doesn't check selection or visibility intentionally */ Bone *bone = pchan->bone; if (bone) { - stats_pose(scene, rv3d, pchan); + calc_tw_center(scene, pchan->pose_head); + protectflag_to_drawflags_pchan(rv3d, pchan); totsel = 1; ok = true; } @@ -543,7 +538,8 @@ static int calc_manipulator_stats(const bContext *C) for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { Bone *bone = pchan->bone; if (bone && (bone->flag & BONE_TRANSFORM)) { - stats_pose(scene, rv3d, pchan); + calc_tw_center(scene, pchan->pose_head); + protectflag_to_drawflags_pchan(rv3d, pchan); } } ok = true; @@ -623,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: { @@ -634,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: { @@ -1720,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; @@ -1730,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) @@ -1743,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); @@ -1763,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 */ @@ -1779,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) { @@ -1845,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); @@ -1859,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; @@ -1867,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 058af768885..23158495b44 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -451,18 +451,18 @@ void initTransformOrientation(bContext *C, TransInfo *t) case V3D_MANIP_GIMBAL: unit_m3(t->spacemtx); - if (gimbal_axis(ob, t->spacemtx)) { + if (ob && gimbal_axis(ob, t->spacemtx)) { 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)); diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 3c9becc60dc..aecd24d4e40 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -234,7 +234,7 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH /* -------------------------------------------------------------------- */ -/** \Common utilities +/** Common utilities * \{ */ /** @@ -620,7 +620,7 @@ static float dist_aabb_to_plane( /* -------------------------------------------------------------------- */ -/** \Walk DFS +/** Walk DFS * \{ */ typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data); @@ -1122,15 +1122,14 @@ static bool snapDerivedMesh( 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)) - { + 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)) + ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL)) { return retval; } diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index e07831358d6..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) { @@ -497,7 +497,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) n->unit_sys, n->unit_type[idx]); /* Note: with angles, we always get values as radians here... */ - if (BPY_execute_string_as_number(C, str_unit_convert, &val, false)) { + if (BPY_execute_string_as_number(C, str_unit_convert, false, &val)) { n->val[idx] = (float)val; n->val_flag[idx] &= ~NUM_INVALID; } diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index fab5b7e821f..4e021d4833e 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -419,6 +419,9 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op) if (G.debug & G_DEBUG) printf("redo_cb: operator redo %s\n", op->type->name); + + WM_operator_free_all_after(wm, op); + ED_undo_pop_op(C, op); if (op->type->check) { diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 59119529934..d4ceaa39d3c 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -510,7 +510,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_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 6b37a81db8c..212c4c5ab7a 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -3139,7 +3139,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 211394e7932..b5512aa108d 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -360,7 +360,7 @@ static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data) BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]); for (i = 0; i < type; i++) { - BLI_dynstr_appendf(ds, "%f", data[i]); + BLI_dynstr_appendf(ds, "%.12f", data[i]); if (i == type - 1) BLI_dynstr_append(ds, ")"); else @@ -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..ef2060122e0 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,126 @@ 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 = vec3(mix(0.1, 0.03, metallic)) * base_color.rgb; + + 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 + Tangent = vec3(1.0, 0.0, 0.0); + if (N.x != 0.0 || N.y != 0.0) { + vec3 N_xz = normalize(vec3(N.x, 0.0, N.z)); + + vec3 axis = normalize(cross(vec3(0.0, 0.0, 1.0), N_xz)); + float angle = acos(dot(vec3(0.0, 0.0, 1.0), N_xz)); + + Tangent = normalize(rotate_vector(vec3(1.0, 0.0, 0.0), axis, angle)); + } + } + + /* 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(gl_NormalMatrix * light_position_world); + + vec3 H = normalize(light_position + V); + + 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; + + diffuse_and_specular_bsdf = (M_1_PI * mix(Fd, ss, subsurface) * base_color.rgb + Fsheen) + * (1.0 - metallic) + Gs * Fs * Ds; + } + 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); + } + clearcoat_bsdf *= max(CNdotL, 0.0); + + L += light_specular * (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 +3032,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 +3749,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/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..e7abfdc7d67 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); /** * 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..ff19a14dbff 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -214,7 +214,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 +222,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 +238,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 +281,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 +361,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 +402,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 +421,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 +710,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) { @@ -1406,7 +1406,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 +1759,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 +2065,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 +2577,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 +2688,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..ec544e65355 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) 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/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 df1142cb61e..3e878fab66b 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_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 32b43c7ea55..823a7f0812f 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -277,6 +277,7 @@ typedef struct MirrorModifierData { short axis DNA_DEPRECATED; /* deprecated, use flag instead */ short flag; float tolerance; + float uv_offset[2]; struct Object *mirror_ob; } MirrorModifierData; 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_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index b7539eaedd9..92c789f2feb 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/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 73c341e35ba..5e7e7366e35 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -467,13 +467,18 @@ typedef struct UserDef { int audioformat; int audiochannels; - int scrollback; /* console scrollback limit */ - int dpi; /* range 48-128? */ - char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */ + int scrollback; /* console scrollback limit */ + int dpi; /* range 48-128? */ + float ui_scale; /* interface scale */ + int pad1; + char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */ char pad2; short transopts; short menuthreshold1, menuthreshold2; - + + /* startup template */ + char app_template[64]; + struct ListBase themes; struct ListBase uifonts; struct ListBase uistyles; 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 4552c773097..de436172bfd 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -507,7 +507,7 @@ static void rna_float_print(FILE *f, float num) { if (num == -FLT_MAX) fprintf(f, "-FLT_MAX"); else if (num == FLT_MAX) fprintf(f, "FLT_MAX"); - else if ((int64_t)num == num) fprintf(f, "%.1ff", num); + else if ((ABS(num) < INT64_MAX) && ((int64_t)num == num)) fprintf(f, "%.1ff", num); else fprintf(f, "%.10ff", num); } @@ -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 bb839fd77f8..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)); } } } @@ -5547,6 +5589,9 @@ static char *rna_pointer_as_string__bldata(PointerRNA *ptr) return BLI_strdup("None"); } else if (RNA_struct_is_ID(ptr->type)) { + if (ptr->id.data == NULL) { + return BLI_strdup("None"); + } return RNA_path_full_ID_py(ptr->id.data); } else { @@ -5554,9 +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) { - if (RNA_property_flag(prop_ptr) & PROP_IDPROPERTY) { + IDProperty *prop; + if (ptr_prop->data == NULL) { + return BLI_strdup("None"); + } + else if ((prop = rna_idproperty_check(&prop_ptr, ptr)) && prop->type != IDP_ID) { return RNA_pointer_as_string_id(C, ptr_prop); } else { @@ -6397,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_action.c b/source/blender/makesrna/intern/rna_action.c index 0c4c7ddac81..d398ce95a52 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -34,6 +34,8 @@ #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "BKE_action.h" #include "RNA_access.h" @@ -731,6 +733,7 @@ static void rna_def_action(BlenderRNA *brna) RNA_def_property_ui_text(prop, "ID Root Type", "Type of ID block that action can be used on - " "DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); /* API calls */ RNA_api_action(srna); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 9adbf5f6b2e..f271bccd326 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -32,6 +32,8 @@ #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "MEM_guardedalloc.h" #include "RNA_access.h" @@ -742,6 +744,7 @@ static void rna_def_keyingset_path(BlenderRNA *brna) RNA_def_property_enum_default(prop, ID_OB); RNA_def_property_enum_funcs(prop, NULL, "rna_ksPath_id_type_set", NULL); RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */ /* Group */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 07d295c8bbc..891f5c43ca6 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -187,6 +187,9 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po } WM_main_add_notifier(NC_GEOM | ND_DATA, id); + + /* spaces that show animation data of the selected bone need updating */ + WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN, id); } static char *rna_Bone_path(PointerRNA *ptr) 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 4acdee490b8..bccc47aa95d 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -35,6 +35,8 @@ #include "BLI_math.h" +#include "BLT_translation.h" + #include "BKE_action.h" #include "RNA_access.h" @@ -1448,6 +1450,7 @@ static void rna_def_drivertarget(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, NULL, "rna_DriverTarget_id_type_set", NULL); RNA_def_property_editable_func(prop, "rna_DriverTarget_id_type_editable"); RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used"); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data"); /* Target Properties - Property to Drive */ 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_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 47c4b425155..1a8dd05a7b5 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1526,6 +1526,20 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Mirror V", "Mirror the V texture coordinate around the 0.5 point"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "mirror_offset_u", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "uv_offset[0]"); + RNA_def_property_range(prop, -1, 1); + RNA_def_property_ui_range(prop, -1, 1, 2, 4); + RNA_def_property_ui_text(prop, "U Offset", "Amount to offset mirrored UVs from the 0.5 point on the U axis"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "mirror_offset_v", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "uv_offset[1]"); + RNA_def_property_range(prop, -1, 1); + RNA_def_property_ui_range(prop, -1, 1, 2, 4); + RNA_def_property_ui_text(prop, "V Offset", "Amount to offset mirrored UVs from the 0.5 point on the V axis"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "tolerance"); RNA_def_property_range(prop, 0, FLT_MAX); @@ -4717,7 +4731,7 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna) PropertyRNA *prop; srna = RNA_def_struct(brna, "SurfaceDeformModifier", "Modifier"); - RNA_def_struct_ui_text(srna, "SurfaceDeform Modifier", "blablabla"); + RNA_def_struct_ui_text(srna, "SurfaceDeform Modifier", ""); RNA_def_struct_sdna(srna, "SurfaceDeformModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 784004182dd..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) @@ -3327,6 +3344,7 @@ static void def_frame(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); RNA_def_struct_sdna_from(srna, "NodeFrame", "storage"); + RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_ID_NODETREE); prop = RNA_def_property(srna, "shrink", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_FRAME_SHRINK); @@ -4187,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; @@ -4769,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"); @@ -5210,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; @@ -6281,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..a11b755c3c4 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -2095,7 +2095,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 +2300,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 +2315,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 +2363,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 121e4f56a6e..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); @@ -5390,7 +5418,7 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna) prop = RNA_def_property(srna, "jpeg2k_codec", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "jp2_codec"); RNA_def_property_enum_items(prop, jp2_codec_items); - RNA_def_property_ui_text(prop, "Codec", "Codec settings for Jpek2000"); + RNA_def_property_ui_text(prop, "Codec", "Codec settings for Jpeg2000"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); #endif @@ -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 bb70f9dccd0..2619d231adc 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -208,6 +208,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 +227,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 +243,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 +254,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; @@ -263,34 +267,55 @@ static void rna_Scene_alembic_export( /* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */ #include "../../collada/collada.h" +/* Note: This definition must match to the generated function call */ static void rna_Scene_collada_export( Scene *scene, - const char *filepath, + const char *filepath, int apply_modifiers, - int export_mesh_type, + int export_mesh_type, int selected, int include_children, int include_armatures, 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 use_ngons, + int triangulate, int use_object_instantiation, int use_blender_profile, int sort_by_name, + int export_transformation_type, int open_sim, - int export_transformation_type) + int limit_precision, + int keep_bind_info) { - collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, - include_children, include_armatures, include_shapekeys, deform_bones_only, - active_uv_only, include_uv_textures, include_material_textures, - use_texture_copies, use_ngons, use_object_instantiation, use_blender_profile, sort_by_name, export_transformation_type, open_sim); + collada_export(scene, + filepath, + + apply_modifiers, + export_mesh_type, + + selected, + include_children, + include_armatures, + include_shapekeys, + deform_bones_only, + + active_uv_only, + export_texture_type, + use_texture_copies, + + triangulate, + use_object_instantiation, + use_blender_profile, + sort_by_name, + + export_transformation_type, + open_sim, + limit_precision, + keep_bind_info); } #endif @@ -354,35 +379,64 @@ void RNA_api_scene(StructRNA *srna) parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Collada file"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */ - RNA_def_boolean(func, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers"); + + RNA_def_boolean(func, "apply_modifiers", false, + "Apply Modifiers", "Apply modifiers to exported mesh (non destructive))"); + RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX, "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX); - RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements"); - RNA_def_boolean(func, "include_children", 0, "Include Children", "Export all children of selected objects (even if not selected)"); - RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)"); - RNA_def_boolean(func, "include_shapekeys", 0, "Include Shape Keys", "Export all Shape Keys from Mesh Objects"); - 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, "Active UV Layer only", "Export only the active UV Layer"); - 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", 0, "copy", "Copy textures to same folder where the .dae file is exported"); - - RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export"); - RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data"); - RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile", "Export additional Blender specific information (for material, shaders, bones, etc.)"); - RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); - RNA_def_boolean(func, "open_sim", 0, "Export for SL/OpenSim", "Compatibility mode for SL, OpenSim and similar online worlds"); + + RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements"); + + RNA_def_boolean(func, "include_children", false, + "Include Children", "Export all children of selected objects (even if not selected)"); + + RNA_def_boolean(func, "include_armatures", false, + "Include Armatures", "Export related armatures (even if not selected)"); + + RNA_def_boolean(func, "include_shapekeys", true, "Include Shape Keys", "Export all Shape Keys from Mesh Objects"); + + RNA_def_boolean(func, "deform_bones_only", false, + "Deform Bones only", "Only export deforming bones with armatures"); + + RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map"); + + 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"); + + RNA_def_boolean(func, "triangulate", true, "Triangulate", "Export Polygons (Quads & NGons) as Triangles"); + + RNA_def_boolean(func, "use_object_instantiation", true, + "Use Object Instances", "Instantiate multiple Objects from same Data"); + + RNA_def_boolean(func, "use_blender_profile", true, "Use Blender Profile", + "Export additional Blender specific information (for material, shaders, bones, etc.)"); + + RNA_def_boolean(func, "sort_by_name", false, "Sort by Object name", "Sort exported data by Object name"); RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX, - "Transformation", "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_boolean(func, "open_sim", false, + "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds"); + + RNA_def_boolean(func, "limit_precision", false, + "Limit Precision", + "Reduce the precision of the exported data to 6 digits"); + + RNA_def_boolean(func, "keep_bind_info", false, + "Keep Bind Info", + "Store bind pose information in custom bone properties for later use during Collada export"); - RNA_def_function_ui_description(func, "Export to collada file"); #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); @@ -404,6 +458,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..6f8aa32da86 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -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 74888bf4f00..c0f2dbd0706 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -138,23 +138,11 @@ static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe } /* also used by buffer swap switching */ -static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) +static void rna_userdef_dpi_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { /* 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 */ -} - -static void rna_userdef_virtual_pixel_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) -{ - /* 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(); - /* force setting drawable again */ wmWindowManager *wm = bmain->wm.first; if (wm) { @@ -3168,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); @@ -3325,6 +3314,12 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "View & Controls", "Preferences related to viewing data"); /* View */ + 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, 2); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); /* display */ prop = RNA_def_property(srna, "show_tooltips", PROP_BOOLEAN, PROP_NONE); @@ -3916,12 +3911,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem virtual_pixel_mode_items[] = { - {VIRTUAL_PIXEL_NATIVE, "NATIVE", 0, "Native", "Use native pixel size of the display"}, - {VIRTUAL_PIXEL_DOUBLE, "DOUBLE", 0, "Double", "Use double the native pixel size of the display"}, - {0, NULL, 0, NULL, NULL} - }; - srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); @@ -3936,16 +3925,8 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update"); prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "dpi"); - RNA_def_property_range(prop, 48, 144); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); - RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); - - prop = RNA_def_property(srna, "virtual_pixel_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "virtual_pixel"); - RNA_def_property_enum_items(prop, virtual_pixel_mode_items); - RNA_def_property_ui_text(prop, "Virtual Pixel Mode", "Modify the pixel size for hi-res devices"); - RNA_def_property_update(prop, 0, "rna_userdef_virtual_pixel_update"); prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -4678,6 +4659,11 @@ void RNA_def_userdef(BlenderRNA *brna) "Active section of the user preferences shown in the user interface"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + /* don't expose this directly via the UI, modify via an operator */ + prop = RNA_def_property(srna, "app_template", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "app_template"); + RNA_def_property_ui_text(prop, "Application Template", ""); + prop = RNA_def_property(srna, "themes", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "themes", NULL); RNA_def_property_struct_type(prop, "Theme"); 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/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 1f23ab938fb..677ea92aea1 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -87,6 +87,11 @@ static void rna_Operator_report(wmOperator *op, int type, const char *msg) BKE_report(op->reports, type, msg); } +static int rna_Operator_is_repeat(wmOperator *op, bContext *C) +{ + return WM_operator_is_repeat(C, op); +} + /* since event isn't needed... */ static void rna_Operator_enum_search_invoke(bContext *C, wmOperator *op) { @@ -521,6 +526,12 @@ void RNA_api_operator(StructRNA *srna) parm = RNA_def_string(func, "message", NULL, 0, "Report Message", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + /* utility, not for registering */ + func = RNA_def_function(srna, "is_repeat", "rna_Operator_is_repeat"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + /* return */ + parm = RNA_def_boolean(func, "result", 0, "result", ""); + RNA_def_function_return(func, parm); /* Registration */ 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_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index d956763fc1f..f0edcc31a10 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -112,7 +112,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (!mcmd->reader) { mcmd->reader = CacheReader_open_alembic_object(cache_file->handle, - mcmd->reader, + NULL, ob, mcmd->object_path); if (!mcmd->reader) { diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index dd127cc255c..9705edc580c 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -274,8 +274,8 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, int j = maxLoops; dmloopuv += j; /* second set of loops only */ for (; j-- > 0; dmloopuv++) { - if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0]; - if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1]; + if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0] + mmd->uv_offset[0]; + if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1] + mmd->uv_offset[1]; } } } 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_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 68987a1d28e..e5b0f9c0001 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -172,6 +172,7 @@ ModifierTypeInfo modifierType_Surface = { /* structSize */ sizeof(SurfaceModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_NoUserAdd, /* copyData */ NULL, diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index a999d7629af..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); @@ -973,7 +975,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos) adj_result = buildAdjacencyMap(mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys); if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - modifier_setError((ModifierData *)smd, "Target has edges with more than two polys"); + modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); free_bvhtree_from_mesh(&treeData); MEM_freeN(smd->verts); @@ -1019,11 +1021,11 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos) freeData((ModifierData *)smd); } else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - modifier_setError((ModifierData *)smd, "Target has edges with more than two polys"); + modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons"); freeData((ModifierData *)smd); } else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) { - modifier_setError((ModifierData *)smd, "Target contains concave polys"); + modifier_setError((ModifierData *)smd, "Target contains concave polygons"); freeData((ModifierData *)smd); } else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) { @@ -1035,7 +1037,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos) * to explain this whith a reasonably sized message. * Though it shouldn't really matter all that much, * because this is very unlikely to occur */ - modifier_setError((ModifierData *)smd, "Target contains invalid polys"); + modifier_setError((ModifierData *)smd, "Target contains invalid polygons"); freeData((ModifierData *)smd); } @@ -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 48d1688c386..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; @@ -63,7 +65,7 @@ static void node_shader_exec_normal_map(void *data, int UNUSED(thread), bNode *n CLAMP_MIN(strength, 0.0f); - float *N = shi->vno; + float *N = shi->nmapnorm; int uv_index = 0; switch (nm->space) { case SHD_NORMAL_MAP_TANGENT: 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/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 359395b63c4..b694b6e994d 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -333,19 +333,14 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo return 1; } -BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float time) +BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s) { Cloth *cloth = clmd->clothObject; ClothSimSettings *parms = clmd->sim_parms; Implicit_Data *data = cloth->implicit; - ClothVertex *verts = cloth->verts; bool no_compress = parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; - zero_v3(s->f); - zero_m3(s->dfdx); - zero_m3(s->dfdv); - s->flags &= ~CLOTH_SPRING_FLAG_NEEDED; // calculate force of structural + shear springs @@ -361,31 +356,13 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, if (s->type & CLOTH_SPRING_TYPE_SEWING) { // TODO: verify, half verified (couldn't see error) // sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects - BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing, s->f, s->dfdx, s->dfdv); + BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing); } else { - BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f, s->f, s->dfdx, s->dfdv); + BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f); } #endif } - else if (s->type & CLOTH_SPRING_TYPE_GOAL) { -#ifdef CLOTH_FORCE_SPRING_GOAL - float goal_x[3], goal_v[3]; - float k, scaling; - - s->flags |= CLOTH_SPRING_FLAG_NEEDED; - - // current_position = xold + t * (newposition - xold) - /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */ - interp_v3_v3v3(goal_x, verts[s->ij].xold, verts[s->ij].xconst, time / parms->time_scale); - sub_v3_v3v3(goal_v, verts[s->ij].xconst, verts[s->ij].xold); // distance covered over dt==1 - - scaling = parms->goalspring + s->stiffness * fabsf(parms->max_struct - parms->goalspring); - k = verts[s->ij].goal * scaling / (parms->avg_spring_len + FLT_EPSILON); - - BPH_mass_spring_force_spring_goal(data, s->ij, goal_x, goal_v, k, parms->goalfrict * 0.01f, s->f, s->dfdx, s->dfdv); -#endif - } else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */ #ifdef CLOTH_FORCE_SPRING_BEND float kb, cb, scaling; @@ -398,7 +375,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, // Fix for [#45084] for cloth stiffness must have cb proportional to kb cb = kb * parms->bending_damping; - BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb, s->f, s->dfdx, s->dfdv); + BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb); #endif } else if (s->type & CLOTH_SPRING_TYPE_BENDING_ANG) { @@ -474,9 +451,24 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB /* scale gravity force */ mul_v3_v3fl(gravity, clmd->scene->physics_settings.gravity, 0.001f * clmd->sim_parms->effector_weights->global_gravity); } + vert = cloth->verts; for (i = 0; i < cloth->mvert_num; i++, vert++) { BPH_mass_spring_force_gravity(data, i, vert->mass, gravity); + + /* Vertex goal springs */ + if ((!(vert->flags & CLOTH_VERT_FLAG_PINNED)) && (vert->goal > FLT_EPSILON)) { + float goal_x[3], goal_v[3]; + float k; + + /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */ + interp_v3_v3v3(goal_x, vert->xold, vert->xconst, time / clmd->sim_parms->time_scale); + sub_v3_v3v3(goal_v, vert->xconst, vert->xold); /* distance covered over dt==1 */ + + k = vert->goal * clmd->sim_parms->goalspring / (clmd->sim_parms->avg_spring_len + FLT_EPSILON); + + BPH_mass_spring_force_spring_goal(data, i, goal_x, goal_v, k, clmd->sim_parms->goalfrict * 0.01f); + } } #endif @@ -544,8 +536,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB for (LinkNode *link = cloth->springs; link; link = link->next) { ClothSpring *spring = (ClothSpring *)link->link; // only handle active springs - if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) - cloth_calc_spring_force(clmd, spring, time); + if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) { + cloth_calc_spring_force(clmd, spring); + } } } diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h index d1a75ca5297..2f62ab98e12 100644 --- a/source/blender/physics/intern/implicit.h +++ b/source/blender/physics/intern/implicit.h @@ -114,19 +114,15 @@ void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2, void BPH_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float (*winvec)[3]); /* Linear spring force between two points */ bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen, - float stiffness, float damping, bool no_compress, float clamp_force, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]); + float stiffness, float damping, bool no_compress, float clamp_force); /* Bending force, forming a triangle at the base of two structural springs */ -bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, - float kb, float cb, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]); +bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, float kb, float cb); /* Angular bending force based on local target vectors */ bool BPH_mass_spring_force_spring_bending_angular(struct Implicit_Data *data, int i, int j, int k, const float target[3], float stiffness, float damping); /* Global goal spring */ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3], - float stiffness, float damping, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]); + float stiffness, float damping); /* ======== Hair Volumetric Forces ======== */ diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c index 2ad8ee0547f..16cd335dc0c 100644 --- a/source/blender/physics/intern/implicit_blender.c +++ b/source/blender/physics/intern/implicit_blender.c @@ -1579,8 +1579,7 @@ BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3] } bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlen, - float stiffness, float damping, bool no_compress, float clamp_force, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]) + float stiffness, float damping, bool no_compress, float clamp_force) { float extent[3], length, dir[3], vel[3]; @@ -1608,25 +1607,15 @@ bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, floa apply_spring(data, i, j, f, dfdx, dfdv); - if (r_f) copy_v3_v3(r_f, f); - if (r_dfdx) copy_m3_m3(r_dfdx, dfdx); - if (r_dfdv) copy_m3_m3(r_dfdv, dfdv); - return true; } else { - if (r_f) zero_v3(r_f); - if (r_dfdx) zero_m3(r_dfdx); - if (r_dfdv) zero_m3(r_dfdv); - return false; } } /* See "Stable but Responsive Cloth" (Choi, Ko 2005) */ -bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen, - float kb, float cb, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]) +bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen, float kb, float cb) { float extent[3], length, dir[3], vel[3]; @@ -1646,17 +1635,9 @@ bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, flo apply_spring(data, i, j, f, dfdx, dfdv); - if (r_f) copy_v3_v3(r_f, f); - if (r_dfdx) copy_m3_m3(r_dfdx, dfdx); - if (r_dfdv) copy_m3_m3(r_dfdv, dfdv); - return true; } else { - if (r_f) zero_v3(r_f); - if (r_dfdx) zero_m3(r_dfdx); - if (r_dfdv) zero_m3(r_dfdv); - return false; } } @@ -1945,8 +1926,7 @@ bool BPH_mass_spring_force_spring_bending_angular(Implicit_Data *data, int i, in } bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3], - float stiffness, float damping, - float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]) + float stiffness, float damping) { float root_goal_x[3], root_goal_v[3], extent[3], length, dir[3], vel[3]; float f[3], dfdx[3][3], dfdv[3][3]; @@ -1973,17 +1953,9 @@ bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float g add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfdx); add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, dfdv); - if (r_f) copy_v3_v3(r_f, f); - if (r_dfdx) copy_m3_m3(r_dfdx, dfdx); - if (r_dfdv) copy_m3_m3(r_dfdv, dfdv); - return true; } else { - if (r_f) zero_v3(r_f); - if (r_dfdx) zero_m3(r_dfdx); - if (r_dfdv) zero_m3(r_dfdv); - return false; } } diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 3148dab3c50..b4c36a7c516 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -75,7 +75,8 @@ void BPY_thread_restore(BPy_ThreadStatePtr tstate); bool BPY_execute_filepath(struct bContext *C, const char *filepath, struct ReportList *reports); bool BPY_execute_text(struct bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump); -bool BPY_execute_string_as_number(struct bContext *C, const char *expr, double *value, const bool verbose); +bool BPY_execute_string_as_number(struct bContext *C, const char *expr, const bool verbose, double *r_value); +bool BPY_execute_string_as_string(struct bContext *C, const char *expr, const bool verbose, char **r_value); bool BPY_execute_string_ex(struct bContext *C, const char *expr, bool use_eval); bool BPY_execute_string(struct bContext *C, const char *expr); diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 2e15b7b1413..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; } } @@ -335,19 +344,9 @@ static char idp_sequence_type(PyObject *seq_fast) return type; } -/** - * \note group can be a pointer array or a group. - * assume we already checked key is a string. - * - * \return success. - */ -bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob) +static const char *idp_try_read_name(PyObject *name_obj) { - IDProperty *prop = NULL; - IDPropertyTemplate val = {0}; - - const char *name; - + const char *name = NULL; if (name_obj) { Py_ssize_t name_size; name = _PyUnicode_AsStringAndSize(name_obj, &name_size); @@ -356,168 +355,307 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyErr_Format(PyExc_KeyError, "invalid id-property key, expected a string, not a %.200s", Py_TYPE(name_obj)->tp_name); - return false; + return NULL; } if (name_size > MAX_IDPROP_NAME) { PyErr_SetString(PyExc_KeyError, "the length of IDProperty names is limited to 63 characters"); - return false; + return NULL; } } else { name = ""; } + return name; +} - if (PyFloat_Check(ob)) { - val.d = PyFloat_AsDouble(ob); - prop = IDP_New(IDP_DOUBLE, &val, name); - } - else if (PyLong_Check(ob)) { - val.i = _PyLong_AsInt(ob); - if (val.i == -1 && PyErr_Occurred()) { - return false; - } - prop = IDP_New(IDP_INT, &val, name); +/* -------------------------------------------------------------------------- */ + +/** + * The 'idp_from_Py*' functions expect that the input type has been checked before + * and return NULL if the IDProperty can't be created. + */ + +static IDProperty *idp_from_PyFloat(const char *name, PyObject *ob) +{ + IDPropertyTemplate val = {0}; + val.d = PyFloat_AsDouble(ob); + return IDP_New(IDP_DOUBLE, &val, name); +} + +static IDProperty *idp_from_PyLong(const char *name, PyObject *ob) +{ + IDPropertyTemplate val = {0}; + val.i = _PyLong_AsInt(ob); + if (val.i == -1 && PyErr_Occurred()) { + return NULL; } - else if (PyUnicode_Check(ob)) { + return IDP_New(IDP_INT, &val, name); +} + +static IDProperty *idp_from_PyUnicode(const char *name, PyObject *ob) +{ + IDProperty *prop; + IDPropertyTemplate val = {0}; #ifdef USE_STRING_COERCE - Py_ssize_t value_size; - PyObject *value_coerce = NULL; - val.string.str = PyC_UnicodeAsByteAndSize(ob, &value_size, &value_coerce); - val.string.len = (int)value_size + 1; - val.string.subtype = IDP_STRING_SUB_UTF8; - prop = IDP_New(IDP_STRING, &val, name); - Py_XDECREF(value_coerce); + Py_ssize_t value_size; + PyObject *value_coerce = NULL; + val.string.str = PyC_UnicodeAsByteAndSize(ob, &value_size, &value_coerce); + val.string.len = (int)value_size + 1; + val.string.subtype = IDP_STRING_SUB_UTF8; + prop = IDP_New(IDP_STRING, &val, name); + Py_XDECREF(value_coerce); #else - val.str = _PyUnicode_AsString(ob); - prop = IDP_New(IDP_STRING, val, name); + val.str = _PyUnicode_AsString(ob); + prop = IDP_New(IDP_STRING, val, name); #endif - } - else if (PyBytes_Check(ob)) { - val.string.str = PyBytes_AS_STRING(ob); - val.string.len = PyBytes_GET_SIZE(ob); - val.string.subtype = IDP_STRING_SUB_BYTE; + return prop; +} + +static IDProperty *idp_from_PyBytes(const char *name, PyObject *ob) +{ + IDPropertyTemplate val = {0}; + val.string.str = PyBytes_AS_STRING(ob); + val.string.len = PyBytes_GET_SIZE(ob); + val.string.subtype = IDP_STRING_SUB_BYTE; + return IDP_New(IDP_STRING, &val, name); +} - prop = IDP_New(IDP_STRING, &val, name); - //prop = IDP_NewString(PyBytes_AS_STRING(ob), name, PyBytes_GET_SIZE(ob)); - //prop->subtype = IDP_STRING_SUB_BYTE; +static int idp_array_type_from_format_char(char format) +{ + if (format == 'i') return IDP_INT; + if (format == 'f') return IDP_FLOAT; + if (format == 'd') return IDP_DOUBLE; + return -1; +} + +static const char *idp_format_from_array_type(int type) +{ + if (type == IDP_INT) return "i"; + if (type == IDP_FLOAT) return "f"; + if (type == IDP_DOUBLE) return "d"; + return NULL; +} + +static IDProperty *idp_from_PySequence_Buffer(const char *name, Py_buffer *buffer) +{ + IDProperty *prop; + IDPropertyTemplate val = {0}; + + int format = idp_array_type_from_format_char(*buffer->format); + if (format == -1) { + /* should never happen as the type has been checked before */ + return NULL; } - else if (PySequence_Check(ob)) { - PyObject *ob_seq_fast; - PyObject **ob_seq_fast_items; - PyObject *item; - int i; + else { + val.array.type = format; + val.array.len = buffer->len / buffer->itemsize; + } + prop = IDP_New(IDP_ARRAY, &val, name); + memcpy(IDP_Array(prop), buffer->buf, buffer->len); + return prop; +} - if (!(ob_seq_fast = PySequence_Fast(ob, "py -> idprop"))) { - return false; - } +static IDProperty *idp_from_PySequence_Fast(const char *name, PyObject *ob) +{ + IDProperty *prop; + IDPropertyTemplate val = {0}; - ob_seq_fast_items = PySequence_Fast_ITEMS(ob_seq_fast); + PyObject **ob_seq_fast_items; + PyObject *item; + int i; - if ((val.array.type = idp_sequence_type(ob_seq_fast)) == (char)-1) { - Py_DECREF(ob_seq_fast); - PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays"); - return false; - } + ob_seq_fast_items = PySequence_Fast_ITEMS(ob); - /* validate sequence and derive type. - * we assume IDP_INT unless we hit a float - * number; then we assume it's */ + if ((val.array.type = idp_sequence_type(ob)) == (char)-1) { + PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays"); + return NULL; + } - val.array.len = PySequence_Fast_GET_SIZE(ob_seq_fast); + /* validate sequence and derive type. + * we assume IDP_INT unless we hit a float + * number; then we assume it's */ - switch (val.array.type) { - case IDP_DOUBLE: - { - double *prop_data; - - prop = IDP_New(IDP_ARRAY, &val, name); - prop_data = IDP_Array(prop); - for (i = 0; i < val.array.len; i++) { - item = ob_seq_fast_items[i]; - if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) { - Py_DECREF(ob_seq_fast); - return false; - } + val.array.len = PySequence_Fast_GET_SIZE(ob); + + switch (val.array.type) { + case IDP_DOUBLE: + { + double *prop_data; + prop = IDP_New(IDP_ARRAY, &val, name); + prop_data = IDP_Array(prop); + for (i = 0; i < val.array.len; i++) { + item = ob_seq_fast_items[i]; + if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) { + return NULL; } - break; } - case IDP_INT: - { - int *prop_data; - prop = IDP_New(IDP_ARRAY, &val, name); - prop_data = IDP_Array(prop); - for (i = 0; i < val.array.len; i++) { - item = ob_seq_fast_items[i]; - if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) { - Py_DECREF(ob_seq_fast); - return false; - } + break; + } + case IDP_INT: + { + int *prop_data; + prop = IDP_New(IDP_ARRAY, &val, name); + prop_data = IDP_Array(prop); + for (i = 0; i < val.array.len; i++) { + item = ob_seq_fast_items[i]; + if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) { + return NULL; } - break; } - case IDP_IDPARRAY: - { - prop = IDP_NewIDPArray(name); - for (i = 0; i < val.array.len; i++) { - item = ob_seq_fast_items[i]; - - if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) { - Py_DECREF(ob_seq_fast); - return false; - } + break; + } + case IDP_IDPARRAY: + { + prop = IDP_NewIDPArray(name); + for (i = 0; i < val.array.len; i++) { + item = ob_seq_fast_items[i]; + if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) { + return NULL; } - break; } - default: - /* should never happen */ - Py_DECREF(ob_seq_fast); - PyErr_SetString(PyExc_RuntimeError, "internal error with idp array.type"); - return false; + break; } + default: + /* should never happen */ + PyErr_SetString(PyExc_RuntimeError, "internal error with idp array.type"); + return NULL; + } + return prop; +} - Py_DECREF(ob_seq_fast); + +static IDProperty *idp_from_PySequence(const char *name, PyObject *ob) +{ + Py_buffer buffer; + bool use_buffer = false; + + if (PyObject_CheckBuffer(ob)) { + PyObject_GetBuffer(ob, &buffer, PyBUF_SIMPLE | PyBUF_FORMAT); + char format = *buffer.format; + if (ELEM(format, 'i', 'f', 'd')) { + use_buffer = true; + } + else { + PyBuffer_Release(&buffer); + } } - else if (PyMapping_Check(ob)) { - PyObject *keys, *vals, *key, *pval; - int i, len; - /*yay! we get into recursive stuff now!*/ - keys = PyMapping_Keys(ob); - vals = PyMapping_Values(ob); - - /* we allocate the group first; if we hit any invalid data, - * we can delete it easily enough.*/ - prop = IDP_New(IDP_GROUP, &val, name); - len = PyMapping_Length(ob); - for (i = 0; i < len; i++) { - key = PySequence_GetItem(keys, i); - pval = PySequence_GetItem(vals, i); - if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) { - IDP_FreeProperty(prop); - MEM_freeN(prop); - Py_XDECREF(keys); - Py_XDECREF(vals); - Py_XDECREF(key); - Py_XDECREF(pval); - /* error is already set */ - return false; - } + + if (use_buffer) { + IDProperty *prop = idp_from_PySequence_Buffer(name, &buffer); + PyBuffer_Release(&buffer); + return prop; + } + else { + PyObject *ob_seq_fast = PySequence_Fast(ob, "py -> idprop"); + if (ob_seq_fast != NULL) { + IDProperty *prop = idp_from_PySequence_Fast(name, ob_seq_fast); + Py_DECREF(ob_seq_fast); + return prop; + } + else { + return NULL; + } + } +} + +static IDProperty *idp_from_PyMapping(const char *name, PyObject *ob) +{ + IDProperty *prop; + IDPropertyTemplate val = {0}; + + PyObject *keys, *vals, *key, *pval; + int i, len; + /* yay! we get into recursive stuff now! */ + keys = PyMapping_Keys(ob); + vals = PyMapping_Values(ob); + + /* we allocate the group first; if we hit any invalid data, + * we can delete it easily enough.*/ + prop = IDP_New(IDP_GROUP, &val, name); + len = PyMapping_Length(ob); + for (i = 0; i < len; i++) { + key = PySequence_GetItem(keys, i); + pval = PySequence_GetItem(vals, i); + if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) { + IDP_FreeProperty(prop); + MEM_freeN(prop); + Py_XDECREF(keys); + Py_XDECREF(vals); Py_XDECREF(key); Py_XDECREF(pval); + /* error is already set */ + return NULL; } - Py_XDECREF(keys); - Py_XDECREF(vals); + Py_XDECREF(key); + Py_XDECREF(pval); + } + Py_XDECREF(keys); + Py_XDECREF(vals); + 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; + } + + if (PyFloat_Check(ob)) { + return idp_from_PyFloat(name, ob); + } + else if (PyLong_Check(ob)) { + return idp_from_PyLong(name, ob); + } + else if (PyUnicode_Check(ob)) { + return idp_from_PyUnicode(name, ob); + } + else if (PyBytes_Check(ob)) { + return idp_from_PyBytes(name, 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); } else { PyErr_Format(PyExc_TypeError, "invalid id-property type %.200s not supported", Py_TYPE(ob)->tp_name); + return NULL; + } +} + +/* -------------------------------------------------------------------------- */ + +/** + * \note group can be a pointer array or a group. + * assume we already checked key is a string. + * + * \return success. + */ +bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob) +{ + IDProperty *prop = idp_from_PyObject(name_obj, ob); + if (prop == NULL) { return false; } if (group->type == IDP_IDPARRAY) { IDP_AppendArray(group, prop); - // IDP_FreeProperty(item); /* IDP_AppendArray does a shallow copy (memcpy), only free memory */ + /* IDP_AppendArray does a shallow copy (memcpy), only free memory */ MEM_freeN(prop); } else { @@ -613,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); @@ -1371,6 +1511,44 @@ static PyMappingMethods BPy_IDArray_AsMapping = { (objobjargproc)BPy_IDArray_ass_subscript }; +static int itemsize_by_idarray_type(int array_type) +{ + if (array_type == IDP_INT) return sizeof(int); + if (array_type == IDP_FLOAT) return sizeof(float); + if (array_type == IDP_DOUBLE) return sizeof(double); + return -1; /* should never happen */ +} + +static int BPy_IDArray_getbuffer(BPy_IDArray *self, Py_buffer *view, int flags) +{ + IDProperty *prop = self->prop; + int itemsize = itemsize_by_idarray_type(prop->subtype); + int length = itemsize * prop->len; + + if (PyBuffer_FillInfo(view, (PyObject *)self, IDP_Array(prop), length, false, flags) == -1) { + return -1; + } + + view->itemsize = itemsize; + view->format = (char *)idp_format_from_array_type(prop->subtype); + + Py_ssize_t *shape = MEM_mallocN(sizeof(Py_ssize_t), __func__); + shape[0] = prop->len; + view->shape = shape; + + return 0; +} + +static void BPy_IDArray_releasebuffer(BPy_IDArray *UNUSED(self), Py_buffer *view) +{ + MEM_freeN(view->shape); +} + +static PyBufferProcs BPy_IDArray_Buffer = { + (getbufferproc)BPy_IDArray_getbuffer, + (releasebufferproc)BPy_IDArray_releasebuffer, +}; + PyTypeObject BPy_IDArray_Type = { PyVarObject_HEAD_INIT(NULL, 0) @@ -1403,7 +1581,7 @@ PyTypeObject BPy_IDArray_Type = { NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ + &BPy_IDArray_Buffer, /* PyBufferProcs *tp_as_buffer; */ /*** Flags to define presence of optional/expanded features ***/ Py_TPFLAGS_DEFAULT, /* long tp_flags; */ diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 7b2d58a1268..2e789d6d4b3 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -918,11 +918,11 @@ char *PyC_FlagSet_AsString(PyC_FlagSet *item) return cstring; } -int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value) +int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value) { for ( ; item->identifier; item++) { if (STREQ(item->identifier, identifier)) { - *value = item->value; + *r_value = item->value; return 1; } } @@ -930,9 +930,9 @@ int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int * return 0; } -int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *value, const char *error_prefix) +int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *r_value, const char *error_prefix) { - if (PyC_FlagSet_ValueFromID_int(item, identifier, value) == 0) { + if (PyC_FlagSet_ValueFromID_int(item, identifier, r_value) == 0) { const char *enum_str = PyC_FlagSet_AsString(item); PyErr_Format(PyExc_ValueError, "%s: '%.200s' not found in (%s)", @@ -1006,7 +1006,7 @@ PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag) * * \note it is caller's responsibility to acquire & release GIL! */ -bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filename) +bool PyC_RunString_AsNumber(const char *expr, const char *filename, double *r_value) { PyObject *py_dict, *mod, *retval; bool ok = true; @@ -1058,10 +1058,10 @@ bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filenam ok = false; } else if (!isfinite(val)) { - *value = 0.0; + *r_value = 0.0; } else { - *value = val; + *r_value = val; } } @@ -1070,4 +1070,41 @@ bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filenam return ok; } +bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_value) +{ + PyObject *py_dict, *retval; + bool ok = true; + PyObject *main_mod = NULL; + + PyC_MainModule_Backup(&main_mod); + + py_dict = PyC_DefaultNameSpace(filename); + + retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict); + + if (retval == NULL) { + ok = false; + } + else { + const char *val; + Py_ssize_t val_len; + + val = _PyUnicode_AsStringAndSize(retval, &val_len); + if (val == NULL && PyErr_Occurred()) { + ok = false; + } + else { + char *val_alloc = MEM_mallocN(val_len + 1, __func__); + memcpy(val_alloc, val, val_len + 1); + *r_value = val_alloc; + } + + Py_DECREF(retval); + } + + PyC_MainModule_Restore(main_mod); + + return ok; +} + #endif /* #ifndef MATH_STANDALONE */ diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 04cfc8801eb..3f89e1d82a0 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -75,12 +75,13 @@ typedef struct PyC_FlagSet { } PyC_FlagSet; char *PyC_FlagSet_AsString(PyC_FlagSet *item); -int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value); -int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *value, const char *error_prefix); +int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value); +int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *r_value, const char *error_prefix); int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix); PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag); -bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filename); +bool PyC_RunString_AsNumber(const char *expr, const char *filename, double *r_value); +bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_value); int PyC_ParseBool(PyObject *o, void *p); 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..8b3464173d2 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" @@ -109,6 +110,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 +119,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 }; @@ -188,6 +202,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 311f621e13b..7b0daa91523 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); @@ -572,21 +581,58 @@ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr) /** * \return success */ -bool BPY_execute_string_as_number(bContext *C, const char *expr, double *value, const bool verbose) +bool BPY_execute_string_as_number(bContext *C, const char *expr, const bool verbose, double *r_value) { PyGILState_STATE gilstate; bool ok = true; - if (!value || !expr) return -1; + if (!r_value || !expr) { + return -1; + } + + if (expr[0] == '\0') { + *r_value = 0.0; + return ok; + } + + bpy_context_set(C, &gilstate); + + ok = PyC_RunString_AsNumber(expr, "<blender button>", r_value); + + if (ok == false) { + if (verbose) { + BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + } + else { + PyErr_Clear(); + } + } + + bpy_context_clear(C, &gilstate); + + return ok; +} + +/** + * \return success + */ +bool BPY_execute_string_as_string(bContext *C, const char *expr, const bool verbose, char **r_value) +{ + PyGILState_STATE gilstate; + bool ok = true; + + if (!r_value || !expr) { + return -1; + } if (expr[0] == '\0') { - *value = 0.0; + *r_value = NULL; return ok; } bpy_context_set(C, &gilstate); - ok = PyC_RunString_AsNumber(expr, value, "<blender button>"); + ok = PyC_RunString_AsString(expr, "<blender button>", r_value); if (ok == false) { if (verbose) { @@ -602,6 +648,7 @@ bool BPY_execute_string_as_number(bContext *C, const char *expr, double *value, return ok; } + bool BPY_execute_string_ex(bContext *C, const char *expr, bool use_eval) { PyGILState_STATE gilstate; 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 e61018865ab..c7787ba9682 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", ""}, @@ -230,7 +235,7 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw) static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop) { PyGILState_STATE gilstate; - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -279,7 +284,7 @@ static void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struc static int bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -337,7 +342,7 @@ static int bpy_prop_boolean_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p static void bpy_prop_boolean_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -389,9 +394,54 @@ 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 = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -452,7 +502,7 @@ static void bpy_prop_boolean_array_get_cb(struct PointerRNA *ptr, struct Propert static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -513,7 +563,7 @@ static void bpy_prop_boolean_array_set_cb(struct PointerRNA *ptr, struct Propert static int bpy_prop_int_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -571,7 +621,7 @@ static int bpy_prop_int_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) static void bpy_prop_int_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -625,7 +675,7 @@ static void bpy_prop_int_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop static void bpy_prop_int_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int *values) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -686,7 +736,7 @@ static void bpy_prop_int_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const int *values) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -747,7 +797,7 @@ static void bpy_prop_int_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA static float bpy_prop_float_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -805,7 +855,7 @@ static float bpy_prop_float_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p static void bpy_prop_float_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, float value) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -859,7 +909,7 @@ static void bpy_prop_float_set_cb(struct PointerRNA *ptr, struct PropertyRNA *pr static void bpy_prop_float_array_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, float *values) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -920,7 +970,7 @@ static void bpy_prop_float_array_get_cb(struct PointerRNA *ptr, struct PropertyR static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const float *values) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -981,7 +1031,7 @@ static void bpy_prop_float_array_set_cb(struct PointerRNA *ptr, struct PropertyR static void bpy_prop_string_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, char *value) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -1040,7 +1090,7 @@ static void bpy_prop_string_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p static int bpy_prop_string_length_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -1102,7 +1152,7 @@ static int bpy_prop_string_length_cb(struct PointerRNA *ptr, struct PropertyRNA static void bpy_prop_string_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, const char *value) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -1163,7 +1213,7 @@ static void bpy_prop_string_set_cb(struct PointerRNA *ptr, struct PropertyRNA *p static int bpy_prop_enum_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -1221,7 +1271,7 @@ static int bpy_prop_enum_get_cb(struct PointerRNA *ptr, struct PropertyRNA *prop static void bpy_prop_enum_set_cb(struct PointerRNA *ptr, struct PropertyRNA *prop, int value) { - PyObject **py_data = (PyObject **)RNA_property_py_data_get(prop); + PyObject **py_data = RNA_property_py_data_get(prop); PyObject *py_func; PyObject *args; PyObject *self; @@ -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 @@ -2772,7 +2832,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 +2842,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 +2862,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 +2873,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 +2888,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 +2947,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 +2978,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/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c index 974d7c5549c..e0c70483e3c 100644 --- a/source/blender/python/intern/bpy_utils_units.c +++ b/source/blender/python/intern/bpy_utils_units.c @@ -201,7 +201,7 @@ static PyObject *bpyunits_to_value(PyObject *UNUSED(self), PyObject *args, PyObj bUnit_ReplaceString(str, (int)str_len, uref, scale, usys, ucat); - if (!PyC_RunString_AsNumber(str, &result, "<bpy_units_api>")) { + if (!PyC_RunString_AsNumber(str, "<bpy_units_api>", &result)) { if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); 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 4e980e4c0e6..e368e8871f3 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -1301,7 +1301,7 @@ PyDoc_STRVAR(Matrix_to_scale_doc, " :return: Return the scale of a matrix.\n" " :rtype: :class:`Vector`\n" "\n" -" .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n" +" .. note:: This method does not return a negative scale on any axis because it is not possible to obtain this data from the matrix alone.\n" ); static PyObject *Matrix_to_scale(MatrixObject *self) { @@ -1390,11 +1390,11 @@ PyDoc_STRVAR(Matrix_invert_doc, "\n" " Set the matrix to its inverse.\n" "\n" -" :arg fallback: Set the matrix to this value when the inverse can't be calculated\n" +" :arg fallback: Set the matrix to this value when the inverse cannot be calculated\n" " (instead of raising a :exc:`ValueError` exception).\n" " :type fallback: :class:`Matrix`\n" "\n" -" .. seealso:: <https://en.wikipedia.org/wiki/Inverse_matrix>\n" +" .. seealso:: `Inverse matrix <https://en.wikipedia.org/wiki/Inverse_matrix>` on Wikipedia.\n" ); static PyObject *Matrix_invert(MatrixObject *self, PyObject *args) { @@ -1505,7 +1505,7 @@ PyDoc_STRVAR(Matrix_invert_safe_doc, " If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n" " If tweaked matrix is still degenerated, set to the identity matrix instead.\n" "\n" -" .. seealso:: <https://en.wikipedia.org/wiki/Inverse_matrix>\n" +" .. seealso:: `Inverse Matrix <https://en.wikipedia.org/wiki/Inverse_matrix>` on Wikipedia.\n" ); static PyObject *Matrix_invert_safe(MatrixObject *self) { @@ -1554,9 +1554,9 @@ PyDoc_STRVAR(Matrix_adjugate_doc, "\n" " Set the matrix to its adjugate.\n" "\n" -" .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n" +" .. note:: When the matrix cannot be adjugated a :exc:`ValueError` exception is raised.\n" "\n" -" .. seealso:: <https://en.wikipedia.org/wiki/Adjugate_matrix>\n" +" .. seealso:: `Adjugate matrix <https://en.wikipedia.org/wiki/Adjugate_matrix>` on Wikipedia.\n" ); static PyObject *Matrix_adjugate(MatrixObject *self) { @@ -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, @@ -1733,7 +1733,7 @@ PyDoc_STRVAR(Matrix_determinant_doc, " :return: Return the determinant of a matrix.\n" " :rtype: float\n" "\n" -" .. seealso:: <https://en.wikipedia.org/wiki/Determinant>\n" +" .. seealso:: `Determinant <https://en.wikipedia.org/wiki/Determinant>` on Wikipedia.\n" ); static PyObject *Matrix_determinant(MatrixObject *self) { @@ -1755,7 +1755,7 @@ PyDoc_STRVAR(Matrix_transpose_doc, "\n" " Set the matrix to its transpose.\n" "\n" -" .. seealso:: <https://en.wikipedia.org/wiki/Transpose>\n" +" .. seealso:: `Transpose <https://en.wikipedia.org/wiki/Transpose>` on Wikipedia.\n" ); static PyObject *Matrix_transpose(MatrixObject *self) { @@ -1887,10 +1887,10 @@ PyDoc_STRVAR(Matrix_identity_doc, "\n" " Set the matrix to the identity matrix.\n" "\n" -" .. note:: An object with zero location and rotation, a scale of one,\n" +" .. note:: An object with a location and rotation of zero, and a scale of one\n" " will have an identity matrix.\n" "\n" -" .. seealso:: <https://en.wikipedia.org/wiki/Identity_matrix>\n" +" .. seealso:: `Identity matrix <https://en.wikipedia.org/wiki/Identity_matrix>` on Wikipedia.\n" ); static PyObject *Matrix_identity(MatrixObject *self) { @@ -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..f0323340899 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -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/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..41ff8e046e7 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4701,6 +4701,12 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject * if (ob->particlesystem.first) { psysindex= 1; for (psys=ob->particlesystem.first; psys; psys=psys->next, psysindex++) { + /* 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... */ + const bool psys_has_renderdata = (psys->renderdata != NULL); + if (!psys_check_enabled(ob, psys, G.is_rendering)) continue; @@ -4712,8 +4718,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..929eae495cf 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); @@ -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 b4a14f5337d..22dc2b28900 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1112,14 +1112,15 @@ static int multitex(Tex *tex, const short which_output, struct ImagePool *pool, const bool skip_load_image, - const bool texnode_preview) + const bool texnode_preview, + const bool use_nodes) { float tmpvec[3]; int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */ texres->talpha = false; /* is set when image texture returns alpha (considered premul) */ - if (tex->use_nodes && tex->nodetree) { + if (use_nodes && tex->use_nodes && tex->nodetree) { retval = ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, osatex, thread, tex, which_output, R.r.cfra, texnode_preview, NULL, NULL); } @@ -1239,7 +1240,8 @@ static int multitex_nodes_intern(Tex *tex, ImagePool *pool, const bool scene_color_manage, const bool skip_load_image, - const bool texnode_preview) + const bool texnode_preview, + const bool use_nodes) { if (tex==NULL) { memset(texres, 0, sizeof(TexResult)); @@ -1264,7 +1266,8 @@ static int multitex_nodes_intern(Tex *tex, which_output, pool, skip_load_image, - texnode_preview); + texnode_preview, + use_nodes); if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); @@ -1311,7 +1314,8 @@ static int multitex_nodes_intern(Tex *tex, which_output, pool, skip_load_image, - texnode_preview); + texnode_preview, + use_nodes); { ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); @@ -1341,7 +1345,8 @@ static int multitex_nodes_intern(Tex *tex, which_output, pool, skip_load_image, - texnode_preview); + texnode_preview, + use_nodes); } } @@ -1354,7 +1359,8 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, shi, mtex, pool, R.scene_color_manage, (R.r.scemode & R_NO_IMAGE_LOAD) != 0, - (R.r.scemode & R_TEXNODE_PREVIEW) != 0); + (R.r.scemode & R_TEXNODE_PREVIEW) != 0, + true); } /* this is called for surface shading */ @@ -1378,7 +1384,8 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt mtex->which_output, pool, skip_load_image, - (R.r.scemode & R_TEXNODE_PREVIEW) != 0); + (R.r.scemode & R_TEXNODE_PREVIEW) != 0, + true); } } @@ -1408,7 +1415,8 @@ int multitex_ext(Tex *tex, pool, scene_color_manage, skip_load_image, - false); + false, + true); } /* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on)\ @@ -1417,13 +1425,19 @@ int multitex_ext(Tex *tex, */ int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image) { - int use_nodes= tex->use_nodes, retval; - - tex->use_nodes = false; - retval= multitex_nodes_intern(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool, scene_color_manage, skip_load_image, false); - tex->use_nodes= use_nodes; - - return retval; + return multitex_nodes_intern(tex, + texvec, + NULL, NULL, + 0, + texres, + 0, + 0, + NULL, NULL, + pool, + scene_color_manage, + skip_load_image, + false, + false); } @@ -1481,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]); @@ -1595,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; @@ -2873,7 +2889,8 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_ mtex->which_output, re->pool, skip_load_image, - texnode_preview); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */ + texnode_preview, + true); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */ /* texture output */ @@ -3051,7 +3068,8 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) mtex->which_output, har->pool, skip_load_image, - texnode_preview); + texnode_preview, + true); /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { @@ -3274,7 +3292,8 @@ void do_sky_tex( mtex->which_output, R.pool, skip_load_image, - texnode_preview); + texnode_preview, + true); /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { @@ -3500,7 +3519,8 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r mtex->which_output, R.pool, skip_load_image, - texnode_preview); + texnode_preview, + true); /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { @@ -3614,7 +3634,8 @@ int externtex(MTex *mtex, mtex->which_output, pool, skip_load_image, - texnode_preview); + texnode_preview, + true); if (rgb) { texr.tin = IMB_colormanagement_get_luminance(&texr.tr); 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 c4de95e863e..8dea0930b9e 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -2141,9 +2141,19 @@ 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) { + switch (matrix_id) { case RE_VIEW_MATRIX: return (const float(*)[4])R.viewmat; case RE_VIEWINV_MATRIX: @@ -2171,4 +2181,4 @@ float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) } return result; -}
\ No newline at end of file +} 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/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index b6245a8c0d1..925563a0777 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -128,10 +128,6 @@ if(WITH_PYTHON) ../python ) add_definitions(-DWITH_PYTHON) - - if(WITH_PYTHON_SECURITY) - add_definitions(-DWITH_PYTHON_SECURITY) - endif() endif() if(WITH_GAMEENGINE) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 2b82f1becb3..492dec2cc10 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -102,7 +102,7 @@ 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); /* returns true if draw method is triple buffer */ bool WM_is_draw_triple(struct wmWindow *win); @@ -252,6 +252,7 @@ int WM_operator_confirm_message(struct bContext *C, struct wmOperator *o /* operator api */ void WM_operator_free (struct wmOperator *op); +void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op); void WM_operator_type_set(struct wmOperator *op, struct wmOperatorType *ot); void WM_operator_stack_clear(struct wmWindowManager *wm); void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot); @@ -276,6 +277,7 @@ int WM_operator_call (struct bContext *C, struct wmOperator *op); int WM_operator_call_notest(struct bContext *C, struct wmOperator *op); int WM_operator_repeat (struct bContext *C, struct wmOperator *op); bool WM_operator_repeat_check(const struct bContext *C, struct wmOperator *op); +bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op); int WM_operator_name_call_ptr(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties); int WM_operator_name_call(struct bContext *C, const char *opstring, short context, struct PointerRNA *properties); int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties, struct ReportList *reports, const bool is_undo); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index cd46e24264d..97f9257b4cb 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -542,7 +542,15 @@ typedef struct wmOperatorType { * canceled due to some external reason, cancel is called * - see defines below for return values */ int (*invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT; + + /* Called when a modal operator is canceled (not used often). + * Internal cleanup can be done here if needed. */ void (*cancel)(struct bContext *, struct wmOperator *); + + /* Modal is used for operators which continuously run, eg: + * fly mode, knife tool, circle select are all examples of modal operators. + * Modal operators can handle events which would normally access other operators, + * they keep running until they don't return `OPERATOR_RUNNING_MODAL`. */ int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT; /* verify if the operator can be executed in the current context, note diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index b76a1f1d422..67e961b9cd0 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -107,6 +107,17 @@ void WM_operator_free(wmOperator *op) MEM_freeN(op); } +void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op) +{ + op = op->next; + while (op != NULL) { + wmOperator *op_next = op->next; + BLI_remlink(&wm->operators, op); + WM_operator_free(op); + op = op_next; + } +} + /** * Use with extreme care!, * properties, customdata etc - must be compatible. @@ -149,18 +160,23 @@ static void wm_reports_free(wmWindowManager *wm) void wm_operator_register(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); - int tot; + int tot = 0; BLI_addtail(&wm->operators, op); - tot = BLI_listbase_count(&wm->operators); - - while (tot > MAX_OP_REGISTERED) { - wmOperator *opt = wm->operators.first; - BLI_remlink(&wm->operators, opt); - WM_operator_free(opt); - tot--; + + /* only count registered operators */ + while (op) { + wmOperator *op_prev = op->prev; + if (op->type->flag & OPTYPE_REGISTER) { + tot += 1; + } + if (tot > MAX_OP_REGISTERED) { + BLI_remlink(&wm->operators, op); + WM_operator_free(op); + } + op = op_prev; } - + /* so the console is redrawn */ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); WM_event_add_notifier(C, NC_WM | ND_HISTORY, NULL); @@ -467,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 eba132062c9..f26ee0e73ec 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -715,7 +715,9 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca */ static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot) { - return wm && (wm->op_undo_depth == 0) && (ot->flag & OPTYPE_REGISTER); + /* Check undo flag here since undo operators are also added to the list, + * to support checking if the same operator is run twice. */ + return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO)); } static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat) @@ -878,6 +880,20 @@ bool WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op) return false; } +bool WM_operator_is_repeat(const bContext *C, const wmOperator *op) +{ + /* may be in the operators list or not */ + wmOperator *op_prev; + if (op->prev == NULL && op->next == NULL) { + wmWindowManager *wm = CTX_wm_manager(C); + op_prev = wm->operators.last; + } + else { + op_prev = op->prev; + } + return (op_prev && (op->type == op_prev->type)); +} + static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, PointerRNA *properties, ReportList *reports) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 05d63869074..379772d5175 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 from_memory) +static void wm_init_userdef(bContext *C, const bool use_factory_settings) { Main *bmain = CTX_data_main(C); @@ -336,7 +336,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory) } /* avoid re-saving for every small change to our prefs, allow overrides */ - if (from_memory) { + if (use_factory_settings) { BLO_update_defaults_userpref_blend(); } @@ -470,6 +470,10 @@ static void wm_file_read_post(bContext *C, bool is_startup_file) if (is_startup_file) { /* possible python hasn't been initialized */ if (CTX_py_init_get(C)) { + /* Only run when we have a template path found. */ + if (BKE_appdir_app_template_any()) { + BPY_execute_string(C, "__import__('bl_app_template_utils').reset()"); + } /* sync addons, these may have changed from the defaults */ BPY_execute_string(C, "__import__('addon_utils').reset_all()"); @@ -554,7 +558,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) /* confusing this global... */ G.relbase_valid = 1; - retval = BKE_blendfile_read(C, filepath, reports); + retval = BKE_blendfile_read(C, filepath, reports, 0); /* when loading startup.blend's, we can be left with a blank path */ if (G.main->name[0]) { G.save_over = 1; @@ -629,22 +633,34 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) /** - * called on startup, (context entirely filled with NULLs) - * or called for 'New File' - * both startup.blend and userpref.blend are checked - * the optional parameter custom_file points to an alternative startup page - * custom_file can be NULL + * Called on startup, (context entirely filled with NULLs) + * or called for 'New File' both startup.blend and userpref.blend are checked. + * + * \param use_factory_settings: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead. + * Used for "Restore Factory Settings". + * \param filepath_startup_override: Optional path pointing to an alternative blend file (may be NULL). + * \param app_template_override: Template to use instead of the template defined in user-preferences. + * When not-null, this is written into the user preferences. */ -int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file) +int wm_homefile_read( + bContext *C, ReportList *reports, + bool use_factory_settings, bool use_empty_data, + const char *filepath_startup_override, const char *app_template_override) { ListBase wmbase; - char startstr[FILE_MAX]; - char prefstr[FILE_MAX]; - int success = 0; + bool success = false; + + char filepath_startup[FILE_MAX]; + char filepath_userdef[FILE_MAX]; + + /* When 'app_template' is set: '{BLENDER_USER_CONFIG}/{app_template}' */ + char app_template_system[FILE_MAX]; + /* When 'app_template' is set: '{BLENDER_SYSTEM_SCRIPTS}/startup/bl_app_templates_system/{app_template}' */ + char app_template_config[FILE_MAX]; /* Indicates whether user preferences were really load from memory. * - * This is used for versioning code, and for this we can not rely on from_memory + * This is used for versioning code, and for this we can not rely on use_factory_settings * passed via argument. This is because there might be configuration folder * exists but it might not have userpref.blend and in this case we fallback to * reading home file from memory. @@ -652,9 +668,10 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c * And in this case versioning code is to be run. */ bool read_userdef_from_memory = true; + eBLOReadSkip skip_flags = 0; /* options exclude eachother */ - BLI_assert((from_memory && custom_file) == 0); + BLI_assert((use_factory_settings && filepath_startup_override) == 0); if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) { BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC); @@ -665,71 +682,146 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c UI_view2d_zoom_cache_reset(); G.relbase_valid = 0; - if (!from_memory) { - const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); - if (custom_file) { - BLI_strncpy(startstr, custom_file, FILE_MAX); - if (cfgdir) { - BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); - } - else { - prefstr[0] = '\0'; - } + /* put aside screens to match with persistent windows later */ + wm_window_match_init(C, &wmbase); + + filepath_startup[0] = '\0'; + filepath_userdef[0] = '\0'; + app_template_system[0] = '\0'; + app_template_config[0] = '\0'; + + const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL); + if (!use_factory_settings) { + if (cfgdir) { + BLI_path_join(filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL); + BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL); } - else if (cfgdir) { - BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE); - BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); + else { + use_factory_settings = true; + } + + if (filepath_startup_override) { + BLI_strncpy(filepath_startup, filepath_startup_override, FILE_MAX); + } + } + + /* load preferences before startup.blend */ + if (!use_factory_settings && BLI_exists(filepath_userdef)) { + UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL); + if (userdef != NULL) { + 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); + } + } + + const char *app_template = NULL; + + if (filepath_startup_override != NULL) { + /* pass */ + } + else if (app_template_override && app_template_override[0]) { + app_template = app_template_override; + } + else if (!use_factory_settings && U.app_template[0]) { + app_template = U.app_template; + } + + if (app_template != NULL) { + BKE_appdir_app_template_id_search(app_template, app_template_system, sizeof(app_template_system)); + BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL); + } + + /* insert template name into startup file */ + if (app_template != NULL) { + /* note that the path is being set even when 'use_factory_settings == true' + * this is done so we can load a templates factory-settings */ + if (!use_factory_settings) { + BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_config, BLENDER_STARTUP_FILE, NULL); + if (BLI_access(filepath_startup, R_OK) != 0) { + filepath_startup[0] = '\0'; + } } else { - startstr[0] = '\0'; - prefstr[0] = '\0'; - from_memory = 1; + filepath_startup[0] = '\0'; + } + + if (filepath_startup[0] == '\0') { + BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_system, BLENDER_STARTUP_FILE, NULL); } } - - /* put aside screens to match with persistent windows later */ - wm_window_match_init(C, &wmbase); - - if (!from_memory) { - if (BLI_access(startstr, R_OK) == 0) { - success = (BKE_blendfile_read(C, startstr, NULL) != BKE_BLENDFILE_READ_FAIL); + + if (!use_factory_settings || (filepath_startup[0] != '\0')) { + if (BLI_access(filepath_startup, R_OK) == 0) { + success = (BKE_blendfile_read(C, filepath_startup, NULL, skip_flags) != BKE_BLENDFILE_READ_FAIL); } if (BLI_listbase_is_empty(&U.themes)) { if (G.debug & G_DEBUG) - printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr); - success = 0; + printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", filepath_startup); + success = false; } } - if (success == 0 && custom_file && reports) { - BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", custom_file); - /*We can not return from here because wm is already reset*/ + if (success == false && filepath_startup_override && reports) { + /* We can not return from here because wm is already reset */ + BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", filepath_startup_override); } - if (success == 0) { - success = BKE_blendfile_read_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true); + if (success == false) { + success = BKE_blendfile_read_from_memory( + C, datatoc_startup_blend, datatoc_startup_blend_size, + NULL, skip_flags, true); if (BLI_listbase_is_empty(&wmbase)) { wm_clear_default_size(C); } - BKE_tempdir_init(U.tempdir); + } -#ifdef WITH_PYTHON_SECURITY - /* use alternative setting for security nuts - * otherwise we'd need to patch the binary blob - startup.blend.c */ - U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; -#endif + if (use_empty_data) { + BKE_blendfile_read_make_empty(C); } - - /* check new prefs only after startup.blend was finished */ - if (!from_memory && BLI_exists(prefstr)) { - int done = BKE_blendfile_read_userdef(prefstr, NULL); - if (done != BKE_BLENDFILE_READ_FAIL) { - read_userdef_from_memory = false; - printf("Read new prefs: %s\n", prefstr); + + /* Load template preferences, + * unlike regular preferences we only use some of the settings, + * see: BKE_blender_userdef_set_app_template */ + if (app_template_system[0] != '\0') { + char temp_path[FILE_MAX]; + temp_path[0] = '\0'; + if (!use_factory_settings) { + BLI_path_join(temp_path, sizeof(temp_path), app_template_config, BLENDER_USERPREF_FILE, NULL); + if (BLI_access(temp_path, R_OK) != 0) { + temp_path[0] = '\0'; + } + } + + if (temp_path[0] == '\0') { + BLI_path_join(temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL); + } + + UserDef *userdef_template = NULL; + /* just avoids missing file warning */ + if (BLI_exists(temp_path)) { + userdef_template = BKE_blendfile_userdef_read(temp_path, NULL); + } + if (userdef_template == NULL) { + /* 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); + } + if (userdef_template) { + BKE_blender_userdef_set_app_template(userdef_template); + BKE_blender_userdef_free_data(userdef_template); + MEM_freeN(userdef_template); } } - + + if (app_template_override) { + BLI_strncpy(U.app_template, app_template_override, sizeof(U.app_template)); + } + /* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise * can remove this eventually, only in a 2.53 and older, now its not written */ G.fileflags &= ~G_FILE_RELATIVE_REMAP; @@ -744,11 +836,14 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c G.main->name[0] = '\0'; /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ - if (!G.background) GPU_default_lights(); - - /* XXX */ - G.save_over = 0; // start with save preference untitled.blend - G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */ + if (!G.background) { + GPU_default_lights(); + } + + /* start with save preference untitled.blend */ + G.save_over = 0; + /* disable auto-play in startup.blend... */ + G.fileflags &= ~G_FILE_AUTOPLAY; wm_file_read_post(C, true); @@ -998,7 +1093,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 */ @@ -1264,6 +1359,13 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) char filepath[FILE_MAX]; int fileflags; + const char *app_template = U.app_template[0] ? U.app_template : NULL; + const char * const cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, app_template); + if (cfgdir == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unable to create user config path"); + return OPERATOR_CANCELLED; + } + BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE); /* check current window and close it if temp */ @@ -1273,7 +1375,8 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) /* update keymaps in user preferences */ WM_keyconfig_update(wm); - BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_STARTUP_FILE, NULL); + printf("trying to save homefile at %s ", filepath); ED_editors_flush_edits(C, false); @@ -1351,21 +1454,44 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); char filepath[FILE_MAX]; + const char *cfgdir; + bool ok = false; /* update keymaps in user preferences */ WM_keyconfig_update(wm); - BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE); - printf("trying to save userpref at %s ", filepath); - - if (BKE_blendfile_write_userdef(filepath, op->reports) == 0) { - printf("fail\n"); - return OPERATOR_CANCELLED; + if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) { + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + printf("trying to save userpref at %s ", filepath); + if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) { + printf("ok\n"); + ok = true; + } + else { + printf("fail\n"); + } + } + else { + BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path"); } - printf("ok\n"); + if (U.app_template[0] && (cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) { + /* Also save app-template prefs */ + BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL); + printf("trying to save app-template userpref at %s ", filepath); + if (BKE_blendfile_userdef_write(filepath, op->reports) == 0) { + printf("fail\n"); + ok = true; + } + else { + printf("ok\n"); + } + } + else if (U.app_template[0]) { + BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path"); + } - return OPERATOR_FINISHED; + return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } void WM_OT_save_userpref(wmOperatorType *ot) @@ -1400,11 +1526,11 @@ void WM_OT_read_history(wmOperatorType *ot) static int wm_homefile_read_exec(bContext *C, wmOperator *op) { - const bool from_memory = (STREQ(op->type->idname, "WM_OT_read_factory_settings")); + const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings")); char filepath_buf[FILE_MAX]; const char *filepath = NULL; - if (!from_memory) { + if (!use_factory_settings) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath"); /* This can be used when loading of a start-up file should only change @@ -1426,7 +1552,34 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op) G.fileflags &= ~G_FILE_NO_UI; } - return wm_homefile_read(C, op->reports, from_memory, filepath) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + char app_template_buf[sizeof(U.app_template)]; + const char *app_template; + PropertyRNA *prop_app_template = RNA_struct_find_property(op->ptr, "app_template"); + const bool use_splash = !use_factory_settings && RNA_boolean_get(op->ptr, "use_splash"); + const bool use_empty_data = RNA_boolean_get(op->ptr, "use_empty"); + + if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) { + RNA_property_string_get(op->ptr, prop_app_template, app_template_buf); + app_template = app_template_buf; + } + else if (!use_factory_settings) { + /* TODO: dont reset prefs on 'New File' */ + BLI_strncpy(app_template_buf, U.app_template, sizeof(app_template_buf)); + app_template = app_template_buf; + } + else { + app_template = NULL; + } + + if (wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, filepath, app_template)) { + if (use_splash) { + WM_init_splash(C); + } + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void WM_OT_read_homefile(wmOperatorType *ot) @@ -1449,17 +1602,36 @@ void WM_OT_read_homefile(wmOperatorType *ot) "Load user interface setup from the .blend file"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + /* So the splash can be kept open after loading a file (for templates). */ + prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* omit poll to run in background mode */ } void WM_OT_read_factory_settings(wmOperatorType *ot) { + PropertyRNA *prop; + ot->name = "Load Factory Settings"; ot->idname = "WM_OT_read_factory_settings"; ot->description = "Load default file and user preferences"; ot->invoke = WM_operator_confirm; ot->exec = wm_homefile_read_exec; + + prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* omit poll to run in background mode */ } 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 4b2369a1a7c..9bafe72d805 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -192,7 +192,7 @@ void WM_init(bContext *C, int argc, const char **argv) wm_init_reports(C); /* get the default database, plus a wm */ - wm_homefile_read(C, NULL, G.factory_startup, NULL); + wm_homefile_read(C, NULL, G.factory_startup, false, NULL, NULL); BLT_lang_set(NULL); @@ -572,7 +572,7 @@ void WM_exit_ext(bContext *C, const bool do_python) ED_file_exit(); /* for fsmenu */ UI_exit(); - BKE_blender_userdef_free(); + BKE_blender_userdef_free_data(&U); RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */ diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index e201fa433d4..db5fc23146f 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -121,6 +121,13 @@ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi) if (ot->srna != kmi->ptr->type) { /* matches wm_keymap_item_properties_set but doesnt alloc new ptr */ WM_operator_properties_create_ptr(kmi->ptr, ot); + /* 'kmi->ptr->data' NULL'd above, keep using existing properties. + * Note: the operators property types may have changed, + * we will need a more comprehensive sanitize function to support this properly. + */ + if (kmi->properties) { + kmi->ptr->data = kmi->properties; + } WM_operator_properties_sanitize(kmi->ptr, 1); } } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index cef5e7e4a8e..d3ebd3e4d2c 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -900,7 +900,7 @@ void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot) void WM_operator_properties_create(PointerRNA *ptr, const char *opstring) { - wmOperatorType *ot = WM_operatortype_find(opstring, 0); + wmOperatorType *ot = WM_operatortype_find(opstring, false); if (ot) WM_operator_properties_create_ptr(ptr, ot); @@ -1118,6 +1118,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op) block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); + search[0] = '\0'; #if 0 /* ok, this isn't so easy... */ uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); #endif @@ -1402,20 +1403,6 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2) } } -static void popup_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg)) -{ - wmOperator *op = op_ptr; - if (op->type->check) { - if (op->type->check(C, op)) { - /* check for popup and re-layout buttons */ - ARegion *ar_menu = CTX_wm_menu(C); - if (ar_menu) { - ED_region_tag_refresh_ui(ar_menu); - } - } - } -} - /* Dialogs are popups that require user verification (click OK) before exec */ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData) { @@ -1434,8 +1421,6 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData) layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style); - UI_block_func_set(block, popup_check_cb, op, NULL); - uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); /* clear so the OK button is left alone */ @@ -1474,8 +1459,6 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData) layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style); - UI_block_func_set(block, popup_check_cb, op, NULL); - /* since ui is defined the auto-layout args are not used */ uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0); @@ -1522,7 +1505,7 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) data->width = width; data->height = height; data->free_op = true; /* if this runs and gets registered we may want not to free it */ - UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data); + UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data, op); return OPERATOR_RUNNING_MODAL; } @@ -1552,7 +1535,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, if (!do_redo || !(U.uiflag & USER_GLOBALUNDO)) return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y); - UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op); + UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op, op); if (do_call) wm_block_redo_cb(C, op, 0); @@ -1594,7 +1577,7 @@ int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int h data->free_op = true; /* if this runs and gets registered we may want not to free it */ /* op is not executed until popup OK but is clicked */ - UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data); + UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op); return OPERATOR_RUNNING_MODAL; } @@ -1761,6 +1744,36 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar ibuf = IMB_ibImageFromMemory((unsigned char *)datatoc_splash_png, datatoc_splash_png_size, IB_rect, NULL, "<splash screen>"); } + + /* overwrite splash with template image */ + if (U.app_template[0] != '\0') { + ImBuf *ibuf_template = NULL; + char splash_filepath[FILE_MAX]; + char template_directory[FILE_MAX]; + + if (BKE_appdir_app_template_id_search( + U.app_template, + template_directory, sizeof(template_directory))) + { + BLI_join_dirfile( + splash_filepath, sizeof(splash_filepath), template_directory, + (U.pixelsize == 2) ? "splash_2x.png" : "splash.png"); + ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL); + if (ibuf_template) { + const int x_expect = ibuf->x; + const int y_expect = 230 * (int)U.pixelsize; + /* don't cover the header text */ + if (ibuf_template->x == x_expect && ibuf_template->y == y_expect) { + memcpy(ibuf->rect, ibuf_template->rect, ibuf_template->x * ibuf_template->y * sizeof(char[4])); + } + else { + printf("Splash expected %dx%d found %dx%d, ignoring: %s\n", + x_expect, y_expect, ibuf_template->x, ibuf_template->y, splash_filepath); + } + IMB_freeImBuf(ibuf_template); + } + } + } #endif block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); @@ -1786,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_window.c b/source/blender/windowmanager/intern/wm_window.c index 2d43c47679d..de169881bc4 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -77,6 +77,7 @@ #include "GPU_extensions.h" #include "GPU_init_exit.h" #include "GPU_glew.h" +#include "BLF_api.h" /* for assert */ #ifndef NDEBUG @@ -311,7 +312,7 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) if (tmpwin == NULL) do_exit = 1; - if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved) { + if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) { if (do_exit) { if (!GHOST_confirmQuit(win->ghostwin)) return; @@ -374,14 +375,39 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) } } -static float wm_window_get_virtual_pixelsize(void) +static void wm_window_set_dpi(wmWindow *win) { - return ((U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1.0f : 2.0f); -} + int auto_dpi = GHOST_GetDPIHint(win->ghostwin); -float wm_window_pixelsize(wmWindow *win) -{ - return (GHOST_GetNativePixelSize(win->ghostwin) * wm_window_get_virtual_pixelsize()); + /* 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) { + int virtual_pixel = (U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1 : 2; + + if (U.dpi == 0) { + U.ui_scale = virtual_pixel; + } + else { + U.ui_scale = (virtual_pixel * U.dpi * 96.0f) / (auto_dpi * 72.0f); + } + + CLAMP(U.ui_scale, 0.25f, 4.0f); + } + + /* Blender's UI drawing assumes DPI 72 as a good default following macOS + * while Windows and Linux use DPI 96. GHOST assumes a default 96 so we + * remap the DPI to Blender's convention. */ + int dpi = auto_dpi * U.ui_scale * (72.0 / 96.0f); + + /* Automatically set larger pixel size for high DPI. */ + int pixelsize = MAX2(1, dpi / 54); + + /* Set user preferences globals for drawing, and for forward compatibility. */ + U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin) * pixelsize; + U.dpi = dpi / pixelsize; + U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE; + + BKE_blender_userdef_refresh(); } /* belongs to below */ @@ -456,10 +482,8 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm glClear(GL_COLOR_BUFFER_BIT); } - /* displays with larger native pixels, like Macbook. Used to scale dpi with */ /* needed here, because it's used before it reads userdef */ - U.pixelsize = wm_window_pixelsize(win); - BKE_blender_userdef_refresh(); + wm_window_set_dpi(win); wm_window_swap_buffers(win); @@ -618,15 +642,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; - const short px_virtual = (short)wm_window_get_virtual_pixelsize(); + + /* 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); @@ -644,9 +680,8 @@ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type) win->posy = rect.ymin; } - /* multiply with virtual pixelsize, ghost handles native one (e.g. for retina) */ - win->sizex = BLI_rcti_size_x(&rect) * px_virtual; - win->sizey = BLI_rcti_size_y(&rect) * px_virtual; + win->sizex = BLI_rcti_size_x(&rect); + win->sizey = BLI_rcti_size_y(&rect); if (win->ghostwin) { wm_window_set_size(win, win->sizex, win->sizey); @@ -835,8 +870,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) GHOST_ActivateWindowDrawingContext(win->ghostwin); /* this can change per window */ - U.pixelsize = wm_window_pixelsize(win); - BKE_blender_userdef_refresh(); + wm_window_set_dpi(win); } } @@ -1035,6 +1069,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr if (type == GHOST_kEventWindowSize) { WM_jobs_stop(wm, win->screen, NULL); } + + wm_window_set_dpi(win); /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { @@ -1118,7 +1154,19 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr } break; } - + + case GHOST_kEventWindowDPIHintChanged: + { + 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; + } + case GHOST_kEventOpenMainFile: { PointerRNA props_ptr; @@ -1199,11 +1247,9 @@ 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; - U.pixelsize = wm_window_pixelsize(win); + wm_window_set_dpi(win); if (U.pixelsize != prev_pixelsize) { - BKE_blender_userdef_refresh(); - // close all popups since they are positioned with the pixel // size baked in and it's difficult to correct them wmWindow *oldWindow = CTX_wm_window(C); diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index 396907a3f6d..9a1518e15b0 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -35,7 +35,10 @@ struct wmOperatorType; /* wm_files.c */ void wm_history_file_read(void); -int wm_homefile_read(struct bContext *C, struct ReportList *reports, bool from_memory, const char *filepath); +int wm_homefile_read( + struct bContext *C, struct ReportList *reports, + bool use_factory_settings, bool use_empty_data, + const char *filepath_startup_override, const char *app_template_override); void wm_file_read_report(bContext *C); void WM_OT_save_homefile(struct wmOperatorType *ot); diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index c106f9d7851..f70ec6b47f6 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -63,8 +63,6 @@ void wm_window_swap_buffers (wmWindow *win); void wm_window_set_swap_interval(wmWindow *win, int interval); bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut); -float wm_window_pixelsize(wmWindow *win); - void wm_get_cursor_position (wmWindow *win, int *x, int *y); void wm_cursor_position_from_ghost (wmWindow *win, int *x, int *y); void wm_cursor_position_to_ghost (wmWindow *win, int *x, int *y); diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 58bebc66a3e..66c72be3d5d 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -35,24 +35,13 @@ if(WIN32 AND NOT UNIX) string(SUBSTRING ${BLENDER_VERSION} 0 1 bver1) string(SUBSTRING ${BLENDER_VERSION} 2 1 bver2) string(SUBSTRING ${BLENDER_VERSION} 3 1 bver3) - if(MINGW) - add_definitions( - -DWINDRES - -DBLEN_VER_RC_STR_M=${BLENDER_VERSION} - -DBLEN_VER_RC_1=${bver1} - -DBLEN_VER_RC_2=${bver2} - -DBLEN_VER_RC_3=${bver3} - -DBLEN_VER_RC_4=0 - ) - else() - add_definitions( - -DBLEN_VER_RC_STR=${BLENDER_VERSION} - -DBLEN_VER_RC_1=${bver1} - -DBLEN_VER_RC_2=${bver2} - -DBLEN_VER_RC_3=${bver3} - -DBLEN_VER_RC_4=0 - ) - endif() + add_definitions( + -DBLEN_VER_RC_STR=${BLENDER_VERSION} + -DBLEN_VER_RC_1=${bver1} + -DBLEN_VER_RC_2=${bver2} + -DBLEN_VER_RC_3=${bver3} + -DBLEN_VER_RC_4=0 + ) add_executable( blenderplayer ${EXETYPE} @@ -176,11 +165,17 @@ endif() extern_rangetree extern_wcwidth bf_intern_libmv - extern_glog - extern_gflags extern_sdlew ) + if(NOT WITH_SYSTEM_GLOG) + list(APPEND BLENDER_SORTED_LIBS extern_glog) + endif() + + if(NOT WITH_SYSTEM_GFLAGS) + list(APPEND BLENDER_SORTED_LIBS extern_gflags) + endif() + if(WITH_MOD_CLOTH_ELTOPO) list(APPEND BLENDER_SORTED_LIBS extern_eltopo) endif() diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 08d00e9148a..d00c7b6a022 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -199,6 +199,7 @@ extern bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id); extern const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid); extern const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid); extern struct PyObject *pyrna_id_CreatePyObject(struct ID *id); +extern bool pyrna_id_CheckPyObject(struct PyObject *obj); /* bpy_interface.c */ bool BPY_string_is_keyword(const char *str) { return false; } @@ -229,7 +230,7 @@ void EDBM_mesh_normals_update(struct BMEditMesh *em) RET_NONE void *g_system; bool EDBM_mtexpoly_check(struct BMEditMesh *em) RET_ZERO -float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL +float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL float RE_filter_value(int type, float x) RET_ZERO struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) RET_NULL void RE_texture_rng_init() RET_NONE @@ -243,6 +244,7 @@ float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *c int RE_engine_get_spherical_stereo(struct RenderEngine *engine, struct Object *camera) RET_ZERO void RE_SetActiveRenderView(struct Render *re, const char *viewname) RET_NONE +struct RenderPass *RE_pass_find_by_name(volatile struct RenderLayer *rl, const char *name, const char *viewname) RET_NULL struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL bool RE_HasFakeLayer(RenderResult *res) RET_ZERO @@ -273,6 +275,8 @@ struct Object *RE_GetCamera(struct Render *re) RET_NULL float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]) RET_ZERO const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int matrix_id))[4] RET_NULL const float (*RE_render_current_get_matrix(int matrix_id))[4] RET_NULL +float RE_object_instance_get_object_pass_index(struct ObjectInstanceRen *obi) RET_ZERO +float RE_object_instance_get_random_id(struct ObjectInstanceRen *obi) RET_ZERO /* blenkernel */ bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil) RET_ZERO @@ -306,6 +310,7 @@ int WM_operator_confirm(struct bContext *C, struct wmOperator *op, const struct struct MenuType *WM_menutype_find(const char *idname, bool quiet) RET_NULL void WM_operator_stack_clear(struct wmWindowManager *wm) RET_NONE void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot) RET_NONE +bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op) RET_ZERO; void WM_autosave_init(wmWindowManager *wm) RET_NONE void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner) RET_NONE @@ -477,7 +482,7 @@ void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist struct BGpic *ED_view3D_background_image_new(struct View3D *v3d) RET_NULL void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic) RET_NONE void ED_view3D_background_image_clear(struct View3D *v3d) RET_NONE -void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]) RET_NONE +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) RET_NONE float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) RET_ZERO void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa) RET_NONE void ED_node_shader_default(const struct bContext *C, struct ID *id) RET_NONE @@ -649,7 +654,8 @@ struct RenderData *RE_engine_get_render_data(struct Render *re) RET_NULL void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result) RET_NONE void RE_engine_update_progress(struct RenderEngine *engine, float progress) RET_NONE void RE_engine_set_error_message(RenderEngine *engine, const char *msg) RET_NONE -void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int merge_results) RET_NONE +void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername) RET_NONE +void RE_engine_end_result(RenderEngine *engine, struct RenderResult *result, int cancel, int highlight, int merge_results) RET_NONE void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info) RET_NONE void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y) RET_NONE void RE_result_load_from_file(struct RenderResult *result, struct ReportList *reports, const char *filename) RET_NONE @@ -674,6 +680,7 @@ void RE_point_density_free(struct PointDensity *pd) RET_NONE void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE void RE_FreeAllPersistentData(void) RET_NONE float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO +void RE_engine_register_pass(struct RenderEngine *engine, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int channels, const char *chanid, int type) RET_NONE /* python */ struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL @@ -714,7 +721,9 @@ struct uiLayout *uiLayoutRadial(struct uiLayout *layout) RET_NULL int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title, const char *opname, const char *propname, const struct wmEvent *event) RET_ZERO -/* RNA COLLADA dependency */ +/* RNA COLLADA dependency */ +/* XXX (gaia) Why do we need this declaration here? */ +/* The collada header is included anyways further up... */ int collada_export(struct Scene *sce, const char *filepath, int apply_modifiers, @@ -727,8 +736,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, @@ -736,12 +744,17 @@ int collada_export(struct Scene *sce, int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim) RET_ZERO + int open_sim, + int limit_precision, + int keep_bind_info) RET_ZERO void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE /* bpy/python internal api */ -void operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE +extern void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata); +extern void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata); +void BPY_RNA_operator_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE +void BPY_RNA_operator_macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE void BPY_text_free_code(struct Text *text) RET_NONE void BPY_id_release(struct ID *id) RET_NONE int BPY_context_member_get(struct bContext *C, const char *member, struct bContextDataResult *result) RET_ZERO @@ -749,9 +762,9 @@ void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTa float BPY_driver_exec(PathResolvedRNA *anim_rna, struct ChannelDriver *driver, const float evaltime) RET_ZERO /* might need this one! */ void BPY_DECREF(void *pyob_ptr) RET_NONE void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets) RET_NONE -void macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) RET_ZERO struct PyObject *pyrna_id_CreatePyObject(struct ID *id) RET_NULL +bool pyrna_id_CheckPyObject(struct PyObject *obj) RET_ZERO void BPY_context_update(struct bContext *C) RET_NONE const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) RET_ARG(msgid) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index eea45545949..8f26e248424 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -113,24 +113,13 @@ if(WIN32 AND NOT UNIX) string(SUBSTRING ${BLENDER_VERSION} 0 1 bver1) string(SUBSTRING ${BLENDER_VERSION} 2 1 bver2) string(SUBSTRING ${BLENDER_VERSION} 3 1 bver3) - if(MINGW) - add_definitions( - -DWINDRES - -DBLEN_VER_RC_STR_M=${BLENDER_VERSION} - -DBLEN_VER_RC_1=${bver1} - -DBLEN_VER_RC_2=${bver2} - -DBLEN_VER_RC_3=${bver3} - -DBLEN_VER_RC_4=0 - ) - else() - add_definitions( - -DBLEN_VER_RC_STR=${BLENDER_VERSION} - -DBLEN_VER_RC_1=${bver1} - -DBLEN_VER_RC_2=${bver2} - -DBLEN_VER_RC_3=${bver3} - -DBLEN_VER_RC_4=0 - ) - endif() + add_definitions( + -DBLEN_VER_RC_STR=${BLENDER_VERSION} + -DBLEN_VER_RC_1=${bver1} + -DBLEN_VER_RC_2=${bver2} + -DBLEN_VER_RC_3=${bver3} + -DBLEN_VER_RC_4=0 + ) list(APPEND SRC @@ -652,7 +641,6 @@ elseif(WIN32) if(WITH_PYTHON) string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) - # MinGW TODO: This bit of Python configuration diverges from MSVC if(NOT CMAKE_COMPILER_IS_GNUCC) install( FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll @@ -721,9 +709,9 @@ elseif(WIN32) add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy COMMAND ${CMAKE_COMMAND} -E - tar xzvf "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}.tar.gz" + tar xzvf "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}$<$<CONFIG:Debug>:d>.tar.gz" DEPENDS - ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}.tar.gz + ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}$<$<CONFIG:Debug>:d>.tar.gz ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages ) @@ -749,20 +737,6 @@ elseif(WIN32) DESTINATION ${BLENDER_VERSION}/python/bin CONFIGURATIONS Debug ) - - # MinGW needs Python DLL - if(MINGW) - install( - FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}.dll - DESTINATION "." - CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel - ) - install( - FILES ${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}_d.dll - DESTINATION "." - CONFIGURATIONS Debug - ) - endif() endif() unset(_PYTHON_VERSION_NO_DOTS) @@ -785,57 +759,19 @@ elseif(WIN32) FILES ${LIBDIR}/pthreads/lib/pthreadVC2.dll DESTINATION "." ) - else() - #MinGW64 comes with own version. For portable builds it will probaly have to be copied to work - if(NOT WITH_MINGW64) - install( - FILES ${LIBDIR}/pthreads/lib/pthreadGC2.dll - DESTINATION "." - ) - elseif(WITH_MINGW64) - install( - FILES - ${LIBDIR}/binaries/libgcc_s_sjlj-1.dll - ${LIBDIR}/binaries/libwinpthread-1.dll - ${LIBDIR}/binaries/libstdc++-6.dll - DESTINATION "." - ) - - if(WITH_OPENMP) - install( - FILES - ${LIBDIR}/binaries/libgomp-1.dll - DESTINATION "." - ) - endif() - endif() endif() if(WITH_CODEC_FFMPEG) - if(WITH_MINGW64) - install( - FILES - ${LIBDIR}/ffmpeg/lib/avcodec-53.dll - ${LIBDIR}/ffmpeg/lib/avformat-53.dll - ${LIBDIR}/ffmpeg/lib/avdevice-53.dll - ${LIBDIR}/ffmpeg/lib/avutil-51.dll - ${LIBDIR}/ffmpeg/lib/swscale-2.dll - ${LIBDIR}/ffmpeg/lib/swresample-0.dll - ${LIBDIR}/ffmpeg/lib/xvidcore.dll - DESTINATION "." - ) - else() - install( - FILES - ${LIBDIR}/ffmpeg/lib/avcodec-57.dll - ${LIBDIR}/ffmpeg/lib/avformat-57.dll - ${LIBDIR}/ffmpeg/lib/avdevice-57.dll - ${LIBDIR}/ffmpeg/lib/avutil-55.dll - ${LIBDIR}/ffmpeg/lib/swscale-4.dll - ${LIBDIR}/ffmpeg/lib/swresample-2.dll - DESTINATION "." - ) - endif() + install( + FILES + ${LIBDIR}/ffmpeg/lib/avcodec-57.dll + ${LIBDIR}/ffmpeg/lib/avformat-57.dll + ${LIBDIR}/ffmpeg/lib/avdevice-57.dll + ${LIBDIR}/ffmpeg/lib/avutil-55.dll + ${LIBDIR}/ffmpeg/lib/swscale-4.dll + ${LIBDIR}/ffmpeg/lib/swresample-2.dll + DESTINATION "." + ) endif() if(WITH_CODEC_SNDFILE) @@ -851,30 +787,13 @@ elseif(WIN32) ${LIBDIR}/openal/lib/OpenAL32.dll DESTINATION "." ) - # MinGW TODO: Need to update to a newer OpenAL version - # which does not depend on wrap_oal.dll - if(CMAKE_COMPILER_IS_GNUCC) - install( - FILES - ${LIBDIR}/openal/lib/wrap_oal.dll - DESTINATION "." - ) - endif() endif() if(WITH_SDL) - #MinGW TODO: Update to SDL2 - if(NOT CMAKE_COMPILER_IS_GNUCC) - install( - FILES ${LIBDIR}/sdl/lib/SDL2.dll - DESTINATION "." - ) - else() - install( - FILES ${LIBDIR}/sdl/lib/SDL.dll - DESTINATION "." - ) - endif() + install( + FILES ${LIBDIR}/sdl/lib/SDL2.dll + DESTINATION "." + ) endif() if(WITH_SYSTEM_AUDASPACE) @@ -901,19 +820,11 @@ elseif(WIN32) if(WITH_OPENCOLORIO) set(OCIOBIN ${LIBDIR}/opencolorio/bin) - if(NOT MINGW) install( FILES ${OCIOBIN}/OpenColorIO.dll DESTINATION "." ) - else() - install( - FILES - ${OCIOBIN}/libOpenColorIO.dll - DESTINATION "." - ) - endif() endif() elseif(APPLE) @@ -997,21 +908,26 @@ elseif(APPLE) # python if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK) - # the python zip is first extract as part of the build process, + # the python zip is first extracted as part of the build process, # and then later installed as part of make install. this is much # quicker, and means we can easily exclude files on copy - # Not needed for PYTHON_MODULE or WEB_PLUGIN due uses Pyhon framework + # Not needed for PYTHON_MODULE or WEB_PLUGIN due uses Pyhon framework + # use a hash of the .zip path to handle switching between different + # lib directories without needing a clean build + string(SHA1 PYTHON_ZIP_HASH ${LIBDIR}/release/${PYTHON_ZIP}) + set(PYTHON_EXTRACT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PYTHON_ZIP_HASH}/python) + add_custom_target( extractpyzip - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/python) + DEPENDS ${PYTHON_EXTRACT_DIR}) set(PYTHON_ZIP "python_${CMAKE_OSX_ARCHITECTURES}.zip") add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/python - COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/python/" - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/python/" - COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/python/" + OUTPUT ${PYTHON_EXTRACT_DIR} + COMMAND ${CMAKE_COMMAND} -E remove_directory "${PYTHON_EXTRACT_DIR}/" + COMMAND ${CMAKE_COMMAND} -E make_directory "${PYTHON_EXTRACT_DIR}/" + COMMAND ${CMAKE_COMMAND} -E chdir "${PYTHON_EXTRACT_DIR}/" ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}" DEPENDS ${LIBDIR}/release/${PYTHON_ZIP}) @@ -1019,13 +935,13 @@ elseif(APPLE) # copy extracted python files install_dir( - ${CMAKE_CURRENT_BINARY_DIR}/python + ${PYTHON_EXTRACT_DIR} \${TARGETDIR_VER} ) # copy site-packages files install_dir( ${LIBDIR}/release/site-packages - ${CMAKE_CURRENT_BINARY_DIR}/python/lib/python${PYTHON_VERSION} + \${TARGETDIR_VER}/python/lib/python${PYTHON_VERSION} ) install(DIRECTORY ${LIBDIR}/python/bin @@ -1082,16 +998,16 @@ elseif(APPLE) # python if(WITH_PYTHON AND NOT WITH_PYTHON_FRAMEWORK) add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/python - COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/python/" - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/python/" - COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/python/" + OUTPUT ${PYTHON_EXTRACT_DIR} + COMMAND ${CMAKE_COMMAND} -E remove_directory "${PYTHON_EXTRACT_DIR}/" + COMMAND ${CMAKE_COMMAND} -E make_directory "${PYTHON_EXTRACT_DIR}/" + COMMAND ${CMAKE_COMMAND} -E chdir "${PYTHON_EXTRACT_DIR}/" ${CMAKE_COMMAND} -E tar xzfv "${LIBDIR}/release/${PYTHON_ZIP}" DEPENDS ${LIBDIR}/release/${PYTHON_ZIP}) # copy extracted python files install_dir( - ${CMAKE_CURRENT_BINARY_DIR}/python + ${PYTHON_EXTRACT_DIR} \${PLAYER_TARGETDIR_VER} ) endif() diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index d7fe8d8ce59..6e698166fd9 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -40,7 +40,7 @@ # pragma warning (disable:4786) #endif -#include "glew-mx.h" +#include "GPU_glew.h" #include "KX_BlenderCanvas.h" #include "KX_BlenderKeyboardDevice.h" @@ -104,13 +104,13 @@ typedef void * wmUIHandlerRemoveFunc; # include AUD_DEVICE_H #endif -static BlendFileData *load_game_data(char *filename) +static BlendFileData *load_game_data(const char *filename) { ReportList reports; BlendFileData *bfd; BKE_reports_init(&reports, RPT_STORE); - bfd= BLO_read_from_file(filename, &reports); + bfd= BLO_read_from_file(filename, &reports, BLO_READ_SKIP_USERDEF); if (!bfd) { printf("Loading %s failed: ", filename); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp index 927b26faf8a..a6b2340d7b4 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp @@ -29,7 +29,7 @@ * \ingroup blroutines */ -#include "glew-mx.h" +#include "GPU_glew.h" #include "MEM_guardedalloc.h" diff --git a/source/gameengine/Expressions/intern/HashedPtr.cpp b/source/gameengine/Expressions/intern/HashedPtr.cpp index 005ac16b231..11d9482f993 100644 --- a/source/gameengine/Expressions/intern/HashedPtr.cpp +++ b/source/gameengine/Expressions/intern/HashedPtr.cpp @@ -40,10 +40,8 @@ CHashedPtr::CHashedPtr(void* val) : m_valptr(val) unsigned int CHashedPtr::hash() const { -#if defined(_WIN64) && !defined(FREE_WINDOWS64) +#if defined(_WIN64) unsigned __int64 key = (unsigned __int64)m_valptr; -#elif defined(FREE_WINDOWS64) - unsigned long long key = (unsigned long long)m_valptr; #else unsigned long key = (unsigned long)m_valptr; #endif diff --git a/source/gameengine/Expressions/intern/InputParser.cpp b/source/gameengine/Expressions/intern/InputParser.cpp index e8cc7fba284..583d8da63cb 100644 --- a/source/gameengine/Expressions/intern/InputParser.cpp +++ b/source/gameengine/Expressions/intern/InputParser.cpp @@ -37,7 +37,7 @@ // cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc... #include "EXP_IfExpr.h" -#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS) +#if defined(WIN32) || defined(WIN64) #define strcasecmp _stricmp #ifndef strtoll diff --git a/source/gameengine/Expressions/intern/PyObjectPlus.cpp b/source/gameengine/Expressions/intern/PyObjectPlus.cpp index de45bee76a7..1e4a59aeb5c 100644 --- a/source/gameengine/Expressions/intern/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/intern/PyObjectPlus.cpp @@ -335,7 +335,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * Py_DECREF(resultlist); return NULL; } - // walkthrough + ATTR_FALLTHROUGH; case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast<int*>(ptr); @@ -406,7 +406,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * { return NULL; } - // walkthrough + ATTR_FALLTHROUGH; case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast<int*>(ptr); @@ -638,7 +638,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt PyErr_Format(PyExc_AttributeError, "Size check error for attribute, \"%s\", report to blender.org", attrdef->m_name); goto UNDO_AND_ERROR; } - // walkthrough + ATTR_FALLTHROUGH; case KX_PYATTRIBUTE_TYPE_INT: { int *var = reinterpret_cast<int*>(ptr); @@ -883,7 +883,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt PyErr_Format(PyExc_AttributeError, "attribute size check error for attribute \"%s\", report to blender.org", attrdef->m_name); goto FREE_AND_ERROR; } - // walkthrough + ATTR_FALLTHROUGH; case KX_PYATTRIBUTE_TYPE_INT: { int *var = reinterpret_cast<int*>(ptr); diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index abb64cf1733..e34a5296139 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -133,7 +133,7 @@ bool SCA_PropertySensor::CheckPropertyCondition() { case KX_PROPSENSOR_NOTEQUAL: reverse = true; - /* fall-through */ + ATTR_FALLTHROUGH; case KX_PROPSENSOR_EQUAL: { CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); @@ -231,7 +231,7 @@ bool SCA_PropertySensor::CheckPropertyCondition() } case KX_PROPSENSOR_LESSTHAN: reverse = true; - /* fall-through */ + ATTR_FALLTHROUGH; case KX_PROPSENSOR_GREATERTHAN: { CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h index 9a108203ee8..688ed8ac0f4 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.h +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h @@ -40,7 +40,7 @@ # include <windows.h> #endif /* WIN32 */ -#include "glew-mx.h" +#include "GPU_glew.h" #include <map> diff --git a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h index 504df2376bb..24922197723 100644 --- a/source/gameengine/GamePlayer/common/GPC_MouseDevice.h +++ b/source/gameengine/GamePlayer/common/GPC_MouseDevice.h @@ -67,8 +67,6 @@ public: * Call this routine to update the mouse device when a button state changes. * \param button Which button state changes. * \param isDown The new state of the button. - * \param x Position x-coordinate of the cursor at the time of the state change. - * \param y Position y-coordinate of the cursor at the time of the state change. * \return Indication as to whether the event was processed. */ virtual bool ConvertButtonEvent(TButtonId button, bool isDown); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 408006a0dae..50c34bbadaf 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -36,7 +36,7 @@ # include <windows.h> #endif -#include "glew-mx.h" +#include "GPU_glew.h" #include "GPU_extensions.h" #include "GPU_init_exit.h" diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index dd93a6ff424..0c206dfce3d 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -355,7 +355,7 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL BLI_strncpy(bfd->main->name, progname, sizeof(bfd->main->name)); } } else { - bfd= BLO_read_from_file(progname, &reports); + bfd= BLO_read_from_file(progname, &reports, BLO_READ_SKIP_NONE); } if (!bfd && filename) { diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 95679b5d3a6..9cbd61590b6 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -169,7 +169,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) rasty->GetViewMatrix().getValue(&viewmat[0][0]); float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL); + GPU_material_bind_uniforms(gpumat, obmat, viewmat, obcol, auto_bump_scale, NULL, NULL); mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol); } diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 72815cadc70..d344e18c313 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -22,7 +22,7 @@ * \ingroup ketsji */ -#include "glew-mx.h" +#include "GPU_glew.h" #include <iostream> #include "BL_Shader.h" diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index cc7fea5ad25..c3b799b9424 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -22,7 +22,7 @@ * \ingroup ketsji */ -#include "glew-mx.h" +#include "GPU_glew.h" #include <iostream> #include <map> diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 476fbd29b8b..d26e35f8138 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -22,7 +22,7 @@ * \ingroup ketsji */ -#include "glew-mx.h" +#include "GPU_glew.h" #include "KX_BlenderMaterial.h" #include "BL_Material.h" diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h index 420565e62f6..5a0c4588ae2 100644 --- a/source/gameengine/Ketsji/KX_Dome.h +++ b/source/gameengine/Ketsji/KX_Dome.h @@ -38,7 +38,7 @@ #include "RAS_IRasterizer.h" #include "KX_KetsjiEngine.h" -#include "glew-mx.h" +#include "GPU_glew.h" #include <vector> #include "MEM_guardedalloc.h" diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index f3947fdd710..be1a4b4ef3a 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -31,10 +31,8 @@ */ -#if defined(_WIN64) && !defined(FREE_WINDOWS64) +#if defined(_WIN64) typedef unsigned __int64 uint_ptr; -#elif defined(FREE_WINDOWS64) -typedef unsigned long long uint_ptr; #else typedef unsigned long uint_ptr; #endif diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index b0a8e376eb6..d82a0fd533b 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -80,12 +80,6 @@ #define DEFAULT_LOGIC_TIC_RATE 60.0 //#define DEFAULT_PHYSICS_TIC_RATE 60.0 -#ifdef FREE_WINDOWS /* XXX mingw64 (gcc 4.7.0) defines a macro for DrawText that translates to DrawTextA. Not good */ -#ifdef DrawText -#undef DrawText -#endif -#endif - const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = { "Physics:", // tc_physics "Logic:", // tc_logic diff --git a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp index 239bfde4c98..c84b2474c90 100644 --- a/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp +++ b/source/gameengine/Ketsji/KX_ObstacleSimulation.cpp @@ -345,6 +345,7 @@ static MT_Point3 nearestPointToObstacle(MT_Point3& pos ,KX_Obstacle* obstacle) MT_Point3 res = obstacle->m_pos + abdir*proj; return res; } + ATTR_FALLTHROUGH; } case KX_OBSTACLE_CIRCLE : default: diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index cdc2f9f3644..97a7e161e9f 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -30,7 +30,7 @@ * \ingroup ketsji */ -#include "glew-mx.h" +#include "GPU_glew.h" #ifdef _MSC_VER # pragma warning (disable:4786) diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index a27f37c0441..d858097abef 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -108,7 +108,7 @@ void KX_SoundActuator::play() case KX_SOUNDACT_LOOPBIDIRECTIONAL: case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: sound = AUD_Sound_pingpong(sound); - // fall through + ATTR_FALLTHROUGH; case KX_SOUNDACT_LOOPEND: case KX_SOUNDACT_LOOPSTOP: loop = true; @@ -124,7 +124,7 @@ void KX_SoundActuator::play() AUD_Device_free(device); // in case of pingpong, we have to free the sound - if(sound != m_sound) + if (sound != m_sound) AUD_Sound_free(sound); if (m_handle != NULL) { diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt index e52dc1ba052..8b00f1b47fa 100644 --- a/source/gameengine/Physics/Bullet/CMakeLists.txt +++ b/source/gameengine/Physics/Bullet/CMakeLists.txt @@ -37,6 +37,7 @@ set(INC ../../SceneGraph ../../../blender/blenkernel ../../../blender/blenlib + ../../../blender/gpu ../../../blender/makesdna ../../../../intern/container ../../../../intern/guardedalloc diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt index c65fcac5161..fc7dc90e03b 100644 --- a/source/gameengine/Rasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../../blender/makesdna ../../blender/blenlib ../../blender/blenkernel + ../../blender/gpu ../../blender/imbuf ../../../intern/container ../../../intern/glew-mx diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index 82b26749fd1..f379e2eb486 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -24,7 +24,7 @@ * \ingroup bgerast */ -#define STRINGIFY(A) #A +#include "BLI_utildefines.h" #include "RAS_OpenGLFilters/RAS_Blur2DFilter.h" #include "RAS_OpenGLFilters/RAS_Sharpen2DFilter.h" @@ -43,7 +43,7 @@ #include "RAS_2DFilterManager.h" #include <iostream> -#include "glew-mx.h" +#include "GPU_glew.h" #include <stdio.h> diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index b2d580161ca..71c8cfe745f 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -30,7 +30,7 @@ #include <windows.h> #endif // WIN32 -#include "glew-mx.h" +#include "GPU_glew.h" #include "RAS_MaterialBucket.h" #include "RAS_TexVert.h" diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp index fff988a07c5..69e859f06d9 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "glew-mx.h" +#include "GPU_glew.h" #include <stdio.h> diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp index e589bffcaf1..58b3c61bd05 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLOffScreen.cpp @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "glew-mx.h" +#include "GPU_glew.h" #include <stdio.h> diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 3f82c513f7d..5eed9b3b8f8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -35,7 +35,7 @@ #include "RAS_OpenGLRasterizer.h" -#include "glew-mx.h" +#include "GPU_glew.h" #include "RAS_ICanvas.h" #include "RAS_Rect.h" @@ -994,8 +994,8 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, } bool negX = (scale[0] < 0.0f); - bool negY = (scale[0] < 0.0f); - bool negZ = (scale[0] < 0.0f); + bool negY = (scale[1] < 0.0f); + bool negZ = (scale[2] < 0.0f); if (negX || negY || negZ) { m_viewmatrix.tscale((negX)?-1.0f:1.0f, (negY)?-1.0f:1.0f, (negZ)?-1.0f:1.0f, 1.0); } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp index d54b3232067..26b956cd74e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLSync.cpp @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "glew-mx.h" +#include "GPU_glew.h" #include <stdio.h> diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp index 316871e6025..f980116f5f8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp @@ -27,7 +27,7 @@ #include "RAS_StorageVA.h" -#include "glew-mx.h" +#include "GPU_glew.h" RAS_StorageVA::RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer) : m_drawingmode(RAS_IRasterizer::KX_TEXTURED), diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp index 114defb60a5..4ba5882a46e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp @@ -28,7 +28,7 @@ #include "RAS_StorageVBO.h" #include "RAS_MeshObject.h" -#include "glew-mx.h" +#include "GPU_glew.h" VBO::VBO(RAS_DisplayArray *data, unsigned int indices) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h index 4c8e4a8931c..c82b6a3206d 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h @@ -29,7 +29,7 @@ #define __KX_VERTEXBUFFEROBJECTSTORAGE #include <map> -#include "glew-mx.h" +#include "GPU_glew.h" #include "RAS_IStorage.h" #include "RAS_IRasterizer.h" diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index 0db1fa293da..b91a312a5d7 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -43,7 +43,7 @@ extern "C" { #include "Exception.h" -#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS) +#if (defined(WIN32) || defined(WIN64)) #define strcasecmp _stricmp #endif diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h index 4c9fc5a58fb..5a09c9a67b3 100644 --- a/source/gameengine/VideoTexture/ImageBase.h +++ b/source/gameengine/VideoTexture/ImageBase.h @@ -40,7 +40,7 @@ #include "FilterBase.h" -#include "glew-mx.h" +#include "GPU_glew.h" // forward declarations struct PyImage; diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 7e8c534d7d5..57062343b67 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -36,7 +36,7 @@ #include <math.h> -#include "glew-mx.h" +#include "GPU_glew.h" #include "KX_PythonInit.h" #include "DNA_scene_types.h" diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index 8852c190053..ad3d8875e28 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -33,7 +33,7 @@ #include "EXP_PyObjectPlus.h" #include <structmember.h> -#include "glew-mx.h" +#include "GPU_glew.h" #include "KX_PythonInit.h" #include "RAS_ICanvas.h" diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index bb995747360..48dc4c705bf 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -55,7 +55,7 @@ #include "Exception.h" #include <memory.h> -#include "glew-mx.h" +#include "GPU_glew.h" extern "C" { #include "IMB_imbuf.h" diff --git a/source/gameengine/VideoTexture/VideoDeckLink.h b/source/gameengine/VideoTexture/VideoDeckLink.h index 50099d2ead4..d5419176691 100644 --- a/source/gameengine/VideoTexture/VideoDeckLink.h +++ b/source/gameengine/VideoTexture/VideoDeckLink.h @@ -47,7 +47,7 @@ extern "C" { #include "BLI_threads.h" #include "BLI_blenlib.h" } -#include "GL/glew.h" +#include "GPU_glew.h" #ifdef WIN32 #include "dvpapi.h" #endif |