Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorDalai Felinto <dfelinto@gmail.com>2016-11-02 12:48:06 +0300
committerDalai Felinto <dfelinto@gmail.com>2016-11-02 12:59:52 +0300
commita41bbd3053c8f07c24ccb07eaeff09cc078cc4d4 (patch)
treeaed76b27fa7b6fde5023b6d3ecd5f5079ed24aad /source
parentfb6f42dc4f0dc24a992a631b7aac3290449e815a (diff)
parent13ee9b8ebe08ee95478f51537f10e9a1b1e4d863 (diff)
Merge remote-tracking branch 'origin/master' into blender2.8
Diffstat (limited to 'source')
-rw-r--r--source/blender/alembic/ABC_alembic.h15
-rw-r--r--source/blender/alembic/intern/abc_camera.cc4
-rw-r--r--source/blender/alembic/intern/abc_curves.cc52
-rw-r--r--source/blender/alembic/intern/abc_curves.h3
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc307
-rw-r--r--source/blender/alembic/intern/abc_mesh.h11
-rw-r--r--source/blender/alembic/intern/abc_object.cc63
-rw-r--r--source/blender/alembic/intern/abc_object.h22
-rw-r--r--source/blender/alembic/intern/abc_points.cc32
-rw-r--r--source/blender/alembic/intern/abc_points.h2
-rw-r--r--source/blender/alembic/intern/abc_util.cc62
-rw-r--r--source/blender/alembic/intern/abc_util.h7
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc340
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h2
-rw-r--r--source/blender/blenkernel/BKE_icons.h1
-rw-r--r--source/blender/blenkernel/BKE_library.h4
-rw-r--r--source/blender/blenkernel/BKE_object_deform.h2
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c4
-rw-r--r--source/blender/blenkernel/intern/cachefile.c41
-rw-r--r--source/blender/blenkernel/intern/constraint.c16
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c4
-rw-r--r--source/blender/blenkernel/intern/icons.c20
-rw-r--r--source/blender/blenkernel/intern/image.c19
-rw-r--r--source/blender/blenkernel/intern/library.c7
-rw-r--r--source/blender/blenkernel/intern/object_deform.c22
-rw-r--r--source/blender/blenkernel/intern/smoke.c11
-rw-r--r--source/blender/blenkernel/intern/tracking.c8
-rw-r--r--source/blender/blenlib/BLI_bitmap_draw_2d.h37
-rw-r--r--source/blender/blenlib/BLI_math_geom.h5
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c2
-rw-r--r--source/blender/blenlib/intern/astar.c2
-rw-r--r--source/blender/blenlib/intern/bitmap_draw_2d.c331
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c2
-rw-r--r--source/blender/blenlib/intern/math_geom.c136
-rw-r--r--source/blender/blenlib/intern/path_util.c2
-rw-r--r--source/blender/blenlib/intern/smallhash.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c5
-rw-r--r--source/blender/bmesh/bmesh_class.h2
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c77
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c85
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h5
-rw-r--r--source/blender/compositor/operations/COM_SunBeamsOperation.cpp4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc3
-rw-r--r--source/blender/editors/animation/anim_ops.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c56
-rw-r--r--source/blender/editors/interface/interface_icons.c2
-rw-r--r--source/blender/editors/interface/interface_templates.c3
-rw-r--r--source/blender/editors/io/io_alembic.c20
-rw-r--r--source/blender/editors/io/io_cache.c4
-rw-r--r--source/blender/editors/mesh/editmesh_select.c3
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/object/object_vgroup.c3
-rw-r--r--source/blender/editors/render/render_preview.c31
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c3
-rw-r--r--source/blender/editors/space_view3d/drawobject.c4
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c187
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h6
-rw-r--r--source/blender/gpu/GPU_shader.h1
-rw-r--r--source/blender/gpu/intern/gpu_shader.c13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl12
-rw-r--r--source/blender/makesdna/DNA_ID.h13
-rw-r--r--source/blender/makesdna/DNA_cachefile_types.h2
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h1
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h1
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h23
-rw-r--r--source/blender/makesrna/intern/rna_cachefile.c23
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c23
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c17
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c48
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c17
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c7
-rw-r--r--source/blender/physics/intern/hair_volume.cpp4
-rw-r--r--source/blender/python/intern/bpy_library_load.c7
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c12
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c4
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c3
82 files changed, 1500 insertions, 851 deletions
diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h
index e62713f57f5..e92d5f2d9f7 100644
--- a/source/blender/alembic/ABC_alembic.h
+++ b/source/blender/alembic/ABC_alembic.h
@@ -28,6 +28,7 @@ extern "C" {
#endif
struct bContext;
+struct CacheReader;
struct DerivedMesh;
struct ListBase;
struct Object;
@@ -92,21 +93,25 @@ AbcArchiveHandle *ABC_create_handle(const char *filename, struct ListBase *objec
void ABC_free_handle(AbcArchiveHandle *handle);
-void ABC_get_transform(AbcArchiveHandle *handle,
- struct Object *ob,
- const char *object_path,
+void ABC_get_transform(struct CacheReader *reader,
float r_mat[4][4],
float time,
float scale);
-struct DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
+struct DerivedMesh *ABC_read_mesh(struct CacheReader *reader,
struct Object *ob,
struct DerivedMesh *dm,
- const char *object_path,
const float time,
const char **err_str,
int flags);
+void CacheReader_free(struct CacheReader *reader);
+
+struct CacheReader *CacheReader_open_alembic_object(struct AbcArchiveHandle *handle,
+ struct CacheReader *reader,
+ struct Object *object,
+ const char *object_path);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_camera.cc
index 5c34ec1391f..d5271e3ca31 100644
--- a/source/blender/alembic/intern/abc_camera.cc
+++ b/source/blender/alembic/intern/abc_camera.cc
@@ -119,7 +119,7 @@ bool AbcCameraReader::valid() const
void AbcCameraReader::readObjectData(Main *bmain, float time)
{
- Camera *bcam = static_cast<Camera *>(BKE_camera_add(bmain, "abc_camera"));
+ Camera *bcam = static_cast<Camera *>(BKE_camera_add(bmain, m_data_name.c_str()));
ISampleSelector sample_sel(time);
CameraSample cam_sample;
@@ -155,8 +155,6 @@ void AbcCameraReader::readObjectData(Main *bmain, float time)
bcam->gpu_dof.focus_distance = cam_sample.getFocusDistance();
bcam->gpu_dof.fstop = cam_sample.getFStop();
- BLI_strncpy(bcam->id.name + 2, m_data_name.c_str(), m_data_name.size() + 1);
-
m_object = BKE_object_add_only_object(bmain, OB_CAMERA, m_object_name.c_str());
m_object->data = bcam;
}
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc
index 2b54741a5c5..7e5ea3b1853 100644
--- a/source/blender/alembic/intern/abc_curves.cc
+++ b/source/blender/alembic/intern/abc_curves.cc
@@ -37,6 +37,7 @@ extern "C" {
#include "BLI_listbase.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_curve.h"
#include "BKE_object.h"
@@ -353,3 +354,54 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
BLI_addtail(BKE_curve_nurbs_get(cu), nu);
}
}
+
+/* NOTE: Alembic only stores data about control points, but the DerivedMesh
+ * passed from the cache modifier contains the displist, which has more data
+ * than the control points, so to avoid corrupting the displist we modify the
+ * object directly and create a new DerivedMesh from that. Also we might need to
+ * create new or delete existing NURBS in the curve.
+ */
+DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float time, int /*read_flag*/)
+{
+ ISampleSelector sample_sel(time);
+ const ICurvesSchema::Sample sample = m_curves_schema.getValue(sample_sel);
+
+ const P3fArraySamplePtr &positions = sample.getPositions();
+ const Int32ArraySamplePtr num_vertices = sample.getCurvesNumVertices();
+
+ int vertex_idx = 0;
+ int curve_idx = 0;
+ Curve *curve = static_cast<Curve *>(m_object->data);
+
+ const int curve_count = BLI_listbase_count(&curve->nurb);
+
+ if (curve_count != num_vertices->size()) {
+ BKE_nurbList_free(&curve->nurb);
+ read_curve_sample(curve, m_curves_schema, time);
+ }
+ else {
+ Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
+ for (; nurbs; nurbs = nurbs->next, ++curve_idx) {
+ const int totpoint = (*num_vertices)[curve_idx];
+
+ if (nurbs->bp) {
+ BPoint *point = nurbs->bp;
+
+ for (int i = 0; i < totpoint; ++i, ++point, ++vertex_idx) {
+ const Imath::V3f &pos = (*positions)[vertex_idx];
+ copy_yup_zup(point->vec, pos.getValue());
+ }
+ }
+ else if (nurbs->bezt) {
+ BezTriple *bezier = nurbs->bezt;
+
+ for (int i = 0; i < totpoint; ++i, ++bezier, ++vertex_idx) {
+ const Imath::V3f &pos = (*positions)[vertex_idx];
+ copy_yup_zup(bezier->vec[1], pos.getValue());
+ }
+ }
+ }
+ }
+
+ return CDDM_from_curve(m_object);
+}
diff --git a/source/blender/alembic/intern/abc_curves.h b/source/blender/alembic/intern/abc_curves.h
index ee47f1931ea..979ee8af639 100644
--- a/source/blender/alembic/intern/abc_curves.h
+++ b/source/blender/alembic/intern/abc_curves.h
@@ -56,10 +56,11 @@ public:
bool valid() const;
void readObjectData(Main *bmain, float time);
+ DerivedMesh *read_derivedmesh(DerivedMesh *, const float time, int);
};
/* ************************************************************************** */
void read_curve_sample(Curve *cu, const Alembic::AbcGeom::ICurvesSchema &schema, const float time);
-#endif /* __ABC_CURVES_H__ */ \ No newline at end of file
+#endif /* __ABC_CURVES_H__ */
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index 9b19a063e4e..3d80756fcca 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -646,75 +646,6 @@ void AbcMeshWriter::getGeoGroups(
/* Some helpers for mesh generation */
namespace utils {
-void mesh_add_verts(Mesh *mesh, size_t len)
-{
- if (len == 0) {
- return;
- }
-
- const int totvert = mesh->totvert + len;
- CustomData vdata;
- CustomData_copy(&mesh->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert);
- CustomData_copy_data(&mesh->vdata, &vdata, 0, 0, mesh->totvert);
-
- if (!CustomData_has_layer(&vdata, CD_MVERT)) {
- CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
- }
-
- CustomData_free(&mesh->vdata, mesh->totvert);
- mesh->vdata = vdata;
- BKE_mesh_update_customdata_pointers(mesh, false);
-
- mesh->totvert = totvert;
-}
-
-static void mesh_add_mloops(Mesh *mesh, size_t len)
-{
- if (len == 0) {
- return;
- }
-
- /* new face count */
- const int totloops = mesh->totloop + len;
-
- CustomData ldata;
- CustomData_copy(&mesh->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloops);
- CustomData_copy_data(&mesh->ldata, &ldata, 0, 0, mesh->totloop);
-
- if (!CustomData_has_layer(&ldata, CD_MLOOP)) {
- CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloops);
- }
-
- CustomData_free(&mesh->ldata, mesh->totloop);
- mesh->ldata = ldata;
- BKE_mesh_update_customdata_pointers(mesh, false);
-
- mesh->totloop = totloops;
-}
-
-static void mesh_add_mpolygons(Mesh *mesh, size_t len)
-{
- if (len == 0) {
- return;
- }
-
- const int totpolys = mesh->totpoly + len;
-
- CustomData pdata;
- CustomData_copy(&mesh->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpolys);
- CustomData_copy_data(&mesh->pdata, &pdata, 0, 0, mesh->totpoly);
-
- if (!CustomData_has_layer(&pdata, CD_MPOLY)) {
- CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpolys);
- }
-
- CustomData_free(&mesh->pdata, mesh->totpoly);
- mesh->pdata = pdata;
- BKE_mesh_update_customdata_pointers(mesh, false);
-
- mesh->totpoly = totpolys;
-}
-
static void build_mat_map(const Main *bmain, std::map<std::string, Material *> &mat_map)
{
Material *material = static_cast<Material *>(bmain->mat.first);
@@ -786,45 +717,6 @@ struct AbcMeshData {
UInt32ArraySamplePtr uvs_indices;
};
-static void *add_customdata_cb(void *user_data, const char *name, int data_type)
-{
- Mesh *mesh = static_cast<Mesh *>(user_data);
- CustomDataType cd_data_type = static_cast<CustomDataType>(data_type);
- void *cd_ptr = NULL;
-
- int index = -1;
- if (cd_data_type == CD_MLOOPUV) {
- index = ED_mesh_uv_texture_add(mesh, name, true);
- cd_ptr = CustomData_get_layer(&mesh->ldata, cd_data_type);
- }
- else if (cd_data_type == CD_MLOOPCOL) {
- index = ED_mesh_color_add(mesh, name, true);
- cd_ptr = CustomData_get_layer(&mesh->ldata, cd_data_type);
- }
-
- if (index == -1) {
- return NULL;
- }
-
- return cd_ptr;
-}
-
-CDStreamConfig create_config(Mesh *mesh)
-{
- CDStreamConfig config;
-
- config.mvert = mesh->mvert;
- config.mpoly = mesh->mpoly;
- config.mloop = mesh->mloop;
- config.totpoly = mesh->totpoly;
- config.totloop = mesh->totloop;
- config.user_data = mesh;
- config.loopdata = &mesh->ldata;
- config.add_customdata_cb = add_customdata_cb;
-
- return config;
-}
-
static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions, const P3fArraySamplePtr &ceil_positions, const float weight)
{
float tmp[3];
@@ -1002,23 +894,15 @@ void AbcMeshReader::readObjectData(Main *bmain, float time)
m_object->data = mesh;
const ISampleSelector sample_sel(time);
- const IPolyMeshSchema::Sample sample = m_schema.getValue(sample_sel);
-
- const P3fArraySamplePtr &positions = sample.getPositions();
- const Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
- const Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
-
- utils::mesh_add_verts(mesh, positions->size());
- utils::mesh_add_mpolygons(mesh, face_counts->size());
- utils::mesh_add_mloops(mesh, face_indices->size());
- m_mesh_data = create_config(mesh);
+ DerivedMesh *dm = CDDM_from_mesh(mesh);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL);
- bool has_smooth_normals = false;
- read_mesh_sample(m_settings, m_schema, sample_sel, m_mesh_data, has_smooth_normals);
+ if (ndm != dm) {
+ dm->release(dm);
+ }
- BKE_mesh_calc_normals(mesh);
- BKE_mesh_calc_edges(mesh, false, false);
+ DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
if (m_settings->validate_meshes) {
BKE_mesh_validate(mesh, false, false);
@@ -1031,6 +915,120 @@ void AbcMeshReader::readObjectData(Main *bmain, float time)
}
}
+static bool check_smooth_poly_flag(DerivedMesh *dm)
+{
+ MPoly *mpolys = dm->getPolyArray(dm);
+
+ for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i) {
+ MPoly &poly = mpolys[i];
+
+ if ((poly.flag & ME_SMOOTH) != 0) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void set_smooth_poly_flag(DerivedMesh *dm)
+{
+ MPoly *mpolys = dm->getPolyArray(dm);
+
+ for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i) {
+ MPoly &poly = mpolys[i];
+ poly.flag |= ME_SMOOTH;
+ }
+}
+
+static void *add_customdata_cb(void *user_data, const char *name, int data_type)
+{
+ DerivedMesh *dm = static_cast<DerivedMesh *>(user_data);
+ CustomDataType cd_data_type = static_cast<CustomDataType>(data_type);
+ void *cd_ptr = NULL;
+
+ if (ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) {
+ cd_ptr = CustomData_get_layer_named(dm->getLoopDataLayout(dm), cd_data_type, name);
+
+ if (cd_ptr == NULL) {
+ cd_ptr = CustomData_add_layer_named(dm->getLoopDataLayout(dm),
+ cd_data_type,
+ CD_DEFAULT,
+ NULL,
+ dm->getNumLoops(dm),
+ name);
+ }
+ }
+
+ return cd_ptr;
+}
+
+CDStreamConfig get_config(DerivedMesh *dm)
+{
+ CDStreamConfig config;
+
+ config.user_data = dm;
+ config.mvert = dm->getVertArray(dm);
+ config.mloop = dm->getLoopArray(dm);
+ config.mpoly = dm->getPolyArray(dm);
+ config.totloop = dm->getNumLoops(dm);
+ config.totpoly = dm->getNumPolys(dm);
+ config.loopdata = dm->getLoopDataLayout(dm);
+ config.add_customdata_cb = add_customdata_cb;
+
+ return config;
+}
+
+DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag)
+{
+ ISampleSelector sample_sel(time);
+ const IPolyMeshSchema::Sample sample = m_schema.getValue(sample_sel);
+
+ const P3fArraySamplePtr &positions = sample.getPositions();
+ const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
+ const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
+
+ DerivedMesh *new_dm = NULL;
+
+ /* Only read point data when streaming meshes, unless we need to create new ones. */
+ ImportSettings settings;
+ settings.read_flag |= read_flag;
+
+ if (dm->getNumVerts(dm) != positions->size()) {
+ new_dm = CDDM_from_template(dm,
+ positions->size(),
+ 0,
+ 0,
+ face_indices->size(),
+ face_counts->size());
+
+ settings.read_flag |= MOD_MESHSEQ_READ_ALL;
+ }
+
+ CDStreamConfig config = get_config(new_dm ? new_dm : dm);
+ config.time = time;
+
+ bool do_normals = false;
+ read_mesh_sample(&settings, m_schema, sample_sel, config, do_normals);
+
+ if (new_dm) {
+ /* Check if we had ME_SMOOTH flag set to restore it. */
+ if (!do_normals && check_smooth_poly_flag(dm)) {
+ set_smooth_poly_flag(new_dm);
+ }
+
+ CDDM_calc_normals(new_dm);
+ CDDM_calc_edges(new_dm);
+
+ return new_dm;
+ }
+
+ if (do_normals) {
+ CDDM_calc_normals(dm);
+ }
+
+ return dm;
+}
+
void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
const ISampleSelector &sample_sel)
{
@@ -1178,21 +1176,17 @@ void AbcSubDReader::readObjectData(Main *bmain, float time)
m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
m_object->data = mesh;
- const ISampleSelector sample_sel(time);
- const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
-
- const P3fArraySamplePtr &positions = sample.getPositions();
- const Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
- const Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
-
- utils::mesh_add_verts(mesh, positions->size());
- utils::mesh_add_mpolygons(mesh, face_counts->size());
- utils::mesh_add_mloops(mesh, face_indices->size());
+ DerivedMesh *dm = CDDM_from_mesh(mesh);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL);
- m_mesh_data = create_config(mesh);
+ if (ndm != dm) {
+ dm->release(dm);
+ }
- read_subd_sample(m_settings, m_schema, sample_sel, m_mesh_data);
+ DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
+ const ISampleSelector sample_sel(time);
+ const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
Int32ArraySamplePtr indices = sample.getCreaseIndices();
Alembic::Abc::FloatArraySamplePtr sharpnesses = sample.getCreaseSharpnesses();
@@ -1262,3 +1256,48 @@ void read_subd_sample(ImportSettings *settings,
/* TODO: face sets */
}
+
+DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag)
+{
+ ISampleSelector sample_sel(time);
+ const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
+
+ const P3fArraySamplePtr &positions = sample.getPositions();
+ const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
+ const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
+
+ DerivedMesh *new_dm = NULL;
+
+ ImportSettings settings;
+ settings.read_flag |= read_flag;
+
+ if (dm->getNumVerts(dm) != positions->size()) {
+ new_dm = CDDM_from_template(dm,
+ positions->size(),
+ 0,
+ 0,
+ face_indices->size(),
+ face_counts->size());
+
+ settings.read_flag |= MOD_MESHSEQ_READ_ALL;
+ }
+
+ /* Only read point data when streaming meshes, unless we need to create new ones. */
+ CDStreamConfig config = get_config(new_dm ? new_dm : dm);
+ config.time = time;
+ read_subd_sample(&settings, m_schema, sample_sel, config);
+
+ if (new_dm) {
+ /* Check if we had ME_SMOOTH flag set to restore it. */
+ if (check_smooth_poly_flag(dm)) {
+ set_smooth_poly_flag(new_dm);
+ }
+
+ CDDM_calc_normals(new_dm);
+ CDDM_calc_edges(new_dm);
+
+ return new_dm;
+ }
+
+ return dm;
+}
diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h
index 41abe78f75f..66e6585a3d3 100644
--- a/source/blender/alembic/intern/abc_mesh.h
+++ b/source/blender/alembic/intern/abc_mesh.h
@@ -102,6 +102,8 @@ public:
void readObjectData(Main *bmain, float time);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag);
+
private:
void readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
const Alembic::AbcGeom::ISampleSelector &sample_sel);
@@ -126,6 +128,7 @@ public:
bool valid() const;
void readObjectData(Main *bmain, float time);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag);
};
void read_subd_sample(ImportSettings *settings,
@@ -135,16 +138,10 @@ void read_subd_sample(ImportSettings *settings,
/* ************************************************************************** */
-namespace utils {
-
-void mesh_add_verts(struct Mesh *mesh, size_t len);
-
-}
-
void read_mverts(MVert *mverts,
const Alembic::AbcGeom::P3fArraySamplePtr &positions,
const Alembic::AbcGeom::N3fArraySamplePtr &normals);
-CDStreamConfig create_config(Mesh *mesh);
+CDStreamConfig get_config(DerivedMesh *dm);
#endif /* __ABC_MESH_H__ */
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index 32468fdaded..314b2568bed 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -126,6 +126,7 @@ AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings
, m_settings(&settings)
, m_min_time(std::numeric_limits<chrono_t>::max())
, m_max_time(std::numeric_limits<chrono_t>::min())
+ , m_refcount(0)
{
m_name = object.getFullName();
std::vector<std::string> parts;
@@ -153,6 +154,11 @@ Object *AbcObjectReader::object() const
return m_object;
}
+void AbcObjectReader::object(Object *ob)
+{
+ m_object = ob;
+}
+
static Imath::M44d blend_matrices(const Imath::M44d &m0, const Imath::M44d &m1, const float weight)
{
float mat0[4][4], mat1[4][4], ret[4][4];
@@ -210,6 +216,28 @@ Imath::M44d get_matrix(const IXformSchema &schema, const float time)
void AbcObjectReader::readObjectMatrix(const float time)
{
+ bool is_constant = false;
+
+ this->read_matrix(m_object->obmat, time, m_settings->scale, is_constant);
+ invert_m4_m4(m_object->imat, m_object->obmat);
+
+ BKE_object_apply_mat4(m_object, m_object->obmat, false, false);
+
+ if (!is_constant) {
+ bConstraint *con = BKE_constraint_add_for_object(m_object, NULL, CONSTRAINT_TYPE_TRANSFORM_CACHE);
+ bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
+ BLI_strncpy(data->object_path, m_iobject.getFullName().c_str(), FILE_MAX);
+
+ data->cache_file = m_settings->cache_file;
+ id_us_plus(&data->cache_file->id);
+
+ data->reader = reinterpret_cast<CacheReader *>(this);
+ this->incref();
+ }
+}
+
+void AbcObjectReader::read_matrix(float mat[4][4], const float time, const float scale, bool &is_constant)
+{
IXform ixform;
bool has_alembic_parent = false;
@@ -250,23 +278,12 @@ void AbcObjectReader::readObjectMatrix(const float time)
}
const Imath::M44d matrix = get_matrix(schema, time);
- convert_matrix(matrix, m_object, m_object->obmat, m_settings->scale, has_alembic_parent);
-
- invert_m4_m4(m_object->imat, m_object->obmat);
-
- BKE_object_apply_mat4(m_object, m_object->obmat, false, false);
-
- if (!schema.isConstant()) {
- bConstraint *con = BKE_constraint_add_for_object(m_object, NULL, CONSTRAINT_TYPE_TRANSFORM_CACHE);
- bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
- BLI_strncpy(data->object_path, m_iobject.getFullName().c_str(), FILE_MAX);
+ convert_matrix(matrix, m_object, mat, scale, has_alembic_parent);
- data->cache_file = m_settings->cache_file;
- id_us_plus(&data->cache_file->id);
- }
+ is_constant = schema.isConstant();
}
-void AbcObjectReader::addCacheModifier() const
+void AbcObjectReader::addCacheModifier()
{
ModifierData *md = modifier_new(eModifierType_MeshSequenceCache);
BLI_addtail(&m_object->modifiers, md);
@@ -277,6 +294,9 @@ void AbcObjectReader::addCacheModifier() const
id_us_plus(&mcmd->cache_file->id);
BLI_strncpy(mcmd->object_path, m_iobject.getFullName().c_str(), FILE_MAX);
+
+ mcmd->reader = reinterpret_cast<CacheReader *>(this);
+ this->incref();
}
chrono_t AbcObjectReader::minTime() const
@@ -288,3 +308,18 @@ chrono_t AbcObjectReader::maxTime() const
{
return m_max_time;
}
+
+int AbcObjectReader::refcount() const
+{
+ return m_refcount;
+}
+
+void AbcObjectReader::incref()
+{
+ ++m_refcount;
+}
+
+void AbcObjectReader::decref()
+{
+ --m_refcount;
+}
diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h
index a35faa37565..7ff927b4d33 100644
--- a/source/blender/alembic/intern/abc_object.h
+++ b/source/blender/alembic/intern/abc_object.h
@@ -130,6 +130,8 @@ static bool has_animations(Schema &schema, ImportSettings *settings)
/* ************************************************************************** */
+struct DerivedMesh;
+
using Alembic::AbcCoreAbstract::chrono_t;
class AbcObjectReader {
@@ -145,6 +147,10 @@ protected:
chrono_t m_min_time;
chrono_t m_max_time;
+ /* Use reference counting since the same reader may be used by multiple
+ * modifiers and/or constraints. */
+ int m_refcount;
+
public:
explicit AbcObjectReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
@@ -153,17 +159,31 @@ public:
const Alembic::Abc::IObject &iobject() const;
Object *object() const;
+ void object(Object *ob);
virtual bool valid() const = 0;
virtual void readObjectData(Main *bmain, float time) = 0;
+ virtual DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag)
+ {
+ (void)time;
+ (void)read_flag;
+ return dm;
+ }
+
void readObjectMatrix(const float time);
- void addCacheModifier() const;
+ void addCacheModifier();
chrono_t minTime() const;
chrono_t maxTime() const;
+
+ int refcount() const;
+ void incref();
+ void decref();
+
+ void read_matrix(float mat[4][4], const float time, const float scale, bool &is_constant);
};
Imath::M44d get_matrix(const Alembic::AbcGeom::IXformSchema &schema, const float time);
diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc
index bf9c483901d..291a19bd2d5 100644
--- a/source/blender/alembic/intern/abc_points.cc
+++ b/source/blender/alembic/intern/abc_points.cc
@@ -32,6 +32,7 @@ extern "C" {
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
@@ -156,14 +157,14 @@ void AbcPointsReader::readObjectData(Main *bmain, float time)
{
Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
- const ISampleSelector sample_sel(time);
- m_sample = m_schema.getValue(sample_sel);
+ DerivedMesh *dm = CDDM_from_mesh(mesh);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, time, 0);
- const P3fArraySamplePtr &positions = m_sample.getPositions();
- utils::mesh_add_verts(mesh, positions->size());
+ if (ndm != dm) {
+ dm->release(dm);
+ }
- CDStreamConfig config = create_config(mesh);
- read_points_sample(m_schema, sample_sel, config, time);
+ DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
if (m_settings->validate_meshes) {
BKE_mesh_validate(mesh, false, false);
@@ -199,3 +200,22 @@ void read_points_sample(const IPointsSchema &schema,
read_mverts(config.mvert, positions, vnormals);
}
+
+DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/)
+{
+ ISampleSelector sample_sel(time);
+ const IPointsSchema::Sample sample = m_schema.getValue(sample_sel);
+
+ const P3fArraySamplePtr &positions = sample.getPositions();
+
+ DerivedMesh *new_dm = NULL;
+
+ if (dm->getNumVerts(dm) != positions->size()) {
+ new_dm = CDDM_new(positions->size(), 0, 0, 0, 0);
+ }
+
+ CDStreamConfig config = get_config(new_dm ? new_dm : dm);
+ read_points_sample(m_schema, sample_sel, config, time);
+
+ return new_dm ? new_dm : dm;
+}
diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_points.h
index cfa51e66a22..0e69639ad8e 100644
--- a/source/blender/alembic/intern/abc_points.h
+++ b/source/blender/alembic/intern/abc_points.h
@@ -58,6 +58,8 @@ public:
bool valid() const;
void readObjectData(Main *bmain, float time);
+
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag);
};
void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema,
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index 60c66bca1c8..f87d18605d4 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -22,6 +22,15 @@
#include "abc_util.h"
+#include "abc_camera.h"
+#include "abc_curves.h"
+#include "abc_mesh.h"
+#include "abc_nurbs.h"
+#include "abc_points.h"
+#include "abc_transform.h"
+
+#include <Alembic/AbcMaterial/IMaterial.h>
+
#include <algorithm>
extern "C" {
@@ -462,3 +471,56 @@ float get_weight_and_index(float time,
return bias;
}
+
+//#define USE_NURBS
+
+AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings)
+{
+ AbcObjectReader *reader = NULL;
+
+ const Alembic::AbcGeom::MetaData &md = object.getMetaData();
+
+ if (Alembic::AbcGeom::IXform::matches(md)) {
+ reader = new AbcEmptyReader(object, settings);
+ }
+ else if (Alembic::AbcGeom::IPolyMesh::matches(md)) {
+ reader = new AbcMeshReader(object, settings);
+ }
+ else if (Alembic::AbcGeom::ISubD::matches(md)) {
+ reader = new AbcSubDReader(object, settings);
+ }
+ else if (Alembic::AbcGeom::INuPatch::matches(md)) {
+#ifdef USE_NURBS
+ /* TODO(kevin): importing cyclic NURBS from other software crashes
+ * at the moment. This is due to the fact that NURBS in other
+ * software have duplicated points which causes buffer overflows in
+ * Blender. Need to figure out exactly how these points are
+ * duplicated, in all cases (cyclic U, cyclic V, and cyclic UV).
+ * Until this is fixed, disabling NURBS reading. */
+ reader = new AbcNurbsReader(child, settings);
+#endif
+ }
+ else if (Alembic::AbcGeom::ICamera::matches(md)) {
+ reader = new AbcCameraReader(object, settings);
+ }
+ else if (Alembic::AbcGeom::IPoints::matches(md)) {
+ reader = new AbcPointsReader(object, settings);
+ }
+ else if (Alembic::AbcMaterial::IMaterial::matches(md)) {
+ /* Pass for now. */
+ }
+ else if (Alembic::AbcGeom::ILight::matches(md)) {
+ /* Pass for now. */
+ }
+ else if (Alembic::AbcGeom::IFaceSet::matches(md)) {
+ /* Pass, those are handled in the mesh reader. */
+ }
+ else if (Alembic::AbcGeom::ICurves::matches(md)) {
+ reader = new AbcCurveReader(object, settings);
+ }
+ else {
+ assert(false);
+ }
+
+ return reader;
+}
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index 9e9f0c397ba..2f423a9f8c5 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -32,8 +32,13 @@
# define ABC_INLINE static inline
#endif
+struct CacheReader {
+ int unused;
+};
+
using Alembic::Abc::chrono_t;
+class AbcObjectReader;
class ImportSettings;
struct ID;
@@ -100,6 +105,8 @@ float get_weight_and_index(float time,
Alembic::AbcGeom::index_t &i0,
Alembic::AbcGeom::index_t &i1);
+AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings);
+
/* ************************** */
/* TODO(kevin): for now keeping these transformations hardcoded to make sure
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index c6988351db8..e690a255505 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -467,6 +467,7 @@ static void visit_object(const IObject &object,
if (reader) {
readers.push_back(reader);
+ reader->incref();
AlembicObjectPath *abc_path = static_cast<AlembicObjectPath *>(
MEM_callocN(sizeof(AlembicObjectPath), "AlembicObjectPath"));
@@ -710,7 +711,12 @@ static void import_endjob(void *user_data)
}
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
- delete *iter;
+ AbcObjectReader *reader = *iter;
+ reader->decref();
+
+ if (reader->refcount() == 0) {
+ delete reader;
+ }
}
if (data->parent_map) {
@@ -771,296 +777,31 @@ void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
-/* ******************************* */
+/* ************************************************************************** */
-void ABC_get_transform(AbcArchiveHandle *handle, Object *ob, const char *object_path, float r_mat[4][4], float time, float scale)
+void ABC_get_transform(CacheReader *reader, float r_mat[4][4], float time, float scale)
{
- ArchiveReader *archive = archive_from_handle(handle);
-
- if (!archive || !archive->valid()) {
+ if (!reader) {
return;
}
- IObject tmp;
- find_iobject(archive->getTop(), tmp, object_path);
-
- IXform ixform;
-
- if (IXform::matches(tmp.getHeader())) {
- ixform = IXform(tmp, kWrapExisting);
- }
- else {
- ixform = IXform(tmp.getParent(), kWrapExisting);
- }
-
- IXformSchema schema = ixform.getSchema();
-
- if (!schema.valid()) {
- return;
- }
-
- const Imath::M44d matrix = get_matrix(schema, time);
- convert_matrix(matrix, ob, r_mat, scale);
-}
-
-/* ***************************************** */
-
-static bool check_smooth_poly_flag(DerivedMesh *dm)
-{
- MPoly *mpolys = dm->getPolyArray(dm);
-
- for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i) {
- MPoly &poly = mpolys[i];
-
- if ((poly.flag & ME_SMOOTH) != 0) {
- return true;
- }
- }
-
- return false;
-}
-
-static void set_smooth_poly_flag(DerivedMesh *dm)
-{
- MPoly *mpolys = dm->getPolyArray(dm);
-
- for (int i = 0, e = dm->getNumPolys(dm); i < e; ++i) {
- MPoly &poly = mpolys[i];
- poly.flag |= ME_SMOOTH;
- }
-}
-
-static void *add_customdata_cb(void *user_data, const char *name, int data_type)
-{
- DerivedMesh *dm = static_cast<DerivedMesh *>(user_data);
- CustomDataType cd_data_type = static_cast<CustomDataType>(data_type);
- void *cd_ptr = NULL;
-
- if (ELEM(cd_data_type, CD_MLOOPUV, CD_MLOOPCOL)) {
- cd_ptr = CustomData_get_layer_named(dm->getLoopDataLayout(dm), cd_data_type, name);
-
- if (cd_ptr == NULL) {
- cd_ptr = CustomData_add_layer_named(dm->getLoopDataLayout(dm),
- cd_data_type,
- CD_DEFAULT,
- NULL,
- dm->getNumLoops(dm),
- name);
- }
- }
-
- return cd_ptr;
-}
-
-ABC_INLINE CDStreamConfig get_config(DerivedMesh *dm)
-{
- CDStreamConfig config;
-
- config.user_data = dm;
- config.mvert = dm->getVertArray(dm);
- config.mloop = dm->getLoopArray(dm);
- config.mpoly = dm->getPolyArray(dm);
- config.totloop = dm->getNumLoops(dm);
- config.totpoly = dm->getNumPolys(dm);
- config.loopdata = dm->getLoopDataLayout(dm);
- config.add_customdata_cb = add_customdata_cb;
-
- return config;
-}
-
-static DerivedMesh *read_mesh_sample(DerivedMesh *dm, const IObject &iobject, const float time, int read_flag)
-{
- IPolyMesh mesh(iobject, kWrapExisting);
- IPolyMeshSchema schema = mesh.getSchema();
- ISampleSelector sample_sel(time);
- const IPolyMeshSchema::Sample sample = schema.getValue(sample_sel);
-
- const P3fArraySamplePtr &positions = sample.getPositions();
- const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
- const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
-
- DerivedMesh *new_dm = NULL;
-
- /* Only read point data when streaming meshes, unless we need to create new ones. */
- ImportSettings settings;
- settings.read_flag |= read_flag;
-
- if (dm->getNumVerts(dm) != positions->size()) {
- new_dm = CDDM_from_template(dm,
- positions->size(),
- 0,
- 0,
- face_indices->size(),
- face_counts->size());
-
- settings.read_flag |= MOD_MESHSEQ_READ_ALL;
- }
-
- CDStreamConfig config = get_config(new_dm ? new_dm : dm);
- config.time = time;
-
- 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 (!do_normals && check_smooth_poly_flag(dm)) {
- set_smooth_poly_flag(new_dm);
- }
-
- CDDM_calc_normals(new_dm);
- CDDM_calc_edges(new_dm);
-
- return new_dm;
- }
-
- if (do_normals) {
- CDDM_calc_normals(dm);
- }
+ AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader);
- return dm;
+ bool is_constant = false;
+ abc_reader->read_matrix(r_mat, time, scale, is_constant);
}
-using Alembic::AbcGeom::ISubDSchema;
-
-static DerivedMesh *read_subd_sample(DerivedMesh *dm, const IObject &iobject, const float time, int read_flag)
-{
- ISubD mesh(iobject, kWrapExisting);
- ISubDSchema schema = mesh.getSchema();
- ISampleSelector sample_sel(time);
- const ISubDSchema::Sample sample = schema.getValue(sample_sel);
-
- const P3fArraySamplePtr &positions = sample.getPositions();
- const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
- const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
-
- DerivedMesh *new_dm = NULL;
-
- ImportSettings settings;
- settings.read_flag |= read_flag;
-
- if (dm->getNumVerts(dm) != positions->size()) {
- new_dm = CDDM_from_template(dm,
- positions->size(),
- 0,
- 0,
- face_indices->size(),
- face_counts->size());
-
- settings.read_flag |= MOD_MESHSEQ_READ_ALL;
- }
-
- /* Only read point data when streaming meshes, unless we need to create new ones. */
- CDStreamConfig config = get_config(new_dm ? new_dm : dm);
- config.time = time;
- read_subd_sample(&settings, schema, sample_sel, config);
+/* ************************************************************************** */
- if (new_dm) {
- /* Check if we had ME_SMOOTH flag set to restore it. */
- if (check_smooth_poly_flag(dm)) {
- set_smooth_poly_flag(new_dm);
- }
-
- CDDM_calc_normals(new_dm);
- CDDM_calc_edges(new_dm);
-
- return new_dm;
- }
-
- return dm;
-}
-
-static DerivedMesh *read_points_sample(DerivedMesh *dm, const IObject &iobject, const float time)
-{
- IPoints points(iobject, kWrapExisting);
- IPointsSchema schema = points.getSchema();
- ISampleSelector sample_sel(time);
- const IPointsSchema::Sample sample = schema.getValue(sample_sel);
-
- const P3fArraySamplePtr &positions = sample.getPositions();
-
- DerivedMesh *new_dm = NULL;
-
- if (dm->getNumVerts(dm) != positions->size()) {
- new_dm = CDDM_new(positions->size(), 0, 0, 0, 0);
- }
-
- CDStreamConfig config = get_config(new_dm ? new_dm : dm);
- read_points_sample(schema, sample_sel, config, time);
-
- return new_dm ? new_dm : dm;
-}
-
-/* NOTE: Alembic only stores data about control points, but the DerivedMesh
- * passed from the cache modifier contains the displist, which has more data
- * than the control points, so to avoid corrupting the displist we modify the
- * object directly and create a new DerivedMesh from that. Also we might need to
- * create new or delete existing NURBS in the curve.
- */
-static DerivedMesh *read_curves_sample(Object *ob, const IObject &iobject, const float time)
-{
- ICurves points(iobject, kWrapExisting);
- ICurvesSchema schema = points.getSchema();
- ISampleSelector sample_sel(time);
- const ICurvesSchema::Sample sample = schema.getValue(sample_sel);
-
- const P3fArraySamplePtr &positions = sample.getPositions();
- const Int32ArraySamplePtr num_vertices = sample.getCurvesNumVertices();
-
- int vertex_idx = 0;
- int curve_idx = 0;
- Curve *curve = static_cast<Curve *>(ob->data);
-
- const int curve_count = BLI_listbase_count(&curve->nurb);
-
- if (curve_count != num_vertices->size()) {
- BKE_nurbList_free(&curve->nurb);
- read_curve_sample(curve, schema, time);
- }
- else {
- Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
- for (; nurbs; nurbs = nurbs->next, ++curve_idx) {
- const int totpoint = (*num_vertices)[curve_idx];
-
- if (nurbs->bp) {
- BPoint *point = nurbs->bp;
-
- for (int i = 0; i < totpoint; ++i, ++point, ++vertex_idx) {
- const Imath::V3f &pos = (*positions)[vertex_idx];
- copy_yup_zup(point->vec, pos.getValue());
- }
- }
- else if (nurbs->bezt) {
- BezTriple *bezier = nurbs->bezt;
-
- for (int i = 0; i < totpoint; ++i, ++bezier, ++vertex_idx) {
- const Imath::V3f &pos = (*positions)[vertex_idx];
- copy_yup_zup(bezier->vec[1], pos.getValue());
- }
- }
- }
- }
-
- return CDDM_from_curve(ob);
-}
-
-DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
+DerivedMesh *ABC_read_mesh(CacheReader *reader,
Object *ob,
DerivedMesh *dm,
- const char *object_path,
const float time,
const char **err_str,
int read_flag)
{
- ArchiveReader *archive = archive_from_handle(handle);
-
- if (!archive || !archive->valid()) {
- *err_str = "Invalid archive!";
- return NULL;
- }
-
- IObject iobject;
- find_iobject(archive->getTop(), iobject, object_path);
+ AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader);
+ IObject iobject = abc_reader->iobject();
if (!iobject.valid()) {
*err_str = "Invalid object: verify object path";
@@ -1075,7 +816,7 @@ DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
return NULL;
}
- return read_mesh_sample(dm, iobject, time, read_flag);
+ return abc_reader->read_derivedmesh(dm, time, read_flag);
}
else if (ISubD::matches(header)) {
if (ob->type != OB_MESH) {
@@ -1083,7 +824,7 @@ DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
return NULL;
}
- return read_subd_sample(dm, iobject, time, read_flag);
+ return abc_reader->read_derivedmesh(dm, time, read_flag);
}
else if (IPoints::matches(header)) {
if (ob->type != OB_MESH) {
@@ -1091,7 +832,7 @@ DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
return NULL;
}
- return read_points_sample(dm, iobject, time);
+ return abc_reader->read_derivedmesh(dm, time, read_flag);
}
else if (ICurves::matches(header)) {
if (ob->type != OB_CURVE) {
@@ -1099,9 +840,48 @@ DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
return NULL;
}
- return read_curves_sample(ob, iobject, time);
+ return abc_reader->read_derivedmesh(dm, time, read_flag);
}
*err_str = "Unsupported object type: verify object path"; // or poke developer
return NULL;
}
+
+/* ************************************************************************** */
+
+void CacheReader_free(CacheReader *reader)
+{
+ AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader);
+ abc_reader->decref();
+
+ if (abc_reader->refcount() == 0) {
+ delete abc_reader;
+ }
+}
+
+CacheReader *CacheReader_open_alembic_object(AbcArchiveHandle *handle, CacheReader *reader, Object *object, const char *object_path)
+{
+ if (object_path[0] == '\0') {
+ return reader;
+ }
+
+ ArchiveReader *archive = archive_from_handle(handle);
+
+ if (!archive || !archive->valid()) {
+ return reader;
+ }
+
+ IObject iobject;
+ find_iobject(archive->getTop(), iobject, object_path);
+
+ if (reader) {
+ CacheReader_free(reader);
+ }
+
+ ImportSettings settings;
+ AbcObjectReader *abc_reader = create_reader(iobject, settings);
+ abc_reader->object(object);
+ abc_reader->incref();
+
+ return reinterpret_cast<CacheReader *>(abc_reader);
+}
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index a55cb51766c..7e1c069df9a 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -63,6 +63,8 @@ bool BKE_cachefile_filepath_get(
float BKE_cachefile_time_offset(struct CacheFile *cache_file, const float time, const float fps);
+void BKE_cachefile_clean(struct Scene *scene, struct CacheFile *cache_file);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index efef8d4be78..6944c5ccd28 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -114,6 +114,7 @@ struct PreviewImage *BKE_previewimg_cached_thumbnail_read(
const char *name, const char *path, const int source, bool force_update);
void BKE_previewimg_cached_release(const char *name);
+void BKE_previewimg_cached_release_pointer(struct PreviewImage *prv);
#define ICON_RENDER_DEFAULT_HEIGHT 32
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 7882bdf1126..33c68158262 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -39,6 +39,7 @@ extern "C" {
#include "BLI_compiler_attrs.h"
struct BlendThumbnail;
+struct GHash;
struct ListBase;
struct ID;
struct ImBuf;
@@ -125,7 +126,8 @@ void BKE_id_ui_prefix(char name[66 + 1], const struct ID *id);
void BKE_library_free(struct Library *lib);
void BKE_library_make_local(
- struct Main *bmain, const struct Library *lib, const bool untagged_only, const bool set_fake);
+ struct Main *bmain, const struct Library *lib, struct GHash *old_to_new_ids,
+ const bool untagged_only, const bool set_fake);
/* use when "" is given to new_id() */
diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h
index a0a885c2a04..19a2220006a 100644
--- a/source/blender/blenkernel/BKE_object_deform.h
+++ b/source/blender/blenkernel/BKE_object_deform.h
@@ -51,9 +51,11 @@ bool BKE_object_defgroup_clear(struct Object *ob, struct bDeformGroup *dg, const
bool BKE_object_defgroup_clear_all(struct Object *ob, const bool use_selection);
void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup);
+void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked);
void BKE_object_defgroup_remove_all(struct Object *ob);
+
/* Select helpers */
enum eVGroupSelect;
bool *BKE_object_defgroup_subset_from_select_type(
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index a4c28121040..e57524af546 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -101,7 +101,7 @@ bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *repor
IMB_colormanagement_check_file_config(bmain_dst);
/* Append, rather than linking. */
Library *lib = BLI_findstring(&bmain_dst->library, libname, offsetof(Library, filepath));
- BKE_library_make_local(bmain_dst, lib, true, false);
+ BKE_library_make_local(bmain_dst, lib, NULL, true, false);
/* Important we unset, otherwise these object wont
* link into other scenes from this blend file.
*/
@@ -150,7 +150,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
/* append, rather than linking */
lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath));
- BKE_library_make_local(bmain, lib, true, false);
+ BKE_library_make_local(bmain, lib, NULL, true, false);
/* important we unset, otherwise these object wont
* link into other scenes from this blend file */
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index e62e652b4a6..6a08673144e 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -29,6 +29,8 @@
#include "DNA_anim_types.h"
#include "DNA_cachefile_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BLI_fileops.h"
@@ -43,6 +45,7 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_scene.h"
#ifdef WITH_ALEMBIC
@@ -196,3 +199,41 @@ float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const f
const float frame = (cache_file->override_frame ? cache_file->frame : time);
return cache_file->is_sequence ? frame : frame / fps;
}
+
+/* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */
+void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
+{
+ for (Base *base = scene->base.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
+
+ if (md) {
+ MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
+
+ if (cache_file == mcmd->cache_file) {
+#ifdef WITH_ALEMBIC
+ CacheReader_free(mcmd->reader);
+#endif
+ mcmd->reader = NULL;
+ mcmd->object_path[0] = '\0';
+ }
+ }
+
+ for (bConstraint *con = ob->constraints.first; con; con = con->next) {
+ if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) {
+ continue;
+ }
+
+ bTransformCacheConstraint *data = con->data;
+
+ if (cache_file == data->cache_file) {
+#ifdef WITH_ALEMBIC
+ CacheReader_free(data->reader);
+#endif
+ data->reader = NULL;
+ data->object_path[0] = '\0';
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index c4afa58b7d3..b85f1b838ff 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -4364,8 +4364,14 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa
BKE_cachefile_ensure_handle(G.main, cache_file);
- ABC_get_transform(cache_file->handle, cob->ob, data->object_path,
- cob->matrix, time, cache_file->scale);
+ if (!data->reader) {
+ data->reader = CacheReader_open_alembic_object(cache_file->handle,
+ data->reader,
+ cob->ob,
+ data->object_path);
+ }
+
+ ABC_get_transform(data->reader, cob->matrix, time, cache_file->scale);
#else
UNUSED_VARS(con, cob);
#endif
@@ -4393,6 +4399,12 @@ static void transformcache_free(bConstraint *con)
if (data->cache_file) {
id_us_min(&data->cache_file->id);
}
+
+ if (data->reader) {
+#ifdef WITH_ALEMBIC
+ CacheReader_free(data->reader);
+#endif
+ }
}
static void transformcache_new_data(void *cdata)
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 184688b5e74..1c0b11e287c 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -2809,7 +2809,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
if (mcmd->cache_file && (&mcmd->cache_file->id == id)) {
- ob->recalc |= OB_RECALC_DATA;
+ ob->recalc |= OB_RECALC_ALL;
continue;
}
}
@@ -2822,7 +2822,7 @@ void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
bTransformCacheConstraint *data = con->data;
if (data->cache_file && (&data->cache_file->id == id)) {
- ob->recalc |= OB_RECALC_DATA;
+ ob->recalc |= OB_RECALC_ALL;
break;
}
}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 2d5b15c8f9d..7669c4ba112 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -143,7 +143,7 @@ static PreviewImage *previewimg_create_ex(size_t deferred_data_size)
memset(prv_img, 0, sizeof(*prv_img)); /* leave deferred data dirty */
if (deferred_data_size) {
- prv_img->use_deferred = true;
+ prv_img->tag |= PRV_TAG_DEFFERED;
}
for (i = 0; i < NUM_ICON_SIZES; ++i) {
@@ -355,11 +355,14 @@ PreviewImage *BKE_previewimg_cached_thumbnail_read(
return prv;
}
-void BKE_previewimg_cached_release(const char *name)
+void BKE_previewimg_cached_release_pointer(PreviewImage *prv)
{
- PreviewImage *prv = BLI_ghash_popkey(gCachedPreviews, name, MEM_freeN);
-
if (prv) {
+ if (prv->tag & PRV_TAG_DEFFERED_RENDERING) {
+ /* We cannot delete the preview while it is being loaded in another thread... */
+ prv->tag |= PRV_TAG_DEFFERED_DELETE;
+ return;
+ }
if (prv->icon_id) {
BKE_icon_delete(prv->icon_id);
}
@@ -367,11 +370,18 @@ void BKE_previewimg_cached_release(const char *name)
}
}
+void BKE_previewimg_cached_release(const char *name)
+{
+ PreviewImage *prv = BLI_ghash_popkey(gCachedPreviews, name, MEM_freeN);
+
+ BKE_previewimg_cached_release_pointer(prv);
+}
+
/** Handle deferred (lazy) loading/generation of preview image, if needed.
* For now, only used with file thumbnails. */
void BKE_previewimg_ensure(PreviewImage *prv, const int size)
{
- if (prv->use_deferred) {
+ if ((prv->tag & PRV_TAG_DEFFERED) != 0) {
const bool do_icon = ((size == ICON_SIZE_ICON) && !prv->rect[ICON_SIZE_ICON]);
const bool do_preview = ((size == ICON_SIZE_PREVIEW) && !prv->rect[ICON_SIZE_PREVIEW]);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index a4eef2f9230..df3a7630bb0 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1580,24 +1580,7 @@ void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const ImBuf *i
}
/* planes */
- /* TODO(sergey): Channels doesn't correspond actual planes used for image buffer
- * For example byte buffer will have 4 channels but it might easily
- * be BW or RGB image.
- *
- * Need to use im_format->planes = imbuf->planes instead?
- */
- switch (imbuf->channels) {
- case 0:
- case 4: im_format->planes = R_IMF_PLANES_RGBA;
- break;
- case 3: im_format->planes = R_IMF_PLANES_RGB;
- break;
- case 1: im_format->planes = R_IMF_PLANES_BW;
- break;
- default: im_format->planes = R_IMF_PLANES_RGB;
- break;
- }
-
+ im_format->planes = imbuf->planes;
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 4ed1fad7323..9abf09a0944 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -73,6 +73,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
@@ -1623,7 +1624,8 @@ void BKE_main_id_clear_newpoins(Main *bmain)
* We'll probably need at some point a true dependency graph between datablocks, but for now this should work
* good enough (performances is not a critical point here anyway).
*/
-void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged_only, const bool set_fake)
+void BKE_library_make_local(
+ Main *bmain, const Library *lib, GHash *old_to_new_ids, const bool untagged_only, const bool set_fake)
{
ListBase *lbarray[MAX_LIBARRAY];
ID *id, *id_next;
@@ -1695,6 +1697,9 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged
BLI_assert(id->lib != NULL);
BKE_libblock_remap(bmain, id, id->newid, ID_REMAP_SKIP_INDIRECT_USAGE);
+ if (old_to_new_ids) {
+ BLI_ghash_insert(old_to_new_ids, id, id->newid);
+ }
}
/* Third step: remove datablocks that have been copied to be localized and are no more used in the end...
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index 72968d1964c..91c67899dfb 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -399,8 +399,9 @@ void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup)
/**
* Remove all vgroups from object. Work in Object and Edit modes.
+ * When only_unlocked=true, locked vertex groups are not removed.
*/
-void BKE_object_defgroup_remove_all(Object *ob)
+void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
{
bDeformGroup *dg = (bDeformGroup *)ob->defbase.first;
const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
@@ -409,10 +410,12 @@ void BKE_object_defgroup_remove_all(Object *ob)
while (dg) {
bDeformGroup *next_dg = dg->next;
- if (edit_mode)
- object_defgroup_remove_edit_mode(ob, dg);
- else
- object_defgroup_remove_object_mode(ob, dg);
+ if (!only_unlocked || (dg->flag & DG_LOCK_WEIGHT) == 0) {
+ if (edit_mode)
+ object_defgroup_remove_edit_mode(ob, dg);
+ else
+ object_defgroup_remove_object_mode(ob, dg);
+ }
dg = next_dg;
}
@@ -437,6 +440,15 @@ void BKE_object_defgroup_remove_all(Object *ob)
}
/**
+ * Remove all vgroups from object. Work in Object and Edit modes.
+ */
+void BKE_object_defgroup_remove_all(struct Object *ob)
+{
+ BKE_object_defgroup_remove_all_ex(ob, false);
+}
+
+
+/**
* Get MDeformVert vgroup data from given object. Should only be used in Object mode.
*
* \return True if the id type supports weights.
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 05356123727..1da263797f6 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -355,6 +355,10 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd)
MEM_freeN(smd->domain->effector_weights);
smd->domain->effector_weights = NULL;
+ if (smd->domain->coba) {
+ MEM_freeN(smd->domain->coba);
+ }
+
MEM_freeN(smd->domain);
smd->domain = NULL;
}
@@ -531,6 +535,9 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->slice_depth = 0.5f;
smd->domain->slice_axis = 0;
smd->domain->vector_scale = 1.0f;
+
+ smd->domain->coba = NULL;
+ smd->domain->coba_field = FLUID_FIELD_DENSITY;
}
else if (smd->type & MOD_SMOKE_TYPE_FLOW)
{
@@ -631,6 +638,10 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
tsmd->domain->draw_velocity = smd->domain->draw_velocity;
tsmd->domain->vector_draw_type = smd->domain->vector_draw_type;
tsmd->domain->vector_scale = smd->domain->vector_scale;
+
+ if (smd->domain->coba) {
+ tsmd->domain->coba = MEM_dupallocN(smd->domain->coba);
+ }
}
else if (tsmd->flow) {
tsmd->flow->noise_texture = smd->flow->noise_texture;
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index a86606f1099..96ab8693122 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -44,6 +44,7 @@
#include "DNA_scene_types.h"
#include "BLI_utildefines.h"
+#include "BLI_bitmap_draw_2d.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_math_base.h"
@@ -997,9 +998,10 @@ static void track_mask_gpencil_layer_rasterize(int frame_width, int frame_height
point[1] = (stroke_points[i].y - marker->search_min[1]) * frame_height;
}
/* TODO: add an option to control whether AA is enabled or not */
- fill_poly_v2i_n(0, 0, mask_width, mask_height,
- (const int (*)[2])mask_points, stroke->totpoints,
- track_mask_set_pixel_cb, &data);
+ BLI_bitmap_draw_2d_poly_v2i_n(
+ 0, 0, mask_width, mask_height,
+ (const int (*)[2])mask_points, stroke->totpoints,
+ track_mask_set_pixel_cb, &data);
MEM_freeN(mask_points);
}
stroke = stroke->next;
diff --git a/source/blender/blenlib/BLI_bitmap_draw_2d.h b/source/blender/blenlib/BLI_bitmap_draw_2d.h
new file mode 100644
index 00000000000..fe890e94f1b
--- /dev/null
+++ b/source/blender/blenlib/BLI_bitmap_draw_2d.h
@@ -0,0 +1,37 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_BITMAP_DRAW_2D_H__
+#define __BLI_BITMAP_DRAW_2D_H__
+
+/** \file BLI_bitmap_draw_2d.h
+ * \ingroup bli
+ */
+
+void BLI_bitmap_draw_2d_line_v2v2i(
+ const int p1[2], const int p2[2],
+ bool (*callback)(int, int, void *), void *userData);
+
+void BLI_bitmap_draw_2d_poly_v2i_n(
+ const int xmin, const int ymin, const int xmax, const int ymax,
+ const int polyXY[][2], const int polyCorners,
+ void (*callback)(int x, int x_end, int y, void *), void *userData);
+
+#endif /* __BLI_BITMAP_DRAW_2D_H__ */
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 84a25f533bf..514b0300274 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -325,11 +325,6 @@ bool clip_segment_v3_plane_n(
const float p1[3], const float p2[3], const float plane_array[][4], const int plane_tot,
float r_p1[3], float r_p2[3]);
-void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData);
-void fill_poly_v2i_n(
- const int xmin, const int ymin, const int xmax, const int ymax,
- const int polyXY[][2], const int polyCorners,
- void (*callback)(int x, int x_end, int y, void *), void *userData);
/****************************** Interpolation ********************************/
/* tri or quad, d can be NULL */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 9978d1d19af..6e717a3ae7e 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -56,6 +56,7 @@ set(SRC
intern/array_store_utils.c
intern/array_utils.c
intern/astar.c
+ intern/bitmap_draw_2d.c
intern/boxpack2d.c
intern/buffer.c
intern/callbacks.c
@@ -127,6 +128,7 @@ set(SRC
BLI_array_utils.h
BLI_astar.h
BLI_bitmap.h
+ BLI_bitmap_draw_2d.h
BLI_blenlib.h
BLI_boxpack2d.h
BLI_buffer.h
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index f943a8119c4..944ee18e6b2 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -1588,7 +1588,7 @@ double BLI_ghash_calc_quality_ex(
if (r_variance) {
/* We already know our mean (i.e. load factor), easy to compute variance.
- * See http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Two-pass_algorithm
+ * See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Two-pass_algorithm
*/
double sum = 0.0;
for (i = 0; i < gh->nbuckets; i++) {
diff --git a/source/blender/blenlib/intern/astar.c b/source/blender/blenlib/intern/astar.c
index 21d974de1c4..0020dbe4612 100644
--- a/source/blender/blenlib/intern/astar.c
+++ b/source/blender/blenlib/intern/astar.c
@@ -35,7 +35,7 @@
* in addition to distance already walked. This heuristic allows more efficiency
* in finding optimal path.
*
- * Implementation based on Wikipedia A* page [http://en.wikipedia.org/wiki/A*_search_algorithm].
+ * Implementation based on Wikipedia A* page [https://en.wikipedia.org/wiki/A*_search_algorithm].
*
* Note that most memory handling here is done through two different MemArena's. Those should also be used to allocate
* custom data needed to a specific use of A*.
diff --git a/source/blender/blenlib/intern/bitmap_draw_2d.c b/source/blender/blenlib/intern/bitmap_draw_2d.c
new file mode 100644
index 00000000000..afc54511d13
--- /dev/null
+++ b/source/blender/blenlib/intern/bitmap_draw_2d.c
@@ -0,0 +1,331 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: some of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * */
+
+/** \file blender/blenlib/intern/bitmap_draw_2d.c
+ * \ingroup bli
+ *
+ * Utility functions for primitive drawing operations.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap_draw_2d.h"
+
+#include "BLI_math_base.h"
+#include "BLI_sort.h"
+#include "BLI_utildefines.h"
+
+#include "BLI_strict_flags.h"
+
+/* -------------------------------------------------------------------- */
+/* Draw Line */
+
+/**
+ * Plot a line from \a p1 to \a p2 (inclusive).
+ */
+void BLI_bitmap_draw_2d_line_v2v2i(
+ const int p1[2], const int p2[2],
+ bool (*callback)(int, int, void *), void *userData)
+{
+ /* Bresenham's line algorithm. */
+ int x1 = p1[0];
+ int y1 = p1[1];
+ int x2 = p2[0];
+ int y2 = p2[1];
+
+ int ix;
+ int iy;
+
+ /* if x1 == x2 or y1 == y2, then it does not matter what we set here */
+ int delta_x = (x2 > x1 ? ((void)(ix = 1), x2 - x1) : ((void)(ix = -1), x1 - x2)) << 1;
+ int delta_y = (y2 > y1 ? ((void)(iy = 1), y2 - y1) : ((void)(iy = -1), y1 - y2)) << 1;
+
+ if (callback(x1, y1, userData) == 0) {
+ return;
+ }
+
+ if (delta_x >= delta_y) {
+ /* error may go below zero */
+ int error = delta_y - (delta_x >> 1);
+
+ while (x1 != x2) {
+ if (error >= 0) {
+ if (error || (ix > 0)) {
+ y1 += iy;
+ error -= delta_x;
+ }
+ /* else do nothing */
+ }
+ /* else do nothing */
+
+ x1 += ix;
+ error += delta_y;
+
+ if (callback(x1, y1, userData) == 0) {
+ return;
+ }
+ }
+ }
+ else {
+ /* error may go below zero */
+ int error = delta_x - (delta_y >> 1);
+
+ while (y1 != y2) {
+ if (error >= 0) {
+ if (error || (iy > 0)) {
+ x1 += ix;
+ error -= delta_y;
+ }
+ /* else do nothing */
+ }
+ /* else do nothing */
+
+ y1 += iy;
+ error += delta_x;
+
+ if (callback(x1, y1, userData) == 0) {
+ return;
+ }
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Draw Filled Polygon */
+
+/* sort edge-segments on y, then x axis */
+static int draw_poly_v2i_n__span_y_sort(const void *a_p, const void *b_p, void *verts_p)
+{
+ const int (*verts)[2] = verts_p;
+ const int *a = a_p;
+ const int *b = b_p;
+ const int *co_a = verts[a[0]];
+ const int *co_b = verts[b[0]];
+
+ if (co_a[1] < co_b[1]) {
+ return -1;
+ }
+ else if (co_a[1] > co_b[1]) {
+ return 1;
+ }
+ else if (co_a[0] < co_b[0]) {
+ return -1;
+ }
+ else if (co_a[0] > co_b[0]) {
+ return 1;
+ }
+ else {
+ /* co_a & co_b are identical, use the line closest to the x-min */
+ const int *co = co_a;
+ co_a = verts[a[1]];
+ co_b = verts[b[1]];
+ int ord = (((co_b[0] - co[0]) * (co_a[1] - co[1])) -
+ ((co_a[0] - co[0]) * (co_b[1] - co[1])));
+ if (ord > 0) {
+ return -1;
+ }
+ if (ord < 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Draws a filled polyon with support for self intersections.
+ *
+ * \param callback: Takes the x, y coords and x-span (\a x_end is not inclusive),
+ * note that \a x_end will always be greater than \a x, so we can use:
+ *
+ * \code{.c}
+ * do {
+ * func(x, y);
+ * } while (++x != x_end);
+ * \endcode
+ */
+void BLI_bitmap_draw_2d_poly_v2i_n(
+ const int xmin, const int ymin, const int xmax, const int ymax,
+ const int verts[][2], const int nr,
+ void (*callback)(int x, int x_end, int y, void *), void *userData)
+{
+ /* Originally by Darel Rex Finley, 2007.
+ * Optimized by Campbell Barton, 2016 to track sorted intersections. */
+
+ int (*span_y)[2] = MEM_mallocN(sizeof(*span_y) * (size_t)nr, __func__);
+ int span_y_len = 0;
+
+ for (int i_curr = 0, i_prev = nr - 1; i_curr < nr; i_prev = i_curr++) {
+ const int *co_prev = verts[i_prev];
+ const int *co_curr = verts[i_curr];
+
+ if (co_prev[1] != co_curr[1]) {
+ /* Any segments entirely above or below the area of interest can be skipped. */
+ if ((min_ii(co_prev[1], co_curr[1]) >= ymax) ||
+ (max_ii(co_prev[1], co_curr[1]) < ymin))
+ {
+ continue;
+ }
+
+ int *s = span_y[span_y_len++];
+ if (co_prev[1] < co_curr[1]) {
+ s[0] = i_prev;
+ s[1] = i_curr;
+ }
+ else {
+ s[0] = i_curr;
+ s[1] = i_prev;
+ }
+ }
+ }
+
+ BLI_qsort_r(span_y, (size_t)span_y_len, sizeof(*span_y), draw_poly_v2i_n__span_y_sort, (void *)verts);
+
+ struct NodeX {
+ int span_y_index;
+ int x;
+ } *node_x = MEM_mallocN(sizeof(*node_x) * (size_t)(nr + 1), __func__);
+ int node_x_len = 0;
+
+ int span_y_index = 0;
+ if (span_y_len != 0 && verts[span_y[0][0]][1] < ymin) {
+ while ((span_y_index < span_y_len) &&
+ (verts[span_y[span_y_index][0]][1] < ymin))
+ {
+ BLI_assert(verts[span_y[span_y_index][0]][1] <
+ verts[span_y[span_y_index][1]][1]);
+ if (verts[span_y[span_y_index][1]][1] >= ymin) {
+ struct NodeX *n = &node_x[node_x_len++];
+ n->span_y_index = span_y_index;
+ }
+ span_y_index += 1;
+ }
+ }
+
+ /* Loop through the rows of the image. */
+ for (int pixel_y = ymin; pixel_y < ymax; pixel_y++) {
+ bool is_sorted = true;
+ bool do_remove = false;
+
+ for (int i = 0, x_ix_prev = INT_MIN; i < node_x_len; i++) {
+ struct NodeX *n = &node_x[i];
+ const int *s = span_y[n->span_y_index];
+ const int *co_prev = verts[s[0]];
+ const int *co_curr = verts[s[1]];
+
+ BLI_assert(co_prev[1] < pixel_y && co_curr[1] >= pixel_y);
+
+ const double x = (co_prev[0] - co_curr[0]);
+ const double y = (co_prev[1] - co_curr[1]);
+ const double y_px = (pixel_y - co_curr[1]);
+ const int x_ix = (int)((double)co_curr[0] + ((y_px / y) * x));
+ n->x = x_ix;
+
+ if (is_sorted && (x_ix_prev > x_ix)) {
+ is_sorted = false;
+ }
+ if (do_remove == false && co_curr[1] == pixel_y) {
+ do_remove = true;
+ }
+ x_ix_prev = x_ix;
+ }
+
+ /* Sort the nodes, via a simple "Bubble" sort. */
+ if (is_sorted == false) {
+ int i = 0;
+ const int node_x_end = node_x_len - 1;
+ while (i < node_x_end) {
+ if (node_x[i].x > node_x[i + 1].x) {
+ SWAP(struct NodeX, node_x[i], node_x[i + 1]);
+ if (i != 0) {
+ i -= 1;
+ }
+ }
+ else {
+ i += 1;
+ }
+ }
+ }
+
+ /* Fill the pixels between node pairs. */
+ for (int i = 0; i < node_x_len; i += 2) {
+ int x_src = node_x[i].x;
+ int x_dst = node_x[i + 1].x;
+
+ if (x_src >= xmax) {
+ break;
+ }
+
+ if (x_dst > xmin) {
+ if (x_src < xmin) {
+ x_src = xmin;
+ }
+ if (x_dst > xmax) {
+ x_dst = xmax;
+ }
+ /* for single call per x-span */
+ if (x_src < x_dst) {
+ callback(x_src - xmin, x_dst - xmin, pixel_y - ymin, userData);
+ }
+ }
+ }
+
+ /* Clear finalized nodes in one pass, only when needed
+ * (avoids excessive array-resizing). */
+ if (do_remove == true) {
+ int i_dst = 0;
+ for (int i_src = 0; i_src < node_x_len; i_src += 1) {
+ const int *s = span_y[node_x[i_src].span_y_index];
+ const int *co = verts[s[1]];
+ if (co[1] != pixel_y) {
+ if (i_dst != i_src) {
+ /* x is initialized for the next pixel_y (no need to adjust here) */
+ node_x[i_dst].span_y_index = node_x[i_src].span_y_index;
+ }
+ i_dst += 1;
+ }
+ }
+ node_x_len = i_dst;
+ }
+
+ /* Scan for new x-nodes */
+ while ((span_y_index < span_y_len) &&
+ (verts[span_y[span_y_index][0]][1] == pixel_y))
+ {
+ /* note, node_x these are just added at the end,
+ * not ideal but sorting once will resolve. */
+
+ /* x is initialized for the next pixel_y */
+ struct NodeX *n = &node_x[node_x_len++];
+ n->span_y_index = span_y_index;
+ span_y_index += 1;
+ }
+ }
+
+ MEM_freeN(span_y);
+ MEM_freeN(node_x);
+}
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index abb8ff35a45..01a805a09b6 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -269,7 +269,7 @@ MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack)
/**
* ITU-R BT.709 primaries
- * http://en.wikipedia.org/wiki/Relative_luminance
+ * https://en.wikipedia.org/wiki/Relative_luminance
*
* Real values are:
* ``Y = 0.2126390059(R) + 0.7151686788(G) + 0.0721923154(B)``
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index dd30f267f78..f31d0935b77 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2885,142 +2885,6 @@ bool clip_segment_v3_plane_n(
return true;
}
-void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData)
-{
- int x1 = p1[0];
- int y1 = p1[1];
- int x2 = p2[0];
- int y2 = p2[1];
-
- int ix;
- int iy;
-
- /* if x1 == x2 or y1 == y2, then it does not matter what we set here */
- int delta_x = (x2 > x1 ? ((void)(ix = 1), x2 - x1) : ((void)(ix = -1), x1 - x2)) << 1;
- int delta_y = (y2 > y1 ? ((void)(iy = 1), y2 - y1) : ((void)(iy = -1), y1 - y2)) << 1;
-
- if (callback(x1, y1, userData) == 0) {
- return;
- }
-
- if (delta_x >= delta_y) {
- /* error may go below zero */
- int error = delta_y - (delta_x >> 1);
-
- while (x1 != x2) {
- if (error >= 0) {
- if (error || (ix > 0)) {
- y1 += iy;
- error -= delta_x;
- }
- /* else do nothing */
- }
- /* else do nothing */
-
- x1 += ix;
- error += delta_y;
-
- if (callback(x1, y1, userData) == 0) {
- return;
- }
- }
- }
- else {
- /* error may go below zero */
- int error = delta_x - (delta_y >> 1);
-
- while (y1 != y2) {
- if (error >= 0) {
- if (error || (iy > 0)) {
- x1 += ix;
- error -= delta_y;
- }
- /* else do nothing */
- }
- /* else do nothing */
-
- y1 += iy;
- error += delta_x;
-
- if (callback(x1, y1, userData) == 0) {
- return;
- }
- }
- }
-}
-
-/**
- * \param callback: Takes the x, y coords and x-span (\a x_end is not inclusive),
- * note that \a x_end will always be greater than \a x, so we can use:
- *
- * \code{.c}
- * do {
- * func(x, y);
- * } while (++x != x_end);
- * \endcode
- */
-void fill_poly_v2i_n(
- const int xmin, const int ymin, const int xmax, const int ymax,
- const int verts[][2], const int nr,
- void (*callback)(int x, int x_end, int y, void *), void *userData)
-{
- /* originally by Darel Rex Finley, 2007 */
-
- int nodes, pixel_y, i, j, swap;
- int *node_x = MEM_mallocN(sizeof(*node_x) * (size_t)(nr + 1), __func__);
-
- /* Loop through the rows of the image. */
- for (pixel_y = ymin; pixel_y < ymax; pixel_y++) {
-
- /* Build a list of nodes. */
- nodes = 0; j = nr - 1;
- for (i = 0; i < nr; i++) {
- if ((verts[i][1] < pixel_y && verts[j][1] >= pixel_y) ||
- (verts[j][1] < pixel_y && verts[i][1] >= pixel_y))
- {
- node_x[nodes++] = (int)(verts[i][0] +
- ((double)(pixel_y - verts[i][1]) / (verts[j][1] - verts[i][1])) *
- (verts[j][0] - verts[i][0]));
- }
- j = i;
- }
-
- /* Sort the nodes, via a simple "Bubble" sort. */
- i = 0;
- while (i < nodes - 1) {
- if (node_x[i] > node_x[i + 1]) {
- SWAP_TVAL(swap, node_x[i], node_x[i + 1]);
- if (i) i--;
- }
- else {
- i++;
- }
- }
-
- /* Fill the pixels between node pairs. */
- for (i = 0; i < nodes; i += 2) {
- if (node_x[i] >= xmax) break;
- if (node_x[i + 1] > xmin) {
- if (node_x[i ] < xmin) node_x[i ] = xmin;
- if (node_x[i + 1] > xmax) node_x[i + 1] = xmax;
-
-#if 0
- /* for many x/y calls */
- for (j = node_x[i]; j < node_x[i + 1]; j++) {
- callback(j - xmin, pixel_y - ymin, userData);
- }
-#else
- /* for single call per x-span */
- if (node_x[i] < node_x[i + 1]) {
- callback(node_x[i] - xmin, node_x[i + 1] - xmin, pixel_y - ymin, userData);
- }
-#endif
- }
- }
- }
- MEM_freeN(node_x);
-}
-
/****************************** Axis Utils ********************************/
/**
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index ded10ad7713..f0d0bd00dea 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -430,7 +430,7 @@ void BLI_cleanup_file(const char *relabase, char *path)
* \return true if \a fname was changed, false otherwise.
*
* For now, simply replaces reserved chars (as listed in
- * http://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words )
+ * https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words )
* by underscores ('_').
*
* \note Space case ' ' is a bit of an edge case here - in theory it is allowed, but again can be an issue
diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c
index 0b976e9612e..ccac221d836 100644
--- a/source/blender/blenlib/intern/smallhash.c
+++ b/source/blender/blenlib/intern/smallhash.c
@@ -34,7 +34,7 @@
* based on a doubling hashing approach (non-chaining) which uses more buckets then entries
* stepping over buckets when two keys share the same hash so any key can find a free bucket.
*
- * See: http://en.wikipedia.org/wiki/Double_hashing
+ * See: https://en.wikipedia.org/wiki/Double_hashing
*
* \warning This should _only_ be used for small hashes where allocating a hash every time is unacceptable.
* Otherwise #GHash should be used instead.
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 31839a59ce1..677c90051f7 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2145,6 +2145,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p
prv->gputexture[i] = NULL;
}
prv->icon_id = 0;
+ prv->tag = 0;
}
return prv;
@@ -4740,6 +4741,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
smd->domain->tex = NULL;
smd->domain->tex_shadow = NULL;
smd->domain->tex_wt = NULL;
+ smd->domain->coba = newdataadr(fd, smd->domain->coba);
smd->domain->effector_weights = newdataadr(fd, smd->domain->effector_weights);
if (!smd->domain->effector_weights)
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index ed41ac0cb93..03436f4658a 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1515,6 +1515,11 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
writestruct(wd, DATA, SmokeDomainSettings, 1, smd->domain);
if (smd->domain) {
+
+ if (smd->domain->coba) {
+ writestruct(wd, DATA, ColorBand, 1, smd->domain->coba);
+ }
+
writestruct(wd, DATA, EffectorWeights, 1, smd->domain->effector_weights);
}
}
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 72ea7bd7f5d..104df625ee6 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -245,7 +245,7 @@ typedef struct BMesh {
/* ID of the shape key this bmesh came from */
int shapenr;
- int walkers, totflags;
+ int totflags;
ListBase selected;
BMFace *act_face;
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index e83b752947c..d2f638fa8f8 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -287,7 +287,7 @@ static BMLoop *bm_face_boundary_add(
#endif
BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL /* starte->l */, create_flag);
- bmesh_radial_append(starte, l);
+ bmesh_radial_loop_append(starte, l);
#ifdef USE_BMESH_HOLES
lst->first = lst->last = l;
@@ -295,8 +295,6 @@ static BMLoop *bm_face_boundary_add(
#else
f->l_first = l;
#endif
-
- l->f = f;
return l;
}
@@ -458,14 +456,11 @@ BMFace *BM_face_create(
f = bm_face_create__internal(bm);
startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag);
-
- startl->v = verts[0];
- startl->e = edges[0];
+
for (i = 1; i < len; i++) {
l = bm_loop_create(bm, verts[i], edges[i], f, NULL /* edges[i]->l */, create_flag);
-
- l->f = f;
- bmesh_radial_append(edges[i], l);
+
+ bmesh_radial_loop_append(edges[i], l);
l->prev = lastl;
lastl->next = l;
@@ -904,7 +899,7 @@ void BM_face_kill(BMesh *bm, BMFace *f)
do {
l_next = l_iter->next;
- bmesh_radial_loop_remove(l_iter, l_iter->e);
+ bmesh_radial_loop_remove(l_iter->e, l_iter);
bm_kill_only_loop(bm, l_iter);
} while ((l_iter = l_next) != l_first);
@@ -949,7 +944,7 @@ void BM_face_kill_loose(BMesh *bm, BMFace *f)
l_next = l_iter->next;
e = l_iter->e;
- bmesh_radial_loop_remove(l_iter, e);
+ bmesh_radial_loop_remove(e, l_iter);
bm_kill_only_loop(bm, l_iter);
if (e->l == NULL) {
@@ -981,23 +976,8 @@ void BM_face_kill_loose(BMesh *bm, BMFace *f)
*/
void BM_edge_kill(BMesh *bm, BMEdge *e)
{
-
- if (e->l) {
- BMLoop *l = e->l, *lnext, *startl = e->l;
-
- do {
- lnext = l->radial_next;
- if (lnext->f == l->f) {
- BM_face_kill(bm, l->f);
- break;
- }
-
- BM_face_kill(bm, l->f);
-
- if (l == lnext)
- break;
- l = lnext;
- } while (l != startl);
+ while (e->l) {
+ BM_face_kill(bm, e->l->f);
}
bmesh_disk_edge_remove(e, e->v1);
@@ -1011,15 +991,8 @@ void BM_edge_kill(BMesh *bm, BMEdge *e)
*/
void BM_vert_kill(BMesh *bm, BMVert *v)
{
- if (v->e) {
- BMEdge *e, *e_next;
-
- e = v->e;
- while (v->e) {
- e_next = bmesh_disk_edge_next(e, v);
- BM_edge_kill(bm, e);
- e = e_next;
- }
+ while (v->e) {
+ BM_edge_kill(bm, v->e);
}
bm_kill_only_vert(bm, v);
@@ -1077,7 +1050,7 @@ static bool bm_loop_reverse_loop(
int i, j, edok;
for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) {
- bmesh_radial_loop_remove(l_iter, (edar[i] = l_iter->e));
+ bmesh_radial_loop_remove((edar[i] = l_iter->e), l_iter);
}
/* actually reverse the loop */
@@ -1113,7 +1086,7 @@ static bool bm_loop_reverse_loop(
}
/* rebuild radial */
for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next)
- bmesh_radial_append(l_iter->e, l_iter);
+ bmesh_radial_loop_append(l_iter->e, l_iter);
#ifndef NDEBUG
/* validate radial */
@@ -1585,8 +1558,8 @@ BMFace *bmesh_sfme(
} while ((l_iter = l_iter->next) != l_first);
/* link up the new loops into the new edges radial */
- bmesh_radial_append(e, l_f1);
- bmesh_radial_append(e, l_f2);
+ bmesh_radial_loop_append(e, l_f1);
+ bmesh_radial_loop_append(e, l_f2);
f2->len = f2len;
@@ -1700,7 +1673,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
l = l_next;
l->f->len++;
l_next = l_next != l_next->radial_next ? l_next->radial_next : NULL;
- bmesh_radial_loop_remove(l, NULL);
+ bmesh_radial_loop_unlink(l);
l_new = bm_loop_create(bm, NULL, NULL, l->f, l, 0);
l_new->prev = l;
@@ -1725,8 +1698,8 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
l->radial_next = l->radial_prev = NULL;
}
- bmesh_radial_append(l_new->e, l_new);
- bmesh_radial_append(l->e, l);
+ bmesh_radial_loop_append(l_new->e, l_new);
+ bmesh_radial_loop_append(l->e, l);
}
else if (BM_verts_in_edge(l_new->v, l_new->next->v, e_new)) {
l_new->e = e_new;
@@ -1743,8 +1716,8 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
l->radial_next = l->radial_prev = NULL;
}
- bmesh_radial_append(l_new->e, l_new);
- bmesh_radial_append(l->e, l);
+ bmesh_radial_loop_append(l_new->e, l_new);
+ bmesh_radial_loop_append(l->e, l);
}
}
@@ -2619,8 +2592,8 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
l = e_src->l;
BLI_assert(BM_vert_in_edge(e_dst, l->v));
BLI_assert(BM_vert_in_edge(e_dst, l->next->v));
- bmesh_radial_loop_remove(l, e_src);
- bmesh_radial_append(e_dst, l);
+ bmesh_radial_loop_remove(e_src, l);
+ bmesh_radial_loop_append(e_dst, l);
}
BLI_assert(bmesh_radial_length(e_src->l) == 0);
@@ -2667,8 +2640,8 @@ void bmesh_edge_separate(
}
e_new = BM_edge_create(bm, e->v1, e->v2, e, BM_CREATE_NOP);
- bmesh_radial_loop_remove(l_sep, e);
- bmesh_radial_append(e_new, l_sep);
+ bmesh_radial_loop_remove(e, l_sep);
+ bmesh_radial_loop_append(e_new, l_sep);
l_sep->e = e_new;
if (copy_select) {
@@ -2855,8 +2828,8 @@ BMVert *bmesh_urmv_loop_multi(
do {
l_next = l_iter->radial_next;
if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
- bmesh_radial_loop_remove(l_iter, e);
- bmesh_radial_append(e_new, l_iter);
+ bmesh_radial_loop_remove(e, l_iter);
+ bmesh_radial_loop_append(e_new, l_iter);
l_iter->e = e_new;
}
} while ((l_iter = l_next) != l_first);
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 1f64f7b74cc..2591c33fc73 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -45,7 +45,7 @@
#include "bmesh.h"
#include "bmesh_log.h"
-#include "range_tree_c_api.h"
+#include "range_tree.h"
#include "BLI_strict_flags.h"
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 5ee0e904a33..6ce7c100b0d 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -161,7 +161,7 @@ static bool bm_face_split_edgenet_find_loop_pair(
e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary);
if (edges_boundary_len > 2) {
- BLI_SMALLSTACK_SWAP(edges_search, edges_wire);
+ BLI_SMALLSTACK_SWAP(edges_search, edges_boundary);
}
}
else {
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
index cb302139a4c..edde8cb5d31 100644
--- a/source/blender/bmesh/intern/bmesh_structure.c
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -143,7 +143,7 @@ void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src)
* to store non-manifold conditions since BM does not keep track of region/shell information.
*
* Functions relating to this cycle:
- * - #bmesh_radial_append
+ * - #bmesh_radial_loop_append
* - #bmesh_radial_loop_remove
* - #bmesh_radial_facevert_count
* - #bmesh_radial_facevert_check
@@ -389,6 +389,30 @@ bool bmesh_radial_validate(int radlen, BMLoop *l)
return true;
}
+void bmesh_radial_loop_append(BMEdge *e, BMLoop *l)
+{
+ if (e->l == NULL) {
+ e->l = l;
+ l->radial_next = l->radial_prev = l;
+ }
+ else {
+ l->radial_prev = e->l;
+ l->radial_next = e->l->radial_next;
+
+ e->l->radial_next->radial_prev = l;
+ e->l->radial_next = l;
+
+ e->l = l;
+ }
+
+ if (UNLIKELY(l->e && l->e != e)) {
+ /* l is already in a radial cycle for a different edge */
+ BMESH_ASSERT(0);
+ }
+
+ l->e = e;
+}
+
/**
* \brief BMESH RADIAL REMOVE LOOP
*
@@ -397,28 +421,27 @@ bool bmesh_radial_validate(int radlen, BMLoop *l)
* updated (in the case that the edge's link into the radial
* cycle was the loop which is being removed from the cycle).
*/
-void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e)
+void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l)
{
/* if e is non-NULL, l must be in the radial cycle of e */
- if (UNLIKELY(e && e != l->e)) {
+ if (UNLIKELY(e != l->e)) {
BMESH_ASSERT(0);
}
if (l->radial_next != l) {
- if (e && l == e->l)
+ if (l == e->l) {
e->l = l->radial_next;
+ }
l->radial_next->radial_prev = l->radial_prev;
l->radial_prev->radial_next = l->radial_next;
}
else {
- if (e) {
- if (l == e->l) {
- e->l = NULL;
- }
- else {
- BMESH_ASSERT(0);
- }
+ if (l == e->l) {
+ e->l = NULL;
+ }
+ else {
+ BMESH_ASSERT(0);
}
}
@@ -428,6 +451,22 @@ void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e)
l->e = NULL;
}
+/**
+ * A version of #bmesh_radial_loop_remove which only performs the radial unlink,
+ * leaving the edge untouched.
+ */
+void bmesh_radial_loop_unlink(BMLoop *l)
+{
+ if (l->radial_next != l) {
+ l->radial_next->radial_prev = l->radial_prev;
+ l->radial_prev->radial_next = l->radial_next;
+ }
+
+ /* l is no longer in a radial cycle; empty the links
+ * to the cycle and the link back to an edge */
+ l->radial_next = l->radial_prev = NULL;
+ l->e = NULL;
+}
/**
* \brief BME RADIAL FIND FIRST FACE VERT
@@ -484,30 +523,6 @@ int bmesh_radial_length(const BMLoop *l)
return i;
}
-void bmesh_radial_append(BMEdge *e, BMLoop *l)
-{
- if (e->l == NULL) {
- e->l = l;
- l->radial_next = l->radial_prev = l;
- }
- else {
- l->radial_prev = e->l;
- l->radial_next = e->l->radial_next;
-
- e->l->radial_next->radial_prev = l;
- e->l->radial_next = l;
-
- e->l = l;
- }
-
- if (UNLIKELY(l->e && l->e != e)) {
- /* l is already in a radial cycle for a different edge */
- BMESH_ASSERT(0);
- }
-
- l->e = e;
-}
-
/**
* \brief RADIAL COUNT FACE VERT
*
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index 07f94796bb2..679e7a269b3 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -55,8 +55,9 @@ BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WA
BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* RADIAL CYCLE MANAGMENT */
-void bmesh_radial_append(BMEdge *e, BMLoop *l) ATTR_NONNULL();
-void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e) ATTR_NONNULL(1);
+void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) ATTR_NONNULL();
+void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) ATTR_NONNULL();
+void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL();
/* note:
* bmesh_radial_loop_next(BMLoop *l) / prev.
* just use member access l->radial_next, l->radial_prev now */
diff --git a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
index a681583809c..70e0b2cfb57 100644
--- a/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
+++ b/source/blender/compositor/operations/COM_SunBeamsOperation.cpp
@@ -186,8 +186,8 @@ struct BufferLineAccumulator {
}
/* TODO implement proper filtering here, see
- * http://en.wikipedia.org/wiki/Lanczos_resampling
- * http://en.wikipedia.org/wiki/Sinc_function
+ * https://en.wikipedia.org/wiki/Lanczos_resampling
+ * https://en.wikipedia.org/wiki/Sinc_function
*
* using lanczos with x = distance from the line segment,
* normalized to a == 0.5f, could give a good result
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
index 76cd81f1b8f..da71db09f3d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
@@ -47,7 +47,7 @@ namespace DEG {
/* -------------------------------------------------- */
/* Performs a transitive reduction to remove redundant relations.
- * http://en.wikipedia.org/wiki/Transitive_reduction
+ * https://en.wikipedia.org/wiki/Transitive_reduction
*
* XXX The current implementation is somewhat naive and has O(V*E) worst case
* runtime.
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 75fb55a1b4d..b61b31a6be6 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -209,6 +209,9 @@ void DEG_id_tag_update_ex(Main *bmain, ID *id, short flag)
if (flag & (OB_RECALC_OB | OB_RECALC_DATA)) {
DEG_graph_id_tag_update(bmain, graph, id);
}
+ else if (flag & OB_RECALC_TIME) {
+ DEG_graph_id_tag_update(bmain, graph, id);
+ }
}
}
}
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 262ce0b9e23..d7899061218 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -263,7 +263,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
ot->poll = change_frame_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* rna */
ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 863f5e3852c..f3eeadb6604 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2219,7 +2219,7 @@ static void ui_but_drop(bContext *C, const wmEvent *event, uiBut *but, uiHandleB
/* ******************* copy and paste ******************** */
/* c = copy, v = paste */
-static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, char mode)
+static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, const char mode, const bool copy_array)
{
int buf_paste_len = 0;
const char *buf_paste = "";
@@ -2255,6 +2255,46 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
if (but->poin == NULL && but->rnapoin.data == NULL) {
/* pass */
}
+ else if (copy_array && but->rnapoin.data && but->rnaprop &&
+ ELEM(RNA_property_subtype(but->rnaprop), PROP_COLOR, PROP_TRANSLATION, PROP_DIRECTION,
+ PROP_VELOCITY, PROP_ACCELERATION, PROP_MATRIX, PROP_EULER, PROP_QUATERNION, PROP_AXISANGLE,
+ PROP_XYZ, PROP_XYZ_LENGTH, PROP_COLOR_GAMMA, PROP_COORDS))
+ {
+ float values[4];
+ int array_length = RNA_property_array_length(&but->rnapoin, but->rnaprop);
+
+ if (mode == 'c') {
+ char buf_copy[UI_MAX_DRAW_STR];
+
+ if (array_length == 4) {
+ values[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
+ }
+ else {
+ values[3] = 0.0f;
+ }
+ ui_but_v3_get(but, values);
+
+ BLI_snprintf(buf_copy, sizeof(buf_copy), "[%f, %f, %f, %f]", values[0], values[1], values[2], values[3]);
+ WM_clipboard_text_set(buf_copy, 0);
+ }
+ else {
+ if (sscanf(buf_paste, "[%f, %f, %f, %f]", &values[0], &values[1], &values[2], &values[3]) >= array_length) {
+ button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
+ ui_but_v3_set(but, values);
+ if (but->rnaprop && array_length == 4) {
+ RNA_property_float_set_index(&but->rnapoin, but->rnaprop, 3, values[3]);
+ }
+ data->value = values[but->rnaindex];
+
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ else {
+ WM_report(RPT_ERROR, "Paste expected 4 numbers, formatted: '[n, n, n, n]'");
+ show_report = true;
+ }
+ }
+ }
else if (mode == 'c') {
/* Get many decimal places, then strip trailing zeros.
* note: too high values start to give strange results */
@@ -6617,15 +6657,22 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
void ui_panel_menu(bContext *C, ARegion *ar, Panel *pa)
{
bScreen *sc = CTX_wm_screen(C);
+ const bool has_panel_category = UI_panel_category_is_visible(ar);
+ const bool any_item_visible = has_panel_category;
PointerRNA ptr;
uiPopupMenu *pup;
uiLayout *layout;
+ if (!any_item_visible) {
+ return;
+ }
+
RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr);
pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- if (UI_panel_category_is_visible(ar)) {
+
+ if (has_panel_category) {
char tmpstr[80];
BLI_snprintf(tmpstr, sizeof(tmpstr), "%s" UI_SEP_CHAR_S "%s", IFACE_("Pin"), IFACE_("Shift+Left Mouse"));
uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE);
@@ -6636,7 +6683,6 @@ void ui_panel_menu(bContext *C, ARegion *ar, Panel *pa)
uiBut *but = block->buttons.last;
but->flag |= UI_BUT_HAS_SEP_CHAR;
}
-
}
UI_popup_menu_end(C, pup);
}
@@ -6959,7 +7005,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if ((data->state == BUTTON_STATE_HIGHLIGHT) || (event->type == EVT_DROP)) {
/* handle copy-paste */
if (ELEM(event->type, CKEY, VKEY) && event->val == KM_PRESS &&
- IS_EVENT_MOD(event, ctrl, oskey) && !event->shift && !event->alt)
+ IS_EVENT_MOD(event, ctrl, oskey) && !event->shift)
{
/* Specific handling for listrows, we try to find their overlapping tex button. */
if (but->type == UI_BTYPE_LISTROW) {
@@ -6969,7 +7015,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
data = but->active;
}
}
- ui_but_copy_paste(C, but, data, (event->type == CKEY) ? 'c' : 'v');
+ ui_but_copy_paste(C, but, data, (event->type == CKEY) ? 'c' : 'v', event->alt);
return WM_UI_HANDLER_BREAK;
}
/* handle drop */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index f82ed82a922..02812f6a842 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1087,7 +1087,7 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
if (prv) {
const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
- if (id || prv->use_deferred) {
+ if (id || (prv->tag & PRV_TAG_DEFFERED) != 0) {
ui_id_preview_image_render_size(C, NULL, id, prv, size, true);
}
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 462ad34582b..09c5854fb26 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -3851,6 +3851,8 @@ void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
return;
}
+ SpaceButs *sbuts = CTX_wm_space_buts(C);
+
uiLayout *row = uiLayoutRow(layout, false);
uiBlock *block = uiLayoutGetBlock(row);
uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
@@ -3876,6 +3878,7 @@ void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
row = uiLayoutRow(layout, false);
+ uiLayoutSetEnabled(row, (sbuts->mainb == BCONTEXT_CONSTRAINT));
uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE);
/* TODO: unused for now, so no need to expose. */
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 2256bd7f8c5..a991f59e8e2 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -68,6 +68,8 @@
static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ RNA_boolean_set(op->ptr, "init_scene_frame_range", true);
+
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
Main *bmain = CTX_data_main(C);
char filepath[FILE_MAX];
@@ -231,11 +233,22 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "ngon_method", 0, NULL, ICON_NONE);
}
-static void wm_alembic_export_draw(bContext *UNUSED(C), wmOperator *op)
+static void wm_alembic_export_draw(bContext *C, wmOperator *op)
{
PointerRNA ptr;
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+
+ /* Conveniently set start and end frame to match the scene's frame range. */
+ Scene *scene = CTX_data_scene(C);
+
+ if (scene != NULL && RNA_boolean_get(&ptr, "init_scene_frame_range")) {
+ RNA_int_set(&ptr, "start", SFRA);
+ RNA_int_set(&ptr, "end", EFRA);
+
+ RNA_boolean_set(&ptr, "init_scene_frame_range", false);
+ }
+
ui_alembic_export_settings(op->layout, &ptr);
}
@@ -334,6 +347,11 @@ void WM_OT_alembic_export(wmOperatorType *ot)
RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_quad_method_items,
MOD_TRIANGULATE_NGON_BEAUTY, "Polygon Method", "Method for splitting the polygons into triangles");
+
+ /* This dummy prop is used to check whether we need to init the start and
+ * end frame values to that of the scene's, otherwise they are reset at
+ * every change, draw update. */
+ RNA_def_boolean(ot->srna, "init_scene_frame_range", false, "", "");
}
/* ************************************************************************** */
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index c5eea94f5e1..ebe8898571d 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -59,7 +59,9 @@ static int cachefile_open_invoke(bContext *C, wmOperator *op, const wmEvent *eve
{
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
char filepath[FILE_MAX];
- BLI_strncpy(filepath, G.main->name, sizeof(filepath));
+ Main *bmain = CTX_data_main(C);
+
+ BLI_strncpy(filepath, bmain->name, sizeof(filepath));
BLI_replace_extension(filepath, sizeof(filepath), ".abc");
RNA_string_set(op->ptr, "filepath", filepath);
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 5d5731a7e16..a6de1b284b7 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -32,6 +32,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_bitmap.h"
+#include "BLI_bitmap_draw_2d.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
@@ -294,7 +295,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short
lasso_mask_data.px = dr_mask;
lasso_mask_data.width = (xmax - xmin) + 1;
- fill_poly_v2i_n(
+ BLI_bitmap_draw_2d_poly_v2i_n(
xmin, ymin, xmax + 1, ymax + 1,
mcords, tot,
edbm_mask_lasso_px_cb, &lasso_mask_data);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 41c1669addd..b593ac0f2e8 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2233,7 +2233,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
"Orphan library objects added to the current scene to avoid loss");
}
- BKE_library_make_local(bmain, NULL, false, false); /* NULL is all libs */
+ BKE_library_make_local(bmain, NULL, NULL, false, false); /* NULL is all libs */
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index bd016b7fcfb..82da6f58912 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -2604,6 +2604,8 @@ static int vertex_group_remove_exec(bContext *C, wmOperator *op)
if (RNA_boolean_get(op->ptr, "all"))
BKE_object_defgroup_remove_all(ob);
+ else if (RNA_boolean_get(op->ptr, "all_unlocked"))
+ BKE_object_defgroup_remove_all_ex(ob, true);
else
vgroup_delete_active(ob);
@@ -2633,6 +2635,7 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot)
/* properties */
RNA_def_boolean(ot->srna, "all", 0, "All", "Remove all vertex groups");
+ RNA_def_boolean(ot->srna, "all_unlocked", 0, "All Unlocked", "Remove all unlocked vertex groups");
}
static int vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index ddbf59b2cf7..87c08dc6583 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -1080,13 +1080,19 @@ static void icon_preview_add_size(IconPreview *ip, unsigned int *rect, int sizex
static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short *do_update, float *progress)
{
IconPreview *ip = (IconPreview *)customdata;
- IconPreviewSize *cur_size = ip->sizes.first;
+ IconPreviewSize *cur_size;
const bool use_new_shading = BKE_scene_use_new_shading_nodes(ip->scene);
- while (cur_size) {
+ for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
PreviewImage *prv = ip->owner;
+
+ if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
+ /* Non-thread-protected reading is not an issue here. */
+ continue;
+ }
+
ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview");
- const bool is_render = !prv->use_deferred;
+ const bool is_render = !(prv->tag & PRV_TAG_DEFFERED);
/* construct shader preview from image size and previewcustomdata */
sp->scene = ip->scene;
@@ -1117,8 +1123,6 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
common_preview_startjob(sp, stop, do_update, progress);
shader_preview_free(sp);
-
- cur_size = cur_size->next;
}
}
@@ -1147,6 +1151,15 @@ static void icon_preview_endjob(void *customdata)
}
#endif
}
+
+ if (ip->owner) {
+ PreviewImage *prv_img = ip->owner;
+ prv_img->tag &= ~PRV_TAG_DEFFERED_RENDERING;
+ if (prv_img->tag & PRV_TAG_DEFFERED_DELETE) {
+ BLI_assert(prv_img->tag & PRV_TAG_DEFFERED);
+ BKE_previewimg_cached_release_pointer(prv_img);
+ }
+ }
}
static void icon_preview_free(void *customdata)
@@ -1205,6 +1218,14 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r
icon_preview_add_size(ip, rect, sizex, sizey);
+ /* Special threading hack: warn main code that this preview is being rendered and cannot be freed... */
+ {
+ PreviewImage *prv_img = owner;
+ if (prv_img->tag & PRV_TAG_DEFFERED) {
+ prv_img->tag |= PRV_TAG_DEFFERED_RENDERING;
+ }
+ }
+
/* setup job */
WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index a47b9a0b936..a4887c579ac 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -37,6 +37,7 @@
#include "BIF_glutil.h"
+#include "BLI_bitmap_draw_2d.h"
#include "BLI_math_matrix.h"
#include "BLI_math_geom.h"
#include "BLI_utildefines.h"
@@ -439,7 +440,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
data.width = data.rect.xmax - data.rect.xmin;
data.px = BLI_BITMAP_NEW(data.width * (data.rect.ymax - data.rect.ymin), __func__);
- fill_poly_v2i_n(
+ BLI_bitmap_draw_2d_poly_v2i_n(
data.rect.xmin, data.rect.ymin, data.rect.xmax, data.rect.ymax,
mcords, mcords_tot,
mask_lasso_px_cb, &data);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 1ca75246ba8..e1f577d1724 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -7629,10 +7629,6 @@ afterdraw:
if (!render_override && sds->draw_velocity) {
draw_smoke_velocity(sds, viewnormal);
}
-
-#ifdef SMOKE_DEBUG_HEAT
- draw_smoke_heat(smd->domain, ob);
-#endif
}
}
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 9cfcd6cef05..584f442bd44 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -1,4 +1,4 @@
-/*
+/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
@@ -42,6 +42,7 @@
#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_texture.h"
#include "smoke_API.h"
@@ -62,28 +63,33 @@ struct GPUTexture;
# include "PIL_time_utildefines.h"
#endif
-static GPUTexture *create_flame_spectrum_texture(void)
+/* *************************** Transfer functions *************************** */
+
+enum {
+ TFUNC_FLAME_SPECTRUM = 0,
+ TFUNC_COLOR_RAMP = 1,
+};
+
+#define TFUNC_WIDTH 256
+
+static void create_flame_spectrum_texture(float *data)
{
-#define SPEC_WIDTH 256
#define FIRE_THRESH 7
#define MAX_FIRE_ALPHA 0.06f
#define FULL_ON_FIRE 100
- GPUTexture *tex;
- int i, j, k;
- float *spec_data = MEM_mallocN(SPEC_WIDTH * 4 * sizeof(float), "spec_data");
- float *spec_pixels = MEM_mallocN(SPEC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
+ float *spec_pixels = MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels");
- blackbody_temperature_to_rgb_table(spec_data, SPEC_WIDTH, 1500, 3000);
+ blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000);
- for (i = 0; i < 16; i++) {
- for (j = 0; j < 16; j++) {
- for (k = 0; k < SPEC_WIDTH; k++) {
- int index = (j * SPEC_WIDTH * 16 + i * SPEC_WIDTH + k) * 4;
+ for (int i = 0; i < 16; i++) {
+ for (int j = 0; j < 16; j++) {
+ for (int k = 0; k < TFUNC_WIDTH; k++) {
+ int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4;
if (k >= FIRE_THRESH) {
- spec_pixels[index] = (spec_data[k * 4]);
- spec_pixels[index + 1] = (spec_data[k * 4 + 1]);
- spec_pixels[index + 2] = (spec_data[k * 4 + 2]);
+ spec_pixels[index] = (data[k * 4]);
+ spec_pixels[index + 1] = (data[k * 4 + 1]);
+ spec_pixels[index + 2] = (data[k * 4 + 2]);
spec_pixels[index + 3] = MAX_FIRE_ALPHA * (
(k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH));
}
@@ -94,19 +100,69 @@ static GPUTexture *create_flame_spectrum_texture(void)
}
}
- tex = GPU_texture_create_1D(SPEC_WIDTH, spec_pixels, NULL);
+ memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH);
- MEM_freeN(spec_data);
MEM_freeN(spec_pixels);
-#undef SPEC_WIDTH
#undef FIRE_THRESH
#undef MAX_FIRE_ALPHA
#undef FULL_ON_FIRE
+}
+
+static void create_color_ramp(const ColorBand *coba, float *data)
+{
+ for (int i = 0; i < TFUNC_WIDTH; i++) {
+ do_colorband(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
+ }
+}
+
+static GPUTexture *create_transfer_function(int type, const ColorBand *coba)
+{
+ float *data = MEM_mallocN(sizeof(float) * 4 * TFUNC_WIDTH, __func__);
+
+ switch (type) {
+ case TFUNC_FLAME_SPECTRUM:
+ create_flame_spectrum_texture(data);
+ break;
+ case TFUNC_COLOR_RAMP:
+ create_color_ramp(coba, data);
+ break;
+ }
+
+ GPUTexture *tex = GPU_texture_create_1D(TFUNC_WIDTH, data, NULL);
+
+ MEM_freeN(data);
return tex;
}
+static GPUTexture *create_field_texture(SmokeDomainSettings *sds)
+{
+ float *field = NULL;
+
+ switch (sds->coba_field) {
+#ifdef WITH_SMOKE
+ case FLUID_FIELD_DENSITY: field = smoke_get_density(sds->fluid); break;
+ case FLUID_FIELD_HEAT: field = smoke_get_heat(sds->fluid); break;
+ case FLUID_FIELD_FUEL: field = smoke_get_fuel(sds->fluid); break;
+ case FLUID_FIELD_REACT: field = smoke_get_react(sds->fluid); break;
+ case FLUID_FIELD_FLAME: field = smoke_get_flame(sds->fluid); break;
+ case FLUID_FIELD_VELOCITY_X: field = smoke_get_velocity_x(sds->fluid); break;
+ case FLUID_FIELD_VELOCITY_Y: field = smoke_get_velocity_y(sds->fluid); break;
+ case FLUID_FIELD_VELOCITY_Z: field = smoke_get_velocity_z(sds->fluid); break;
+ case FLUID_FIELD_COLOR_R: field = smoke_get_color_r(sds->fluid); break;
+ case FLUID_FIELD_COLOR_G: field = smoke_get_color_g(sds->fluid); break;
+ case FLUID_FIELD_COLOR_B: field = smoke_get_color_b(sds->fluid); break;
+ case FLUID_FIELD_FORCE_X: field = smoke_get_force_x(sds->fluid); break;
+ case FLUID_FIELD_FORCE_Y: field = smoke_get_force_y(sds->fluid); break;
+ case FLUID_FIELD_FORCE_Z: field = smoke_get_force_z(sds->fluid); break;
+#endif
+ default: return NULL;
+ }
+
+ return GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, field);
+}
+
typedef struct VolumeSlicer {
float size[3];
float min[3];
@@ -347,6 +403,7 @@ static int create_view_aligned_slices(VolumeSlicer *slicer,
}
static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture *tex_spec,
+ GPUTexture *tex_tfunc, GPUTexture *tex_coba,
bool use_fire, const float min[3],
const float ob_sizei[3], const float invsize[3])
{
@@ -359,6 +416,8 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
int densityscale_location;
int spec_location, flame_location;
int shadow_location, actcol_location;
+ int tfunc_location = 0;
+ int coba_location = 0;
if (use_fire) {
spec_location = GPU_shader_get_uniform(shader, "spectrum_texture");
@@ -370,6 +429,11 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
soot_location = GPU_shader_get_uniform(shader, "soot_texture");
stepsize_location = GPU_shader_get_uniform(shader, "step_size");
densityscale_location = GPU_shader_get_uniform(shader, "density_scale");
+
+ if (sds->use_coba) {
+ tfunc_location = GPU_shader_get_uniform(shader, "transfer_texture");
+ coba_location = GPU_shader_get_uniform(shader, "color_band_texture");
+ }
}
GPU_shader_bind(shader);
@@ -397,6 +461,14 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
if ((sds->active_fields & SM_ACTIVE_COLORS) == 0)
mul_v3_v3(active_color, sds->active_color);
GPU_shader_uniform_vector(shader, actcol_location, 3, 1, active_color);
+
+ if (sds->use_coba) {
+ GPU_texture_bind(tex_tfunc, 4);
+ GPU_shader_uniform_texture(shader, tfunc_location, tex_tfunc);
+
+ GPU_texture_bind(tex_coba, 5);
+ GPU_shader_uniform_texture(shader, coba_location, tex_coba);
+ }
}
GPU_shader_uniform_vector(shader, min_location, 3, 1, min);
@@ -404,7 +476,8 @@ static void bind_shader(SmokeDomainSettings *sds, GPUShader *shader, GPUTexture
GPU_shader_uniform_vector(shader, invsize_location, 3, 1, invsize);
}
-static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool use_fire)
+static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec,
+ GPUTexture *tex_tfunc, GPUTexture *tex_coba, bool use_fire)
{
GPU_shader_unbind();
@@ -417,20 +490,30 @@ static void unbind_shader(SmokeDomainSettings *sds, GPUTexture *tex_spec, bool u
}
else {
GPU_texture_unbind(sds->tex_shadow);
+
+ if (sds->use_coba) {
+ GPU_texture_unbind(tex_tfunc);
+ GPU_texture_free(tex_tfunc);
+
+ GPU_texture_unbind(tex_coba);
+ GPU_texture_free(tex_coba);
+ }
}
}
static void draw_buffer(SmokeDomainSettings *sds, GPUShader *shader, const VolumeSlicer *slicer,
const float ob_sizei[3], const float invsize[3], const int num_points, const bool do_fire)
{
- GPUTexture *tex_spec = (do_fire) ? create_flame_spectrum_texture() : NULL;
+ GPUTexture *tex_spec = (do_fire) ? create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL) : NULL;
+ GPUTexture *tex_tfunc = (sds->use_coba) ? create_transfer_function(TFUNC_COLOR_RAMP, sds->coba) : NULL;
+ GPUTexture *tex_coba = (sds->use_coba) ? create_field_texture(sds) : NULL;
GLuint vertex_buffer;
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * num_points, &slicer->verts[0][0], GL_STATIC_DRAW);
- bind_shader(sds, shader, tex_spec, do_fire, slicer->min, ob_sizei, invsize);
+ bind_shader(sds, shader, tex_spec, tex_tfunc, tex_coba, do_fire, slicer->min, ob_sizei, invsize);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, NULL);
@@ -439,7 +522,7 @@ static void draw_buffer(SmokeDomainSettings *sds, GPUShader *shader, const Volum
glDisableClientState(GL_VERTEX_ARRAY);
- unbind_shader(sds, tex_spec, do_fire);
+ unbind_shader(sds, tex_spec, tex_tfunc, tex_coba, do_fire);
/* cleanup */
@@ -459,7 +542,16 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) && sds->tex_flame;
- GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_SMOKE);
+ GPUBuiltinShader builtin_shader;
+
+ if (sds->use_coba) {
+ builtin_shader = GPU_SHADER_SMOKE_COBA;
+ }
+ else {
+ builtin_shader = GPU_SHADER_SMOKE;
+ }
+
+ GPUShader *shader = GPU_shader_get_builtin_shader(builtin_shader);
if (!shader) {
fprintf(stderr, "Unable to create GLSL smoke shader.\n");
@@ -549,7 +641,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob,
draw_buffer(sds, shader, &slicer, ob_sizei, invsize, num_points, false);
/* Draw fire separately (T47639). */
- if (use_fire) {
+ if (use_fire && !sds->use_coba) {
glBlendFunc(GL_ONE, GL_ONE);
draw_buffer(sds, fire_shader, &slicer, ob_sizei, invsize, num_points, true);
}
@@ -759,50 +851,3 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3])
UNUSED_VARS(domain, viewnormal);
#endif
}
-
-#ifdef SMOKE_DEBUG_HEAT
-void draw_smoke_heat(SmokeDomainSettings *domain, Object *ob)
-{
- float x, y, z;
- float x0, y0, z0;
- int *base_res = domain->base_res;
- int *res = domain->res;
- int *res_min = domain->res_min;
- int *res_max = domain->res_max;
- float *heat = smoke_get_heat(domain->fluid);
-
- float min[3];
- float *cell_size = domain->cell_size;
- float step_size = ((float)max_iii(base_res[0], base_res[1], base_res[2])) / 16.f;
- float vf = domain->scale / 16.f * 2.f; /* velocity factor */
-
- /* set first position so that it doesn't jump when domain moves */
- x0 = res_min[0] + fmod(-(float)domain->shift[0] + res_min[0], step_size);
- y0 = res_min[1] + fmod(-(float)domain->shift[1] + res_min[1], step_size);
- z0 = res_min[2] + fmod(-(float)domain->shift[2] + res_min[2], step_size);
- if (x0 < res_min[0]) x0 += step_size;
- if (y0 < res_min[1]) y0 += step_size;
- if (z0 < res_min[2]) z0 += step_size;
- add_v3_v3v3(min, domain->p0, domain->obj_shift_f);
-
- for (x = floor(x0); x < res_max[0]; x += step_size)
- for (y = floor(y0); y < res_max[1]; y += step_size)
- for (z = floor(z0); z < res_max[2]; z += step_size) {
- int index = (floor(x) - res_min[0]) + (floor(y) - res_min[1]) * res[0] + (floor(z) - res_min[2]) * res[0] * res[1];
-
- float pos[3] = {min[0] + ((float)x + 0.5f) * cell_size[0], min[1] + ((float)y + 0.5f) * cell_size[1], min[2] + ((float)z + 0.5f) * cell_size[2]};
-
- /* draw heat as different sized points */
- if (heat[index] >= 0.01f) {
- float col_gb = 1.0f - heat[index];
- CLAMP(col_gb, 0.0f, 1.0f);
- glColor3f(1.0f, col_gb, col_gb);
- glPointSize(24.0f * heat[index]);
-
- glBegin(GL_POINTS);
- glVertex3f(pos[0], pos[1], pos[2]);
- glEnd();
- }
- }
-}
-#endif
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 2c4b04ebd34..6b53e9b0ae8 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -41,6 +41,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap_draw_2d.h"
#include "BLI_blenlib.h"
#include "BLI_kdopbvh.h"
#include "BLI_math.h"
@@ -5048,7 +5049,7 @@ bool ED_view3d_autodist_depth_seg(ARegion *ar, const int mval_sta[2], const int
copy_v2_v2_int(p1, mval_sta);
copy_v2_v2_int(p2, mval_end);
- plot_line_v2v2i(p1, p2, depth_segment_cb, &data);
+ BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data);
*depth = data.depth;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index fb3ef8bd599..a5d8ebb7ce1 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -310,14 +310,8 @@ void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
const float min[3], const float max[3],
const float viewnormal[3]);
-//#define SMOKE_DEBUG_HEAT
-
void draw_smoke_velocity(struct SmokeDomainSettings *domain, float viewnormal[3]);
-#ifdef SMOKE_DEBUG_HEAT
-void draw_smoke_heat(struct SmokeDomainSettings *domain, struct Object *ob);
-#endif
-
/* workaround for trivial but noticeable camera bug caused by imprecision
* between view border calculation in 2D/3D space, workaround for bug [#28037].
* without this define we get the old behavior which is to try and align them
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index aead5baaaf1..74dc91b55ef 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -89,6 +89,7 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
GPU_SHADER_SMOKE = 2,
GPU_SHADER_SMOKE_FIRE = 3,
+ GPU_SHADER_SMOKE_COBA = 4,
/* specialized drawing */
GPU_SHADER_TEXT,
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 2e1c3b70a6e..699028d6570 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -106,6 +106,7 @@ static struct GPUShadersGlobal {
GPUShader *sep_gaussian_blur;
GPUShader *smoke;
GPUShader *smoke_fire;
+ GPUShader *smoke_coba;
/* cache for shader fx. Those can exist in combinations so store them here */
GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
/* specialized drawing */
@@ -653,6 +654,13 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.smoke_fire;
break;
+ case GPU_SHADER_SMOKE_COBA:
+ if (!GG.shaders.smoke_coba)
+ GG.shaders.smoke_coba = GPU_shader_create(
+ datatoc_gpu_shader_smoke_vert_glsl, datatoc_gpu_shader_smoke_frag_glsl,
+ NULL, NULL, "#define USE_COBA;\n", 0, 0, 0);
+ retval = GG.shaders.smoke_coba;
+ break;
case GPU_SHADER_TEXT:
if (!GG.shaders.text)
GG.shaders.text = GPU_shader_create(
@@ -954,6 +962,11 @@ void GPU_shader_free_builtin_shaders(void)
GG.shaders.smoke_fire = NULL;
}
+ if (GG.shaders.smoke_coba) {
+ GPU_shader_free(GG.shaders.smoke_coba);
+ GG.shaders.smoke_coba = NULL;
+ }
+
if (GG.shaders.text) {
GPU_shader_free(GG.shaders.text);
GG.shaders.text = NULL;
diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
index fd790009e02..6ded453225e 100644
--- a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
@@ -8,10 +8,17 @@ uniform float density_scale;
uniform sampler3D soot_texture;
uniform sampler3D shadow_texture;
+#ifdef USE_COBA
+uniform sampler1D transfer_texture;
+uniform sampler3D color_band_texture;
+#endif
+
void main()
{
/* compute color and density from volume texture */
vec4 soot = texture3D(soot_texture, coords);
+
+#ifndef USE_COBA
vec3 soot_color;
if (soot.a != 0) {
soot_color = active_color * soot.rgb / soot.a;
@@ -31,6 +38,11 @@ void main()
/* premultiply alpha */
vec4 color = vec4(soot_alpha * soot_color, soot_alpha);
+#else
+ float color_band = texture3D(color_band_texture, coords).r;
+ vec4 transfer_function = texture1D(transfer_texture, color_band);
+ vec4 color = transfer_function * density_scale;
+#endif
gl_FragColor = color;
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 45eb31235f5..7bbbb8addcc 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -172,6 +172,13 @@ enum ePreviewImage_Flag {
PRV_USER_EDITED = (1 << 1), /* if user-edited, do not auto-update this anymore! */
};
+/* for PreviewImage->tag */
+enum {
+ PRV_TAG_DEFFERED = (1 << 0), /* Actual loading of preview is deffered. */
+ PRV_TAG_DEFFERED_RENDERING = (1 << 1), /* Deffered preview is being loaded. */
+ PRV_TAG_DEFFERED_DELETE = (1 << 2), /* Deffered preview should be deleted asap. */
+};
+
typedef struct PreviewImage {
/* All values of 2 are really NUM_ICON_SIZES */
unsigned int w[2];
@@ -184,12 +191,12 @@ typedef struct PreviewImage {
struct GPUTexture *gputexture[2];
int icon_id; /* Used by previews outside of ID context. */
- char pad[3];
- char use_deferred; /* for now a mere bool, if we add more deferred loading methods we can switch to bitflag. */
+ short tag; /* Runtime data. */
+ char pad[2];
} PreviewImage;
#define PRV_DEFERRED_DATA(prv) \
- (CHECK_TYPE_INLINE(prv, PreviewImage *), BLI_assert((prv)->use_deferred), (void *)((prv) + 1))
+ (CHECK_TYPE_INLINE(prv, PreviewImage *), BLI_assert((prv)->tag & PRV_TAG_DEFFERED), (void *)((prv) + 1))
/**
* Defines for working with IDs.
diff --git a/source/blender/makesdna/DNA_cachefile_types.h b/source/blender/makesdna/DNA_cachefile_types.h
index dd47d63fc19..46b1adf2725 100644
--- a/source/blender/makesdna/DNA_cachefile_types.h
+++ b/source/blender/makesdna/DNA_cachefile_types.h
@@ -36,10 +36,10 @@
extern "C" {
#endif
-
/* CacheFile::flag */
enum {
CACHEFILE_DS_EXPAND = (1 << 0),
+ CACHEFILE_DIRTY = (1 << 1),
};
/* CacheFile::draw_flag */
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index fc4e7de73f5..ca774864e95 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -461,6 +461,7 @@ typedef struct bObjectSolverConstraint {
/* Transform matrix cache constraint */
typedef struct bTransformCacheConstraint {
struct CacheFile *cache_file;
+ struct CacheReader *reader;
char object_path[1024]; /* FILE_MAX */
} bTransformCacheConstraint;
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 7872ee09259..4a3d330a698 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -1517,6 +1517,7 @@ typedef struct MeshSeqCacheModifierData {
ModifierData modifier;
struct CacheFile *cache_file;
+ struct CacheReader *reader;
char object_path[1024]; /* 1024 = FILE_MAX */
char read_flag;
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index 68b7f559fce..4ee83346fe3 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -77,6 +77,23 @@ enum {
VECTOR_DRAW_STREAMLINE = 1,
};
+enum {
+ FLUID_FIELD_DENSITY = 0,
+ FLUID_FIELD_HEAT = 1,
+ FLUID_FIELD_FUEL = 2,
+ FLUID_FIELD_REACT = 3,
+ FLUID_FIELD_FLAME = 4,
+ FLUID_FIELD_VELOCITY_X = 5,
+ FLUID_FIELD_VELOCITY_Y = 6,
+ FLUID_FIELD_VELOCITY_Z = 7,
+ FLUID_FIELD_COLOR_R = 8,
+ FLUID_FIELD_COLOR_G = 9,
+ FLUID_FIELD_COLOR_B = 10,
+ FLUID_FIELD_FORCE_X = 11,
+ FLUID_FIELD_FORCE_Y = 12,
+ FLUID_FIELD_FORCE_Z = 13,
+};
+
/* cache compression */
#define SM_CACHE_LIGHT 0
#define SM_CACHE_HEAVY 1
@@ -190,9 +207,13 @@ typedef struct SmokeDomainSettings {
float slice_per_voxel;
float slice_depth;
float display_thickness;
+
+ struct ColorBand *coba;
float vector_scale;
char vector_draw_type;
- char pad2[3];
+ char use_coba;
+ char coba_field; /* simulation field used for the color mapping */
+ char pad2;
} SmokeDomainSettings;
diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c
index 7249ebd5feb..09fdeb15b10 100644
--- a/source/blender/makesrna/intern/rna_cachefile.c
+++ b/source/blender/makesrna/intern/rna_cachefile.c
@@ -37,6 +37,8 @@
#include "BKE_cachefile.h"
#include "BKE_depsgraph.h"
+#include "BLI_string.h"
+
#include "DEG_depsgraph.h"
#include "WM_api.h"
@@ -60,6 +62,12 @@ static void rna_CacheFile_update_handle(Main *bmain, Scene *scene, PointerRNA *p
{
CacheFile *cache_file = ptr->data;
+ if ((cache_file->flag & CACHEFILE_DIRTY) != 0) {
+ BKE_cachefile_clean(scene, cache_file);
+ BLI_freelistN(&cache_file->object_paths);
+ cache_file->flag &= ~CACHEFILE_DIRTY;
+ }
+
BKE_cachefile_reload(bmain, cache_file);
rna_CacheFile_update(bmain, scene, ptr);
@@ -71,6 +79,20 @@ static void rna_CacheFile_object_paths_begin(CollectionPropertyIterator *iter, P
rna_iterator_listbase_begin(iter, &cache_file->object_paths, NULL);
}
+static void rna_CacheFile_filename_set(PointerRNA *ptr, const char *value)
+{
+ CacheFile *cache_file = ptr->data;
+
+ if (STREQ(cache_file->filepath, value)) {
+ return;
+ }
+
+ /* Different file is opened, close all readers. */
+ cache_file->flag |= CACHEFILE_DIRTY;
+
+ BLI_strncpy(cache_file->filepath, value, sizeof(cache_file->filepath));
+}
+
#else
/* cachefile.object_paths */
@@ -103,6 +125,7 @@ static void rna_def_cachefile(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_FILE);
PropertyRNA *prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_CacheFile_filename_set");
RNA_def_property_ui_text(prop, "File Path", "Path to external displacements file");
RNA_def_property_update(prop, 0, "rna_CacheFile_update_handle");
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index db3f76f3cfc..de1a0f24c31 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -148,12 +148,17 @@ static EnumPropertyItem space_object_items[] = {
{0, NULL, 0, NULL, NULL}
};
+#include "DNA_cachefile_types.h"
+
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#ifdef WITH_ALEMBIC
+# include "ABC_alembic.h"
+#endif
static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr)
{
@@ -471,6 +476,22 @@ static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr, PointerRNA v
}
}
+static void rna_Constraint_transformCache_object_path_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+#ifdef WITH_ALEMBIC
+ bConstraint *con = (bConstraint *)ptr->data;
+ bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data;
+ Object *ob = (Object *)ptr->id.data;
+
+ data->reader = CacheReader_open_alembic_object(data->cache_file->handle,
+ data->reader,
+ ob,
+ data->object_path);
+#endif
+
+ rna_Constraint_update(bmain, scene, ptr);
+}
+
#else
static EnumPropertyItem constraint_distance_items[] = {
@@ -2593,7 +2614,7 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna)
prop = RNA_def_property(srna, "object_path", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Object Path", "Path to the object in the Alembic archive used to lookup the transform matrix");
- RNA_def_property_update(prop, 0, "rna_Constraint_update");
+ RNA_def_property_update(prop, 0, "rna_Constraint_transformCache_object_path_update");
}
/* base struct for constraints */
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index de5dd2b2b56..5d78df105da 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1117,6 +1117,21 @@ static int rna_CorrectiveSmoothModifier_is_bind_get(PointerRNA *ptr)
return (csmd->bind_coords != NULL);
}
+static void rna_MeshSequenceCache_object_path_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+#ifdef WITH_ALEMBIC
+ MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)ptr->data;
+ Object *ob = (Object *)ptr->id.data;
+
+ mcmd->reader = CacheReader_open_alembic_object(mcmd->cache_file->handle,
+ mcmd->reader,
+ ob,
+ mcmd->object_path);
+#endif
+
+ rna_Modifier_update(bmain, scene, ptr);
+}
+
#else
static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[])
@@ -4135,7 +4150,7 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
prop = RNA_def_property(srna, "object_path", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Object Path", "Path to the object in the Alembic archive used to lookup geometric data");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_def_property_update(prop, 0, "rna_MeshSequenceCache_object_path_update");
static EnumPropertyItem read_flag_items[] = {
{MOD_MESHSEQ_READ_VERT, "VERT", 0, "Vertex", ""},
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 6baf2f3631d..08054315334 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -30,6 +30,7 @@
#include <limits.h>
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "rna_internal.h"
@@ -51,6 +52,7 @@
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_texture.h"
#include "smoke_API.h"
@@ -354,6 +356,17 @@ static void rna_SmokeFlow_uvlayer_set(PointerRNA *ptr, const char *value)
rna_object_uvlayer_name_set(ptr, value, flow->uvlayer_name, sizeof(flow->uvlayer_name));
}
+static void rna_Smoke_use_color_ramp_set(PointerRNA *ptr, int value)
+{
+ SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
+
+ sds->use_coba = value;
+
+ if (value && sds->coba == NULL) {
+ sds->coba = add_colorband(false);
+ }
+}
+
#else
static void rna_def_smoke_domain_settings(BlenderRNA *brna)
@@ -744,6 +757,41 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3);
RNA_def_property_ui_text(prop, "Scale", "Multiplier for scaling the vectors");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ /* --------- Color mapping. --------- */
+
+ prop = RNA_def_property(srna, "use_color_ramp", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "use_coba", 0);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_Smoke_use_color_ramp_set");
+ RNA_def_property_ui_text(prop, "Use Color Ramp",
+ "Render a simulation field while mapping its voxels values to the colors of a ramp");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ static EnumPropertyItem coba_field_items[] = {
+ {FLUID_FIELD_COLOR_R, "COLOR_R", 0, "Red", "Red component of the color field"},
+ {FLUID_FIELD_COLOR_G, "COLOR_G", 0, "Green", "Green component of the color field"},
+ {FLUID_FIELD_COLOR_B, "COLOR_B", 0, "Blue", "Blue component of the color field"},
+ {FLUID_FIELD_DENSITY, "DENSITY", 0, "Density", "Quantity of soot in the fluid"},
+ {FLUID_FIELD_FLAME, "FLAME", 0, "Flame", "Flame field"},
+ {FLUID_FIELD_FUEL, "FUEL", 0, "Fuel", "Fuel field"},
+ {FLUID_FIELD_HEAT, "HEAT", 0, "Heat", "Temperature of the fluid"},
+ {FLUID_FIELD_VELOCITY_X, "VELOCITY_X", 0, "X Velocity", "X component of the velocity field"},
+ {FLUID_FIELD_VELOCITY_Y, "VELOCITY_Y", 0, "Y Velocity", "Y component of the velocity field"},
+ {FLUID_FIELD_VELOCITY_Z, "VELOCITY_Z", 0, "Z Velocity", "Z component of the velocity field"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ prop = RNA_def_property(srna, "coba_field", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "coba_field");
+ RNA_def_property_enum_items(prop, coba_field_items);
+ RNA_def_property_ui_text(prop, "Field", "Simulation field to color map");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "color_ramp", PROP_POINTER, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "coba");
+ RNA_def_property_struct_type(prop, "ColorRamp");
+ RNA_def_property_ui_text(prop, "Color Ramp", "");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
}
static void rna_def_smoke_flow_settings(BlenderRNA *brna)
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 355ac9563dd..d25e8e38de3 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -65,6 +65,7 @@ static void copyData(ModifierData *md, ModifierData *target)
if (tmcmd->cache_file) {
id_us_plus(&tmcmd->cache_file->id);
+ tmcmd->reader = NULL;
}
}
@@ -75,6 +76,12 @@ static void freeData(ModifierData *md)
if (mcmd->cache_file) {
id_us_min(&mcmd->cache_file->id);
}
+
+ if (mcmd->reader) {
+#ifdef WITH_ALEMBIC
+ CacheReader_free(mcmd->reader);
+#endif
+ }
}
static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
@@ -102,10 +109,16 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
BKE_cachefile_ensure_handle(G.main, cache_file);
- DerivedMesh *result = ABC_read_mesh(cache_file->handle,
+ if (!mcmd->reader) {
+ mcmd->reader = CacheReader_open_alembic_object(cache_file->handle,
+ mcmd->reader,
+ ob,
+ mcmd->object_path);
+ }
+
+ DerivedMesh *result = ABC_read_mesh(mcmd->reader,
ob,
dm,
- mcmd->object_path,
time,
&err_str,
mcmd->read_flag);
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
index bb7f2166a8a..0be47c4f751 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -36,6 +36,7 @@ static bNodeSocketTemplate sh_node_tex_brick_in[] = {
{ SOCK_RGBA, 1, N_("Mortar"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Scale"), 5.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Mortar Size"), 0.02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.125f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
+ { SOCK_FLOAT, 1, N_("Mortar Smooth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Bias"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Brick Width"), 0.5f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
{ SOCK_FLOAT, 1, N_("Row Height"), 0.25f, 0.0f, 0.0f, 0.0f, 0.01f, 100.0f, PROP_NONE, SOCK_NO_INTERNAL_LINK},
@@ -60,6 +61,12 @@ static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node)
tex->squash_freq = 2;
node->storage = tex;
+
+ for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Mortar Smooth")) {
+ ((bNodeSocketValueFloat*)sock->default_value)->value = 0.1f;
+ }
+ }
}
static int node_shader_gpu_tex_brick(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
diff --git a/source/blender/physics/intern/hair_volume.cpp b/source/blender/physics/intern/hair_volume.cpp
index d79cf7d8c31..5cc1231e6cb 100644
--- a/source/blender/physics/intern/hair_volume.cpp
+++ b/source/blender/physics/intern/hair_volume.cpp
@@ -710,7 +710,7 @@ bool BPH_hair_volume_solve_divergence(HairGrid *grid, float /*dt*/, float target
* div(grad(p)) = div(v)
*
* The finite difference approximation yields the linear equation system described here:
- * http://en.wikipedia.org/wiki/Discrete_Poisson_equation
+ * https://en.wikipedia.org/wiki/Discrete_Poisson_equation
*/
lMatrix A(num_cellsA, num_cellsA);
/* Reserve space for the base equation system (without boundary conditions).
@@ -888,7 +888,7 @@ bool BPH_hair_volume_solve_divergence(HairGrid *grid, float /*dt*/, float target
#if 0 /* XXX weighting is incorrect, disabled for now */
/* Velocity filter kernel
- * See http://en.wikipedia.org/wiki/Filter_%28large_eddy_simulation%29
+ * See https://en.wikipedia.org/wiki/Filter_%28large_eddy_simulation%29
*/
BLI_INLINE void hair_volume_filter_box_convolute(HairVertexGrid *grid, float invD, const int kernel_size[3], int i, int j, int k)
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index ec69abbb1df..15f3c665fcf 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -33,6 +33,7 @@
#include <stddef.h>
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "BLI_string.h"
#include "BLI_linklist.h"
#include "BLI_path_util.h"
@@ -405,6 +406,8 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
BLO_blendhandle_close(self->blo_handle);
self->blo_handle = NULL;
+ GHash *old_to_new_ids = BLI_ghash_ptr_new(__func__);
+
/* copied from wm_operator.c */
{
/* mark all library linked objects to be updated */
@@ -412,7 +415,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
/* append, rather than linking */
if ((self->flag & FILE_LINK) == 0) {
- BKE_library_make_local(bmain, lib, true, false);
+ BKE_library_make_local(bmain, lib, old_to_new_ids, true, false);
}
}
@@ -439,6 +442,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
ID *id;
id = PyCapsule_GetPointer(item, NULL);
+ id = BLI_ghash_lookup_default(old_to_new_ids, id, id);
Py_DECREF(item);
RNA_id_pointer_create(id, &id_ptr);
@@ -452,6 +456,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
}
#endif /* USE_RNA_DATABLOCKS */
+ BLI_ghash_free(old_to_new_ids, NULL, NULL);
Py_RETURN_NONE;
}
}
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 71288871104..4e980e4c0e6 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -1394,7 +1394,7 @@ PyDoc_STRVAR(Matrix_invert_doc,
" (instead of raising a :exc:`ValueError` exception).\n"
" :type fallback: :class:`Matrix`\n"
"\n"
-" .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n"
+" .. seealso:: <https://en.wikipedia.org/wiki/Inverse_matrix>\n"
);
static PyObject *Matrix_invert(MatrixObject *self, PyObject *args)
{
@@ -1505,7 +1505,7 @@ PyDoc_STRVAR(Matrix_invert_safe_doc,
" If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n"
" If tweaked matrix is still degenerated, set to the identity matrix instead.\n"
"\n"
-" .. seealso:: <http://en.wikipedia.org/wiki/Inverse_matrix>\n"
+" .. seealso:: <https://en.wikipedia.org/wiki/Inverse_matrix>\n"
);
static PyObject *Matrix_invert_safe(MatrixObject *self)
{
@@ -1556,7 +1556,7 @@ PyDoc_STRVAR(Matrix_adjugate_doc,
"\n"
" .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n"
"\n"
-" .. seealso:: <http://en.wikipedia.org/wiki/Adjugate_matrix>\n"
+" .. seealso:: <https://en.wikipedia.org/wiki/Adjugate_matrix>\n"
);
static PyObject *Matrix_adjugate(MatrixObject *self)
{
@@ -1733,7 +1733,7 @@ PyDoc_STRVAR(Matrix_determinant_doc,
" :return: Return the determinant of a matrix.\n"
" :rtype: float\n"
"\n"
-" .. seealso:: <http://en.wikipedia.org/wiki/Determinant>\n"
+" .. seealso:: <https://en.wikipedia.org/wiki/Determinant>\n"
);
static PyObject *Matrix_determinant(MatrixObject *self)
{
@@ -1755,7 +1755,7 @@ PyDoc_STRVAR(Matrix_transpose_doc,
"\n"
" Set the matrix to its transpose.\n"
"\n"
-" .. seealso:: <http://en.wikipedia.org/wiki/Transpose>\n"
+" .. seealso:: <https://en.wikipedia.org/wiki/Transpose>\n"
);
static PyObject *Matrix_transpose(MatrixObject *self)
{
@@ -1890,7 +1890,7 @@ PyDoc_STRVAR(Matrix_identity_doc,
" .. note:: An object with zero location and rotation, a scale of one,\n"
" will have an identity matrix.\n"
"\n"
-" .. seealso:: <http://en.wikipedia.org/wiki/Identity_matrix>\n"
+" .. seealso:: <https://en.wikipedia.org/wiki/Identity_matrix>\n"
);
static PyObject *Matrix_identity(MatrixObject *self)
{
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index e872ec1a524..3b733f9558c 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -419,7 +419,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive");
if (use_recursive) {
- BKE_library_make_local(bmain, NULL, true, set_fake);
+ BKE_library_make_local(bmain, NULL, NULL, true, set_fake);
}
else {
LinkNode *itemlink;
@@ -430,7 +430,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
ID *new_id = ((WMLinkAppendDataItem *)(itemlink->link))->new_id;
if (new_id && !BLI_gset_haskey(done_libraries, new_id->lib)) {
- BKE_library_make_local(bmain, new_id->lib, true, set_fake);
+ BKE_library_make_local(bmain, new_id->lib, NULL, true, set_fake);
BLI_gset_insert(done_libraries, new_id->lib);
}
}
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 1357729e898..46203333eb5 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -37,6 +37,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap_draw_2d.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -272,7 +273,7 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
unsigned char *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__);
struct LassoFillData lasso_fill_data = {pixel_buf, w};
- fill_poly_v2i_n(
+ BLI_bitmap_draw_2d_poly_v2i_n(
rect.xmin, rect.ymin, rect.xmax, rect.ymax,
(const int (*)[2])moves, tot,
draw_filled_lasso_px_cb, &lasso_fill_data);