diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2016-08-21 14:18:26 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2016-08-21 14:18:26 +0300 |
commit | 069569f82011c833937df07ec7945751c02f0a9c (patch) | |
tree | 8c6ed443d055f23d9ec7764b70e98d133b9766d1 /source | |
parent | be2bc7e0f66b9ed1c863790b3555aa3e7db4cb76 (diff) | |
parent | 43bb8f12f44415c91f07ab5864aee7da51ef4a09 (diff) |
Merge branch 'master' into blender2.8
In addition to pack of conflicts listed below, also had to comment out particle part of new Alembic code... :/
Conflicts:
intern/ghost/intern/GHOST_WindowWin32.cpp
source/blender/blenkernel/BKE_effect.h
source/blender/blenkernel/BKE_pointcache.h
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/rigidbody.c
source/blender/blenkernel/intern/smoke.c
source/blender/blenkernel/intern/softbody.c
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/gpu/intern/gpu_debug.c
source/blender/makesdna/DNA_object_types.h
source/blender/makesrna/intern/rna_particle.c
Diffstat (limited to 'source')
122 files changed, 2469 insertions, 839 deletions
diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_camera.cc index 38a6d3d33cf..5c34ec1391f 100644 --- a/source/blender/alembic/intern/abc_camera.cc +++ b/source/blender/alembic/intern/abc_camera.cc @@ -109,7 +109,7 @@ AbcCameraReader::AbcCameraReader(const Alembic::Abc::IObject &object, ImportSett ICamera abc_cam(m_iobject, kWrapExisting); m_schema = abc_cam.getSchema(); - get_min_max_time(m_schema, m_min_time, m_max_time); + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); } bool AbcCameraReader::valid() const diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc index 4e1e4e7e490..2b54741a5c5 100644 --- a/source/blender/alembic/intern/abc_curves.cc +++ b/source/blender/alembic/intern/abc_curves.cc @@ -190,7 +190,7 @@ AbcCurveReader::AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettin ICurves abc_curves(object, kWrapExisting); m_curves_schema = abc_curves.getSchema(); - get_min_max_time(m_curves_schema, m_min_time, m_max_time); + get_min_max_time(m_iobject, m_curves_schema, m_min_time, m_max_time); } bool AbcCurveReader::valid() const diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index 127e8853789..132c59c0cfb 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -44,6 +44,7 @@ extern "C" { #include "DNA_curve_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_space_types.h" /* for FILE_MAX */ @@ -59,7 +60,6 @@ extern "C" { #include "BKE_idprop.h" #include "BKE_main.h" #include "BKE_modifier.h" -#include "BKE_particle.h" #include "BKE_scene.h" } @@ -175,7 +175,7 @@ void AbcExporter::getShutterSamples(double step, bool time_relative, /* sample all frame */ if (shutter_open == 0.0 && shutter_close == 1.0) { for (double t = 0; t < 1.0; t += step) { - samples.push_back(t / time_factor); + samples.push_back((t + m_settings.frame_start) / time_factor); } } else { @@ -184,7 +184,7 @@ void AbcExporter::getShutterSamples(double step, bool time_relative, const double time_inc = (shutter_close - shutter_open) / nsamples; for (double t = shutter_open; t <= shutter_close; t += time_inc) { - samples.push_back(t / time_factor); + samples.push_back((t + m_settings.frame_start) / time_factor); } } } @@ -325,16 +325,18 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) break; } - double f = *begin; - setCurrentFrame(bmain, f); + const double frame = *begin; - if (shape_frames.count(f) != 0) { + /* 'frame' is offset by start frame, so need to cancel the offset. */ + setCurrentFrame(bmain, frame - m_settings.frame_start); + + if (shape_frames.count(frame) != 0) { for (int i = 0, e = m_shapes.size(); i != e; ++i) { m_shapes[i]->write(); } } - if (xform_frames.count(f) == 0) { + if (xform_frames.count(frame) == 0) { continue; } @@ -518,22 +520,6 @@ void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent) return; } - ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first); - - for (; psys; psys = psys->next) { - if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) { - continue; - } - - if (psys->part->type == PART_HAIR) { - m_settings.export_child_hairs = true; - m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys)); - } - else if (psys->part->type == PART_EMITTER) { - m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys)); - } - } - switch(ob->type) { case OB_MESH: { diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc index 45bf9b7ab8a..967c99d81e1 100644 --- a/source/blender/alembic/intern/abc_hair.cc +++ b/source/blender/alembic/intern/abc_hair.cc @@ -37,7 +37,6 @@ extern "C" { #include "BKE_DerivedMesh.h" #include "BKE_object.h" -#include "BKE_particle.h" } using Alembic::Abc::P3fArraySamplePtr; @@ -54,10 +53,10 @@ AbcHairWriter::AbcHairWriter(Scene *scene, AbcTransformWriter *parent, uint32_t time_sampling, ExportSettings &settings, - ParticleSystem *psys) + void *UNUSED(psys)) : AbcObjectWriter(scene, ob, time_sampling, settings, parent) { - m_psys = psys; + m_psys = NULL; // = psys; OCurves curves(parent->alembicXform(), m_name, m_time_sampling); m_schema = curves.getSchema(); @@ -68,7 +67,7 @@ void AbcHairWriter::do_write() if (!m_psys) { return; } - +#if 0 ParticleSystemModifierData *psmd = psys_get_modifier(m_object, m_psys); if (!psmd->dm_final) { @@ -116,15 +115,17 @@ void AbcHairWriter::do_write() m_sample.setSelfBounds(bounds()); m_schema.set(m_sample); +#endif } void AbcHairWriter::write_hair_sample(DerivedMesh *dm, - ParticleSettings *part, + void *part, std::vector<Imath::V3f> &verts, std::vector<Imath::V3f> &norm_values, std::vector<Imath::V2f> &uv_values, std::vector<int32_t> &hvertices) { +#if 0 /* Get untransformed vertices, there's a xform under the hair. */ float inv_mat[4][4]; invert_m4_m4_safe(inv_mat, m_object->obmat); @@ -225,15 +226,17 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm, ++path; } } +#endif } void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm, - ParticleSettings *part, + void *part, std::vector<Imath::V3f> &verts, std::vector<Imath::V3f> &norm_values, std::vector<Imath::V2f> &uv_values, std::vector<int32_t> &hvertices) { +#if 0 /* Get untransformed vertices, there's a xform under the hair. */ float inv_mat[4][4]; invert_m4_m4_safe(inv_mat, m_object->obmat); @@ -287,4 +290,5 @@ void AbcHairWriter::write_hair_child_sample(DerivedMesh *dm, ++path; } } +#endif } diff --git a/source/blender/alembic/intern/abc_hair.h b/source/blender/alembic/intern/abc_hair.h index d132b60be12..bbd5f2c4361 100644 --- a/source/blender/alembic/intern/abc_hair.h +++ b/source/blender/alembic/intern/abc_hair.h @@ -26,13 +26,11 @@ #include "abc_object.h" struct DerivedMesh; -struct ParticleSettings; -struct ParticleSystem; /* ************************************************************************** */ class AbcHairWriter : public AbcObjectWriter { - ParticleSystem *m_psys; + /*ParticleSystem*/ void *m_psys; Alembic::AbcGeom::OCurvesSchema m_schema; Alembic::AbcGeom::OCurvesSchema::Sample m_sample; @@ -43,20 +41,20 @@ public: AbcTransformWriter *parent, uint32_t time_sampling, ExportSettings &settings, - ParticleSystem *psys); + /*ParticleSystem*/void *psys); private: virtual void do_write(); void write_hair_sample(DerivedMesh *dm, - ParticleSettings *part, + /*ParticleSettings*/ void *part, std::vector<Imath::V3f> &verts, std::vector<Imath::V3f> &norm_values, std::vector<Imath::V2f> &uv_values, std::vector<int32_t> &hvertices); void write_hair_child_sample(DerivedMesh *dm, - ParticleSettings *part, + /*ParticleSettings*/ void *part, std::vector<Imath::V3f> &verts, std::vector<Imath::V3f> &norm_values, std::vector<Imath::V2f> &uv_values, diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index f1c7b6b3aa3..4db33289232 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -272,7 +272,7 @@ static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob) } /* mesh is not a subsurf. break */ - if ((md->type != eModifierType_Displace) && (md->type != eModifierType_ParticleSystem)) { + if ((md->type != eModifierType_Displace) /*&& (md->type != eModifierType_ParticleSystem)*/) { return NULL; } } @@ -968,7 +968,8 @@ AbcMeshReader::AbcMeshReader(const IObject &object, ImportSettings &settings) IPolyMesh ipoly_mesh(m_iobject, kWrapExisting); m_schema = ipoly_mesh.getSchema(); - get_min_max_time(m_schema, m_min_time, m_max_time); + + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); } bool AbcMeshReader::valid() const @@ -1120,7 +1121,8 @@ AbcSubDReader::AbcSubDReader(const IObject &object, ImportSettings &settings) ISubD isubd_mesh(m_iobject, kWrapExisting); m_schema = isubd_mesh.getSchema(); - get_min_max_time(m_schema, m_min_time, m_max_time); + + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); } bool AbcSubDReader::valid() const diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc index a3c18ad6301..4f57dfdae9e 100644 --- a/source/blender/alembic/intern/abc_nurbs.cc +++ b/source/blender/alembic/intern/abc_nurbs.cc @@ -201,7 +201,7 @@ AbcNurbsReader::AbcNurbsReader(const IObject &object, ImportSettings &settings) : AbcObjectReader(object, settings) { getNurbsPatches(m_iobject); - get_min_max_time(m_schemas[0].first, m_min_time, m_max_time); + get_min_max_time(m_iobject, m_schemas[0].first, m_min_time, m_max_time); } bool AbcNurbsReader::valid() const diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc index fa5b71ac094..22a51d984ef 100644 --- a/source/blender/alembic/intern/abc_points.cc +++ b/source/blender/alembic/intern/abc_points.cc @@ -30,11 +30,11 @@ extern "C" { #include "DNA_mesh_types.h" +#include "DNA_object_types.h" #include "BKE_lattice.h" #include "BKE_mesh.h" #include "BKE_object.h" -#include "BKE_particle.h" #include "BKE_scene.h" #include "BLI_math.h" @@ -61,10 +61,10 @@ AbcPointsWriter::AbcPointsWriter(Scene *scene, AbcTransformWriter *parent, uint32_t time_sampling, ExportSettings &settings, - ParticleSystem *psys) + void *UNUSED(psys)) : AbcObjectWriter(scene, ob, time_sampling, settings, parent) { - m_psys = psys; + m_psys = NULL; // = psys; OPoints points(parent->alembicXform(), m_name, m_time_sampling); m_schema = points.getSchema(); @@ -75,7 +75,7 @@ void AbcPointsWriter::do_write() if (!m_psys) { return; } - +#if 0 std::vector<Imath::V3f> points; std::vector<Imath::V3f> velocities; std::vector<float> widths; @@ -132,6 +132,7 @@ void AbcPointsWriter::do_write() m_sample.setSelfBounds(bounds()); m_schema.set(m_sample); +#endif } /* ************************************************************************** */ @@ -141,7 +142,7 @@ AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSett { IPoints ipoints(m_iobject, kWrapExisting); m_schema = ipoints.getSchema(); - get_min_max_time(m_schema, m_min_time, m_max_time); + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); } bool AbcPointsReader::valid() const diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_points.h index 51f3103bd8b..cfa51e66a22 100644 --- a/source/blender/alembic/intern/abc_points.h +++ b/source/blender/alembic/intern/abc_points.h @@ -28,14 +28,12 @@ #include "abc_object.h" #include "abc_customdata.h" -class ParticleSystem; - /* ************************************************************************** */ class AbcPointsWriter : public AbcObjectWriter { Alembic::AbcGeom::OPointsSchema m_schema; Alembic::AbcGeom::OPointsSchema::Sample m_sample; - ParticleSystem *m_psys; + /*ParticleSystem*/ void *m_psys; public: AbcPointsWriter(Scene *scene, @@ -43,7 +41,7 @@ public: AbcTransformWriter *parent, uint32_t time_sampling, ExportSettings &settings, - ParticleSystem *psys); + /*ParticleSystem*/ void *psys); void do_write(); }; diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index 3326ae0ed84..7f8984f9970 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -137,7 +137,7 @@ AbcEmptyReader::AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettin Alembic::AbcGeom::IXform xform(object, Alembic::AbcGeom::kWrapExisting); m_schema = xform.getSchema(); - get_min_max_time(m_schema, m_min_time, m_max_time); + get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time); } bool AbcEmptyReader::valid() const diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h index 688a25d85f6..648570f5f27 100644 --- a/source/blender/alembic/intern/abc_util.h +++ b/source/blender/alembic/intern/abc_util.h @@ -64,7 +64,7 @@ void create_input_transform(const Alembic::AbcGeom::ISampleSelector &sample_sel, float r_mat[4][4], float scale, bool has_alembic_parent = false); template <typename Schema> -void get_min_max_time(const Schema &schema, chrono_t &min, chrono_t &max) +void get_min_max_time_ex(const Schema &schema, chrono_t &min, chrono_t &max) { const Alembic::Abc::TimeSamplingPtr &time_samp = schema.getTimeSampling(); @@ -81,6 +81,18 @@ void get_min_max_time(const Schema &schema, chrono_t &min, chrono_t &max) } } +template <typename Schema> +void get_min_max_time(const Alembic::AbcGeom::IObject &object, const Schema &schema, chrono_t &min, chrono_t &max) +{ + get_min_max_time_ex(schema, min, max); + + const Alembic::AbcGeom::IObject &parent = object.getParent(); + if (parent.valid() && Alembic::AbcGeom::IXform::matches(parent.getMetaData())) { + Alembic::AbcGeom::IXform xform(parent, Alembic::AbcGeom::kWrapExisting); + get_min_max_time_ex(xform.getSchema(), min, max); + } +} + bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name); /* ************************** */ diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 0e96ac22e11..f42c708b4c2 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -585,6 +585,9 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa IArchive *archive = open_archive(data->filename); if (!archive || !archive->valid()) { + if (archive) { + delete archive; + } data->error_code = ABC_ARCHIVE_FAIL; return; } @@ -933,12 +936,12 @@ static DerivedMesh *read_mesh_sample(DerivedMesh *dm, const IObject &iobject, co CDStreamConfig config = get_config(new_dm ? new_dm : dm); - bool has_loop_normals = false; - read_mesh_sample(&settings, schema, sample_sel, config, has_loop_normals); + bool do_normals = false; + read_mesh_sample(&settings, schema, sample_sel, config, do_normals); if (new_dm) { /* Check if we had ME_SMOOTH flag set to restore it. */ - if (!has_loop_normals && check_smooth_poly_flag(dm)) { + if (!do_normals && check_smooth_poly_flag(dm)) { set_smooth_poly_flag(new_dm); } @@ -948,6 +951,10 @@ static DerivedMesh *read_mesh_sample(DerivedMesh *dm, const IObject &iobject, co return new_dm; } + if (do_normals) { + CDDM_calc_normals(dm); + } + return dm; } diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index d5b4a584ec6..8fedcd4ab06 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -146,6 +146,10 @@ void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct ///////////////////////////////////////////////// // used in effect.c ///////////////////////////////////////////////// + +/* explicit control over layer mask and dupli recursion */ +struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli); + struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type); typedef struct ColliderCache { diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 6d6740cb975..90fe3601372 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -60,6 +60,8 @@ typedef struct EffectedPoint { unsigned int flag; int index; + + struct ParticleSystem *psys; /* particle system the point belongs to */ } EffectedPoint; typedef struct GuideEffectorData { @@ -105,7 +107,7 @@ typedef struct EffectorCache { } EffectorCache; void free_partdeflect(struct PartDeflect *pd); -struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct EffectorWeights *weights, bool precalc); +struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct EffectorWeights *weights, bool for_simulation); void pdEndEffectors(struct ListBase **effectors); void pdPrecalculateEffectors(struct ListBase *effectors); void pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index df739996c54..8ae5c2b3c45 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -49,7 +49,7 @@ void BKE_material_free(struct Material *ma); void BKE_material_free_ex(struct Material *ma, bool do_id_user); void test_object_materials(struct Object *ob, struct ID *id); void test_all_objects_materials(struct Main *bmain, struct ID *id); -void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user); +void BKE_material_resize_object(struct Main *bmain, struct Object *ob, const short totcol, bool do_id_user); 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); @@ -90,10 +90,10 @@ void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma); void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob); /* rna api */ -void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user); -void BKE_material_append_id(struct ID *id, struct Material *ma); -struct Material *BKE_material_pop_id(struct ID *id, int index, bool update_data); /* index is an int because of RNA */ -void BKE_material_clear_id(struct ID *id, bool update_data); +void BKE_material_resize_id(struct Main *bmain, struct ID *id, short totcol, bool do_id_user); +void BKE_material_append_id(struct Main *bmain, struct ID *id, struct Material *ma); +struct Material *BKE_material_pop_id(struct Main *bmain, struct ID *id, int index, bool update_data); /* index is an int because of RNA */ +void BKE_material_clear_id(struct Main *bmain, struct ID *id, bool update_data); /* rendering */ void init_render_material(struct Material *, int, float *); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 1938bb08395..30873567297 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -277,9 +277,9 @@ void BKE_tracking_detect_harris(struct MovieTracking *tracking, struct ListBase bool place_outside_layer); /* **** 2D stabilization **** */ -void BKE_tracking_stabilization_data_get(struct MovieTracking *tracking, int framenr, int width, int height, +void BKE_tracking_stabilization_data_get(struct MovieClip *clip, int framenr, int width, int height, float translation[2], float *scale, float *angle); -struct ImBuf *BKE_tracking_stabilize_frame(struct MovieTracking *tracking, int framenr, struct ImBuf *ibuf, +struct ImBuf *BKE_tracking_stabilize_frame(struct MovieClip *clip, int framenr, struct ImBuf *ibuf, float translation[2], float *scale, float *angle); void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, float translation[2], float scale, float angle, float mat[4][4]); diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h index 7b3199efb41..69ca75836d9 100644 --- a/source/blender/blenkernel/depsgraph_private.h +++ b/source/blender/blenkernel/depsgraph_private.h @@ -34,6 +34,11 @@ #include "DNA_constraint_types.h" #include "BKE_constraint.h" +struct Scene; +struct Group; +struct EffectorWeights; +struct ModifierData; + /* **** DAG relation types *** */ /* scene link to object */ @@ -152,6 +157,11 @@ DagNode *dag_get_node(DagForest *forest, void *fob); DagNode *dag_get_sub_node(DagForest *forest, void *fob); void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name); +typedef bool (*DagCollobjFilterFunction)(struct Object *obj, struct ModifierData *md); + +void dag_add_collision_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name); +void dag_add_forcefield_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name); + void graph_print_queue(DagNodeQueue *nqueue); void graph_print_queue_dist(DagNodeQueue *nqueue); void graph_print_adj_list(DagForest *dag); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 7ad2b118e72..bfdbb510091 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1506,7 +1506,7 @@ static bool animsys_store_rna_setting( if (array_len && array_index >= array_len) { if (G.debug & G_DEBUG) { printf("Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d\n", - (ptr && ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", + (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", path, array_index, array_len - 1); } } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index d257a1cfcae..2d06bc88aa7 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -687,20 +687,24 @@ static void cdDM_drawMappedFaces( const int orig = (index_mp_to_orig) ? index_mp_to_orig[i] : i; bool is_hidden; - if (use_hide) { - if (flag & DM_DRAW_SELECT_USE_EDITMODE) { - BMFace *efa = BM_face_at_index(bm, orig); - is_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) != 0; + if (orig != ORIGINDEX_NONE) { + if (use_hide) { + if (flag & DM_DRAW_SELECT_USE_EDITMODE) { + BMFace *efa = BM_face_at_index(bm, orig); + is_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) != 0; + } + else { + is_hidden = (me->mpoly[orig].flag & ME_HIDE) != 0; + } + + if (!is_hidden) { + GPU_select_index_get(orig + 1, &selcol); + } } else { - is_hidden = (me->mpoly[orig].flag & ME_HIDE) != 0; - } - - if ((orig != ORIGINDEX_NONE) && !is_hidden) GPU_select_index_get(orig + 1, &selcol); + } } - else if (orig != ORIGINDEX_NONE) - GPU_select_index_get(orig + 1, &selcol); for (j = 0; j < mpoly->totloop; j++) fi_map[start_element++] = selcol; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4ab6c82b2c2..87733341cdd 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -80,8 +80,10 @@ void cloth_init(ClothModifierData *clmd ) clmd->sim_parms->gravity[1] = 0.0; clmd->sim_parms->gravity[2] = -9.81; clmd->sim_parms->structural = 15.0; + clmd->sim_parms->max_struct = 15.0; clmd->sim_parms->shear = 15.0; clmd->sim_parms->bending = 0.5; + clmd->sim_parms->max_bend = 0.5; clmd->sim_parms->bending_damping = 0.5; clmd->sim_parms->Cdis = 5.0; clmd->sim_parms->Cvi = 1.0; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 8cac856b560..35a7aafdbde 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -503,12 +503,13 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned // return all collision objects in scene // collision object will exclude self -Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type) +Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli) { Base *base; Object **objs; GroupObject *go; unsigned int numobj= 0, maxobj= 100; + int level = dupli ? 0 : 1; objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray"); @@ -516,16 +517,14 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned if (group) { /* use specified group */ for (go= group->gobject.first; go; go= go->next) - add_collision_object(&objs, &numobj, &maxobj, go->ob, self, 0, modifier_type); + add_collision_object(&objs, &numobj, &maxobj, go->ob, self, level, modifier_type); } else { Scene *sce_iter; /* add objects in same layer in scene */ for (SETLOOPER(scene, sce_iter, base)) { - /* Need to check for active layers, too. - Otherwise this check fails if the objects are not on the same layer - DG */ - if ((base->lay & self->lay) || (base->lay & scene->lay)) - add_collision_object(&objs, &numobj, &maxobj, base->object, self, 0, modifier_type); + if ( base->lay & layer ) + add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type); } } @@ -535,6 +534,13 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned return objs; } +Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type) +{ + /* Need to check for active layers, too. + Otherwise this check fails if the objects are not on the same layer - DG */ + return get_collisionobjects_ext(scene, self, group, self->lay | scene->lay, numcollobj, modifier_type, true); +} + static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level) { CollisionModifierData *cmd= NULL; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index b6bfe336183..184688b5e74 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -61,11 +61,14 @@ #include "DNA_windowmanager_types.h" #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" +#include "DNA_modifier_types.h" +#include "DNA_rigidbody_types.h" #include "BKE_anim.h" #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_DerivedMesh.h" +#include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_fcurve.h" #include "BKE_global.h" @@ -450,29 +453,51 @@ static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *l la->id.tag &= ~LIB_TAG_DOIT; } -static void check_and_create_collision_relation(DagForest *dag, Object *ob, DagNode *node, Object *ob1, int skip_forcefield, bool no_collision) +static void create_collision_relation(DagForest *dag, DagNode *node, Object *ob1, const char *name) { - DagNode *node2; - if (ob1->pd && (ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) { - if ((skip_forcefield && ob1->pd->forcefield == skip_forcefield) || (no_collision && ob1->pd->forcefield == 0)) - return; - node2 = dag_get_node(dag, ob1); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Collision"); + DagNode *node2 = dag_get_node(dag, ob1); + dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, name); +} + +void dag_add_collision_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name) +{ + unsigned int numcollobj; + Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli); + + for (unsigned int i = 0; i < numcollobj; i++) { + Object *ob1 = collobjs[i]; + + if (!fn || fn(ob1, modifiers_findByType(ob1, modifier_type))) { + create_collision_relation(dag, node, ob1, name); + } } + + if (collobjs) + MEM_freeN(collobjs); } -static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield, bool no_collision) +void dag_add_forcefield_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name) { - Base *base; + ListBase *effectors = pdInitEffectors(scene, ob, effector_weights, false); + + if (effectors) { + for (EffectorCache *eff = effectors->first; eff; eff = eff->next) { + if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) { + create_collision_relation(dag, node, eff->ob, name); - /* would be nice to have a list of colliders here - * so for now walk all objects in scene check 'same layer rule' */ - for (base = scene->base.first; base; base = base->next) { - if ((base->lay & ob->lay)) { - Object *ob1 = base->object; - check_and_create_collision_relation(dag, ob, node, ob1, skip_forcefield, no_collision); + if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) { + create_collision_relation(dag, node, eff->pd->f_source, "Smoke Force Domain"); + } + + if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { + /* Actual code uses get_collider_cache */ + dag_add_collision_relations(dag, scene, ob, node, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption"); + } + } } } + + pdEndEffectors(&effectors); } static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Object *ob, int mask) @@ -622,22 +647,13 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Sc } } - /* softbody collision */ + /* rigidbody force fields */ if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_LATTICE)) { - if (modifiers_isModifierEnabled(ob, eModifierType_Softbody) || - modifiers_isModifierEnabled(ob, eModifierType_Cloth) || - modifiers_isModifierEnabled(ob, eModifierType_DynamicPaint)) - { - dag_add_collision_field_relation(dag, scene, ob, node, 0, false); /* TODO: use effectorweight->group */ - } - else if (modifiers_isModifierEnabled(ob, eModifierType_Smoke)) { - dag_add_collision_field_relation(dag, scene, ob, node, PFIELD_SMOKEFLOW, false); - } - else if (ob->rigidbody_object) { - dag_add_collision_field_relation(dag, scene, ob, node, 0, true); + if (ob->rigidbody_object && scene->rigidbody_world) { + dag_add_forcefield_relations(dag, scene, ob, node, scene->rigidbody_world->effector_weights, true, 0, "Force Field"); } } - + /* object data drivers */ if (ob->data) { AnimData *adt = BKE_animdata_from_id((ID *)ob->data); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 824683f5b99..9afcd7f2bbb 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -152,15 +152,20 @@ static EffectorCache *new_effector_cache(Scene *scene, Object *ob, PartDeflect * eff->frame = -1; return eff; } -static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src) +static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation) { EffectorCache *eff = NULL; - if ( ob == ob_src || weights->weight[ob->pd->forcefield] == 0.0f ) + if ( ob == ob_src ) return; - if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal ) - return; + if (for_simulation) { + if (weights->weight[ob->pd->forcefield] == 0.0f ) + return; + + if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal ) + return; + } if (*effectors == NULL) *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); @@ -175,7 +180,7 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector /* returns ListBase handle with objects taking part in the effecting */ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, - EffectorWeights *weights, bool precalc) + EffectorWeights *weights, bool for_simulation) { Base *base; unsigned int layer= ob_src->lay; @@ -187,7 +192,7 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, for (go= weights->group->gobject.first; go; go= go->next) { if ( (go->ob->lay & layer) ) { if ( go->ob->pd && go->ob->pd->forcefield ) - add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src); + add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src, for_simulation); } } } @@ -195,12 +200,12 @@ ListBase *pdInitEffectors(Scene *scene, Object *ob_src, for (base = scene->base.first; base; base= base->next) { if ( (base->lay & layer) ) { if ( base->object->pd && base->object->pd->forcefield ) - add_object_to_effectors(&effectors, scene, weights, base->object, ob_src); + add_object_to_effectors(&effectors, scene, weights, base->object, ob_src, for_simulation); } } } - if (precalc) + if (for_simulation) pdPrecalculateEffectors(effectors); return effectors; diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index e4bac0a947a..2242113b79b 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -1268,7 +1268,7 @@ void BKE_gpencil_palettecolor_changename(bGPdata *gpd, char *oldname, const char for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (gps = gpf->strokes.first; gps; gps = gps->next) { if (STREQ(gps->colorname, oldname)) { - strcpy(gps->colorname, newname); + BLI_strncpy(gps->colorname, newname, sizeof(gps->colorname)); } } } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 470108545b8..54945242fe4 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -58,6 +58,7 @@ #include "BKE_animsys.h" #include "BKE_displist.h" #include "BKE_global.h" +#include "BKE_depsgraph.h" #include "BKE_icons.h" #include "BKE_image.h" #include "BKE_library.h" @@ -398,7 +399,7 @@ static void material_data_index_clear_id(ID *id) } } -void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user) +void BKE_material_resize_id(Main *bmain, ID *id, short totcol, bool do_id_user) { Material ***matar = give_matarar_id(id); short *totcolp = give_totcolp_id(id); @@ -424,9 +425,11 @@ void BKE_material_resize_id(struct ID *id, short totcol, bool do_id_user) *matar = MEM_recallocN(*matar, sizeof(void *) * totcol); } *totcolp = totcol; + + DAG_relations_tag_update(bmain); } -void BKE_material_append_id(ID *id, Material *ma) +void BKE_material_append_id(Main *bmain, ID *id, Material *ma) { Material ***matar; if ((matar = give_matarar_id(id))) { @@ -439,11 +442,12 @@ void BKE_material_append_id(ID *id, Material *ma) (*matar)[(*totcol)++] = ma; id_us_plus((ID *)ma); - test_all_objects_materials(G.main, id); + test_all_objects_materials(bmain, id); + DAG_relations_tag_update(bmain); } } -Material *BKE_material_pop_id(ID *id, int index_i, bool update_data) +Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data) { short index = (short)index_i; Material *ret = NULL; @@ -472,13 +476,15 @@ Material *BKE_material_pop_id(ID *id, int index_i, bool update_data) /* decrease mat_nr index */ material_data_index_remove_id(id, index); } + + DAG_relations_tag_update(bmain); } } return ret; } -void BKE_material_clear_id(struct ID *id, bool update_data) +void BKE_material_clear_id(Main *bmain, ID *id, bool update_data) { Material ***matar; if ((matar = give_matarar_id(id))) { @@ -497,6 +503,8 @@ void BKE_material_clear_id(struct ID *id, bool update_data) /* decrease mat_nr index */ material_data_index_clear_id(id); } + + DAG_relations_tag_update(bmain); } } @@ -553,7 +561,7 @@ Material *give_node_material(Material *ma) return NULL; } -void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user) +void BKE_material_resize_object(Main *bmain, Object *ob, const short totcol, bool do_id_user) { Material **newmatar; char *newmatbits; @@ -590,6 +598,8 @@ void BKE_material_resize_object(Object *ob, const short totcol, bool do_id_user) ob->totcol = totcol; if (ob->totcol && ob->actcol == 0) ob->actcol = 1; if (ob->actcol > ob->totcol) ob->actcol = ob->totcol; + + DAG_relations_tag_update(bmain); } void test_object_materials(Object *ob, ID *id) @@ -601,7 +611,7 @@ void test_object_materials(Object *ob, ID *id) return; } - BKE_material_resize_object(ob, *totcol, false); + BKE_material_resize_object(G.main, ob, *totcol, false); } void test_all_objects_materials(Main *bmain, ID *id) @@ -617,7 +627,7 @@ void test_all_objects_materials(Main *bmain, ID *id) BKE_main_lock(bmain); for (ob = bmain->object.first; ob; ob = ob->id.next) { if (ob->data == id) { - BKE_material_resize_object(ob, *totcol, false); + BKE_material_resize_object(bmain, ob, *totcol, false); } } BKE_main_unlock(bmain); @@ -1881,7 +1891,7 @@ static short mesh_getmaterialnumber(Mesh *me, Material *ma) /* append material */ static short mesh_addmaterial(Mesh *me, Material *ma) { - BKE_material_append_id(&me->id, NULL); + BKE_material_append_id(G.main, &me->id, NULL); me->mat[me->totcol - 1] = ma; id_us_plus(&ma->id); @@ -2020,7 +2030,7 @@ static void convert_tfacematerial(Main *main, Material *ma) /* remove material from mesh */ for (a = 0; a < me->totcol; ) { if (me->mat[a] == ma) { - BKE_material_pop_id(&me->id, a, true); + BKE_material_pop_id(main, &me->id, a, true); } else { a++; diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 0d362086134..482015d3b26 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1033,7 +1033,7 @@ static ImBuf *get_stable_cached_frame(MovieClip *clip, MovieClipUser *user, ImBu stableibuf = cache->stabilized.ibuf; - BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); + BKE_tracking_stabilization_data_get(clip, clip_framenr, stableibuf->x, stableibuf->y, tloc, &tscale, &tangle); /* check for stabilization parameters */ if (tscale != cache->stabilized.scale || @@ -1057,7 +1057,7 @@ static ImBuf *put_stabilized_frame_to_cache(MovieClip *clip, MovieClipUser *user float tloc[2], tscale, tangle; int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, framenr); - stableibuf = BKE_tracking_stabilize_frame(&clip->tracking, clip_framenr, ibuf, tloc, &tscale, &tangle); + stableibuf = BKE_tracking_stabilize_frame(clip, clip_framenr, ibuf, tloc, &tscale, &tangle); copy_v2_v2(cache->stabilized.loc, tloc); @@ -1270,8 +1270,6 @@ void BKE_movieclip_reload(MovieClip *clip) /* clear cache */ free_buffers(clip); - clip->tracking.stabilization.ok = false; - /* update clip source */ detect_clip_source(clip); diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 75f20c7e1d3..3ec174146b1 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -221,31 +221,39 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild if (ctx->group) { unsigned int lay = ctx->group->layer; + int groupid = 0; GroupObject *go; - for (go = ctx->group->gobject.first; go; go = go->next) { + for (go = ctx->group->gobject.first; go; go = go->next, groupid++) { Object *ob = go->ob; if ((ob->lay & lay) && ob != obedit && is_child(ob, parent)) { + DupliContext pctx; + copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false); + /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ - make_child_duplis_cb(ctx, userdata, ob); + make_child_duplis_cb(&pctx, userdata, ob); } } } else { unsigned int lay = ctx->scene->lay; + int baseid = 0; Base *base; - for (base = ctx->scene->base.first; base; base = base->next) { + for (base = ctx->scene->base.first; base; base = base->next, baseid++) { Object *ob = base->object; if ((base->lay & lay) && ob != obedit && is_child(ob, parent)) { + DupliContext pctx; + copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false); + /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ - make_child_duplis_cb(ctx, userdata, ob); + make_child_duplis_cb(&pctx, userdata, ob); } } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index c3e34347e55..73af6a6be65 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -162,7 +162,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) if (type == SCE_COPY_EMPTY) { ListBase rl, rv; - /* XXX. main should become an arg */ scen = BKE_scene_add(bmain, sce->id.name + 2); rl = scen->r.layers; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 98bea27ecb9..4a8629e40a3 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -2458,11 +2458,10 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object * } /* only calculate something when we advanced a single frame */ - if (framenr != (int)smd->time + 1) - return; - /* don't simulate if viewing start frame, but scene frame is not real start frame */ - if (framenr != scene->r.cfra) + bool can_simulate = (framenr == (int)smd->time + 1) && (framenr == scene->r.cfra); + + if (!can_simulate) return; #ifdef DEBUG_TIME @@ -2756,9 +2755,15 @@ float smoke_get_velocity_at(struct Object *ob, float position[3], float velocity int smoke_get_data_flags(SmokeDomainSettings *sds) { int flags = 0; - if (smoke_has_heat(sds->fluid)) flags |= SM_ACTIVE_HEAT; - if (smoke_has_fuel(sds->fluid)) flags |= SM_ACTIVE_FIRE; - if (smoke_has_colors(sds->fluid)) flags |= SM_ACTIVE_COLORS; + + if (sds->fluid) { + if (smoke_has_heat(sds->fluid)) + flags |= SM_ACTIVE_HEAT; + if (smoke_has_fuel(sds->fluid)) + flags |= SM_ACTIVE_FIRE; + if (smoke_has_colors(sds->fluid)) + flags |= SM_ACTIVE_COLORS; + } return flags; } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index f4986f7daba..f0e2cbd657e 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3696,7 +3696,10 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i return; } - if (framenr!=sb->last_frame+1) + /* try to read from cache */ + bool can_simulate = (framenr == sb->last_frame + 1); + + if (!can_simulate) return; softbody_update_positions(ob, sb, vertexCos, numVerts); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index e876bf43809..60f1eb6b98c 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2707,7 +2707,6 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) GPU_vertex_setup(dm); GPU_normal_setup(dm); GPU_triangle_setup(dm); - glShadeModel(GL_SMOOTH); for (a = 0; a < dm->drawObject->totmaterial; a++) { if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) { GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, dm->drawObject->materials[a].start, @@ -2811,8 +2810,6 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, } #endif - glShadeModel(GL_SMOOTH); - CCG_key_top_level(&key, ss); ccgdm_pbvh_update(ccgdm); @@ -2965,6 +2962,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, } } + glShadeModel(GL_SMOOTH); #undef PASSATTRIB } else { @@ -3170,8 +3168,6 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, MEM_freeN(mat_orig_to_new); MEM_freeN(matconv); } - - glShadeModel(GL_SMOOTH); } static void ccgDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial) @@ -3369,6 +3365,7 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, } } + glShadeModel(GL_SMOOTH); #undef PASSATTRIB } @@ -3503,7 +3500,6 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, next_actualFace = 0; - glShadeModel(GL_SMOOTH); /* lastFlag = 0; */ /* UNUSED */ for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) { GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index; @@ -3681,8 +3677,8 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, if (do_draw) { glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); ccgSubSurf_drawGLMesh(ss, true, -1, -1); + glShadeModel(GL_SMOOTH); } - glShadeModel(GL_SMOOTH); return; } #endif @@ -3744,10 +3740,6 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); } - /* no need to set shading mode to flat because - * normals are already used to change shading */ - glShadeModel(GL_SMOOTH); - for (S = 0; S < numVerts; S++) { CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); if (ln) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index a56fc0f9abe..d5d3384bb48 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -241,13 +241,9 @@ static void tracking_reconstruction_copy( /* Copy stabilization structure. */ static void tracking_stabilization_copy( - MovieTrackingStabilization *stabilization_dst, MovieTrackingStabilization *stabilization_src, - GHash *tracks_mapping) + MovieTrackingStabilization *stabilization_dst, MovieTrackingStabilization *stabilization_src) { *stabilization_dst = *stabilization_src; - if (stabilization_src->rot_track) { - stabilization_dst->rot_track = BLI_ghash_lookup(tracks_mapping, stabilization_src->rot_track); - } } /* Copy tracking object. */ @@ -284,7 +280,7 @@ void BKE_tracking_copy(MovieTracking *tracking_dst, MovieTracking *tracking_src) tracking_tracks_copy(&tracking_dst->tracks, &tracking_src->tracks, tracks_mapping); tracking_plane_tracks_copy(&tracking_dst->plane_tracks, &tracking_src->plane_tracks, tracks_mapping); tracking_reconstruction_copy(&tracking_dst->reconstruction, &tracking_src->reconstruction); - tracking_stabilization_copy(&tracking_dst->stabilization, &tracking_src->stabilization, tracks_mapping); + tracking_stabilization_copy(&tracking_dst->stabilization, &tracking_src->stabilization); if (tracking_src->act_track) { tracking_dst->act_track = BLI_ghash_lookup(tracks_mapping, tracking_src->act_track); } @@ -316,7 +312,7 @@ void BKE_tracking_copy(MovieTracking *tracking_dst, MovieTracking *tracking_src) } /* Initialize motion tracking settings to default values, - * used when new movie clip datablock is creating. + * used when new movie clip datablock is created. */ void BKE_tracking_settings_init(MovieTracking *tracking) { @@ -334,10 +330,22 @@ void BKE_tracking_settings_init(MovieTracking *tracking) tracking->settings.object_distance = 1; tracking->stabilization.scaleinf = 1.0f; + tracking->stabilization.anchor_frame = MINFRAME; + zero_v2(tracking->stabilization.target_pos); + tracking->stabilization.target_rot = 0.0f; + tracking->stabilization.scale = 1.0f; + + tracking->stabilization.act_track = 0; + tracking->stabilization.act_rot_track = 0; + tracking->stabilization.tot_track = 0; + tracking->stabilization.tot_rot_track = 0; + + tracking->stabilization.scaleinf = 1.0f; tracking->stabilization.locinf = 1.0f; tracking->stabilization.rotinf = 1.0f; tracking->stabilization.maxscale = 2.0f; tracking->stabilization.filter = TRACKING_FILTER_BILINEAR; + tracking->stabilization.flag |= TRACKING_SHOW_STAB_TRACKS; BKE_tracking_object_add(tracking, "Camera"); } @@ -552,6 +560,7 @@ MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking, ListBase *tr track->flag = settings->default_flag; track->algorithm_flag = settings->default_algorithm_flag; track->weight = settings->default_weight; + track->weight_stab = settings->default_weight; memset(&marker, 0, sizeof(marker)); marker.pos[0] = x; @@ -590,6 +599,12 @@ MovieTrackingTrack *BKE_tracking_track_duplicate(MovieTrackingTrack *track) new_track->markers = MEM_dupallocN(new_track->markers); + /* Orevent duplicate from being used for 2D stabilization. + * If necessary, it shall be added explicitly. + */ + new_track->flag &= ~TRACK_USE_2D_STAB; + new_track->flag &= ~TRACK_USE_2D_STAB_ROT; + return new_track; } diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index eb224020977..4d72d851ae9 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -21,6 +21,7 @@ * Contributor(s): Blender Foundation, * Sergey Sharybin * Keir Mierle + * Ichthyostega * * ***** END GPL LICENSE BLOCK ***** */ @@ -28,292 +29,1302 @@ /** \file blender/blenkernel/intern/tracking_stabilize.c * \ingroup bke * - * This file contains implementation of 2D frame stabilization. + * This file contains implementation of 2D image stabilization. */ #include <limits.h> #include "DNA_movieclip_types.h" +#include "DNA_scene_types.h" +#include "DNA_anim_types.h" +#include "RNA_access.h" #include "BLI_utildefines.h" +#include "BLI_sort_utils.h" +#include "BLI_math_vector.h" #include "BLI_math.h" #include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BKE_fcurve.h" +#include "BLI_ghash.h" +#include "MEM_guardedalloc.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -/* Calculate median point of markers of tracks marked as used for - * 2D stabilization. - * - * NOTE: frame number should be in clip space, not scene space + +/* == Parameterization constants == */ + +/* When measuring the scale changes relative to the rotation pivot point, it + * might happen accidentally that a probe point (tracking point), which doesn't + * actually move on a circular path, gets very close to the pivot point, causing + * the measured scale contribution to go toward infinity. We damp this undesired + * effect by adding a bias (floor) to the measured distances, which will + * dominate very small distances and thus cause the corresponding track's + * contribution to diminish. + * Measurements happen in normalized (0...1) coordinates within a frame. + */ +static float SCALE_ERROR_LIMIT_BIAS = 0.01f; + +/* When to consider a track as completely faded out. + * This is used in conjunction with the "disabled" flag of the track + * to determine start positions, end positions and gaps + */ +static float EPSILON_WEIGHT = 0.005f; + + + +/* == private working data == */ + +/* Per track baseline for stabilization, defined at reference frame. + * A track's reference frame is chosen as close as possible to the (global) + * anchor_frame. Baseline holds the constant part of each track's contribution + * to the observed movement; it is calculated at initialization pass, using the + * measurement value at reference frame plus the average contribution to fill + * the gap between global anchor_frame and the reference frame for this track. + * This struct with private working data is associated to the local call context + * via `StabContext::private_track_data` + */ +typedef struct TrackStabilizationBase { + float stabilization_offset_base[2]; + + /* measured relative to translated pivot */ + float stabilization_rotation_base[2][2]; + + /* measured relative to translated pivot */ + float stabilization_scale_base; + + bool is_init_for_stabilization; + FCurve *track_weight_curve; +} TrackStabilizationBase; + +/* Tracks are reordered for initialization, starting as close as possible to + * anchor_frame */ -static bool stabilization_median_point_get(MovieTracking *tracking, int framenr, float median[2]) +typedef struct TrackInitOrder { + int sort_value; + int reference_frame; + MovieTrackingTrack *data; +} TrackInitOrder; + +/* Per frame private working data, for accessing possibly animated values. */ +typedef struct StabContext { + MovieClip *clip; + MovieTracking *tracking; + MovieTrackingStabilization *stab; + GHash *private_track_data; + FCurve *locinf; + FCurve *rotinf; + FCurve *scaleinf; + FCurve *target_pos[2]; + FCurve *target_rot; + FCurve *target_scale; + bool use_animation; +} StabContext; + + +static TrackStabilizationBase *access_stabilization_baseline_data( + StabContext *ctx, + MovieTrackingTrack *track) { - bool ok = false; - float min[2], max[2]; - MovieTrackingTrack *track; + return BLI_ghash_lookup(ctx->private_track_data, track); +} - INIT_MINMAX2(min, max); +static void attach_stabilization_baseline_data( + StabContext *ctx, + MovieTrackingTrack *track, + TrackStabilizationBase *private_data) +{ + return BLI_ghash_insert(ctx->private_track_data, track, private_data); +} - track = tracking->tracks.first; - while (track) { - if (track->flag & TRACK_USE_2D_STAB) { - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); +static void discard_stabilization_baseline_data(void *val) +{ + if (val != NULL) { + MEM_freeN(val); + } +} - minmax_v2v2_v2(min, max, marker->pos); - ok = true; - } +/* == access animated values for given frame == */ + +static FCurve *retrieve_stab_animation(MovieClip *clip, + const char *data_path, + int idx) +{ + return id_data_find_fcurve(&clip->id, + &clip->tracking.stabilization, + &RNA_MovieTrackingStabilization, + data_path, + idx, + NULL); +} + +static FCurve *retrieve_track_weight_animation(MovieClip *clip, + MovieTrackingTrack *track) +{ + return id_data_find_fcurve(&clip->id, + track, + &RNA_MovieTrackingTrack, + "weight_stab", + 0, + NULL); +} + +static float fetch_from_fcurve(FCurve *animationCurve, + int framenr, + StabContext *ctx, + float default_value) +{ + if (ctx && ctx->use_animation && animationCurve) { + int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(ctx->clip, + framenr); + return evaluate_fcurve(animationCurve, scene_framenr); + } + return default_value; +} + + +static float get_animated_locinf(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->locinf, framenr, ctx, ctx->stab->locinf); +} + +static float get_animated_rotinf(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->rotinf, framenr, ctx, ctx->stab->rotinf); +} + +static float get_animated_scaleinf(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->scaleinf, framenr, ctx, ctx->stab->scaleinf); +} + +static void get_animated_target_pos(StabContext *ctx, + int framenr, + float target_pos[2]) +{ + target_pos[0] = fetch_from_fcurve(ctx->target_pos[0], + framenr, + ctx, + ctx->stab->target_pos[0]); + target_pos[1] = fetch_from_fcurve(ctx->target_pos[1], + framenr, + ctx, + ctx->stab->target_pos[1]); +} + +static float get_animated_target_rot(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->target_rot, + framenr, + ctx, + ctx->stab->target_rot); +} + +static float get_animated_target_scale(StabContext *ctx, int framenr) +{ + return fetch_from_fcurve(ctx->target_scale, framenr, ctx, ctx->stab->scale); +} + +static float get_animated_weight(StabContext *ctx, + MovieTrackingTrack *track, + int framenr) +{ + TrackStabilizationBase *working_data = + access_stabilization_baseline_data(ctx, track); + if (working_data && working_data->track_weight_curve) { + int scene_framenr = BKE_movieclip_remap_clip_to_scene_frame(ctx->clip, + framenr); + return evaluate_fcurve(working_data->track_weight_curve, scene_framenr); + } + /* Use weight at global 'current frame' as fallback default. */ + return track->weight_stab; +} - track = track->next; +static void use_values_from_fcurves(StabContext *ctx, bool toggle) +{ + if (ctx != NULL) { + ctx->use_animation = toggle; } +} - median[0] = (max[0] + min[0]) / 2.0f; - median[1] = (max[1] + min[1]) / 2.0f; - return ok; +/* Prepare per call private working area. + * Used for access to possibly animated values: retrieve available F-curves. + */ +static StabContext *initialize_stabilization_working_context(MovieClip *clip) +{ + StabContext *ctx = MEM_callocN(sizeof(StabContext), + "2D stabilization animation runtime data"); + ctx->clip = clip; + ctx->tracking = &clip->tracking; + ctx->stab = &clip->tracking.stabilization; + ctx->private_track_data = BLI_ghash_ptr_new( + "2D stabilization per track private working data"); + ctx->locinf = retrieve_stab_animation(clip, "influence_location", 0); + ctx->rotinf = retrieve_stab_animation(clip, "influence_rotation", 0); + ctx->scaleinf = retrieve_stab_animation(clip, "influence_scale", 0); + ctx->target_pos[0] = retrieve_stab_animation(clip, "target_pos", 0); + ctx->target_pos[1] = retrieve_stab_animation(clip, "target_pos", 1); + ctx->target_rot = retrieve_stab_animation(clip, "target_rot", 0); + ctx->target_scale = retrieve_stab_animation(clip, "target_zoom", 0); + ctx->use_animation = true; + return ctx; } -/* Calculate stabilization data (translation, scale and rotation) from - * given median of first and current frame medians, tracking data and - * frame number. - * - * NOTE: frame number should be in clip space, not scene space +/* Discard all private working data attached to this call context. + * NOTE: We allocate the record for the per track baseline contribution + * locally for each call context (i.e. call to + * BKE_tracking_stabilization_data_get() + * Thus it is correct to discard all allocations found within the + * corresponding _local_ GHash */ -static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height, - const float firstmedian[2], const float median[2], - float translation[2], float *scale, float *angle) +static void discard_stabilization_working_context(StabContext *ctx) { - MovieTrackingStabilization *stab = &tracking->stabilization; + if (ctx != NULL) { + BLI_ghash_free(ctx->private_track_data, + NULL, + discard_stabilization_baseline_data); + MEM_freeN(ctx); + } +} + +static bool is_init_for_stabilization(StabContext *ctx, + MovieTrackingTrack *track) +{ + TrackStabilizationBase *working_data = + access_stabilization_baseline_data(ctx, track); + return (working_data != NULL && working_data->is_init_for_stabilization); +} + +static bool is_usable_for_stabilization(StabContext *ctx, + MovieTrackingTrack *track) +{ + return (track->flag & TRACK_USE_2D_STAB) && + is_init_for_stabilization(ctx, track); +} - *scale = (stab->scale - 1.0f) * stab->scaleinf + 1.0f; - *angle = 0.0f; +static bool is_effectively_disabled(StabContext *ctx, + MovieTrackingTrack *track, + MovieTrackingMarker *marker) +{ + return (marker->flag & MARKER_DISABLED) || + (EPSILON_WEIGHT > get_animated_weight(ctx, track, marker->framenr)); +} - translation[0] = (firstmedian[0] - median[0]) * width * (*scale); - translation[1] = (firstmedian[1] - median[1]) * height * (*scale); - mul_v2_fl(translation, stab->locinf); +static int search_closest_marker_index(MovieTrackingTrack *track, + int ref_frame) +{ + MovieTrackingMarker *markers = track->markers; + int end = track->markersnr; + int i = track->last_marker; - if ((stab->flag & TRACKING_STABILIZE_ROTATION) && stab->rot_track && stab->rotinf) { - MovieTrackingMarker *marker; - float a[2], b[2]; - float x0 = (float)width / 2.0f, y0 = (float)height / 2.0f; - float x = median[0] * width, y = median[1] * height; + i = MAX2(0, i); + i = MIN2(i, end - 1); + for ( ; i < end - 1 && markers[i].framenr <= ref_frame; ++i); + for ( ; 0 < i && markers[i].framenr > ref_frame; --i); + + track->last_marker = i; + return i; +} + +static void retrieve_next_higher_usable_frame(StabContext *ctx, + MovieTrackingTrack *track, + int i, + int ref_frame, + int *next_higher) +{ + MovieTrackingMarker *markers = track->markers; + int end = track->markersnr; + BLI_assert(0 <= i && i < end); + + while (i < end && + (markers[i].framenr < ref_frame || + is_effectively_disabled(ctx, track, &markers[i]))) + { + ++i; + } + if (i < end && markers[i].framenr < *next_higher) { + BLI_assert(markers[i].framenr >= ref_frame); + *next_higher = markers[i].framenr; + } +} + +static void retrieve_next_lower_usable_frame(StabContext *ctx, + MovieTrackingTrack *track, + int i, + int ref_frame, + int *next_lower) +{ + MovieTrackingMarker *markers = track->markers; + BLI_assert(0 <= i && i < track->markersnr); + while (i >= 0 && + (markers[i].framenr > ref_frame || + is_effectively_disabled(ctx, track, &markers[i]))) + { + --i; + } + if (0 <= i && markers[i].framenr > *next_lower) { + BLI_assert(markers[i].framenr <= ref_frame); + *next_lower = markers[i].framenr; + } +} - marker = BKE_tracking_marker_get(stab->rot_track, 1); - sub_v2_v2v2(a, marker->pos, firstmedian); - a[0] *= width; - a[1] *= height; +/* Find closest frames with usable stabilization data. + * A frame counts as _usable_ when there is at least one track marked for + * translation stabilization, which has an enabled tracking marker at this very + * frame. We search both for the next lower and next higher position, to allow + * the caller to interpolate gaps and to extrapolate at the ends of the + * definition range. + * + * NOTE: Regarding performance note that the individual tracks will cache the + * last search position. + */ +static void find_next_working_frames(StabContext *ctx, + int framenr, + int *next_lower, + int *next_higher) +{ + for (MovieTrackingTrack *track = ctx->tracking->tracks.first; + track != NULL; + track = track->next) + { + if (is_usable_for_stabilization(ctx, track)) { + int startpoint = search_closest_marker_index(track, framenr); + retrieve_next_higher_usable_frame(ctx, + track, + startpoint, + framenr, + next_higher); + retrieve_next_lower_usable_frame(ctx, + track, + startpoint, + framenr, + next_lower); + } + } +} - marker = BKE_tracking_marker_get(stab->rot_track, framenr); - sub_v2_v2v2(b, marker->pos, median); - b[0] *= width; - b[1] *= height; - *angle = -atan2f(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]); - *angle *= stab->rotinf; +/* Find active (enabled) marker closest to the reference frame. */ +static MovieTrackingMarker *get_closest_marker(StabContext *ctx, + MovieTrackingTrack *track, + int ref_frame) +{ + int next_lower = MINAFRAME; + int next_higher = MAXFRAME; + int i = search_closest_marker_index(track, ref_frame); + retrieve_next_higher_usable_frame(ctx, track, i, ref_frame, &next_higher); + retrieve_next_lower_usable_frame(ctx, track, i, ref_frame, &next_lower); + + if ((next_higher - ref_frame) < (ref_frame - next_lower)) { + return BKE_tracking_marker_get_exact(track, next_higher); + } + else { + return BKE_tracking_marker_get_exact(track, next_lower); + } +} + - /* convert to rotation around image center */ - translation[0] -= (x0 + (x - x0) * cosf(*angle) - (y - y0) * sinf(*angle) - x) * (*scale); - translation[1] -= (y0 + (x - x0) * sinf(*angle) + (y - y0) * cosf(*angle) - y) * (*scale); +/* Retrieve tracking data, if available and applicable for this frame. + * The returned weight value signals the validity; data recorded for this + * tracking marker on the exact requested frame is output with the full weight + * of this track, while gaps in the data sequence cause the weight to go to zero. + */ +static MovieTrackingMarker *get_tracking_data_point( + StabContext *ctx, + MovieTrackingTrack *track, + int framenr, + float *r_weight) +{ + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr); + if (marker != NULL && !(marker->flag & MARKER_DISABLED)) { + *r_weight = get_animated_weight(ctx, track, framenr); + return marker; + } + else { + /* No marker at this frame (=gap) or marker disabled. */ + *r_weight = 0.0f; + return NULL; } } -/* Calculate factor of a scale, which will eliminate black areas - * appearing on the frame caused by frame translation. +/* Calculate the contribution of a single track at the time position (frame) of + * the given marker. Each track has a local reference frame, which is as close + * as possible to the global anchor_frame. Thus the translation contribution is + * comprised of the offset relative to the image position at that reference + * frame, plus a guess of the contribution for the time span between the + * anchor_frame and the local reference frame of this track. The constant part + * of this contribution is precomputed initially. At the anchor_frame, by + * definition the contribution of all tracks is zero, keeping the frame in place. + * + * track_ref is per track baseline contribution at reference frame; filled in at + * initialization + * marker is tracking data to use as contribution for current frame. + * result_offset is a total cumulated contribution of this track, + * relative to the stabilization anchor_frame, + * in normalized (0...1) coordinates. + */ +static void translation_contribution(TrackStabilizationBase *track_ref, + MovieTrackingMarker *marker, + float result_offset[2]) +{ + add_v2_v2v2(result_offset, + track_ref->stabilization_offset_base, + marker->pos); +} + +/* Similar to the ::translation_contribution(), the rotation contribution is + * comprised of the contribution by this individual track, and the averaged + * contribution from anchor_frame to the ref point of this track. + * - Contribution is in terms of angles, -pi < angle < +pi, and all averaging + * happens in this domain. + * - Yet the actual measurement happens as vector between pivot and the current + * tracking point + * - Currently we use the center of frame as approximation for the rotation pivot + * point. + * - Moreover, the pivot point has to be compensated for the already determined + * shift offset, in order to get the pure rotation around the pivot. + * To turn this into a _contribution_, the likewise corrected angle at the + * reference frame has to be subtracted, to get only the pure angle difference + * this tracking point has captured. + * - To get from vectors to angles, we have to go through an arcus tangens, + * which involves the issue of the definition range: the resulting angles will + * flip by 360deg when the measured vector passes from the 2nd to the third + * quadrant, thus messing up the average calculation. Since _any_ tracking + * point might be used, these problems are quite common in practice. + * - Thus we perform the subtraction of the reference and the addition of the + * baseline contribution in polar coordinates as simple addition of angles; + * since these parts are fixed, we can bake them into a rotation matrix. + * With this approach, the border of the arcus tangens definition range will + * be reached only, when the _whole_ contribution approaches +- 180deg, + * meaning we've already tilted the frame upside down. This situation is way + * less common and can be tolerated. + * - As an additional feature, when activated, also changes in image scale + * relative to the rotation center can be picked up. To handle those values + * in the same framework, we average the scales as logarithms. + * + * aspect is a total aspect ratio of the undistorted image (includes fame and + * pixel aspect). + */ +static void rotation_contribution(TrackStabilizationBase *track_ref, + MovieTrackingMarker *marker, + float aspect, + float target_pos[2], + float averaged_translation_contribution[2], + float *result_angle, + float *result_scale) +{ + float len; + float pos[2]; + float pivot[2]; + copy_v2_fl(pivot, 0.5f); /* Use center of frame as hard wired pivot. */ + add_v2_v2(pivot, averaged_translation_contribution); + sub_v2_v2(pivot, target_pos); + sub_v2_v2v2(pos, marker->pos, pivot); + + pos[0] *= aspect; + mul_m2v2(track_ref->stabilization_rotation_base, pos); + + *result_angle = atan2f(pos[1],pos[0]); + + len = len_v2(pos) + SCALE_ERROR_LIMIT_BIAS; + *result_scale = len * track_ref->stabilization_scale_base; + BLI_assert(0.0 < *result_scale); +} + + +/* Weighted average of the per track cumulated contributions at given frame. + * Returns truth if all desired calculations could be done and all averages are + * available. + * + * NOTE: Even if the result is not `true`, the returned translation and angle + * are always sensible and as good as can be. Especially in the + * initialization phase we might not be able to get any average (yet) or + * get only a translation value. Since initialization visits tracks in a + * specific order, starting from anchor_frame, the result is logically + * correct non the less. But under normal operation conditions, + * a result of `false` should disable the stabilization function */ -static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, int width, int height) +static bool average_track_contributions(StabContext *ctx, + int framenr, + float aspect, + float r_translation[2], + float *r_angle, + float *r_scale_step) { - float firstmedian[2]; + bool ok; + float weight_sum; + MovieTrackingTrack *track; + MovieTracking *tracking = ctx->tracking; MovieTrackingStabilization *stab = &tracking->stabilization; - float aspect = tracking->camera.pixel_aspect; - - /* Early output if stabilization data is already up-to-date. */ - if (stab->ok) - return stab->scale; - - /* See comment in BKE_tracking_stabilization_data_get about first frame. */ - if (stabilization_median_point_get(tracking, 1, firstmedian)) { - int sfra = INT_MAX, efra = INT_MIN, cfra; - float scale = 1.0f; - MovieTrackingTrack *track; - - stab->scale = 1.0f; - - /* Calculate frame range of tracks used for stabilization. */ - track = tracking->tracks.first; - while (track) { - if (track->flag & TRACK_USE_2D_STAB || - ((stab->flag & TRACKING_STABILIZE_ROTATION) && track == stab->rot_track)) - { - sfra = min_ii(sfra, track->markers[0].framenr); - efra = max_ii(efra, track->markers[track->markersnr - 1].framenr); - } + BLI_assert(stab->flag & TRACKING_2D_STABILIZATION); - track = track->next; + zero_v2(r_translation); + *r_scale_step = 0.0f; /* logarithm */ + *r_angle = 0.0f; + + ok = false; + weight_sum = 0.0f; + for (track = tracking->tracks.first; track; track = track->next) { + if (!is_init_for_stabilization(ctx, track)) { + continue; + } + if (track->flag & TRACK_USE_2D_STAB) { + float weight = 0.0f; + MovieTrackingMarker *marker = get_tracking_data_point(ctx, + track, + framenr, + &weight); + if (marker) { + TrackStabilizationBase *stabilization_base = + access_stabilization_baseline_data(ctx, track); + BLI_assert(stabilization_base != NULL); + float offset[2]; + weight_sum += weight; + translation_contribution(stabilization_base, marker, offset); + mul_v2_fl(offset, weight); + add_v2_v2(r_translation, offset); + ok |= (weight_sum > EPSILON_WEIGHT); + } } + } + if (!ok) { + return false; + } - /* For every frame we calculate scale factor needed to eliminate black - * area and choose largest scale factor as final one. - */ - for (cfra = sfra; cfra <= efra; cfra++) { - float median[2]; - float translation[2], angle, tmp_scale; - int i; - float mat[4][4]; - float points[4][2] = {{0.0f, 0.0f}, {0.0f, height}, {width, height}, {width, 0.0f}}; - float si, co; + r_translation[0] /= weight_sum; + r_translation[1] /= weight_sum; - stabilization_median_point_get(tracking, cfra, median); + if (!(stab->flag & TRACKING_STABILIZE_ROTATION)) { + return ok; + } - stabilization_calculate_data(tracking, cfra, width, height, firstmedian, median, translation, - &tmp_scale, &angle); + ok = false; + weight_sum = 0.0f; + for (track = tracking->tracks.first; track; track = track->next) { + if (!is_init_for_stabilization(ctx, track)) { + continue; + } + if (track->flag & TRACK_USE_2D_STAB_ROT) { + float weight = 0.0f; + MovieTrackingMarker *marker = get_tracking_data_point(ctx, + track, + framenr, + &weight); + if (marker) { + TrackStabilizationBase *stabilization_base = + access_stabilization_baseline_data(ctx, track); + BLI_assert(stabilization_base != NULL); + float rotation, scale; + float target_pos[2]; + weight_sum += weight; + get_animated_target_pos(ctx, framenr, target_pos); + rotation_contribution(stabilization_base, + marker, + aspect, + target_pos, + r_translation, + &rotation, + &scale); + *r_angle += rotation * weight; + if (stab->flag & TRACKING_STABILIZE_SCALE) { + *r_scale_step += logf(scale) * weight; + } + else { + *r_scale_step = 0; + } + ok |= (weight_sum > EPSILON_WEIGHT); + } + } + } + if (ok) { + *r_scale_step /= weight_sum; + *r_angle /= weight_sum; + } + else { + /* We reach this point because translation could be calculated, + * but rotation/scale found no data to work on. + */ + *r_scale_step = 0.0f; + *r_angle = 0.0f; + } + return true; +} - BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation, 1.0f, angle, mat); - si = sinf(angle); - co = cosf(angle); +/* Linear interpolation of data retrieved at two measurement points. + * This function is used to fill gaps in the middle of the covered area, + * at frames without any usable tracks for stabilization. + * + * framenr is a position to interpolate for. + * frame_a is a valid measurement point below framenr + * frame_b is a valid measurement point above framenr + * Returns truth if both measurements could actually be retrieved. + * Otherwise output parameters remain unaltered + */ +static bool interpolate_averaged_track_contributions(StabContext *ctx, + int framenr, + int frame_a, + int frame_b, + float aspect, + float translation[2], + float *r_angle, + float *r_scale_step) +{ + float t, s; + float trans_a[2], trans_b[2]; + float angle_a, angle_b; + float scale_a, scale_b; + bool success = false; + + BLI_assert(frame_a <= frame_b); + BLI_assert(frame_a <= framenr); + BLI_assert(framenr <= frame_b); + + t = ((float)framenr - frame_a) / (frame_b - frame_a); + s = 1.0f - t; + + success = average_track_contributions(ctx, frame_a, aspect, trans_a, &angle_a, &scale_a); + if (!success) { + return false; + } + success = average_track_contributions(ctx, frame_b, aspect, trans_b, &angle_b, &scale_b); + if (!success) { + return false; + } - for (i = 0; i < 4; i++) { - int j; - float a[3] = {0.0f, 0.0f, 0.0f}, b[3] = {0.0f, 0.0f, 0.0f}; + interp_v2_v2v2(translation, trans_a, trans_b, t); + *r_scale_step = s * scale_a + t * scale_b; + *r_angle = s * angle_a + t * angle_b; + return true; +} - copy_v3_v3(a, points[i]); - copy_v3_v3(b, points[(i + 1) % 4]); - mul_m4_v3(mat, a); - mul_m4_v3(mat, b); +/* Reorder tracks starting with those providing a tracking data frame + * closest to the global anchor_frame. Tracks with a gap at anchor_frame or + * starting farer away from anchor_frame altogether will be visited later. + * This allows to build up baseline contributions incrementally. + * + * order is an array for sorting the tracks. Must be of suitable size to hold + * all tracks. + * Returns number of actually usable tracks, can be less than the overall number + * of tracks. + * + * NOTE: After returning, the order array holds entries up to the number of + * usable tracks, appropriately sorted starting with the closest tracks. + * Initialization includes disabled tracks, since they might be enabled + * through automation later. + */ +static int establish_track_initialization_order(StabContext *ctx, + TrackInitOrder *order) +{ + size_t tracknr = 0; + MovieTrackingTrack *track; + MovieTracking *tracking = ctx->tracking; + int anchor_frame = tracking->stabilization.anchor_frame; - for (j = 0; j < 4; j++) { - float point[3] = {points[j][0], points[j][1], 0.0f}; - float v1[3], v2[3]; + for (track = tracking->tracks.first; track != NULL; track = track->next) { + MovieTrackingMarker *marker; + order[tracknr].data = track; + marker = get_closest_marker(ctx, track, anchor_frame); + if (marker != NULL && + (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT))) + { + order[tracknr].sort_value = abs(marker->framenr - anchor_frame); + order[tracknr].reference_frame = marker->framenr; + ++tracknr; + } + } + if (tracknr) { + qsort(order, tracknr, sizeof(TrackInitOrder), BLI_sortutil_cmp_int); + } + return tracknr; +} - sub_v3_v3v3(v1, b, a); - sub_v3_v3v3(v2, point, a); - if (cross_v2v2(v1, v2) >= 0.0f) { - const float rotDx[4][2] = {{1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}, {0.0f, 1.0f}}; - const float rotDy[4][2] = {{0.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, -1.0f}, {-1.0f, 0.0f}}; +/* Setup the constant part of this track's contribution to the determined frame + * movement. Tracks usually don't provide tracking data for every frame. Thus, + * for determining data at a given frame, we split up the contribution into a + * part covered by actual measurements on this track, and the initial gap + * between this track's reference frame and the global anchor_frame. + * The (missing) data for the gap can be substituted by the average offset + * observed by the other tracks covering the gap. This approximation doesn't + * introduce wrong data, but it records data with incorrect weight. A totally + * correct solution would require us to average the contribution per frame, and + * then integrate stepwise over all frames -- which of course would be way more + * expensive, especially for longer clips. To the contrary, our solution + * cumulates the total contribution per track and averages afterwards over all + * tracks; it can thus be calculated just based on the data of a single frame, + * plus the "baseline" for the reference frame, which is what we are computing + * here. + * + * Since we're averaging _contributions_, we have to calculate the _difference_ + * of the measured position at current frame and the position at the reference + * frame. But the "reference" part of this difference is constant and can thus + * be packed together with the baseline contribution into a single precomputed + * vector per track. + * + * In case of the rotation contribution, the principle is the same, but we have + * to compensate for the already determined translation and measure the pure + * rotation, simply because this is how we model the offset: shift plus rotation + * around the shifted rotation center. To circumvent problems with the + * definition range of the arcus tangens function, we perform this baseline + * addition and reference angle subtraction in polar coordinates and bake this + * operation into a precomputed rotation matrix. + * + * track is a track to be initialized to initialize + * reference_frame is a local frame for this track, the closest pick to the + * global anchor_frame. + * aspect is a total aspect ratio of the undistorted image (includes fame and + * pixel aspect). + * target_pos is a possibly animated target position as set by the user for + * the reference_frame + * average_translation is a value observed by the _other_ tracks for the gap + * between reference_frame and anchor_frame. This + * average must not contain contributions of frames + * not yet initialized + * average_angle in a similar way, the rotation value observed by the + * _other_ tracks. + * average_scale_step is an image scale factor observed on average by the other + * tracks for this frame. This value is recorded and + * averaged as logarithm. The recorded scale changes + * are damped for very small contributions, to limit + * the effect of probe points approaching the pivot + * too closely. + * + * NOTE: when done, this track is marked as initialized + */ +static void initialize_track_for_stabilization(StabContext *ctx, + MovieTrackingTrack *track, + int reference_frame, + float aspect, + const float target_pos[2], + const float average_translation[2], + float average_angle, + float average_scale_step) +{ + float pos[2], angle, len; + float pivot[2]; + TrackStabilizationBase *local_data = + access_stabilization_baseline_data(ctx, track); + MovieTrackingMarker *marker = + BKE_tracking_marker_get_exact(track, reference_frame); + /* Logic for initialization order ensures there *is* a marker on that + * very frame. + */ + BLI_assert(marker != NULL); + BLI_assert(local_data != NULL); - float dx = translation[0] * rotDx[j][0] + translation[1] * rotDx[j][1], - dy = translation[0] * rotDy[j][0] + translation[1] * rotDy[j][1]; + /* Per track baseline value for translation. */ + sub_v2_v2v2(local_data->stabilization_offset_base, + average_translation, + marker->pos); - float w, h, E, F, G, H, I, J, K, S; + /* Per track baseline value for rotation. */ + copy_v2_fl(pivot, 0.5f); /* Use center of frame as hard wired pivot. */ + add_v2_v2(pivot, average_translation); + sub_v2_v2(pivot, target_pos); + sub_v2_v2v2(pos, marker->pos, pivot); - if (j % 2) { - w = (float)height / 2.0f; - h = (float)width / 2.0f; - } - else { - w = (float)width / 2.0f; - h = (float)height / 2.0f; - } + pos[0] *= aspect; + angle = average_angle - atan2f(pos[1],pos[0]); + rotate_m2(local_data->stabilization_rotation_base, angle); - E = -w * co + h * si; - F = -h * co - w * si; + /* Per track baseline value for zoom. */ + len = len_v2(pos) + SCALE_ERROR_LIMIT_BIAS; + local_data->stabilization_scale_base = expf(average_scale_step) / len; - if ((i % 2) == (j % 2)) { - G = -w * co - h * si; - H = h * co - w * si; - } - else { - G = w * co + h * si; - H = -h * co + w * si; - } + local_data->is_init_for_stabilization = true; +} - I = F - H; - J = G - E; - K = G * F - E * H; - S = (-w * I - h * J) / (dx * I + dy * J + K); +static void initialize_all_tracks(StabContext *ctx, float aspect) +{ + size_t i, track_cnt = 0; + MovieClip *clip = ctx->clip; + MovieTracking *tracking = ctx->tracking; + MovieTrackingTrack *track; + TrackInitOrder *order; - scale = max_ff(scale, S); - } - } - } + /* Attempt to start initialization at anchor_frame. + * By definition, offset contribution is zero there. + */ + int reference_frame = tracking->stabilization.anchor_frame; + float average_angle=0, average_scale_step=0; + float average_translation[2]; + float target_pos_at_ref_frame[2]; + zero_v2(target_pos_at_ref_frame); + zero_v2(average_translation); + + /* Initialize private working data. */ + for (track = tracking->tracks.first; track != NULL; track = track->next) { + TrackStabilizationBase *local_data = + access_stabilization_baseline_data(ctx, track); + if (!local_data) { + local_data = MEM_callocN(sizeof(TrackStabilizationBase), + "2D stabilization per track baseline data"); + attach_stabilization_baseline_data(ctx, track, local_data); } + BLI_assert(local_data != NULL); + local_data->track_weight_curve = retrieve_track_weight_animation(clip, + track); + local_data->is_init_for_stabilization = false; - stab->scale = scale; + ++track_cnt; + } + if (!track_cnt) { + return; + } - if (stab->maxscale > 0.0f) - stab->scale = min_ff(stab->scale, stab->maxscale); + order = MEM_mallocN(track_cnt * sizeof(TrackInitOrder), + "stabilization track order"); + if (!order) { + return; } - else { - stab->scale = 1.0f; + + track_cnt = establish_track_initialization_order(ctx, order); + if (track_cnt == 0) { + goto cleanup; } - stab->ok = true; + for (i = 0; i < track_cnt; ++i) { + track = order[i].data; + if (reference_frame != order[i].reference_frame) { + reference_frame = order[i].reference_frame; + average_track_contributions(ctx, + reference_frame, + aspect, + average_translation, + &average_angle, + &average_scale_step); + get_animated_target_pos(ctx, + reference_frame, + target_pos_at_ref_frame); + } + initialize_track_for_stabilization(ctx, + track, + reference_frame, + aspect, + target_pos_at_ref_frame, + average_translation, + average_angle, + average_scale_step); + } - return stab->scale; +cleanup: + MEM_freeN(order); } -/* Get stabilization data (translation, scaling and angle) for a given frame. + +/* Retrieve the measurement of frame movement by averaging contributions of + * active tracks. + * + * translation is a measurement in normalized 0..1 coordinates. + * angle is a measurement in radians -pi..+pi counter clockwise relative to + * translation compensated frame center + * scale_step is a measurement of image scale changes, in logarithmic scale + * (zero means scale == 1) + * Returns calculation enabled and all data retrieved as expected for this frame. * - * NOTE: frame number should be in clip space, not scene space + * NOTE: when returning `false`, output parameters are reset to neutral values. */ -void BKE_tracking_stabilization_data_get(MovieTracking *tracking, int framenr, int width, int height, - float translation[2], float *scale, float *angle) +static bool stabilization_determine_offset_for_frame(StabContext *ctx, + int framenr, + float aspect, + float r_translation[2], + float *r_angle, + float *r_scale_step) { - float firstmedian[2], median[2]; - MovieTrackingStabilization *stab = &tracking->stabilization; + bool success = false; /* Early output if stabilization is disabled. */ - if ((stab->flag & TRACKING_2D_STABILIZATION) == 0) { - zero_v2(translation); - *scale = 1.0f; - *angle = 0.0f; + if ((ctx->stab->flag & TRACKING_2D_STABILIZATION) == 0) { + zero_v2(r_translation); + *r_scale_step = 0.0f; + *r_angle = 0.0f; + return false; + } - return; + success = average_track_contributions(ctx, + framenr, + aspect, + r_translation, + r_angle, + r_scale_step); + if (!success) { + /* Try to hold extrapolated settings beyond the definition range + * and to interpolate in gaps without any usable tracking data + * to prevent sudden jump to image zero position. + */ + int next_lower = MINAFRAME; + int next_higher = MAXFRAME; + use_values_from_fcurves(ctx, true); + find_next_working_frames(ctx, framenr, &next_lower, &next_higher); + if (next_lower >= MINFRAME && next_higher < MAXFRAME) { + success = interpolate_averaged_track_contributions(ctx, + framenr, + next_lower, + next_higher, + aspect, + r_translation, + r_angle, + r_scale_step); + } + else if (next_higher < MAXFRAME) { + /* Before start of stabilized range: extrapolate start point + * settings. + */ + success = average_track_contributions(ctx, + next_higher, + aspect, + r_translation, + r_angle, + r_scale_step); + } + else if (next_lower >= MINFRAME) { + /* After end of stabilized range: extrapolate end point settings. */ + success = average_track_contributions(ctx, + next_lower, + aspect, + r_translation, + r_angle, + r_scale_step); + } + use_values_from_fcurves(ctx, false); } + return success; +} - /* Even if tracks does not start at frame 1, their position will - * be estimated at this frame, which will give reasonable result - * in most of cases. - * - * However, it's still better to replace this with real first - * frame number at which tracks are appearing. +/* Calculate stabilization data (translation, scale and rotation) from given raw + * measurements. Result is in absolute image dimensions (expanded image, square + * pixels), includes automatic or manual scaling and compensates for a target + * frame position, if given. + * + * size is a size of the expanded image, the width in pixels is size * aspect. + * aspect is a ratio (width / height) of the effective canvas (square pixels). + * do_compensate denotes whether to actually output values necessary to + * _compensate_ the determined frame movement. + * Otherwise, the effective target movement is returned. + */ +static void stabilization_calculate_data(StabContext *ctx, + int framenr, + int size, + float aspect, + bool do_compensate, + float scale_step, + float r_translation[2], + float *r_scale, + float *r_angle) +{ + float target_pos[2]; + float scaleinf = get_animated_scaleinf(ctx, framenr); + + *r_scale = (get_animated_target_scale(ctx,framenr) - 1.0f) * scaleinf + 1.0f; + + if (ctx->stab->flag & TRACKING_STABILIZE_SCALE) { + *r_scale *= expf(scale_step * scaleinf); /* Averaged in log scale */ + } + + mul_v2_fl(r_translation, get_animated_locinf(ctx, framenr)); + *r_angle *= get_animated_rotinf(ctx, framenr); + + /* Compensate for a target frame position. + * This allows to follow tracking / panning shots in a semi manual fashion, + * when animating the settings for the target frame position. */ - if (stabilization_median_point_get(tracking, 1, firstmedian)) { - stabilization_median_point_get(tracking, framenr, median); + get_animated_target_pos(ctx, framenr, target_pos); + sub_v2_v2(r_translation, target_pos); + *r_angle -= get_animated_target_rot(ctx,framenr); + + /* Convert from relative to absolute coordinates, square pixels. */ + r_translation[0] *= (float)size * aspect; + r_translation[1] *= (float)size; - if ((stab->flag & TRACKING_AUTOSCALE) == 0) - stab->scale = 1.0f; + /* Output measured data, or inverse of the measured values for + * compensation? + */ + if (do_compensate) { + mul_v2_fl(r_translation, -1.0f); + *r_angle *= -1.0f; + if (*r_scale != 0.0f) { + *r_scale = 1.0f / *r_scale; + } + } +} - if (!stab->ok) { - if (stab->flag & TRACKING_AUTOSCALE) - stabilization_calculate_autoscale_factor(tracking, width, height); - stabilization_calculate_data(tracking, framenr, width, height, firstmedian, median, - translation, scale, angle); +/* Determine the inner part of the frame, which is always safe to use. + * When enlarging the image by the inverse of this factor, any black areas + * appearing due to frame translation and rotation will be removed. + * + * NOTE: When calling this function, basic initialization of tracks must be + * done already + */ +static void stabilization_determine_safe_image_area(StabContext *ctx, + int size, + float image_aspect) +{ + MovieTrackingStabilization *stab = ctx->stab; + float pixel_aspect = ctx->tracking->camera.pixel_aspect; - stab->ok = true; + int sfra = INT_MAX, efra = INT_MIN, cfra; + float scale = 1.0f, scale_step = 0.0f; + MovieTrackingTrack *track; + stab->scale = 1.0f; + + /* Calculate maximal frame range of tracks where stabilization is active. */ + for (track = ctx->tracking->tracks.first; track; track = track->next) { + if ((track->flag & TRACK_USE_2D_STAB) || + ((stab->flag & TRACKING_STABILIZE_ROTATION) && + (track->flag & TRACK_USE_2D_STAB_ROT))) + { + int first_frame = track->markers[0].framenr; + int last_frame = track->markers[track->markersnr - 1].framenr; + sfra = min_ii(sfra, first_frame); + efra = max_ii(efra, last_frame); } - else { - stabilization_calculate_data(tracking, framenr, width, height, firstmedian, median, - translation, scale, angle); + } + + /* For every frame we calculate scale factor needed to eliminate black border area + * and choose largest scale factor as final one. + */ + for (cfra = sfra; cfra <= efra; cfra++) { + float translation[2], angle, tmp_scale; + int i; + float mat[4][4]; + float points[4][2] = {{0.0f, 0.0f}, + {0.0f, size}, + {image_aspect * size, size}, + {image_aspect * size, 0.0f}}; + float si, co; + bool do_compensate = true; + + stabilization_determine_offset_for_frame(ctx, + cfra, + image_aspect, + translation, + &angle, + &scale_step); + stabilization_calculate_data(ctx, + cfra, + size, + image_aspect, + do_compensate, + scale_step, + translation, + &tmp_scale, + &angle); + + BKE_tracking_stabilization_data_to_mat4(size * image_aspect, + size, + pixel_aspect, + translation, + 1.0f, + angle, + mat); + + si = sinf(angle); + co = cosf(angle); + + /* Investigate the transformed border lines for this frame; + * find out, where it cuts the original frame. + */ + for (i = 0; i < 4; i++) { + int j; + float a[3] = {0.0f, 0.0f, 0.0f}, + b[3] = {0.0f, 0.0f, 0.0f}; + + copy_v2_v2(a, points[i]); + copy_v2_v2(b, points[(i + 1) % 4]); + a[2] = b[2] = 0.0f; + + mul_m4_v3(mat, a); + mul_m4_v3(mat, b); + + for (j = 0; j < 4; j++) { + float point[3] = {points[j][0], points[j][1], 0.0f}; + float v1[3], v2[3]; + + sub_v3_v3v3(v1, b, a); + sub_v3_v3v3(v2, point, a); + + if (cross_v2v2(v1, v2) >= 0.0f) { + const float rot_dx[4][2] = {{1.0f, 0.0f}, + {0.0f, -1.0f}, + {-1.0f, 0.0f}, + {0.0f, 1.0f}}; + const float rot_dy[4][2] = {{0.0f, 1.0f}, + {1.0f, 0.0f}, + {0.0f, -1.0f}, + {-1.0f, 0.0f}}; + + float dx = translation[0] * rot_dx[j][0] + + translation[1] * rot_dx[j][1], + dy = translation[0] * rot_dy[j][0] + + translation[1] * rot_dy[j][1]; + + float w, h, E, F, G, H, I, J, K, S; + + if (j % 2) { + w = (float)size / 2.0f; + h = image_aspect*size / 2.0f; + } + else { + w = image_aspect*size / 2.0f; + h = (float)size / 2.0f; + } + + E = -w * co + h * si; + F = -h * co - w * si; + + if ((i % 2) == (j % 2)) { + G = -w * co - h * si; + H = h * co - w * si; + } + else { + G = w * co + h * si; + H = -h * co + w * si; + } + + I = F - H; + J = G - E; + K = G * F - E * H; + + S = (dx * I + dy * J + K) / (-w * I - h * J); + + scale = min_ff(scale, S); + } + } } } + + stab->scale = scale; + + if (stab->maxscale > 0.0f) { + stab->scale = max_ff(stab->scale, 1.0f / stab->maxscale); + } +} + + +/* Prepare working data and determine reference point for each track. + * + * NOTE: These calculations _could_ be cached and reused for all frames of the + * same clip. However, since proper initialization depends on (weight) + * animation and setup of tracks, ensuring consistency of cached init data + * turns out to be tricky, hard to maintain and generally not worth the + * effort. Thus we'll re-initialize on every frame. + */ +static StabContext *init_stabilizer(MovieClip *clip, int width, int height) +{ + MovieTracking *tracking = &clip->tracking; + MovieTrackingStabilization *stab = &tracking->stabilization; + float pixel_aspect = tracking->camera.pixel_aspect; + float aspect = (float)width * pixel_aspect / height; + int size = height; + + StabContext *ctx = initialize_stabilization_working_context(clip); + BLI_assert(ctx != NULL); + initialize_all_tracks(ctx, aspect); + if (stab->flag & TRACKING_AUTOSCALE) { + stabilization_determine_safe_image_area(ctx, size, aspect); + } + /* By default, just use values for the global current frame. */ + use_values_from_fcurves(ctx, false); + return ctx; +} + + +/* === public interface functions === */ + +/* Get stabilization data (translation, scaling and angle) for a given frame. + * Returned data describes how to compensate the detected movement, but with any + * chosen scale factor already applied and any target frame position already + * compensated. In case stabilization fails or is disabled, neutral values are + * returned. + * + * framenr is a frame number, relative to the clip (not relative to the scene + * timeline) + * width is an effective width of the canvas (square pixels), used to scale the + * determined translation + * + * Outputs: + * - translation of the lateral shift, absolute canvas coordinates + * (square pixels). + * - scale of the scaling to apply + * - angle of the rotation angle, relative to the frame center + */ +/* TODO(sergey): Use r_ prefix for output parameters here. */ +void BKE_tracking_stabilization_data_get(MovieClip *clip, + int framenr, + int width, + int height, + float translation[2], + float *scale, + float *angle) +{ + StabContext *ctx = NULL; + MovieTracking *tracking = &clip->tracking; + bool enabled = (tracking->stabilization.flag & TRACKING_2D_STABILIZATION); + /* Might become a parameter of a stabilization compositor node. */ + bool do_compensate = true; + float scale_step = 0.0f; + float pixel_aspect = tracking->camera.pixel_aspect; + float aspect = (float)width * pixel_aspect / height; + int size = height; + + if (enabled) { + ctx = init_stabilizer(clip, width, height); + } + + if (enabled && + stabilization_determine_offset_for_frame(ctx, + framenr, + aspect, + translation, + angle, + &scale_step)) + { + stabilization_calculate_data(ctx, + framenr, + size, + aspect, + do_compensate, + scale_step, + translation, + scale, + angle); + } else { zero_v2(translation); *scale = 1.0f; *angle = 0.0f; } + discard_stabilization_working_context(ctx); } -/* Stabilize given image buffer using stabilization data for - * a specified frame number. +/* Stabilize given image buffer using stabilization data for a specified + * frame number. * - * NOTE: frame number should be in clip space, not scene space + * NOTE: frame number should be in clip space, not scene space. */ -ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf *ibuf, - float translation[2], float *scale, float *angle) +/* TODO(sergey): Use r_ prefix for output parameters here. */ +ImBuf *BKE_tracking_stabilize_frame(MovieClip *clip, + int framenr, + ImBuf *ibuf, + float translation[2], + float *scale, + float *angle) { float tloc[2], tscale, tangle; + MovieTracking *tracking = &clip->tracking; MovieTrackingStabilization *stab = &tracking->stabilization; ImBuf *tmpibuf; int width = ibuf->x, height = ibuf->y; - float aspect = tracking->camera.pixel_aspect; + float pixel_aspect = tracking->camera.pixel_aspect; float mat[4][4]; int j, filter = tracking->stabilization.filter; void (*interpolation)(struct ImBuf *, struct ImBuf *, float, float, int, int) = NULL; @@ -349,8 +1360,12 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf tmpibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, ibuf_flags); /* Calculate stabilization matrix. */ - BKE_tracking_stabilization_data_get(tracking, framenr, width, height, tloc, &tscale, &tangle); - BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat); + BKE_tracking_stabilization_data_get(clip, framenr, width, height, tloc, &tscale, &tangle); + BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, pixel_aspect, tloc, tscale, tangle, mat); + + /* The following code visits each nominal target grid position + * and picks interpolated data "backwards" from source. + * thus we need the inverse of the transformation to apply. */ invert_m4(mat); if (filter == TRACKING_FILTER_NEAREST) @@ -397,48 +1412,61 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf return tmpibuf; } -/* Get 4x4 transformation matrix which corresponds to - * stabilization data and used for easy coordinate - * transformation. + +/* Build a 4x4 transformation matrix based on the given 2D stabilization data. + * mat is a 4x4 matrix in homogeneous coordinates, adapted to the + * final image buffer size and compensated for pixel aspect ratio, + * ready for direct OpenGL drawing. * - * NOTE: The reason it is 4x4 matrix is because it's - * used for OpenGL drawing directly. + * TODO(sergey): The signature of this function should be changed. we actually + * don't need the dimensions of the image buffer. Instead we + * should consider to provide the pivot point of the rotation as a + * further stabilization data parameter. */ -void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, +void BKE_tracking_stabilization_data_to_mat4(int buffer_width, + int buffer_height, + float pixel_aspect, float translation[2], float scale, float angle, float mat[4][4]) { float translation_mat[4][4], rotation_mat[4][4], scale_mat[4][4], - center_mat[4][4], inv_center_mat[4][4], + pivot_mat[4][4], inv_pivot_mat[4][4], aspect_mat[4][4], inv_aspect_mat[4][4]; - float scale_vector[3] = {scale, scale, scale}; + float scale_vector[3] = {scale, scale, 1.0f}; + + float pivot[2]; /* XXX this should be a parameter, it is part of the stabilization data */ + + /* Use the motion compensated image center as rotation center. + * This is not 100% correct, but reflects the way the rotation data was + * measured. Actually we'd need a way to find a good pivot, and use that + * both for averaging and for compensation. + */ + /* TODO(sergey) pivot shouldn't be calculated here, rather received + * as a parameter. + */ + pivot[0] = pixel_aspect * buffer_width / 2.0f - translation[0]; + pivot[1] = (float)buffer_height / 2.0f - translation[1]; unit_m4(translation_mat); unit_m4(rotation_mat); unit_m4(scale_mat); - unit_m4(center_mat); unit_m4(aspect_mat); + unit_m4(pivot_mat); + unit_m4(inv_pivot_mat); /* aspect ratio correction matrix */ - aspect_mat[0][0] = 1.0f / aspect; + aspect_mat[0][0] /= pixel_aspect; invert_m4_m4(inv_aspect_mat, aspect_mat); - /* image center as rotation center - * - * Rotation matrix is constructing in a way rotation happens around image center, - * and it's matter of calculating translation in a way, that applying translation - * after rotation would make it so rotation happens around median point of tracks - * used for translation stabilization. - */ - center_mat[3][0] = (float)width / 2.0f; - center_mat[3][1] = (float)height / 2.0f; - invert_m4_m4(inv_center_mat, center_mat); + add_v2_v2(pivot_mat[3], pivot); + sub_v2_v2(inv_pivot_mat[3], pivot); size_to_mat4(scale_mat, scale_vector); /* scale matrix */ add_v2_v2(translation_mat[3], translation); /* translation matrix */ rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ - mul_m4_series(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat, - scale_mat, inv_center_mat); + mul_m4_series(mat, aspect_mat, translation_mat, + pivot_mat, scale_mat, rotation_mat, inv_pivot_mat, + inv_aspect_mat); } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 9dbc045f1b0..de55a1977bf 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -1393,7 +1393,7 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char avcodec_get_context_defaults3(&c, NULL); - strncpy(name_, str, sizeof(name_)); + BLI_strncpy(name_, str, sizeof(name_)); name = name_; while (*name == ' ') name++; diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c index 6000c1a680c..21ddddad32e 100644 --- a/source/blender/blenlib/intern/array_store.c +++ b/source/blender/blenlib/intern/array_store.c @@ -579,7 +579,7 @@ static void bchunk_list_calc_trim_len( /** * Append and don't manage merging small chunks. */ -static bool bchunk_list_append_only( +static void bchunk_list_append_only( BArrayMemory *bs_mem, BChunkList *chunk_list, BChunk *chunk) { @@ -588,7 +588,6 @@ static bool bchunk_list_append_only( cref->link = chunk; chunk_list->chunk_refs_len += 1; chunk->users += 1; - return chunk; } /** diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cb67fe0dbed..999616f3865 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4436,7 +4436,7 @@ static void lib_link_object(FileData *fd, Main *main) /* Only expand so as not to loose any object materials that might be set. */ if (totcol_data && (*totcol_data > ob->totcol)) { /* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */ - BKE_material_resize_object(ob, *totcol_data, false); + BKE_material_resize_object(main, ob, *totcol_data, false); } } @@ -7090,7 +7090,7 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) clip->tracking_context = NULL; clip->tracking.stats = NULL; - clip->tracking.stabilization.ok = 0; + /* Needed for proper versioning, will be NULL for all newer files anyway. */ clip->tracking.stabilization.rot_track = newdataadr(fd, clip->tracking.stabilization.rot_track); clip->tracking.dopesheet.ok = 0; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index c102140acda..95ea1fd12cf 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -62,6 +62,7 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_screen.h" +#include "BKE_tracking.h" #include "BKE_gpencil.h" #include "BLI_math.h" @@ -74,6 +75,26 @@ #include "MEM_guardedalloc.h" +/** + * Setup rotation stabilization from ancient single track spec. + * Former Version of 2D stabilization used a single tracking marker to determine the rotation + * to be compensated. Now several tracks can contribute to rotation detection and this feature + * is enabled by the MovieTrackingTrack#flag on a per track base. + */ +static void migrate_single_rot_stabilization_track_settings(MovieTrackingStabilization *stab) +{ + if (stab->rot_track) { + if (!(stab->rot_track->flag & TRACK_USE_2D_STAB_ROT)) { + stab->tot_rot_track++; + stab->rot_track->flag |= TRACK_USE_2D_STAB_ROT; + } + } + stab->rot_track = NULL; /* this field is now ignored */ + + /* by default show the track lists expanded, to improve "discoverability" */ + stab->flag |= TRACKING_SHOW_STAB_TRACKS; +} + static void do_version_constraints_radians_degrees_270_1(ListBase *lb) { bConstraint *con; @@ -1158,7 +1179,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) if (!MAIN_VERSION_ATLEAST(main, 277, 3)) { /* ------- init of grease pencil initialization --------------- */ - if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "bGPDpalettecolor", "palcolor")) { + if (!DNA_struct_elem_find(fd->filesdna, "bGPDstroke", "bGPDpalettecolor", "*palcolor")) { for (Scene *scene = main->scene.first; scene; scene = scene->id.next) { ToolSettings *ts = scene->toolsettings; /* initialize use position for sculpt brushes */ @@ -1209,7 +1230,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { /* set stroke to palette and force recalculation */ - strcpy(gps->colorname, gpl->info); + BLI_strncpy(gps->colorname, gpl->info, sizeof(gps->colorname)); gps->palcolor = NULL; gps->flag |= GP_STROKE_RECALC_COLOR; gps->thickness = gpl->thickness; @@ -1233,4 +1254,41 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) /* ------- end of grease pencil initialization --------------- */ } + { + if (!DNA_struct_elem_find(fd->filesdna, "MovieTrackingTrack", "float", "weight_stab")) { + MovieClip *clip; + for (clip = main->movieclip.first; clip; clip = clip->id.next) { + MovieTracking *tracking = &clip->tracking; + MovieTrackingObject *tracking_object; + for (tracking_object = tracking->objects.first; + tracking_object != NULL; + tracking_object = tracking_object->next) + { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); + MovieTrackingTrack *track; + for (track = tracksbase->first; + track != NULL; + track = track->next) + { + track->weight_stab = track->weight; + } + } + } + } + + if (!DNA_struct_elem_find(fd->filesdna, "MovieTrackingStabilization", "int", "tot_rot_track")) { + MovieClip *clip; + for (clip = main->movieclip.first; clip != NULL; clip = clip->id.next) { + if (clip->tracking.stabilization.rot_track) { + migrate_single_rot_stabilization_track_settings(&clip->tracking.stabilization); + if (!clip->tracking.stabilization.scale) { + /* ensure init. + * Was previously used for autoscale only, + * now used always (as "target scale") */ + clip->tracking.stabilization.scale = 1.0f; + } + } + } + } + } } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index b647f5a667d..1dfb9dee8eb 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -3563,7 +3563,7 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme) BLI_assert(first_bme != NULL); bv->edges[i].e = first_bme; BM_BEVEL_EDGE_TAG_ENABLE(first_bme); - if (fast_bevel_edge_order(bv)) + if (i == 0 && fast_bevel_edge_order(bv)) break; i = bevel_edge_order_extend(bm, bv, i); i++; @@ -3588,6 +3588,7 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme) e2 = (i == bv->edgecount - 1) ? &bv->edges[0] : &bv->edges[i + 1]; bme = e->e; bme2 = e2->e; + BLI_assert(bme != NULL); BM_ITER_ELEM(l, &iter, bme, BM_LOOPS_OF_EDGE) { f = l->f; if ((l->prev->e == bme2 || l->next->e == bme2) && !e->fnext && !e2->fprev) diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 52a0df5b9d1..372d341f223 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -430,7 +430,7 @@ static int *bm_edge_symmetry_map(BMesh *bm, unsigned int symmetry_axis, float li tree = BLI_kdtree_new(bm->totedge); - etable = MEM_mallocN(sizeof(BMEdge **) * bm->totedge, __func__); + etable = MEM_mallocN(sizeof(*etable) * bm->totedge, __func__); edge_symmetry_map = MEM_mallocN(sizeof(*edge_symmetry_map) * bm->totedge, __func__); BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index e205608a365..b16e2e2b0d3 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -49,6 +49,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], double dmat[4][4]; UnitConverter *converter = new UnitConverter(); converter->mat4_to_dae_double(dmat, local); + delete converter; TransformBase::decompose(local, loc, rot, NULL, scale); diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp index 933223dacac..b3f1b5a4458 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp @@ -91,7 +91,7 @@ void MovieClipNode::convertToOperations(NodeConverter &converter, const Composit if (stab->flag & TRACKING_2D_STABILIZATION) { int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(movieClip, context.getFramenumber()); - BKE_tracking_stabilization_data_get(&movieClip->tracking, clip_framenr, ibuf->x, ibuf->y, loc, &scale, &angle); + BKE_tracking_stabilization_data_get(movieClip, clip_framenr, ibuf->x, ibuf->y, loc, &scale, &angle); } } diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp index 5ddf15f7684..41f7da7c49f 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp @@ -47,7 +47,7 @@ void MovieClipAttributeOperation::executePixelSampled(float output[4], angle = 0.0f; if (this->m_clip) { int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_clip, this->m_framenumber); - BKE_tracking_stabilization_data_get(&this->m_clip->tracking, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle); + BKE_tracking_stabilization_data_get(this->m_clip, clip_framenr, getWidth(), getHeight(), loc, &scale, &angle); } switch (this->m_attribute) { case MCA_SCALE: diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index 0209e94debe..0945da439ef 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -42,6 +42,8 @@ struct Depsgraph; struct Main; struct Scene; +struct Group; +struct EffectorWeights; #ifdef __cplusplus extern "C" { @@ -112,6 +114,12 @@ void DEG_add_object_cache_relation(struct DepsNodeHandle *handle, struct CacheFi /* TODO(sergey): Remove once all geometry update is granular. */ void DEG_add_special_eval_flag(struct Depsgraph *graph, struct ID *id, short flag); +/* Utility functions for physics modifiers */ +typedef bool (*DEG_CollobjFilterFunction)(struct Object *obj, struct ModifierData *md); + +void DEG_add_collision_relations(struct DepsNodeHandle *handle, struct Scene *scene, Object *ob, struct Group *group, int layer, unsigned int modifier_type, DEG_CollobjFilterFunction fn, bool dupli, const char *name); +void DEG_add_forcefield_relations(struct DepsNodeHandle *handle, struct Scene *scene, Object *ob, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name); + /* ************************************************ */ #ifdef __cplusplus diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 6ca03ea7b63..f016b379327 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -64,6 +64,7 @@ extern "C" { #include "DNA_scene_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" +#include "DNA_object_force.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -71,6 +72,7 @@ extern "C" { #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_effect.h" +#include "BKE_collision.h" #include "BKE_fcurve.h" #include "BKE_group.h" #include "BKE_key.h" @@ -241,6 +243,54 @@ void DepsgraphRelationBuilder::add_operation_relation( } } +void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name) +{ + unsigned int numcollobj; + Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, eModifierType_Collision, dupli); + + for (unsigned int i = 0; i < numcollobj; i++) + { + Object *ob1 = collobjs[i]; + + ComponentKey trf_key(&ob1->id, DEPSNODE_TYPE_TRANSFORM); + add_relation(trf_key, key, DEPSREL_TYPE_STANDARD, name); + + ComponentKey coll_key(&ob1->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(coll_key, key, DEPSREL_TYPE_STANDARD, name); + } + + if (collobjs) + MEM_freeN(collobjs); +} + +void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, EffectorWeights *eff, bool add_absorption, const char *name) +{ + ListBase *effectors = pdInitEffectors(scene, ob, eff, false); + + 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); + } + + 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 eff_key(&eff->pd->f_source->id, DEPSNODE_TYPE_GEOMETRY); + add_relation(eff_key, key, DEPSREL_TYPE_STANDARD, "Smoke Force Domain"); + } + + if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { + add_collision_relations(key, scene, ob, NULL, eff->ob->lay, true, "Force Absorption"); + } + } + } + + pdEndEffectors(&effectors); +} + /* **** Functions to build relations between entities **** */ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index ce6d2c961fd..7874dc052f0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -63,6 +63,8 @@ struct bConstraint; struct Scene; struct Tex; struct World; +struct EffectorWeights; +struct ParticleSystem; struct PropertyRNA; @@ -244,6 +246,9 @@ struct DepsgraphRelationBuilder void build_compositor(Scene *scene); void build_gpencil(ID *owner, bGPdata *gpd); + void add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name); + void add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, EffectorWeights *eff, bool add_absorption, const char *name); + template <typename KeyType> OperationDepsNode *find_operation_node(const KeyType &key); diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index ae830da1252..119b2054d24 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -36,11 +36,15 @@ 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" #include "BKE_main.h" +#include "BKE_collision.h" +#include "BKE_effect.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -304,3 +308,45 @@ void DEG_scene_graph_free(Scene *scene) scene->depsgraph = NULL; } } + +void DEG_add_collision_relations(DepsNodeHandle *handle, Scene *scene, Object *ob, Group *group, int layer, unsigned int modifier_type, DEG_CollobjFilterFunction fn, bool dupli, const char *name) +{ + unsigned int numcollobj; + Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli); + + for (unsigned int i = 0; i < numcollobj; i++) { + Object *ob1 = collobjs[i]; + + if (!fn || fn(ob1, modifiers_findByType(ob1, (ModifierType)modifier_type))) { + DEG_add_object_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name); + DEG_add_object_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name); + } + } + + if (collobjs) + MEM_freeN(collobjs); +} + +void DEG_add_forcefield_relations(DepsNodeHandle *handle, Scene *scene, Object *ob, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name) +{ + ListBase *effectors = pdInitEffectors(scene, ob, effector_weights, false); + + if (effectors) { + for (EffectorCache *eff = (EffectorCache*)effectors->first; eff; eff = eff->next) { + if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) { + DEG_add_object_relation(handle, eff->ob, DEG_OB_COMP_TRANSFORM, name); + + if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) { + DEG_add_object_relation(handle, eff->pd->f_source, DEG_OB_COMP_TRANSFORM, "Smoke Force Domain"); + DEG_add_object_relation(handle, eff->pd->f_source, DEG_OB_COMP_GEOMETRY, "Smoke Force Domain"); + } + + if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { + DEG_add_collision_relations(handle, scene, ob, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption"); + } + } + } + } + + pdEndEffectors(&effectors); +} diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt index 084006ce277..1559512d713 100644 --- a/source/blender/editors/CMakeLists.txt +++ b/source/blender/editors/CMakeLists.txt @@ -19,6 +19,10 @@ # ***** END GPL LICENSE BLOCK ***** if(WITH_BLENDER) + if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) + endif() + add_subdirectory(animation) add_subdirectory(armature) add_subdirectory(curve) diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index eaae9532889..fe5c7c555f9 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -3822,7 +3822,12 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void /* send notifiers before doing anything else... */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); - + + /* verify that we have a channel to operate on. */ + if (!ale_setting) { + return; + } + if (ale_setting->type == ANIMTYPE_GPLAYER) WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); @@ -3830,17 +3835,13 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void if (ANIM_animdata_get_context(C, &ac) == 0) return; - /* verify that we have a channel to operate on, and that it has all we need */ - if (ale_setting) { - /* check if the setting is on... */ - on = ANIM_channel_setting_get(&ac, ale_setting, setting); - - /* on == -1 means setting not found... */ - if (on == -1) - return; - } - else + /* check if the setting is on... */ + on = ANIM_channel_setting_get(&ac, ale_setting, setting); + + /* on == -1 means setting not found... */ + if (on == -1) { return; + } /* get all channels that can possibly be chosen - but ignore hierarchy */ filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS; diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 876f873e5fa..2aa6d30c114 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -883,7 +883,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *UNUSED(op)) /* asign new color (only if different) */ if (STREQ(gps->colorname, color->info) == false) { - strcpy(gps->colorname, color->info); + BLI_strncpy(gps->colorname, color->info, sizeof(gps->colorname)); gps->flag |= GP_STROKE_RECALC_COLOR; } } @@ -1271,7 +1271,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op) /* if new, set current color */ if (type == GP_STROKE_JOINCOPY) { new_stroke->palcolor = palcolor; - strcpy(new_stroke->colorname, palcolor->info); + BLI_strncpy(new_stroke->colorname, palcolor->info, sizeof(new_stroke->colorname)); new_stroke->flag |= GP_STROKE_RECALC_COLOR; } } @@ -1439,8 +1439,8 @@ static int gp_brush_remove_exec(bContext *C, wmOperator *op) if (ELEM(NULL, ts, brush)) return OPERATOR_CANCELLED; - if (BLI_listbase_count(&ts->gp_brushes) < 2) { - BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a brush. Unable to delete brush"); + if (BLI_listbase_count_ex(&ts->gp_brushes, 2) < 2) { + BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a brush, unable to delete the last one"); return OPERATOR_CANCELLED; } @@ -1466,7 +1466,7 @@ static int gp_brush_remove_exec(bContext *C, wmOperator *op) void GPENCIL_OT_brush_remove(wmOperatorType *ot) { /* identifiers */ - ot->name = "Remove brush"; + ot->name = "Remove Brush"; ot->idname = "GPENCIL_OT_brush_remove"; ot->description = "Remove active Grease Pencil drawing brush"; @@ -1797,8 +1797,8 @@ static int gp_palette_remove_exec(bContext *C, wmOperator *op) if (ELEM(NULL, gpd, palette)) return OPERATOR_CANCELLED; - if (BLI_listbase_count(&gpd->palettes) < 2) { - BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a palette. Unable to delete palette"); + if (BLI_listbase_count_ex(&gpd->palettes, 2) < 2) { + BKE_report(op->reports, RPT_ERROR, "Grease Pencil needs a palette, unable to delete the last one"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index b298769c6dc..e58178bf2a7 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -207,7 +207,7 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co /* make a stupid copy first of the entire stroke (to get the flags too) */ gpsd = MEM_dupallocN(gps); - strcpy(gpsd->tmp_layerinfo, layername); /* saves original layer name */ + BLI_strncpy(gpsd->tmp_layerinfo, layername, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */ /* initialize triangle memory - will be calculated on next redraw */ gpsd->triangles = NULL; @@ -266,7 +266,7 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op) /* make direct copies of the stroke and its points */ gpsd = MEM_dupallocN(gps); - strcpy(gpsd->tmp_layerinfo, gpl->info); + BLI_strncpy(gpsd->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo)); gpsd->points = MEM_dupallocN(gps->points); /* triangle information - will be calculated on next redraw */ @@ -386,7 +386,7 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) /* make direct copies of the stroke and its points */ gpsd = MEM_dupallocN(gps); - strcpy(gpsd->tmp_layerinfo, gpl->info); /* saves original layer name */ + BLI_strncpy(gpsd->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */ gpsd->points = MEM_dupallocN(gps->points); /* triangles cache - will be recalculated on next redraw */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index e7e39a85792..dacdc0cf777 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -924,7 +924,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) bGPDpalette *palette = BKE_gpencil_palette_getactive(p->gpd); bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); gps->palcolor = palcolor; - strcpy(gps->colorname, palcolor->info); + 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 diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 79831cefde6..d05a80bed62 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -5415,6 +5415,7 @@ static bool ui_numedit_but_HSVCUBE( return changed; } +#ifdef WITH_INPUT_NDOF static void ui_ndofedit_but_HSVCUBE( uiBut *but, uiHandleButtonData *data, const wmNDOFMotionData *ndof, @@ -5487,6 +5488,7 @@ static void ui_ndofedit_but_HSVCUBE( copy_v3_v3(data->vec, rgb); ui_but_v3_set(but, data->vec); } +#endif /* WITH_INPUT_NDOF */ static int ui_do_but_HSVCUBE( bContext *C, uiBlock *block, uiBut *but, @@ -5514,6 +5516,7 @@ static int ui_do_but_HSVCUBE( return WM_UI_HANDLER_BREAK; } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { const wmNDOFMotionData *ndof = event->customdata; const enum eSnapType snap = ui_event_to_snap(event); @@ -5525,6 +5528,7 @@ static int ui_do_but_HSVCUBE( return WM_UI_HANDLER_BREAK; } +#endif /* WITH_INPUT_NDOF */ /* XXX hardcoded keymap check.... */ else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) { if (ELEM(but->a1, UI_GRAD_V_ALT, UI_GRAD_L_ALT)) { @@ -5680,6 +5684,7 @@ static bool ui_numedit_but_HSVCIRCLE( return changed; } +#ifdef WITH_INPUT_NDOF static void ui_ndofedit_but_HSVCIRCLE( uiBut *but, uiHandleButtonData *data, const wmNDOFMotionData *ndof, @@ -5750,7 +5755,7 @@ static void ui_ndofedit_but_HSVCIRCLE( ui_but_v3_set(but, data->vec); } - +#endif /* WITH_INPUT_NDOF */ static int ui_do_but_HSVCIRCLE( bContext *C, uiBlock *block, uiBut *but, @@ -5778,6 +5783,7 @@ static int ui_do_but_HSVCIRCLE( return WM_UI_HANDLER_BREAK; } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { const enum eSnapType snap = ui_event_to_snap(event); const wmNDOFMotionData *ndof = event->customdata; @@ -5789,6 +5795,7 @@ static int ui_do_but_HSVCIRCLE( return WM_UI_HANDLER_BREAK; } +#endif /* WITH_INPUT_NDOF */ /* XXX hardcoded keymap check.... */ else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) { int len; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index bb9da1a141b..f3157df4d28 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -325,7 +325,9 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } else { if (id) { + Main *bmain = CTX_data_main(C); id_single_user(C, id, &template->ptr, template->prop); + DAG_relations_tag_update(bmain); } } } diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index f60fed398ec..d2b2f12c1a5 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -127,6 +127,7 @@ static int view_pan_init(bContext *C, wmOperator *op) return 1; } +#ifdef WITH_INPUT_NDOF static int view_pan_poll(bContext *C) { ARegion *ar = CTX_wm_region(C); @@ -144,6 +145,7 @@ static int view_pan_poll(bContext *C) /* view can pan */ return 1; } +#endif /* apply transform to view (i.e. adjust 'cur' rect) */ static void view_pan_apply_ex(bContext *C, v2dViewPanData *vpd, float dx, float dy) @@ -1296,7 +1298,7 @@ static void VIEW2D_OT_zoom_border(wmOperatorType *ot) WM_operator_properties_gesture_border(ot, false); } - +#ifdef WITH_INPUT_NDOF static int view2d_ndof_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type != NDOF_MOTION) { @@ -1369,6 +1371,7 @@ static void VIEW2D_OT_ndof(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_LOCK_BYPASS; } +#endif /* WITH_INPUT_NDOF */ /* ********************************************************* */ /* SMOOTH VIEW */ @@ -2067,7 +2070,9 @@ void ED_operatortypes_view2d(void) WM_operatortype_append(VIEW2D_OT_zoom); WM_operatortype_append(VIEW2D_OT_zoom_border); +#ifdef WITH_INPUT_NDOF WM_operatortype_append(VIEW2D_OT_ndof); +#endif WM_operatortype_append(VIEW2D_OT_smoothview); @@ -2097,7 +2102,9 @@ void ED_keymap_view2d(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "VIEW2D_OT_ndof", NDOF_MOTION, 0, 0, 0); +#endif /* zoom - single step */ WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 7a7c42e501b..cd75983e0a0 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -68,8 +68,16 @@ static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + Main *bmain = CTX_data_main(C); char filepath[FILE_MAX]; - BLI_strncpy(filepath, G.main->name, sizeof(filepath)); + + if (bmain->name[0] == '\0') { + BLI_strncpy(filepath, "untitled", sizeof(filepath)); + } + else { + BLI_strncpy(filepath, bmain->name, sizeof(filepath)); + } + BLI_replace_extension(filepath, sizeof(filepath), ".abc"); RNA_string_set(op->ptr, "filepath", filepath); } @@ -124,10 +132,11 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) { - uiLayout *box = uiLayoutBox(layout); + uiLayout *box; uiLayout *row; #ifdef WITH_ALEMBIC_HDF5 + box = uiLayoutBox(layout); row = uiLayoutRow(box, false); uiItemL(row, IFACE_("Archive Options:"), ICON_NONE); @@ -213,15 +222,31 @@ static void wm_alembic_export_draw(bContext *UNUSED(C), wmOperator *op) ui_alembic_export_settings(op->layout, &ptr); } +static bool wm_alembic_export_check(bContext *UNUSED(C), wmOperator *op) +{ + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); + + if (!BLI_testextensie(filepath, ".abc")) { + BLI_ensure_extension(filepath, FILE_MAX, ".abc"); + RNA_string_set(op->ptr, "filepath", filepath); + return true; + } + + return false; +} + void WM_OT_alembic_export(wmOperatorType *ot) { - ot->name = "Export Alembic Archive"; + ot->name = "Export Alembic"; + ot->description = "Export current scene in an Alembic archive"; ot->idname = "WM_OT_alembic_export"; ot->invoke = wm_alembic_export_invoke; ot->exec = wm_alembic_export_exec; ot->poll = WM_operator_winactive; ot->ui = wm_alembic_export_draw; + ot->check = wm_alembic_export_check; WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, @@ -237,7 +262,7 @@ void WM_OT_alembic_export(wmOperatorType *ot) "Transform Samples", "Number of times per frame transformations are sampled", 1, 128); RNA_def_int(ot->srna, "gsamples", 1, 1, 128, - "Geometry Samples", "Number of times per frame object datas are sampled", 1, 128); + "Geometry Samples", "Number of times per frame object data are sampled", 1, 128); RNA_def_float(ot->srna, "sh_open", 0.0f, -1.0f, 1.0f, "Shutter Open", "Time at which the shutter is open", -1.0f, 1.0f); @@ -266,7 +291,7 @@ void WM_OT_alembic_export(wmOperatorType *ot) RNA_def_boolean(ot->srna, "normals", 1, "Normals", "Export normals"); - RNA_def_boolean(ot->srna, "vcolors", 0, "Vertex colors", "Export vertex colors"); + RNA_def_boolean(ot->srna, "vcolors", 0, "Vertex Colors", "Export vertex colors"); RNA_def_boolean(ot->srna, "face_sets", 0, "Face Sets", "Export per face shading group assignments"); @@ -428,7 +453,8 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op) void WM_OT_alembic_import(wmOperatorType *ot) { - ot->name = "Import Alembic Archive"; + ot->name = "Import Alembic"; + ot->description = "Load an Alembic archive"; ot->idname = "WM_OT_alembic_import"; ot->invoke = WM_operator_filesel; diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index d6e2c1ae204..c5eea94f5e1 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -117,6 +117,7 @@ static int cachefile_open_exec(bContext *C, wmOperator *op) void CACHEFILE_OT_open(wmOperatorType *ot) { ot->name = "Open Cache File"; + ot->description = "Load a cache file"; ot->idname = "CACHEFILE_OT_open"; ot->invoke = cachefile_open_invoke; diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index d62651cef81..8659100df87 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -280,6 +280,20 @@ static void wm_collada_export_draw(bContext *UNUSED(C), wmOperator *op) uiCollada_exportSettings(op->layout, &ptr); } +static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op) +{ + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); + + if (!BLI_testextensie(filepath, ".dae")) { + BLI_ensure_extension(filepath, FILE_MAX, ".dae"); + RNA_string_set(op->ptr, "filepath", filepath); + return true; + } + + return false; +} + void WM_OT_collada_export(wmOperatorType *ot) { static EnumPropertyItem prop_bc_export_mesh_type[] = { @@ -302,6 +316,7 @@ void WM_OT_collada_export(wmOperatorType *ot) ot->invoke = wm_collada_export_invoke; ot->exec = wm_collada_export_exec; ot->poll = WM_operator_winactive; + ot->check = wm_collada_export_check; ot->flag |= OPTYPE_PRESET; diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 281a8b2a02d..de93211bec4 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -439,7 +439,7 @@ static void bm_face_split_by_edges_island_connect( LinkNode *e_link, const int e_link_len, MemArena *mem_arena_edgenet) { - BMEdge **edge_arr = BLI_memarena_alloc(mem_arena_edgenet, sizeof(BMEdge **) * e_link_len); + BMEdge **edge_arr = BLI_memarena_alloc(mem_arena_edgenet, sizeof(*edge_arr) * e_link_len); int edge_arr_len = 0; while (e_link) { diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 1a14fad8650..999d5b278ee 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3080,7 +3080,7 @@ static void bm_mesh_hflag_flush_vert(BMesh *bm, const char hflag) * \note This could be used for split-by-material for non mesh types. * \note This could take material data from another object or args. */ -static void mesh_separate_material_assign_mat_nr(Object *ob, const short mat_nr) +static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const short mat_nr) { ID *obdata = ob->data; @@ -3116,18 +3116,18 @@ static void mesh_separate_material_assign_mat_nr(Object *ob, const short mat_nr) ma_obdata = NULL; } - BKE_material_clear_id(obdata, true); - BKE_material_resize_object(ob, 1, true); - BKE_material_resize_id(obdata, 1, true); + BKE_material_clear_id(bmain, obdata, true); + BKE_material_resize_object(bmain, ob, 1, true); + BKE_material_resize_id(bmain, obdata, 1, true); ob->mat[0] = ma_ob; ob->matbits[0] = matbit; (*matarar)[0] = ma_obdata; } else { - BKE_material_clear_id(obdata, true); - BKE_material_resize_object(ob, 0, true); - BKE_material_resize_id(obdata, 0, true); + BKE_material_clear_id(bmain, obdata, true); + BKE_material_resize_object(bmain, ob, 0, true); + BKE_material_resize_id(bmain, obdata, 0, true); } } @@ -3162,7 +3162,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM /* leave the current object with some materials */ if (tot == bm_old->totface) { - mesh_separate_material_assign_mat_nr(base_old->object, mat_nr); + mesh_separate_material_assign_mat_nr(bmain, base_old->object, mat_nr); /* since we're in editmode, must set faces here */ BM_ITER_MESH (f, &iter, bm_old, BM_FACES_OF_MESH) { @@ -3174,7 +3174,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM /* Move selection into a separate object */ base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old); if (base_new) { - mesh_separate_material_assign_mat_nr(base_new->object, mat_nr); + mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr); } result |= (base_new != NULL); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index fb067ccca81..1520b7c1aea 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2105,6 +2105,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo } BKE_main_id_clear_newpoins(bmain); + DAG_relations_tag_update(bmain); } /******************************* Make Local ***********************************/ diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 1431958501d..d53d87db228 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -1102,12 +1102,14 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure); paint_stroke_sample_average(stroke, &sample_average); +#ifdef WITH_INPUT_NDOF /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously! * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it * since the 2D deltas are zero -- code in this file needs to be updated to use the * post-NDOF_MOTION MOUSEMOVE */ if (event->type == NDOF_MOTION) return OPERATOR_PASS_THROUGH; +#endif /* one time initialization */ if (!stroke->stroke_init) { diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index a261202b690..718a4fd3c38 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -240,7 +240,9 @@ static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* auto-set range */ WM_keymap_add_item(keymap, "ACTION_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "ACTION_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "ACTION_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "ACTION_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACTION_OT_view_frame", PAD0, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 2a5d959bb84..14393c6968b 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -106,7 +106,9 @@ void CLIP_OT_change_frame(wmOperatorType *ot); void CLIP_OT_rebuild_proxy(struct wmOperatorType *ot); void CLIP_OT_mode_set(struct wmOperatorType *ot); +#ifdef WITH_INPUT_NDOF void CLIP_OT_view_ndof(struct wmOperatorType *ot); +#endif void CLIP_OT_prefetch(struct wmOperatorType *ot); @@ -185,7 +187,10 @@ void CLIP_OT_detect_features(struct wmOperatorType *ot); void CLIP_OT_stabilize_2d_add(struct wmOperatorType *ot); void CLIP_OT_stabilize_2d_remove(struct wmOperatorType *ot); void CLIP_OT_stabilize_2d_select(struct wmOperatorType *ot); -void CLIP_OT_stabilize_2d_set_rotation(struct wmOperatorType *ot); + +void CLIP_OT_stabilize_2d_rotation_add(struct wmOperatorType *ot); +void CLIP_OT_stabilize_2d_rotation_remove(struct wmOperatorType *ot); +void CLIP_OT_stabilize_2d_rotation_select(struct wmOperatorType *ot); void CLIP_OT_clean_tracks(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 83876ae2669..6778a0b1805 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1405,6 +1405,7 @@ void CLIP_OT_mode_set(wmOperatorType *ot) RNA_def_enum(ot->srna, "mode", rna_enum_clip_editor_mode_items, SC_MODE_TRACKING, "Mode", ""); } +#ifdef WITH_INPUT_NDOF /********************** NDOF operator *********************/ /* Combined pan/zoom from a 3D mouse device. @@ -1451,6 +1452,7 @@ void CLIP_OT_view_ndof(wmOperatorType *ot) ot->invoke = clip_view_ndof_invoke; ot->poll = ED_space_clip_view_clip_poll; } +#endif /* WITH_INPUT_NDOF */ /********************** Prefetch operator *********************/ diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 5964e9a898b..547c2fba66f 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -175,21 +175,14 @@ void clip_graph_tracking_iterate(SpaceClip *sc, bool selected_only, bool include void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) { MovieTracking *tracking = &clip->tracking; - MovieTrackingStabilization *stab = &tracking->stabilization; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); - bool has_bundle = false, update_stab = false; + bool has_bundle = false; char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2]; if (track == act_track) tracking->act_track = NULL; - if (track == stab->rot_track) { - stab->rot_track = NULL; - - update_stab = true; - } - /* handle reconstruction display in 3d viewport */ if (track->flag & TRACK_HAS_BUNDLE) has_bundle = true; @@ -207,8 +200,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); - if (update_stab) { - tracking->stabilization.ok = false; + if (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT)) { 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 396d71f0a20..05e69968e35 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -225,18 +225,6 @@ static void clip_scopes_check_gpencil_change(ScrArea *sa) } } -static void clip_stabilization_tag_refresh(ScrArea *sa) -{ - SpaceClip *sc = (SpaceClip *) sa->spacedata.first; - MovieClip *clip = ED_space_clip_get_clip(sc); - - if (clip) { - MovieTrackingStabilization *stab = &clip->tracking.stabilization; - - stab->ok = false; - } -} - /* ******************** default callbacks for clip space ***************** */ static SpaceLink *clip_new(const bContext *C) @@ -368,7 +356,6 @@ static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) case NA_REMOVED: case NA_EDITED: case NA_EVALUATED: - clip_stabilization_tag_refresh(sa); /* fall-through */ case NA_SELECTED: @@ -412,7 +399,6 @@ static void clip_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn) case NC_SPACE: if (wmn->data == ND_SPACE_CLIP) { clip_scopes_tag_refresh(sa); - clip_stabilization_tag_refresh(sa); ED_area_tag_redraw(sa); } break; @@ -443,7 +429,9 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_change_frame); WM_operatortype_append(CLIP_OT_rebuild_proxy); WM_operatortype_append(CLIP_OT_mode_set); +#ifdef WITH_INPUT_NDOF WM_operatortype_append(CLIP_OT_view_ndof); +#endif WM_operatortype_append(CLIP_OT_prefetch); WM_operatortype_append(CLIP_OT_set_scene_frames); WM_operatortype_append(CLIP_OT_cursor_set); @@ -457,7 +445,7 @@ static void clip_operatortypes(void) /* navigation */ WM_operatortype_append(CLIP_OT_frame_jump); - /* foorage */ + /* set optical center to frame center */ WM_operatortype_append(CLIP_OT_set_center_principal); /* selection */ @@ -505,7 +493,9 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_stabilize_2d_add); WM_operatortype_append(CLIP_OT_stabilize_2d_remove); WM_operatortype_append(CLIP_OT_stabilize_2d_select); - WM_operatortype_append(CLIP_OT_stabilize_2d_set_rotation); + WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_add); + WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_remove); + WM_operatortype_append(CLIP_OT_stabilize_2d_rotation_select); /* clean-up */ WM_operatortype_append(CLIP_OT_clear_track_path); @@ -634,8 +624,10 @@ static void clip_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CLIP_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "CLIP_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "CLIP_OT_view_ndof", NDOF_MOTION, 0, 0, 0); +#endif /* jump to special frame */ kmi = WM_keymap_add_item(keymap, "CLIP_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); @@ -791,7 +783,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf) /* view */ WM_keymap_add_item(keymap, "CLIP_OT_graph_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "CLIP_OT_graph_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "CLIP_OT_graph_center_current_frame", PADPERIOD, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", LKEY, KM_PRESS, 0, 0); @@ -822,7 +816,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "extend", true); /* toggle */ WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif } const char *clip_context_dir[] = {"edit_movieclip", "edit_mask", NULL}; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 61bfa5b315b..d28cbe5fb1d 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1509,8 +1509,10 @@ static int join_tracks_exec(bContext *C, wmOperator *op) SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; + MovieTrackingStabilization *stab = &tracking->stabilization; ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); + bool update_stabilization = false; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); if (act_track == NULL) { @@ -1528,8 +1530,23 @@ static int join_tracks_exec(bContext *C, wmOperator *op) if (TRACK_VIEW_SELECTED(sc, track) && track != act_track) { BKE_tracking_tracks_join(tracking, act_track, track); - if (tracking->stabilization.rot_track == track) { - tracking->stabilization.rot_track = act_track; + if (track->flag & TRACK_USE_2D_STAB) { + update_stabilization = true; + if ((act_track->flag & TRACK_USE_2D_STAB) == 0) { + act_track->flag |= TRACK_USE_2D_STAB; + } else { + stab->tot_track--; + } + BLI_assert(0 <= stab->tot_track); + } + if (track->flag & TRACK_USE_2D_STAB_ROT) { + update_stabilization = true; + if ((act_track->flag & TRACK_USE_2D_STAB_ROT) == 0) { + act_track->flag |= TRACK_USE_2D_STAB_ROT; + } else { + stab->tot_rot_track--; + } + BLI_assert(0 <= stab->tot_rot_track); } for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first; @@ -1551,6 +1568,10 @@ static int join_tracks_exec(bContext *C, wmOperator *op) } } + if (update_stabilization) { + WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); + } + GSetIterator gs_iter; int framenr = ED_space_clip_get_clip_frame_number(sc); GSET_ITER (gs_iter, point_tracks) { diff --git a/source/blender/editors/space_clip/tracking_ops_stabilize.c b/source/blender/editors/space_clip/tracking_ops_stabilize.c index 8d6173e1cea..35b1aead343 100644 --- a/source/blender/editors/space_clip/tracking_ops_stabilize.c +++ b/source/blender/editors/space_clip/tracking_ops_stabilize.c @@ -84,7 +84,6 @@ static int stabilize_2d_add_exec(bContext *C, wmOperator *UNUSED(op)) } if (update) { - stab->ok = 0; DAG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -96,7 +95,7 @@ void CLIP_OT_stabilize_2d_add(wmOperatorType *ot) { /* identifiers */ ot->name = "Add Stabilization Tracks"; - ot->description = "Add selected tracks to 2D stabilization tool"; + ot->description = "Add selected tracks to 2D translation stabilization"; ot->idname = "CLIP_OT_stabilize_2d_add"; /* api callbacks */ @@ -139,7 +138,6 @@ static int stabilize_2d_remove_exec(bContext *C, wmOperator *UNUSED(op)) } if (update) { - stab->ok = 0; DAG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -151,7 +149,7 @@ void CLIP_OT_stabilize_2d_remove(wmOperatorType *ot) { /* identifiers */ ot->name = "Remove Stabilization Track"; - ot->description = "Remove selected track from stabilization"; + ot->description = "Remove selected track from translation stabilization"; ot->idname = "CLIP_OT_stabilize_2d_remove"; /* api callbacks */ @@ -193,7 +191,7 @@ void CLIP_OT_stabilize_2d_select(wmOperatorType *ot) { /* identifiers */ ot->name = "Select Stabilization Tracks"; - ot->description = "Select tracks which are used for stabilization"; + ot->description = "Select tracks which are used for translation stabilization"; ot->idname = "CLIP_OT_stabilize_2d_select"; /* api callbacks */ @@ -204,20 +202,85 @@ void CLIP_OT_stabilize_2d_select(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/***************** set 2d stabilization rotation track operator ****************/ +/********************** add 2d stabilization tracks for rotation operator ****************/ -static int stabilize_2d_set_rotation_exec(bContext *C, wmOperator *UNUSED(op)) +static int stabilize_2d_rotation_add_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; - MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); + MovieTrackingStabilization *stab = &tracking->stabilization; + + bool update = false; + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + if (TRACK_VIEW_SELECTED(sc, track) && + (track->flag & TRACK_USE_2D_STAB_ROT) == 0) + { + track->flag |= TRACK_USE_2D_STAB_ROT; + stab->tot_rot_track++; + update = true; + } + } + + if (update) { + DAG_id_tag_update(&clip->id, 0); + WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); + } + + return OPERATOR_FINISHED; +} + +void CLIP_OT_stabilize_2d_rotation_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Stabilization Rotation Tracks"; + ot->description = "Add selected tracks to 2D rotation stabilization"; + ot->idname = "CLIP_OT_stabilize_2d_rotation_add"; + + /* api callbacks */ + ot->exec = stabilize_2d_rotation_add_exec; + ot->poll = stabilize_2d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/********************** remove 2d stabilization tracks for rotation operator *************/ + +static int stabilize_2d_rotation_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTracking *tracking = &clip->tracking; + MovieTrackingStabilization *stab = &tracking->stabilization; + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); + int a = 0; + bool update = false; - if (act_track != NULL) { - MovieTrackingStabilization *stab = &tracking->stabilization; - stab->rot_track = act_track; - stab->ok = 0; + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + if (track->flag & TRACK_USE_2D_STAB_ROT) { + if (a == stab->act_rot_track) { + track->flag &= ~TRACK_USE_2D_STAB_ROT; + stab->act_rot_track--; + stab->tot_rot_track--; + if (stab->act_rot_track < 0) { + stab->act_rot_track = 0; + } + update = true; + break; + } + a++; + } + } + if (update) { DAG_id_tag_update(&clip->id, 0); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip); } @@ -225,18 +288,60 @@ static int stabilize_2d_set_rotation_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -void CLIP_OT_stabilize_2d_set_rotation(wmOperatorType *ot) +void CLIP_OT_stabilize_2d_rotation_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Stabilization Rotation Track"; + ot->description = "Remove selected track from rotation stabilization"; + ot->idname = "CLIP_OT_stabilize_2d_rotation_remove"; + + /* api callbacks */ + ot->exec = stabilize_2d_rotation_remove_exec; + ot->poll = stabilize_2d_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/********************** select 2d stabilization rotation tracks operator *****************/ + +static int stabilize_2d_rotation_select_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTracking *tracking = &clip->tracking; + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); + bool update = false; + + for (MovieTrackingTrack *track = tracksbase->first; + track != NULL; + track = track->next) + { + if (track->flag & TRACK_USE_2D_STAB_ROT) { + BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT); + update = true; + } + } + + if (update) { + WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip); + } + + return OPERATOR_FINISHED; +} + +void CLIP_OT_stabilize_2d_rotation_select(wmOperatorType *ot) { /* identifiers */ - ot->name = "Set Rotation Track"; - ot->description = "Use active track to compensate rotation when " - "doing 2D stabilization"; - ot->idname = "CLIP_OT_stabilize_2d_set_rotation"; + ot->name = "Select Stabilization Rotation Tracks"; + ot->description = "Select tracks which are used for rotation stabilization"; + ot->idname = "CLIP_OT_stabilize_2d_rotation_select"; /* api callbacks */ - ot->exec = stabilize_2d_set_rotation_exec; + ot->exec = stabilize_2d_rotation_select_exec; ot->poll = stabilize_2d_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 478dbd3d9c0..75f0da83e77 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -632,7 +632,9 @@ static void graphedit_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap) /* auto-set range */ WM_keymap_add_item(keymap, "GRAPH_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "GRAPH_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "GRAPH_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "GRAPH_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "GRAPH_OT_view_frame", PAD0, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 69993c3be65..52d04ad4956 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -64,7 +64,9 @@ void IMAGE_OT_view_zoom_in(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_out(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_ratio(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_border(struct wmOperatorType *ot); +#ifdef WITH_INPUT_NDOF void IMAGE_OT_view_ndof(struct wmOperatorType *ot); +#endif void IMAGE_OT_new(struct wmOperatorType *ot); void IMAGE_OT_open(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 1158e692182..f9d76da9f87 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -656,6 +656,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } +#ifdef WITH_INPUT_NDOF /********************** NDOF operator *********************/ /* Combined pan/zoom from a 3D mouse device. @@ -705,6 +706,7 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_LOCK_BYPASS; } +#endif /* WITH_INPUT_NDOF */ /********************** view all operator *********************/ diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 35a658eac23..6ddf78290aa 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -235,7 +235,9 @@ static void image_operatortypes(void) WM_operatortype_append(IMAGE_OT_view_zoom_out); WM_operatortype_append(IMAGE_OT_view_zoom_ratio); WM_operatortype_append(IMAGE_OT_view_zoom_border); +#ifdef WITH_INPUT_NDOF WM_operatortype_append(IMAGE_OT_view_ndof); +#endif WM_operatortype_append(IMAGE_OT_new); WM_operatortype_append(IMAGE_OT_open); @@ -296,8 +298,10 @@ static void image_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MOUSEPAN, 0, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "IMAGE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); // or view selected? WM_keymap_add_item(keymap, "IMAGE_OT_view_ndof", NDOF_MOTION, 0, 0, 0); +#endif WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index 69966e9bf34..12ca141128b 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -186,7 +186,9 @@ static void logic_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_menu(keymap, "LOGIC_MT_logicbricks_add", AKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "LOGIC_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "LOGIC_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif } static void logic_refresh(const bContext *UNUSED(C), ScrArea *UNUSED(sa)) diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 386950ead3a..48037a10b2d 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -242,7 +242,9 @@ static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap) WM_keymap_add_item(keymap, "NLA_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "NLA_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "NLA_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "NLA_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "NLA_OT_view_frame", PAD0, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 7788173a8ee..5118d52efc4 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -295,7 +295,9 @@ void node_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "NODE_OT_hide_socket_toggle", HKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "NODE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "NODE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "NODE_OT_select_border", BKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index ea3869ef387..5f592431558 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -276,25 +276,16 @@ static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, in return NULL; } -static int snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace) +static bool snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace) { bNodeTree *ntree = snode->edittree; - bNodeLink *link; /* then we can connect */ if (replace) nodeRemSocketLinks(ntree, sock_to); - link = nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to); - /* validate the new link */ - ntreeUpdateTree(G.main, ntree); - if (!(link->flag & NODE_LINK_VALID)) { - nodeRemLink(ntree, link); - return 0; - } - - snode_update(snode, node_to); - return 1; + nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to); + return true; } static void snode_autoconnect(SpaceNode *snode, const bool allow_multiple, const bool replace) diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 09594ab543c..ec525e684b0 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -428,6 +428,20 @@ static int ui_node_item_name_compare(const void *a, const void *b) return BLI_natstrcmp(type_a->ui_name, type_b->ui_name); } +static bool ui_node_item_special_poll(const bNodeTree *UNUSED(ntree), + const bNodeType *ntype) +{ + if (STREQ(ntype->idname, "ShaderNodeUVAlongStroke")) { + /* TODO(sergey): Currently we don't have Freestyle nodes edited from + * the buttons context, so can ignore it's nodes completely. + * + * However, we might want to do some extra checks here later. + */ + return false; + } + return true; +} + static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) { bNodeTree *ntree = arg->ntree; @@ -452,11 +466,17 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) BLI_array_declare(sorted_ntypes); NODE_TYPES_BEGIN(ntype) { - if (compatibility && !(ntype->compatibility & compatibility)) + if (compatibility && !(ntype->compatibility & compatibility)) { continue; + } - if (ntype->nclass != nclass) + if (ntype->nclass != nclass) { continue; + } + + if (!ui_node_item_special_poll(ntree, ntype)) { + continue; + } BLI_array_append(sorted_ntypes, ntype); } diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 655e029cfdd..a3cfcae77b8 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -201,7 +201,9 @@ void sequencer_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "SEQUENCER_OT_meta_separate", GKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "SEQUENCER_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_view_frame", PAD0, KM_PRESS, 0, 0); @@ -340,7 +342,9 @@ void sequencer_keymap(wmKeyConfig *keyconf) /* Preview Region ----------------------------------------------------------- */ keymap = WM_keymap_find(keyconf, "SequencerPreview", SPACE_SEQ, 0); WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all_preview", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "SEQUENCER_OT_view_all_preview", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "SEQUENCER_OT_view_ghost_border", OKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 46bddc00f0a..b6fd040e552 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -651,6 +651,7 @@ void ED_spacetype_time(void) art->draw = time_main_region_draw; art->listener = time_main_region_listener; art->keymap = time_keymap; + art->lock = 1; /* Due to pointcache, see T4960. */ BLI_addhead(&st->regiontypes, art); /* regions: header */ diff --git a/source/blender/editors/space_time/time_ops.c b/source/blender/editors/space_time/time_ops.c index 7dd45327352..872793128f0 100644 --- a/source/blender/editors/space_time/time_ops.c +++ b/source/blender/editors/space_time/time_ops.c @@ -219,7 +219,9 @@ void time_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "TIME_OT_start_frame_set", SKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "TIME_OT_end_frame_set", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "TIME_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_item(keymap, "TIME_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); +#endif WM_keymap_add_item(keymap, "TIME_OT_view_frame", PAD0, KM_PRESS, 0, 0); } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 16008253f57..c88e099b1bc 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -744,6 +744,7 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect) glDisable(GL_BLEND); } +#ifdef WITH_INPUT_NDOF /* draw center and axis of rotation for ongoing 3D mouse navigation */ static void draw_rotation_guide(RegionView3D *rv3d) { @@ -854,6 +855,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) glDisable(GL_POINT_SMOOTH); glDepthMask(1); } +#endif /* WITH_INPUT_NDOF */ static void draw_view_icon(RegionView3D *rv3d, rcti *rect) { @@ -4017,10 +4019,11 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie BDR_drawSketch(C); } +#ifdef WITH_INPUT_NDOF if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && (rv3d->persp != RV3D_CAMOB)) /* TODO: draw something else (but not this) during fly mode */ draw_rotation_guide(rv3d); - +#endif } static bool is_cursor_visible(Scene *scene) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index dde6c3949c7..2c4b04ebd34 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1328,6 +1328,8 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } +#ifdef WITH_INPUT_NDOF + /** \name NDOF Utility Functions * \{ */ @@ -1893,6 +1895,8 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot) ot->flag = 0; } +#endif /* WITH_INPUT_NDOF */ + /* ************************ viewmove ******************************** */ diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 31377d0fce8..04a6aa215f4 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -26,8 +26,10 @@ /* defines VIEW3D_OT_fly modal operator */ -//#define NDOF_FLY_DEBUG -//#define NDOF_FLY_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ +#ifdef WITH_INPUT_NDOF +//# define NDOF_FLY_DEBUG +//# define NDOF_FLY_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ +#endif /* WITH_INPUT_NDOF */ #include "DNA_object_types.h" @@ -203,7 +205,10 @@ typedef struct FlyInfo { int mval[2]; /* latest 2D mouse values */ int center_mval[2]; /* center mouse values */ float width, height; /* camera viewport dimensions */ + +#ifdef WITH_INPUT_NDOF wmNDOFMotionData *ndof; /* latest 3D mouse values */ +#endif /* fly state state */ float speed; /* the speed the view is moving per redraw */ @@ -381,7 +386,10 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); copy_v2_v2_int(fly->mval, event->mval); + +#ifdef WITH_INPUT_NDOF fly->ndof = NULL; +#endif fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer(); @@ -449,8 +457,10 @@ static int flyEnd(bContext *C, FlyInfo *fly) rv3d->rflag &= ~RV3D_NAVIGATING; +#ifdef WITH_INPUT_NDOF if (fly->ndof) MEM_freeN(fly->ndof); +#endif if (fly->state == FLY_CONFIRM) { MEM_freeN(fly); @@ -469,6 +479,7 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e else if (event->type == MOUSEMOVE) { copy_v2_v2_int(fly->mval, event->mval); } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { /* do these automagically get delivered? yes. */ // puts("ndof motion detected in fly mode!"); @@ -478,15 +489,15 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e switch (incoming_ndof->progress) { case P_STARTING: /* start keeping track of 3D mouse position */ -#ifdef NDOF_FLY_DEBUG +# ifdef NDOF_FLY_DEBUG puts("start keeping track of 3D mouse position"); -#endif +# endif /* fall-through */ case P_IN_PROGRESS: /* update 3D mouse position */ -#ifdef NDOF_FLY_DEBUG +# ifdef NDOF_FLY_DEBUG putchar('.'); fflush(stdout); -#endif +# endif if (fly->ndof == NULL) { // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); fly->ndof = MEM_dupallocN(incoming_ndof); @@ -498,9 +509,9 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e break; case P_FINISHING: /* stop keeping track of 3D mouse position */ -#ifdef NDOF_FLY_DEBUG +# ifdef NDOF_FLY_DEBUG puts("stop keeping track of 3D mouse position"); -#endif +# endif if (fly->ndof) { MEM_freeN(fly->ndof); // free(fly->ndof); @@ -513,6 +524,7 @@ static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *e break; /* should always be one of the above 3 */ } } +#endif /* WITH_INPUT_NDOF */ /* handle modal keymap first */ else if (event->type == EVT_MODAL_MAP) { switch (event->val) { @@ -959,6 +971,7 @@ static int flyApply(bContext *C, FlyInfo *fly) return OPERATOR_FINISHED; } +#ifdef WITH_INPUT_NDOF static void flyApply_ndof(bContext *C, FlyInfo *fly) { Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); @@ -977,6 +990,7 @@ static void flyApply_ndof(bContext *C, FlyInfo *fly) } } } +#endif /* WITH_INPUT_NDOF */ static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -1023,12 +1037,15 @@ static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event) flyEvent(C, op, fly, event); +#ifdef WITH_INPUT_NDOF if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */ if (event->type == NDOF_MOTION) { flyApply_ndof(C, fly); } } - else if (event->type == TIMER && event->customdata == fly->timer) { + else +#endif /* WITH_INPUT_NDOF */ + if (event->type == TIMER && event->customdata == fly->timer) { flyApply(C, fly); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index e6f12622ce0..46587fefd76 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -46,7 +46,6 @@ struct bContext; struct bMotionPath; struct bPoseChannel; struct Mesh; -struct wmNDOFMotionData; struct wmOperatorType; struct wmWindowManager; struct wmKeyConfig; @@ -76,10 +75,12 @@ void VIEW3D_OT_dolly(struct wmOperatorType *ot); void VIEW3D_OT_zoom_camera_1_to_1(struct wmOperatorType *ot); void VIEW3D_OT_move(struct wmOperatorType *ot); void VIEW3D_OT_rotate(struct wmOperatorType *ot); +#ifdef WITH_INPUT_NDOF void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot); void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot); void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot); void VIEW3D_OT_ndof_all(struct wmOperatorType *ot); +#endif /* WITH_INPUT_NDOF */ void VIEW3D_OT_view_all(struct wmOperatorType *ot); void VIEW3D_OT_viewnumpad(struct wmOperatorType *ot); void VIEW3D_OT_view_selected(struct wmOperatorType *ot); @@ -111,11 +112,15 @@ void view3d_orbit_apply_dyn_ofs( float r_ofs[3], const float ofs_old[3], const float viewquat_old[4], const float viewquat_new[4], const float dyn_ofs[3]); +#ifdef WITH_INPUT_NDOF +struct wmNDOFMotionData; + void view3d_ndof_fly( const struct wmNDOFMotionData *ndof, struct View3D *v3d, struct RegionView3D *rv3d, const bool use_precision, const short protectflag, bool *r_has_translate, bool *r_has_rotate); +#endif /* WITH_INPUT_NDOF */ /* view3d_fly.c */ void view3d_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index b273f46fca3..cfeb8af280e 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -164,10 +164,12 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_zoom); WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1); WM_operatortype_append(VIEW3D_OT_dolly); +#ifdef WITH_INPUT_NDOF WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom); WM_operatortype_append(VIEW3D_OT_ndof_orbit); WM_operatortype_append(VIEW3D_OT_ndof_pan); WM_operatortype_append(VIEW3D_OT_ndof_all); +#endif /* WITH_INPUT_NDOF */ WM_operatortype_append(VIEW3D_OT_view_all); WM_operatortype_append(VIEW3D_OT_viewnumpad); WM_operatortype_append(VIEW3D_OT_view_orbit); @@ -363,7 +365,7 @@ void view3d_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0); - /* NDOF: begin */ +#ifdef WITH_INPUT_NDOF /* note: positioned here so keymaps show keyboard keys if assigned */ /* 3D mouse */ WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit_zoom", NDOF_MOTION, 0, 0, 0); @@ -392,8 +394,7 @@ void view3d_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP); RNA_boolean_set(kmi->ptr, "align_active", true); - /* NDOF: end */ - +#endif /* WITH_INPUT_NDOF */ /* layers, shift + alt are properties set in invoke() */ RNA_int_set(WM_keymap_add_item(keymap, "VIEW3D_OT_layers", ACCENTGRAVEKEY, KM_PRESS, 0, 0)->ptr, "nr", 0); diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index 37b068e3e49..67a40ae4180 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -297,6 +297,8 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) bGPDlayer *gpl; bGPDframe *gpf; bGPDstroke *gps; + bGPDpalette *palette; + bGPDpalettecolor *palcolor; RulerItem *ruler_item; const char *ruler_name = RULER_ID; bool changed = false; @@ -312,6 +314,17 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) gpl->flag |= GP_LAYER_HIDE; } + /* try to get active palette or create a new one */ + palette = BKE_gpencil_palette_getactive(scene->gpd); + if (palette == NULL) { + palette = BKE_gpencil_palette_addnew(scene->gpd, DATA_("GP_Palette"), true); + } + /* try to get color with the ruler name or create a new one */ + palcolor = BKE_gpencil_palettecolor_getbyname(palette, (char *)ruler_name); + if (palcolor == NULL) { + palcolor = BKE_gpencil_palettecolor_addnew(palette, (char *)ruler_name, true); + } + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true); BKE_gpencil_free_strokes(gpf); @@ -342,6 +355,10 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) } } gps->flag = GP_STROKE_3DSPACE; + gps->thickness = 3; + /* assign color to stroke */ + strcpy(gps->colorname, palcolor->info); + gps->palcolor = palcolor; BLI_addtail(&gpf->strokes, gps); changed = true; } diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index c9e4bb301b8..17c08ed4205 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -59,8 +59,10 @@ #include "view3d_intern.h" /* own include */ -//#define NDOF_WALK_DEBUG -//#define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ +#ifdef WITH_INPUT_NDOF +//# define NDOF_WALK_DEBUG +//# define NDOF_WALK_DRAW_TOOMUCH /* is this needed for ndof? - commented so redraw doesnt thrash - campbell */ +#endif #define USE_TABLET_SUPPORT @@ -254,7 +256,10 @@ typedef struct WalkInfo { int prev_mval[2]; /* previous 2D mouse values */ int center_mval[2]; /* center mouse values */ int moffset[2]; + +#ifdef WITH_INPUT_NDOF wmNDOFMotionData *ndof; /* latest 3D mouse values */ +#endif /* walk state state */ float base_speed; /* the base speed without run/slow down modifications */ @@ -572,7 +577,9 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); +#ifdef WITH_INPUT_NDOF walk->ndof = NULL; +#endif walk->time_lastdraw = PIL_check_seconds_timer(); @@ -639,8 +646,10 @@ static int walkEnd(bContext *C, WalkInfo *walk) rv3d->rflag &= ~RV3D_NAVIGATING; +#ifdef WITH_INPUT_NDOF if (walk->ndof) MEM_freeN(walk->ndof); +#endif /* restore the cursor */ WM_cursor_modal_restore(win); @@ -743,6 +752,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent } } } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { /* do these automagically get delivered? yes. */ // puts("ndof motion detected in walk mode!"); @@ -752,15 +762,15 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent switch (incoming_ndof->progress) { case P_STARTING: /* start keeping track of 3D mouse position */ -#ifdef NDOF_WALK_DEBUG +# ifdef NDOF_WALK_DEBUG puts("start keeping track of 3D mouse position"); -#endif +# endif /* fall-through */ case P_IN_PROGRESS: /* update 3D mouse position */ -#ifdef NDOF_WALK_DEBUG +# ifdef NDOF_WALK_DEBUG putchar('.'); fflush(stdout); -#endif +# endif if (walk->ndof == NULL) { // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); walk->ndof = MEM_dupallocN(incoming_ndof); @@ -772,9 +782,9 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent break; case P_FINISHING: /* stop keeping track of 3D mouse position */ -#ifdef NDOF_WALK_DEBUG +# ifdef NDOF_WALK_DEBUG puts("stop keeping track of 3D mouse position"); -#endif +# endif if (walk->ndof) { MEM_freeN(walk->ndof); // free(walk->ndof); @@ -789,6 +799,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent break; /* should always be one of the above 3 */ } } +#endif /* WITH_INPUT_NDOF */ /* handle modal keymap first */ else if (event->type == EVT_MODAL_MAP) { switch (event->val) { @@ -1323,6 +1334,7 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) #undef WALK_BOOST_FACTOR } +#ifdef WITH_INPUT_NDOF static void walkApply_ndof(bContext *C, WalkInfo *walk) { Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); @@ -1341,6 +1353,7 @@ static void walkApply_ndof(bContext *C, WalkInfo *walk) } } } +#endif /* WITH_INPUT_NDOF */ /****** walk operator ******/ static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -1388,12 +1401,15 @@ static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event) walkEvent(C, op, walk, event); +#ifdef WITH_INPUT_NDOF if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */ if (event->type == NDOF_MOTION) { walkApply_ndof(C, walk); } } - else if (event->type == TIMER && event->customdata == walk->timer) { + else +#endif /* WITH_INPUT_NDOF */ + if (event->type == TIMER && event->customdata == walk->timer) { walkApply(C, op, walk); } diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 6e399d9fde3..cbe58ddf586 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -386,7 +386,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) TransInfo *t = op->customdata; const enum TfmMode mode_prev = t->mode; -#if 0 +#if defined(WITH_INPUT_NDOF) && 0 // stable 2D mouse coords map to different 3D coords while the 3D mouse is active // in other words, 2D deltas are no longer good enough! // disable until individual 'transformers' behave better diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp index ab06e207331..028127897ff 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRep.cpp +++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp @@ -135,11 +135,11 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices) int orientationErrors = 0; //special case of first vertex - v = iStrokeVertices.begin(); + v2 = v = iStrokeVertices.begin(); + ++v2; sv = *v; vPrev = v; //in case the stroke has only 2 vertices; - ++v; - sv2 = *v; + sv2 = *v2; Vec2r dir(sv2->getPoint() - sv->getPoint()); Vec2r orthDir(-dir[1], dir[0]); if (orthDir.norm() > ZERO) @@ -189,11 +189,7 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices) int i = 2; // 2 because we have already processed the first vertex - for (vend = iStrokeVertices.end(); v != vend; ++v) { - v2 = v; - ++v2; - if (v2 == vend) - break; + for (vend = iStrokeVertices.end(), ++v, ++v2; v2 != vend; vPrev = v++, ++v2) { sv = (*v); sv2 = (*v2); svPrev = (*vPrev); @@ -289,8 +285,6 @@ void Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices) { _vertices[i - 1]->setPoint2d(p - thickness[0] * stripDir); } - - vPrev = v; } // end of for //special case of last vertex diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index 77beb1d97d9..380bb0dd3ca 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -2099,7 +2099,7 @@ int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real eps } // Find occludee - FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, edge, origin, faceVertices); + FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, origin, edge, faceVertices); return qi; } diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h index a2981c0aa76..9e9ab974b01 100644 --- a/source/blender/makesdna/DNA_genfile.h +++ b/source/blender/makesdna/DNA_genfile.h @@ -100,6 +100,7 @@ void *DNA_struct_reconstruct( int DNA_elem_array_size(const char *str); int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name); +bool DNA_struct_find(const struct SDNA *sdna, const char *stype); bool DNA_struct_elem_find(const struct SDNA *sdna, const char *stype, const char *vartype, const char *name); diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index f1546053c5c..773d203bdb3 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -298,9 +298,8 @@ typedef struct bGPdata { char pad[6]; /* padding for compiler alignment error */ short sflag; /* settings for palette color */ - /* saved paletes and brushes */ + /* saved palettes */ ListBase palettes; - //ListBase brushes; } bGPdata; /* bGPdata->flag */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 5452d515a70..ccde6549d9c 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -329,7 +329,7 @@ typedef struct DupliObject { /* persistent identifier for a dupli object, for inter-frame matching of * objects with motion blur, or inter-update matching for syncing */ - int persistent_id[8]; /* MAX_DUPLI_RECUR */ + int persistent_id[16]; /* 2*MAX_DUPLI_RECUR */ } DupliObject; /* **************** OBJECT ********************* */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 9888b735b8b..42b72c1ff93 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -158,7 +158,10 @@ typedef struct MovieTrackingTrack { * Used to prevent jumps of the camera when tracks are appearing or * disappearing. */ - float weight, pad; + float weight; + + /* track weight especially for 2D stabilization */ + float weight_stab; } MovieTrackingTrack; typedef struct MovieTrackingPlaneMarker { @@ -250,19 +253,24 @@ typedef struct MovieTrackingSettings { typedef struct MovieTrackingStabilization { int flag; - int tot_track, act_track; /* total number and index of active track in list */ + int tot_track, act_track; /* total number of translation tracks and index of active track in list */ + int tot_rot_track, act_rot_track; /* total number of rotation tracks and index of active track in list */ /* 2d stabilization */ float maxscale; /* max auto-scale factor */ - MovieTrackingTrack *rot_track; /* track used to stabilize rotation */ + MovieTrackingTrack *rot_track DNA_DEPRECATED; /* use TRACK_USE_2D_STAB_ROT on individual tracks instead */ + + int anchor_frame; /* reference point to anchor stabilization offset */ + float target_pos[2]; /* expected target position of frame after raw stabilization, will be subtracted */ + float target_rot; /* expected target rotation of frame after raw stabilization, will be compensated */ + float scale; /* zoom factor known to be present on original footage. Also used for autoscale */ float locinf, scaleinf, rotinf; /* influence on location, scale and rotation */ int filter; /* filter used for pixel interpolation */ - /* some pre-computing run-time variables */ - int ok; /* are precomputed values and scaled buf relevant? */ - float scale; /* autoscale factor */ + /* initialization and run-time data */ + int ok DNA_DEPRECATED; /* Without effect now, we initialize on every frame. Formerly used for caching of init values */ } MovieTrackingStabilization; typedef struct MovieTrackingReconstruction { @@ -386,7 +394,8 @@ enum { TRACK_USE_2D_STAB = (1 << 8), TRACK_PREVIEW_GRAYSCALE = (1 << 9), TRACK_DOPE_SEL = (1 << 10), - TRACK_PREVIEW_ALPHA = (1 << 11) + TRACK_PREVIEW_ALPHA = (1 << 11), + TRACK_USE_2D_STAB_ROT = (1 << 12) }; /* MovieTrackingTrack->motion_model */ @@ -452,7 +461,9 @@ enum { enum { TRACKING_2D_STABILIZATION = (1 << 0), TRACKING_AUTOSCALE = (1 << 1), - TRACKING_STABILIZE_ROTATION = (1 << 2) + TRACKING_STABILIZE_ROTATION = (1 << 2), + TRACKING_STABILIZE_SCALE = (1 << 3), + TRACKING_SHOW_STAB_TRACKS = (1 << 5) }; /* MovieTrackingStrabilization->filter */ diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 6a41591e051..96085a79eff 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -1294,6 +1294,11 @@ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const ch return (int)((intptr_t)cp); } +bool DNA_struct_find(const SDNA *sdna, const char *stype) +{ + return DNA_struct_find_nr(sdna, stype) != -1; +} + bool DNA_struct_elem_find(const SDNA *sdna, const char *stype, const char *vartype, const char *name) { const int SDNAnr = DNA_struct_find_nr(sdna, stype); diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 64cacfa3dea..a52f4548733 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -412,6 +412,7 @@ extern StructRNA RNA_MovieClipSequence; extern StructRNA RNA_MovieTracking; extern StructRNA RNA_MovieTrackingObject; extern StructRNA RNA_MovieTrackingTrack; +extern StructRNA RNA_MovieTrackingStabilization; extern StructRNA RNA_MulticamSequence; extern StructRNA RNA_MultiresModifier; extern StructRNA RNA_MusgraveTexture; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index c67780204e1..cc3fd2ce324 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -325,6 +325,10 @@ if(WITH_OPENVDB) endif() endif() +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif() + # Build makesrna executable blender_include_dirs( . diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 94290828e46..b2b97ce85d9 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -50,7 +50,7 @@ #ifndef NDEBUG void BLI_system_backtrace(FILE *fp) { - (void)fp; + (void)fp; } #endif diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 265eab32df8..282da6c0cd4 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -374,15 +374,15 @@ int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assig } } -static void rna_IDMaterials_append_id(ID *id, Material *ma) +static void rna_IDMaterials_append_id(ID *id, Main *bmain, Material *ma) { - BKE_material_append_id(id, ma); + BKE_material_append_id(bmain, id, ma); WM_main_add_notifier(NC_OBJECT | ND_DRAW, id); WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id); } -static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i, int remove_material_slot) +static Material *rna_IDMaterials_pop_id(ID *id, Main *bmain, ReportList *reports, int index_i, int remove_material_slot) { Material *ma; short *totcol = give_totcolp_id(id); @@ -396,7 +396,7 @@ static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i return NULL; } - ma = BKE_material_pop_id(id, index_i, remove_material_slot); + ma = BKE_material_pop_id(bmain, id, index_i, remove_material_slot); if (*totcol == totcol_orig) { BKE_report(reports, RPT_ERROR, "No material to removed"); @@ -412,7 +412,7 @@ static Material *rna_IDMaterials_pop_id(ID *id, ReportList *reports, int index_i static void rna_IDMaterials_clear_id(ID *id, int remove_material_slot) { - BKE_material_clear_id(id, remove_material_slot); + BKE_material_clear_id(G.main, id, remove_material_slot); DAG_id_tag_update(id, OB_RECALC_DATA); WM_main_add_notifier(NC_OBJECT | ND_DRAW, id); @@ -808,12 +808,13 @@ static void rna_def_ID_materials(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "ID Materials", "Collection of materials"); func = RNA_def_function(srna, "append", "rna_IDMaterials_append_id"); + RNA_def_function_flag(func, FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Add a new material to the data block"); parm = RNA_def_pointer(func, "material", "Material", "", "Material to add"); RNA_def_property_flag(parm, PROP_REQUIRED); func = RNA_def_function(srna, "pop", "rna_IDMaterials_pop_id"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_MAIN); RNA_def_function_ui_description(func, "Remove a material from the data block"); parm = RNA_def_int(func, "index", -1, -MAXMAT, MAXMAT, "", "Index of material to remove", 0, MAXMAT); RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned"); diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 781e44c9ed6..d8bcbc2cc72 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -56,6 +56,12 @@ static void rna_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); } +static void rna_cloth_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + DAG_relations_tag_update(bmain); + rna_cloth_update(bmain, scene, ptr); +} + static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; @@ -68,6 +74,16 @@ static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); } +static void rna_ClothSettings_bending_set(struct PointerRNA *ptr, float value) +{ + ClothSimSettings *settings = (ClothSimSettings *)ptr->data; + + settings->bending = value; + + /* check for max clipping */ + if (value > settings->max_bend) + settings->max_bend = value; +} static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value) { @@ -80,6 +96,17 @@ static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value) settings->max_bend = value; } +static void rna_ClothSettings_structural_set(struct PointerRNA *ptr, float value) +{ + ClothSimSettings *settings = (ClothSimSettings *)ptr->data; + + settings->structural = value; + + /* check for max clipping */ + if (value > settings->max_struct) + settings->max_struct = value; +} + static void rna_ClothSettings_max_struct_set(struct PointerRNA *ptr, float value) { ClothSimSettings *settings = (ClothSimSettings *)ptr->data; @@ -493,6 +520,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "structural"); RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_structural_set", NULL); RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure"); RNA_def_property_update(prop, 0, "rna_cloth_update"); @@ -521,6 +549,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "bending"); RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_bending_set", NULL); RNA_def_property_ui_text(prop, "Bending Stiffness", "Wrinkle coefficient (higher = less smaller but more big wrinkles)"); RNA_def_property_update(prop, 0, "rna_cloth_update"); @@ -706,7 +735,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group"); - RNA_def_property_update(prop, 0, "rna_cloth_update"); + RNA_def_property_update(prop, 0, "rna_cloth_dependency_update"); prop = RNA_def_property(srna, "vertex_group_self_collisions", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_CollSettings_selfcol_vgroup_get", "rna_CollSettings_selfcol_vgroup_length", diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 7424c190501..3ecaec75c77 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -482,7 +482,9 @@ static void rna_GPencil_stroke_point_pop(bGPDstroke *stroke, ReportList *reports static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame, const char *colorname) { bGPDstroke *stroke = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); - strcpy(stroke->colorname, colorname); + if (colorname) { + BLI_strncpy(stroke->colorname, colorname, sizeof(stroke->colorname)); + } stroke->palcolor = NULL; stroke->flag |= GP_STROKE_RECALC_COLOR; BLI_addtail(&frame->strokes, stroke); @@ -918,19 +920,19 @@ static void rna_def_gpencil_triangle(BlenderRNA *brna) /* point v1 */ prop = RNA_def_property(srna, "v1", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "v1"); - RNA_def_property_ui_text(prop, "v1", "First triangle vertice index"); + RNA_def_property_ui_text(prop, "v1", "First triangle vertex index"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* point v2 */ prop = RNA_def_property(srna, "v2", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "v2"); - RNA_def_property_ui_text(prop, "v2", "Second triangle vertice index"); + RNA_def_property_ui_text(prop, "v2", "Second triangle vertex index"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* point v3 */ prop = RNA_def_property(srna, "v3", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "v3"); - RNA_def_property_ui_text(prop, "v3", "Third triangle vertice index"); + RNA_def_property_ui_text(prop, "v3", "Third triangle vertex index"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); } @@ -1145,7 +1147,8 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) // TODO: replace these with a "draw type" combo (i.e. strokes only, filled strokes, strokes + fills, volumetric)? prop = RNA_def_property(srna, "use_volumetric_strokes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_VOLUMETRIC); - RNA_def_property_ui_text(prop, "Volumetric Strokes", "Draw strokes as a series of circular blobs, resulting in a volumetric effect"); + RNA_def_property_ui_text(prop, "Volumetric Strokes", + "Draw strokes as a series of circular blobs, resulting in a volumetric effect"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); prop = RNA_def_property(srna, "opacity", PROP_FLOAT, PROP_NONE); @@ -1174,7 +1177,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "thickness"); //RNA_def_property_range(prop, 1, 10); /* 10 px limit comes from Windows OpenGL limits for natively-drawn strokes */ RNA_def_property_int_funcs(prop, NULL, NULL, "rna_GPencilLayer_line_width_range"); - RNA_def_property_ui_text(prop, "Thickness", "Thickness change to apply current strokes (in pixels)"); + RNA_def_property_ui_text(prop, "Thickness", "Thickness change to apply to current strokes (in pixels)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); /* Onion-Skinning */ @@ -1241,8 +1244,8 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) prop = RNA_def_property(srna, "unlock_color", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_UNLOCK_COLOR); RNA_def_property_ui_icon(prop, ICON_RESTRICT_COLOR_OFF, 1); - RNA_def_property_ui_text(prop, "Unlock color", "Unprotect colors selected from further editing " - "and/or frame changes"); + RNA_def_property_ui_text(prop, "Unlock Color", + "Unprotect selected colors from further editing and/or frame changes"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); @@ -1299,7 +1302,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "inverse"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "MatrixInverse", "Parent inverse transformation matrix"); + RNA_def_property_ui_text(prop, "Inverse Matrix", "Parent inverse transformation matrix"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); /* read only parented flag */ diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index c2dad964573..ad927073871 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -448,6 +448,11 @@ static void rna_softbody_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob); } +static void rna_softbody_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + DAG_relations_tag_update(bmain); + rna_softbody_update(bmain, scene, ptr); +} static EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) @@ -959,7 +964,7 @@ static void rna_def_field(BlenderRNA *brna) prop = RNA_def_property(srna, "use_absorption", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_VISIBILITY); RNA_def_property_ui_text(prop, "Absorption", "Force gets absorbed by collision objects"); - RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); + RNA_def_property_update(prop, 0, "rna_FieldSettings_dependency_update"); prop = RNA_def_property(srna, "use_multiple_springs", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_MULTIPLE_SPRINGS); @@ -1436,7 +1441,7 @@ static void rna_def_softbody(BlenderRNA *brna) prop = RNA_def_property(srna, "collision_group", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Collision Group", "Limit colliders to this Group"); - RNA_def_property_update(prop, 0, "rna_softbody_update"); + RNA_def_property_update(prop, 0, "rna_softbody_dependency_update"); prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "effector_weights"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 06b5bd87dd4..be42f3c538f 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2146,23 +2146,26 @@ static void rna_def_gpencil_brush(BlenderRNA *brna) /* Angle when brush is full size */ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "draw_angle"); - RNA_def_property_range(prop, 0.0f, M_PI_2); - RNA_def_property_ui_text(prop, "Angle", "Angle of drawing when brush has full size"); + RNA_def_property_range(prop, -M_PI_2, M_PI_2); + RNA_def_property_ui_text(prop, "Angle", + "Direction of the stroke at which brush gives maximal thickness " + "(0° for horizontal)"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Factor to change brush size depending of angle */ prop = RNA_def_property(srna, "angle_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "draw_angle_factor"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Angle Factor", "Factor to apply when the brush rotate of its full size"); + RNA_def_property_ui_text(prop, "Angle Factor", + "Reduce brush thickness by this factor when stroke is perpendicular to 'Angle' direction"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Smoothing factor for new strokes */ prop = RNA_def_property(srna, "pen_smooth_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "draw_smoothfac"); RNA_def_property_range(prop, 0.0, 2.0f); - RNA_def_property_ui_text(prop, "Smooth", "Amount of smoothing to apply to newly created strokes, to " - "reduce jitter/noise"); + RNA_def_property_ui_text(prop, "Smooth", + "Amount of smoothing to apply to newly created strokes, to reduce jitter/noise"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Iterations of the Smoothing factor */ @@ -2170,8 +2173,7 @@ static void rna_def_gpencil_brush(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "draw_smoothlvl"); RNA_def_property_range(prop, 1, 3); RNA_def_property_ui_text(prop, "Iterations", - "Number of times to smooth newly created strokes " - "[+ reason/effect of using higher values of this property]"); + "Number of times to smooth newly created strokes"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* Subdivision level for new strokes */ diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index ed51f0cffb0..519f28bea24 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -278,8 +278,8 @@ static void rna_Scene_collada_export( int use_object_instantiation, int use_blender_profile, int sort_by_name, - int export_transformation_type, - int open_sim) + int open_sim, + int export_transformation_type) { collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, include_children, include_armatures, include_shapekeys, deform_bones_only, diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 2fe9bdd17e1..34e364981ba 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -705,17 +705,17 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna) prop = RNA_def_property(srna, "affect_position", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_POSITION); - RNA_def_property_ui_text(prop, "Affect position", "The brush affects the position of the point"); + RNA_def_property_ui_text(prop, "Affect Position", "The brush affects the position of the point"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); prop = RNA_def_property(srna, "affect_strength", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_STRENGTH); - RNA_def_property_ui_text(prop, "Affect strength", "The brush affects the color strength of the point"); + RNA_def_property_ui_text(prop, "Affect Strength", "The brush affects the color strength of the point"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); prop = RNA_def_property(srna, "affect_thickness", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_APPLY_THICKNESS); - RNA_def_property_ui_text(prop, "Affect thickness", "The brush affects the thickness of the point"); + RNA_def_property_ui_text(prop, "Affect Thickness", "The brush affects the thickness of the point"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); prop = RNA_def_property(srna, "selection_alpha", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 2564bdb800f..cbfebe5efc4 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -394,6 +394,16 @@ static int rna_track_2d_stabilization(CollectionPropertyIterator *UNUSED(iter), return 0; } +static int rna_track_2d_stabilization_rotation(CollectionPropertyIterator *UNUSED(iter), void *data) +{ + MovieTrackingTrack *track = (MovieTrackingTrack *)data; + + if ((track->flag & TRACK_USE_2D_STAB_ROT) == 0) + return 1; + + return 0; +} + static void rna_tracking_stabTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { MovieClip *clip = (MovieClip *)ptr->id.data; @@ -421,23 +431,36 @@ static void rna_tracking_stabTracks_active_index_range(PointerRNA *ptr, int *min *max = max_ii(0, clip->tracking.stabilization.tot_track - 1); } -static void rna_tracking_resetIntrinsics(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_tracking_stabRotTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { MovieClip *clip = (MovieClip *)ptr->id.data; - MovieTracking *tracking = &clip->tracking; + rna_iterator_listbase_begin(iter, &clip->tracking.tracks, rna_track_2d_stabilization_rotation); +} - if (tracking->camera.intrinsics) { - BKE_tracking_distortion_free(tracking->camera.intrinsics); - tracking->camera.intrinsics = NULL; - } +static int rna_tracking_stabRotTracks_active_index_get(PointerRNA *ptr) +{ + MovieClip *clip = (MovieClip *)ptr->id.data; + return clip->tracking.stabilization.act_rot_track; } -static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +static void rna_tracking_stabRotTracks_active_index_set(PointerRNA *ptr, int value) +{ + MovieClip *clip = (MovieClip *)ptr->id.data; + clip->tracking.stabilization.act_rot_track = value; +} + +static void rna_tracking_stabRotTracks_active_index_range(PointerRNA *ptr, int *min, int *max, + int *UNUSED(softmin), int *UNUSED(softmax)) { MovieClip *clip = (MovieClip *)ptr->id.data; - MovieTrackingStabilization *stab = &clip->tracking.stabilization; - stab->ok = 0; + *min = 0; + *max = max_ii(0, clip->tracking.stabilization.tot_rot_track - 1); +} + +static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +{ + MovieClip *clip = (MovieClip *)ptr->id.data; nodeUpdateID(scene->nodetree, &clip->id); @@ -446,6 +469,17 @@ static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerR DAG_id_tag_update(&clip->id, 0); } +static void rna_tracking_resetIntrinsics(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + MovieClip *clip = (MovieClip *)ptr->id.data; + MovieTracking *tracking = &clip->tracking; + + if (tracking->camera.intrinsics) { + BKE_tracking_distortion_free(tracking->camera.intrinsics); + tracking->camera.intrinsics = NULL; + } +} + static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { MovieTrackingObject *object = (MovieTrackingObject *)ptr->data; @@ -1495,6 +1529,12 @@ static void rna_def_trackingTrack(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Weight", "Influence of this track on a final solution"); + /* weight_stab */ + prop = RNA_def_property(srna, "weight_stab", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "weight_stab"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Stab Weight", "Influence of this track on 2D stabilization"); + /* offset */ prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_array(prop, 2); @@ -1634,15 +1674,15 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) PropertyRNA *prop; static EnumPropertyItem filter_items[] = { - {TRACKING_FILTER_NEAREST, "NEAREST", 0, "Nearest", ""}, - {TRACKING_FILTER_BILINEAR, "BILINEAR", 0, "Bilinear", ""}, - {TRACKING_FILTER_BICUBIC, "BICUBIC", 0, "Bicubic", ""}, + {TRACKING_FILTER_NEAREST, "NEAREST", 0, "Nearest", "No interpolation, use nearest neighbor pixel"}, + {TRACKING_FILTER_BILINEAR, "BILINEAR", 0, "Bilinear", "Simple interpolation between adjacent pixels"}, + {TRACKING_FILTER_BICUBIC, "BICUBIC", 0, "Bicubic", "High quality pixel interpolation"}, {0, NULL, 0, NULL, NULL} }; srna = RNA_def_struct(brna, "MovieTrackingStabilization", NULL); RNA_def_struct_path_func(srna, "rna_trackingStabilization_path"); - RNA_def_struct_ui_text(srna, "Movie tracking stabilization data", "Match-moving stabilization data for tracking"); + RNA_def_struct_ui_text(srna, "Movie tracking stabilization data", "2D stabilization based on tracking markers"); /* 2d stabilization */ prop = RNA_def_property(srna, "use_2d_stabilization", PROP_BOOLEAN, PROP_NONE); @@ -1651,22 +1691,30 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Use 2D stabilization", "Use 2D stabilization for footage"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + /* use_stabilize_rotation */ + prop = RNA_def_property(srna, "use_stabilize_rotation", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_STABILIZE_ROTATION); + RNA_def_property_ui_text(prop, "Stabilize Rotation", "Stabilize detected rotation around center of frame"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + + /* use_stabilize_scale */ + prop = RNA_def_property(srna, "use_stabilize_scale", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_STABILIZE_SCALE); + RNA_def_property_ui_text(prop, "Stabilize Scale", "Compensate any scale changes relative to center of rotation"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + /* tracks */ prop = RNA_def_property(srna, "tracks", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_tracking_stabTracks_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL); RNA_def_property_struct_type(prop, "MovieTrackingTrack"); - RNA_def_property_ui_text(prop, "Tracks", "Collection of tracks used for stabilization"); + RNA_def_property_ui_text(prop, "Translation Tracks", + "Collection of tracks used for 2D stabilization (translation)"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); - /* rotation track */ - prop = RNA_def_property(srna, "rotation_track", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "rot_track"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Rotation Track", "Track used to compensate rotation"); - RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_tracking_flushUpdate"); - /* active track index */ prop = RNA_def_property(srna, "active_track_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "act_track"); @@ -1674,7 +1722,65 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) RNA_def_property_int_funcs(prop, "rna_tracking_stabTracks_active_index_get", "rna_tracking_stabTracks_active_index_set", "rna_tracking_stabTracks_active_index_range"); - RNA_def_property_ui_text(prop, "Active Track Index", "Index of active track in stabilization tracks list"); + RNA_def_property_ui_text(prop, "Active Track Index", + "Index of active track in translation stabilization tracks list"); + + /* tracks used for rotation stabilization */ + prop = RNA_def_property(srna, "rotation_tracks", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_tracking_stabRotTracks_begin", "rna_iterator_listbase_next", + "rna_iterator_listbase_end", "rna_iterator_listbase_get", + NULL, NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "MovieTrackingTrack"); + RNA_def_property_ui_text(prop, "Rotation Tracks", "Collection of tracks used for 2D stabilization (translation)"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + + /* active rotation track index */ + prop = RNA_def_property(srna, "active_rotation_track_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "act_rot_track"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_int_funcs(prop, "rna_tracking_stabRotTracks_active_index_get", + "rna_tracking_stabRotTracks_active_index_set", + "rna_tracking_stabRotTracks_active_index_range"); + RNA_def_property_ui_text(prop, "Active Rotation Track Index", + "Index of active track in rotation stabilization tracks list"); + + /* anchor frame */ + prop = RNA_def_property(srna, "anchor_frame", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "anchor_frame"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_range(prop, MINFRAME, MAXFRAME); + RNA_def_property_ui_text(prop, "Anchor Frame", + "Reference point to anchor stabilization " + "(other frames will be adjusted relative to this frame's position)"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + + /* target position */ + prop = RNA_def_property(srna, "target_position", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_array(prop, 2); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3); /* increment in steps of 0.01 and show 3 digit after point */ + RNA_def_property_float_sdna(prop, NULL, "target_pos"); + RNA_def_property_ui_text(prop, "Expected Position", + "Known relative offset of original shot, will be subtracted " + "(e.g. for panning shot, can be animated)"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + + /* target rotation */ + prop = RNA_def_property(srna, "target_rotation", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "target_rot"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3); + RNA_def_property_ui_text(prop, "Expected Rotation", + "Rotation present on original shot, will be compensated (e.g. for deliberate tilting)"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + + /* target scale */ + prop = RNA_def_property(srna, "target_zoom", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_range(prop, FLT_EPSILON, 100.0f); + RNA_def_property_ui_range(prop, 0.1f, 10.0f, 1, 3); /* increment in steps of 0.01. Show 3 digit after point */ + RNA_def_property_ui_text(prop, "Expected Zoom", + "Explicitly scale resulting frame to compensate zoom of original shot"); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); /* autoscale */ prop = RNA_def_property(srna, "use_autoscale", PROP_BOOLEAN, PROP_NONE); @@ -1705,13 +1811,6 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Scale Influence", "Influence of stabilization algorithm on footage scale"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); - /* use_stabilize_rotation */ - prop = RNA_def_property(srna, "use_stabilize_rotation", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_STABILIZE_ROTATION); - RNA_def_property_ui_text(prop, "Stabilize Rotation", "Stabilize horizon line on the shot"); - RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); - /* influence_rotation */ prop = RNA_def_property(srna, "influence_rotation", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "rotinf"); @@ -1723,8 +1822,16 @@ static void rna_def_trackingStabilization(BlenderRNA *brna) prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "filter"); RNA_def_property_enum_items(prop, filter_items); - RNA_def_property_ui_text(prop, "Filter", "Method to use to filter stabilization"); + RNA_def_property_ui_text(prop, "Interpolate", + "Interpolation to use for sub-pixel shifts and rotations due to stabilization"); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_tracking_flushUpdate"); + + /* UI display : show participating tracks */ + prop = RNA_def_property(srna, "show_tracks_expanded", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_SHOW_STAB_TRACKS); + RNA_def_property_ui_text(prop, "Show Tracks", "Show UI list of tracks participating in stabilization"); + RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); } static void rna_def_reconstructedCamera(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 289019fddde..4488d1b25ee 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -292,11 +292,13 @@ static void rna_userdef_autokeymode_set(PointerRNA *ptr, int value) } } +#ifdef WITH_INPUT_NDOF static void rna_userdef_ndof_deadzone_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { UserDef *userdef = ptr->data; WM_ndof_deadzone_set(userdef->ndof_deadzone); } +#endif static void rna_userdef_timecode_style_set(PointerRNA *ptr, int value) { @@ -4329,6 +4331,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; +#ifdef WITH_INPUT_NDOF static EnumPropertyItem ndof_view_navigation_items[] = { {0, "FREE", 0, "Free", "Use full 6 degrees of freedom by default"}, {NDOF_MODE_ORBIT, "ORBIT", 0, "Orbit", "Orbit about the view center by default"}, @@ -4340,6 +4343,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) {0, "TRACKBALL", 0, "Trackball", "Use trackball style rotation in the viewport"}, {0, NULL, 0, NULL, NULL} }; +#endif /* WITH_INPUT_NDOF */ static EnumPropertyItem view_zoom_styles[] = { {USER_ZOOM_CONT, "CONTINUE", 0, "Continue", "Old style zoom, continues while moving mouse up or down"}, @@ -4417,6 +4421,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Tweak Threshold", "Number of pixels you have to drag before tweak event is triggered"); +#ifdef WITH_INPUT_NDOF /* 3D mouse settings */ /* global options */ prop = RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE); @@ -4497,6 +4502,13 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER); RNA_def_property_ui_text(prop, "Helicopter Mode", "Device up/down directly controls your Z position"); + /* let Python know whether NDOF is enabled */ + prop = RNA_def_boolean(srna, "use_ndof", true, "", ""); +#else + prop = RNA_def_boolean(srna, "use_ndof", false, "", ""); +#endif /* WITH_INPUT_NDOF */ + RNA_def_property_flag(prop, PROP_IDPROPERTY); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); prop = RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dbl_click_time"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 026d2e209a3..f97f194033c 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -167,7 +167,7 @@ static EnumPropertyItem event_ndof_type_items[] = { {NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "Button C", ""}, {0, NULL, 0, NULL, NULL} }; -#endif +#endif /* RNA_RUNTIME */ /* not returned: CAPSLOCKKEY, UNKNOWNKEY */ EnumPropertyItem rna_enum_event_type_items[] = { diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index c2a84bb0ef2..0b99aa55c8d 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -122,19 +122,11 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, { ClothModifierData *clmd = (ClothModifierData *) md; - Base *base; - if (clmd) { - for (base = scene->base.first; base; base = base->next) { - Object *ob1 = base->object; - if (ob1 != ob) { - CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); - if (coll_clmd) { - DagNode *curNode = dag_get_node(forest, ob1); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Cloth Collision"); - } - } - } + /* Actual code uses get_collisionobjects */ + dag_add_collision_relations(forest, scene, ob, obNode, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision"); + + dag_add_forcefield_relations(forest, scene, ob, obNode, clmd->sim_parms->effector_weights, true, 0, "Cloth Field"); } } @@ -146,16 +138,10 @@ static void updateDepsgraph(ModifierData *md, { ClothModifierData *clmd = (ClothModifierData *)md; if (clmd != NULL) { - Base *base; - for (base = scene->base.first; base; base = base->next) { - Object *ob1 = base->object; - if (ob1 != ob) { - CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); - if (coll_clmd) { - DEG_add_object_relation(node, ob1, DEG_OB_COMP_TRANSFORM, "Cloth Modifier"); - } - } - } + /* Actual code uses get_collisionobjects */ + DEG_add_collision_relations(node, scene, ob, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision"); + + DEG_add_forcefield_relations(node, scene, ob, clmd->sim_parms->effector_weights, true, 0, "Cloth Field"); } } diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index edf959f42c6..bde20e56748 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -114,6 +114,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, return dm; } +static bool is_brush_cb(Object *UNUSED(ob), ModifierData *pmd) +{ + return ((DynamicPaintModifierData*)pmd)->brush != NULL; +} + static void updateDepgraph(ModifierData *md, DagForest *forest, struct Main *UNUSED(bmain), struct Scene *scene, @@ -124,16 +129,13 @@ static void updateDepgraph(ModifierData *md, DagForest *forest, /* add relation from canvases to all brush objects */ if (pmd && pmd->canvas) { - Base *base = scene->base.first; - - for (; base; base = base->next) { - DynamicPaintModifierData *pmd2 = - (DynamicPaintModifierData *)modifiers_findByType(base->object, eModifierType_DynamicPaint); - - if (pmd2 && pmd2->brush && ob != base->object) { - DagNode *brushNode = dag_get_node(forest, base->object); - dag_add_relation(forest, brushNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Dynamic Paint Brush"); + for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) { + if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) { + dag_add_forcefield_relations(forest, scene, ob, obNode, surface->effector_weights, true, 0, "Dynamic Paint Field"); } + + /* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */ + dag_add_collision_relations(forest, scene, ob, obNode, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush"); } } } @@ -147,13 +149,13 @@ static void updateDepsgraph(ModifierData *md, DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; /* Add relation from canvases to all brush objects. */ if (pmd->canvas != NULL) { - Base *base = scene->base.first; - for (; base; base = base->next) { - DynamicPaintModifierData *pmd2 = - (DynamicPaintModifierData *)modifiers_findByType(base->object, eModifierType_DynamicPaint); - if (pmd2 && pmd2->brush && ob != base->object) { - DEG_add_object_relation(node, base->object, DEG_OB_COMP_TRANSFORM, "Dynamic Paint Brush"); + for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) { + if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) { + DEG_add_forcefield_relations(node, scene, ob, surface->effector_weights, true, 0, "Dynamic Paint Field"); } + + /* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */ + DEG_add_collision_relations(node, scene, ob, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush"); } } } diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index 237d4cc6718..f04d7432a8f 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -117,219 +117,48 @@ static bool dependsOnTime(ModifierData *UNUSED(md)) return true; } -static void update_depsgraph_flow_coll_object(DagForest *forest, - DagNode *obNode, - Object *object2) +static bool is_flow_cb(Object *UNUSED(ob), ModifierData *md) { - SmokeModifierData *smd; - if ((object2->id.tag & LIB_TAG_DOIT) == 0) { - return; - } - object2->id.tag &= ~LIB_TAG_DOIT; - smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke); - if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) || - ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll))) - { - DagNode *curNode = dag_get_node(forest, object2); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Flow/Coll"); - } - if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { - GroupObject *go; - for (go = object2->dup_group->gobject.first; - go != NULL; - go = go->next) - { - if (go->ob == NULL) { - continue; - } - update_depsgraph_flow_coll_object(forest, obNode, go->ob); - } - } + SmokeModifierData *smd = (SmokeModifierData *) md; + return (smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow; } -static void update_depsgraph_field_source_object(DagForest *forest, - DagNode *obNode, - Object *object, - Object *object2) +static bool is_coll_cb(Object *UNUSED(ob), ModifierData *md) { - if ((object2->id.tag & LIB_TAG_DOIT) == 0) { - return; - } - object2->id.tag &= ~LIB_TAG_DOIT; - if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) { - DagNode *node2 = dag_get_node(forest, object2); - dag_add_relation(forest, obNode, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Source Object"); - } - if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { - GroupObject *go; - for (go = object2->dup_group->gobject.first; - go != NULL; - go = go->next) - { - if (go->ob == NULL) { - continue; - } - update_depsgraph_field_source_object(forest, obNode, object, go->ob); - } - } + SmokeModifierData *smd = (SmokeModifierData *) md; + return (smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll; } static void updateDepgraph(ModifierData *md, DagForest *forest, - struct Main *bmain, + struct Main *UNUSED(bmain), struct Scene *scene, struct Object *ob, DagNode *obNode) { SmokeModifierData *smd = (SmokeModifierData *) md; - Base *base; if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { - if (smd->domain->fluid_group || smd->domain->coll_group) { - GroupObject *go = NULL; - - if (smd->domain->fluid_group) - for (go = smd->domain->fluid_group->gobject.first; go; go = go->next) { - if (go->ob) { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); - - /* check for initialized smoke object */ - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) { - DagNode *curNode = dag_get_node(forest, go->ob); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Flow"); - } - } - } - - if (smd->domain->coll_group) - for (go = smd->domain->coll_group->gobject.first; go; go = go->next) { - if (go->ob) { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); - - /* check for initialized smoke object */ - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) { - DagNode *curNode = dag_get_node(forest, go->ob); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Smoke Coll"); - } - } - } - } - else { - BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - base = scene->base.first; - for (; base; base = base->next) { - update_depsgraph_flow_coll_object(forest, obNode, base->object); - } - } - /* add relation to all "smoke flow" force fields */ - base = scene->base.first; - BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - for (; base; base = base->next) { - update_depsgraph_field_source_object(forest, obNode, ob, base->object); - } - } -} + /* Actual code uses get_collisionobjects */ + dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow"); + dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll"); -static void update_depsgraph_flow_coll_object_new(struct DepsNodeHandle *node, - Object *object2) -{ - SmokeModifierData *smd; - if ((object2->id.tag & LIB_TAG_DOIT) == 0) { - return; - } - object2->id.tag &= ~LIB_TAG_DOIT; - smd = (SmokeModifierData *)modifiers_findByType(object2, eModifierType_Smoke); - if (smd && (((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) || - ((smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll))) - { - DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Smoke Flow/Coll"); - DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Smoke Flow/Coll"); - } - if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { - GroupObject *go; - for (go = object2->dup_group->gobject.first; - go != NULL; - go = go->next) - { - if (go->ob == NULL) { - continue; - } - update_depsgraph_flow_coll_object_new(node, go->ob); - } - } -} - -static void update_depsgraph_field_source_object_new(struct DepsNodeHandle *node, - Object *object, - Object *object2) -{ - if ((object2->id.tag & LIB_TAG_DOIT) == 0) { - return; - } - object2->id.tag &= ~LIB_TAG_DOIT; - if (object2->pd && object2->pd->forcefield == PFIELD_SMOKEFLOW && object2->pd->f_source == object) { - DEG_add_object_relation(node, object2, DEG_OB_COMP_TRANSFORM, "Field Source Object"); - DEG_add_object_relation(node, object2, DEG_OB_COMP_GEOMETRY, "Field Source Object"); - } - if ((object2->transflag & OB_DUPLIGROUP) && object2->dup_group) { - GroupObject *go; - for (go = object2->dup_group->gobject.first; - go != NULL; - go = go->next) - { - if (go->ob == NULL) { - continue; - } - update_depsgraph_field_source_object_new(node, object, go->ob); - } + dag_add_forcefield_relations(forest, scene, ob, obNode, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field"); } } static void updateDepsgraph(ModifierData *md, - struct Main *bmain, + struct Main *UNUSED(bmain), struct Scene *scene, Object *ob, struct DepsNodeHandle *node) { SmokeModifierData *smd = (SmokeModifierData *)md; - Base *base; + if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { - if (smd->domain->fluid_group || smd->domain->coll_group) { - GroupObject *go = NULL; - if (smd->domain->fluid_group != NULL) { - for (go = smd->domain->fluid_group->gobject.first; go; go = go->next) { - if (go->ob != NULL) { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); - /* Check for initialized smoke object. */ - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) { - DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Flow"); - } - } - } - } - if (smd->domain->coll_group != NULL) { - for (go = smd->domain->coll_group->gobject.first; go; go = go->next) { - if (go->ob != NULL) { - SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); - /* Check for initialized smoke object. */ - if (smd2 && (smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll) { - DEG_add_object_relation(node, go->ob, DEG_OB_COMP_TRANSFORM, "Smoke Coll"); - } - } - } - } - } - else { - BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - base = scene->base.first; - for (; base; base = base->next) { - update_depsgraph_flow_coll_object_new(node, base->object); - } - } - /* add relation to all "smoke flow" force fields */ - base = scene->base.first; - BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); - for (; base; base = base->next) { - update_depsgraph_field_source_object_new(node, ob, base->object); - } + /* Actual code uses get_collisionobjects */ + DEG_add_collision_relations(node, scene, ob, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow"); + DEG_add_collision_relations(node, scene, ob, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll"); + + DEG_add_forcefield_relations(node, scene, ob, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field"); } } diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index 7235a19a65e..101f5a4f619 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -36,12 +36,16 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_object_force.h" #include "BLI_utildefines.h" #include "BKE_cdderivedmesh.h" #include "BKE_softbody.h" +#include "depsgraph_private.h" +#include "DEG_depsgraph_build.h" + #include "MOD_modifiertypes.h" static void deformVerts(ModifierData *md, Object *ob, @@ -58,6 +62,31 @@ static bool dependsOnTime(ModifierData *UNUSED(md)) return true; } +static void updateDepgraph(ModifierData *UNUSED(md), DagForest *forest, + struct Main *UNUSED(bmain), + Scene *scene, Object *ob, DagNode *obNode) +{ + if (ob->soft) { + /* Actual code uses ccd_build_deflector_hash */ + dag_add_collision_relations(forest, scene, ob, obNode, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision"); + + dag_add_forcefield_relations(forest, scene, ob, obNode, ob->soft->effector_weights, true, 0, "Softbody Field"); + } +} + +static void updateDepsgraph(ModifierData *UNUSED(md), + struct Main *UNUSED(bmain), + struct Scene *scene, + Object *ob, + struct DepsNodeHandle *node) +{ + if (ob->soft) { + /* Actual code uses ccd_build_deflector_hash */ + DEG_add_collision_relations(node, scene, ob, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision"); + + DEG_add_forcefield_relations(node, scene, ob, ob->soft->effector_weights, true, 0, "Softbody Field"); + } +} ModifierTypeInfo modifierType_Softbody = { /* name */ "Softbody", @@ -80,8 +109,8 @@ ModifierTypeInfo modifierType_Softbody = { /* requiredDataMask */ NULL, /* freeData */ NULL, /* isDisabled */ NULL, - /* updateDepgraph */ NULL, - /* updateDepsgraph */ NULL, + /* updateDepgraph */ updateDepgraph, + /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 01188cb7f65..b6245a8c0d1 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -146,6 +146,10 @@ if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) endif() +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif() + if(WIN32) if(WITH_INPUT_IME) add_definitions(-DWITH_INPUT_IME) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 69905fc296b..2b82f1becb3 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -64,7 +64,10 @@ struct wmDrag; struct ImBuf; struct ImageFormatData; struct ARegion; + +#ifdef WITH_INPUT_NDOF struct wmNDOFMotionData; +#endif typedef struct wmJob wmJob; @@ -186,9 +189,10 @@ void WM_event_add_mousemove(struct bContext *C); bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event); bool WM_event_is_absolute(const struct wmEvent *event); +#ifdef WITH_INPUT_NDOF /* 3D mouse */ void WM_ndof_deadzone_set(float deadzone); - +#endif /* notifiers */ void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference); void WM_main_add_notifier(unsigned int type, void *reference); @@ -498,11 +502,13 @@ bool write_crash_blend(void); /* Lock the interface for any communication */ void WM_set_locked_interface(struct wmWindowManager *wm, bool lock); +#ifdef WITH_INPUT_NDOF void WM_event_ndof_pan_get(const struct wmNDOFMotionData *ndof, float r_pan[3], const bool use_zoom); void WM_event_ndof_rotate_get(const struct wmNDOFMotionData *ndof, float r_rot[3]); float WM_event_ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]); void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]); +#endif /* WITH_INPUT_NDOF */ float WM_event_tablet_data(const struct wmEvent *event, int *pen_flip, float tilt[2]); bool WM_event_is_tablet(const struct wmEvent *event); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 1ab530fe66b..ce4a69a1841 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -485,6 +485,7 @@ typedef enum { /* motion progress, for modal handlers */ P_FINISHED } wmProgress; +#ifdef WITH_INPUT_NDOF typedef struct wmNDOFMotionData { /* awfully similar to GHOST_TEventNDOFMotionData... */ /* Each component normally ranges from -1 to +1, but can exceed that. @@ -496,6 +497,7 @@ typedef struct wmNDOFMotionData { float dt; /* time since previous NDOF Motion event */ wmProgress progress; /* is this the first event, the last, or one of many in between? */ } wmNDOFMotionData; +#endif /* WITH_INPUT_NDOF */ typedef struct wmTimer { struct wmTimer *next, *prev; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 751e714a456..cf93e84d0a1 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -565,6 +565,7 @@ void WM_event_print(const wmEvent *event) BLI_str_utf8_size(event->utf8_buf), event->utf8_buf, event->keymap_idname, (const void *)event); +#ifdef WITH_INPUT_NDOF if (ISNDOF(event->type)) { const wmNDOFMotionData *ndof = event->customdata; if (event->type == NDOF_MOTION) { @@ -575,6 +576,7 @@ void WM_event_print(const wmEvent *event) /* ndof buttons printed already */ } } +#endif /* WITH_INPUT_NDOF */ if (event->tablet_data) { const wmTabletData *wmtab = event->tablet_data; @@ -611,10 +613,12 @@ bool WM_event_is_absolute(const wmEvent *event) return (event->tablet_data != NULL); } +#ifdef WITH_INPUT_NDOF void WM_ndof_deadzone_set(float deadzone) { GHOST_setNDOFDeadZone(deadzone); } +#endif static void wm_add_reports(ReportList *reports) { @@ -2421,9 +2425,11 @@ void wm_event_do_handlers(bContext *C) /* for regions having custom cursors */ wm_paintcursor_test(C, event); } +#ifdef WITH_INPUT_NDOF else if (event->type == NDOF_MOTION) { win->addmousemove = true; } +#endif for (sa = win->screen->areabase.first; sa; sa = sa->next) { /* after restoring a screen from SCREENMAXIMIZED we have to wait @@ -3022,6 +3028,7 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) } } +#ifdef WITH_INPUT_NDOF /* adds customdata to event */ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *ghost) { @@ -3048,6 +3055,7 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g event->customdata = data; event->customdatafree = 1; } +#endif /* WITH_INPUT_NDOF */ /* imperfect but probably usable... draw/enable drags to other windows */ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event) @@ -3435,6 +3443,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } +#ifdef WITH_INPUT_NDOF case GHOST_kEventNDOFMotion: { event.type = NDOF_MOTION; @@ -3470,6 +3479,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } +#endif /* WITH_INPUT_NDOF */ case GHOST_kEventUnknown: case GHOST_kNumEventTypes: @@ -3541,6 +3551,7 @@ void WM_set_locked_interface(wmWindowManager *wm, bool lock) } +#ifdef WITH_INPUT_NDOF /* -------------------------------------------------------------------- */ /* NDOF */ @@ -3583,6 +3594,7 @@ void WM_event_ndof_to_quat(const struct wmNDOFMotionData *ndof, float q[4]) angle = WM_event_ndof_to_axis_angle(ndof, axis); axis_angle_to_quat(q, axis, angle); } +#endif /* WITH_INPUT_NDOF */ /* if this is a tablet event, return tablet pressure and set *pen_flip * to 1 if the eraser tool is being used, 0 otherwise */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 3022d865460..73622cda483 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -198,8 +198,11 @@ void WM_init(bContext *C, int argc, const char **argv) BLT_lang_set(NULL); if (!G.background) { + +#ifdef WITH_INPUT_NDOF /* sets 3D mouse deadzone */ WM_ndof_deadzone_set(U.ndof_deadzone); +#endif GPU_init(); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 78273615602..fcdab746d57 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -4348,7 +4348,6 @@ void wm_window_keymap(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_find(keyconf, "Window", 0, 0); wmKeyMapItem *kmi; - const char *data_path; /* note, this doesn't replace existing keymap items */ WM_keymap_verify_item(keymap, "WM_OT_window_duplicate", WKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); @@ -4386,7 +4385,9 @@ void wm_window_keymap(wmKeyConfig *keyconf) /* menus that can be accessed anywhere in blender */ WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); +#ifdef WITH_INPUT_NDOF WM_keymap_add_menu(keymap, "USERPREF_MT_ndof_settings", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); +#endif /* Space switching */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F2KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was DXF export */ @@ -4433,8 +4434,9 @@ void wm_window_keymap(wmKeyConfig *keyconf) RNA_string_set(kmi->ptr, "data_path", "area.type"); RNA_string_set(kmi->ptr, "value", "DOPESHEET_EDITOR"); +#ifdef WITH_INPUT_NDOF /* ndof speed */ - data_path = "user_preferences.inputs.ndof_sensitivity"; + const char *data_path = "user_preferences.inputs.ndof_sensitivity"; kmi = WM_keymap_add_item(keymap, "WM_OT_context_scale_float", NDOF_BUTTON_PLUS, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path", data_path); RNA_float_set(kmi->ptr, "value", 1.1f); @@ -4450,9 +4452,7 @@ void wm_window_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "WM_OT_context_scale_float", NDOF_BUTTON_MINUS, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", data_path); RNA_float_set(kmi->ptr, "value", 1.0f / 1.5f); - data_path = NULL; - (void)data_path; - +#endif /* WITH_INPUT_NDOF */ gesture_circle_modal_keymap(keyconf); gesture_border_modal_keymap(keyconf); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 425287993d9..2d43c47679d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1197,23 +1197,26 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr } case GHOST_kEventNativeResolutionChange: { - // printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin)); - + // only update if the actual pixel size changes + float prev_pixelsize = U.pixelsize; U.pixelsize = wm_window_pixelsize(win); - 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); - CTX_wm_window_set(C, win); - UI_popup_handlers_remove_all(C, &win->modalhandlers); - CTX_wm_window_set(C, oldWindow); + if (U.pixelsize != prev_pixelsize) { + BKE_blender_userdef_refresh(); - wm_window_make_drawable(wm, win); - wm_draw_window_clear(win); + // 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); + CTX_wm_window_set(C, win); + UI_popup_handlers_remove_all(C, &win->modalhandlers); + CTX_wm_window_set(C, oldWindow); + + wm_window_make_drawable(wm, win); + wm_draw_window_clear(win); - WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); - WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); + } break; } diff --git a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt index 1d681d28589..0e570e19258 100644 --- a/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt +++ b/source/blenderplayer/bad_level_call_stubs/CMakeLists.txt @@ -70,4 +70,8 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif() + blender_add_lib_nolist(blenkernel_blc "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 877403e8b1a..20d3697053b 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -335,7 +335,9 @@ void WM_jobs_callbacks(struct wmJob *job, void WM_jobs_start(struct wmWindowManager *wm, struct wmJob *job) RET_NONE void WM_report(ReportType type, const char *message) RET_NONE -void WM_ndof_deadzone_set(float deadzone) RET_NONE +#ifdef WITH_INPUT_NDOF + void WM_ndof_deadzone_set(float deadzone) RET_NONE +#endif void WM_uilisttype_init(void) RET_NONE struct uiListType *WM_uilisttype_find(const char *idname, bool quiet) RET_NULL diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp index b8907ca5c6b..5beda2e038a 100644 --- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp +++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp @@ -306,7 +306,12 @@ bool KX_NavMeshObject::BuildNavMesh() || vertsPerPoly<3) { printf("Can't build navigation mesh data for object:%s\n", m_name.ReadPtr()); - if (vertices) delete[] vertices; + if (vertices) { + delete[] vertices; + } + if (dvertices) { + delete[] dvertices; + } return false; } |