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
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-03-02 06:09:27 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-03-02 06:09:27 +0300
commit4913e47aa0107cbe1daf06e8020a60916ea883a3 (patch)
tree29cf5e0671027f74296d866cff0df66267bd09c8
parentb7016e69b3fff44d623f8413f9ebd4f7216a9b9b (diff)
parent7e4c23e4d7a3a27a49930824c822b679416724f6 (diff)
Merge branch 'master' into blender2.8
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h39
-rw-r--r--source/blender/blenkernel/intern/constraint.c12
-rw-r--r--source/blender/blenkernel/intern/fcurve.c8
-rw-r--r--source/blender/blenkernel/intern/mesh.c19
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c73
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c16
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h3
-rw-r--r--source/blender/editors/util/numinput.c7
-rw-r--r--source/blender/render/intern/source/external_engine.c3
-rw-r--r--source/blender/windowmanager/intern/wm_files.c2
-rwxr-xr-xtests/python/alembic_tests.py59
-rwxr-xr-xtests/python/modules/test_utils.py97
13 files changed, 227 insertions, 113 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index c3cea6c883c..9d48ddb4f32 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -167,7 +167,7 @@ typedef enum DMDirtyFlag {
DM_DIRTY_TESS_CDLAYERS = 1 << 0,
/* One of the MCOL layers have been updated, force updating of GPUDrawObject's colors buffer.
* This is necessary with modern, VBO draw code, as e.g. in vpaint mode me->mcol may be updated
- * without actually rebuilding dm (hence by defautl keeping same GPUDrawObject, and same colors
+ * without actually rebuilding dm (hence by default keeping same GPUDrawObject, and same colors
* buffer, which prevents update during a stroke!). */
DM_DIRTY_MCOL_UPDATE_DRAW = 1 << 1,
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 9ff842e36f1..19caf30a280 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -193,6 +193,17 @@ void BKE_mesh_calc_normals_looptri(
const struct MLoop *mloop,
const struct MLoopTri *looptri, int looptri_num,
float (*r_tri_nors)[3]);
+void BKE_mesh_loop_tangents_ex(
+ const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
+ float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
+ const int numLoops, const struct MPoly *mpolys, const int numPolys,
+ struct ReportList *reports);
+void BKE_mesh_loop_tangents(
+ struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports);
+void BKE_mesh_loop_manifold_fan_around_vert_next(
+ const struct MLoop *mloops, const struct MPoly *mpolys,
+ const int *loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index,
+ const struct MLoop **r_mlfan_curr, int *r_mlfan_curr_index, int *r_mlfan_vert_index, int *r_mpfan_curr_index);
void BKE_edges_sharp_from_angle_set(
const struct MVert *mverts, const int numVerts,
@@ -210,17 +221,38 @@ typedef struct MLoopNorSpace {
float vec_ortho[3]; /* Third vector, orthogonal to vec_lnor and vec_ref. */
float ref_alpha; /* Reference angle, around vec_ortho, in ]0, pi] range (0.0 marks that space as invalid). */
float ref_beta; /* Reference angle, around vec_lnor, in ]0, 2pi] range (0.0 marks that space as invalid). */
- struct LinkNode *loops; /* All indices (uint_in_ptr) of loops using this lnor space (i.e. smooth fan of loops). */
+ /* All loops using this lnor space (i.e. smooth fan of loops),
+ * as (depending on owning MLoopNorSpaceArrary.data_type):
+ * - Indices (uint_in_ptr), or
+ * - BMLoop pointers. */
+ struct LinkNode *loops;
+ char flags;
} MLoopNorSpace;
/**
+ * MLoopNorSpace.flags
+ */
+enum {
+ MLNOR_SPACE_IS_SINGLE = 1 << 0,
+};
+
+/**
* Collection of #MLoopNorSpace basic storage & pre-allocation.
*/
typedef struct MLoopNorSpaceArray {
MLoopNorSpace **lspacearr; /* MLoop aligned array */
struct LinkNode *loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */
+ char data_type; /* Whether we store loop indices, or pointers to BMLoop. */
struct MemArena *mem;
} MLoopNorSpaceArray;
-void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops);
+/**
+ * MLoopNorSpaceArray.data_type
+ */
+enum {
+ MLNOR_SPACEARR_LOOP_INDEX = 0,
+ MLNOR_SPACEARR_BMLOOP_PTR = 1,
+};
+
+void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops, const char data_type);
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr);
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr);
MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr);
@@ -228,7 +260,8 @@ void BKE_lnor_space_define(
MLoopNorSpace *lnor_space, const float lnor[3], float vec_ref[3], float vec_other[3],
struct BLI_Stack *edge_vectors);
void BKE_lnor_space_add_loop(
- MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space, const int ml_index, const bool add_to_list);
+ MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space,
+ const int ml_index, void *bm_loop, const bool is_single);
void BKE_lnor_space_custom_data_to_normal(MLoopNorSpace *lnor_space, const short clnor_data[2], float r_custom_lnor[3]);
void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, const float custom_lnor[3], short r_clnor_data[2]);
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index b8dc7944a75..f0e60296119 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1929,16 +1929,16 @@ static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *
/* apply scaling factor to the channels not being kept */
switch (data->flag) {
case SAMEVOL_X:
- mul_v3_fl(cob->matrix[1], fac);
- mul_v3_fl(cob->matrix[2], fac);
+ mul_v3_fl(cob->matrix[1], fac / obsize[1]);
+ mul_v3_fl(cob->matrix[2], fac / obsize[2]);
break;
case SAMEVOL_Y:
- mul_v3_fl(cob->matrix[0], fac);
- mul_v3_fl(cob->matrix[2], fac);
+ mul_v3_fl(cob->matrix[0], fac / obsize[0]);
+ mul_v3_fl(cob->matrix[2], fac / obsize[2]);
break;
case SAMEVOL_Z:
- mul_v3_fl(cob->matrix[0], fac);
- mul_v3_fl(cob->matrix[1], fac);
+ mul_v3_fl(cob->matrix[0], fac / obsize[0]);
+ mul_v3_fl(cob->matrix[1], fac / obsize[1]);
break;
}
}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index d7e8c62375b..905f103250a 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1590,11 +1590,9 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
return 0.0f;
}
else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) {
- /* extract scale, and choose the right axis */
- float scale[3];
-
- mat4_to_size(scale, mat);
- return scale[dtar->transChan - DTAR_TRANSCHAN_SCALEX];
+ /* Extract scale, and choose the right axis,
+ * inline 'mat4_to_size'. */
+ return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]);
}
else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) {
/* extract rotation as eulers (if needed)
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index d1b8920d612..9f346d10272 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -2205,6 +2205,8 @@ static int split_faces_prepare_new_verts(
MLoop *ml = mloop;
MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr;
+ BLI_assert(lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX);
+
for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) {
if (!BLI_BITMAP_TEST(done_loops, loop_idx)) {
const int vert_idx = ml->v;
@@ -2214,7 +2216,15 @@ static int split_faces_prepare_new_verts(
BLI_assert(*lnor_space);
- if ((*lnor_space)->loops) {
+ if ((*lnor_space)->flags & MLNOR_SPACE_IS_SINGLE) {
+ /* Single loop in this fan... */
+ BLI_assert(GET_INT_FROM_POINTER((*lnor_space)->loops) == loop_idx);
+ BLI_BITMAP_ENABLE(done_loops, loop_idx);
+ if (vert_used) {
+ ml->v = new_vert_idx;
+ }
+ }
+ else {
for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) {
const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link);
BLI_BITMAP_ENABLE(done_loops, ml_fan_idx);
@@ -2223,13 +2233,6 @@ static int split_faces_prepare_new_verts(
}
}
}
- else {
- /* Single loop in this fan... */
- BLI_BITMAP_ENABLE(done_loops, loop_idx);
- if (vert_used) {
- ml->v = new_vert_idx;
- }
- }
if (!vert_used) {
BLI_BITMAP_ENABLE(verts_used, vert_idx);
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 92c47de5831..2a655752169 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -444,7 +444,7 @@ cleanup:
MEM_freeN(fnors);
}
-void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops)
+void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops, const char data_type)
{
if (!(lnors_spacearr->lspacearr && lnors_spacearr->loops_pool)) {
MemArena *mem;
@@ -456,6 +456,8 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoo
lnors_spacearr->lspacearr = BLI_memarena_calloc(mem, sizeof(MLoopNorSpace *) * (size_t)numLoops);
lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops);
}
+ BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX));
+ lnors_spacearr->data_type = data_type;
}
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
@@ -549,12 +551,32 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space, const float lnor[3],
}
}
-void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space, const int ml_index,
- const bool do_add_loop)
+/**
+ * Add a new given loop to given lnor_space.
+ * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct (in case of BMLOOP_PTR),
+ * or NULL (in case of LOOP_INDEX), loop index is then stored in pointer.
+ * If \a is_single is set, the BMLoop or loop index is directly stored in \a lnor_space->loops pointer (since there
+ * is only one loop in this fan), else it is added to the linked list of loops in the fan.
+ */
+void BKE_lnor_space_add_loop(
+ MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space,
+ const int ml_index, void *bm_loop, const bool is_single)
{
+ BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == NULL) ||
+ (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != NULL));
+
lnors_spacearr->lspacearr[ml_index] = lnor_space;
- if (do_add_loop) {
- BLI_linklist_prepend_nlink(&lnor_space->loops, SET_INT_IN_POINTER(ml_index), &lnors_spacearr->loops_pool[ml_index]);
+ if (bm_loop == NULL) {
+ bm_loop = SET_INT_IN_POINTER(ml_index);
+ }
+ if (is_single) {
+ BLI_assert(lnor_space->loops == NULL);
+ lnor_space->flags |= MLNOR_SPACE_IS_SINGLE;
+ lnor_space->loops = bm_loop;
+ }
+ else {
+ BLI_assert((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0);
+ BLI_linklist_prepend_nlink(&lnor_space->loops, bm_loop, &lnors_spacearr->loops_pool[ml_index]);
}
}
@@ -841,7 +863,7 @@ void BKE_edges_sharp_from_angle_set(
MEM_freeN(loop_to_poly);
}
-static void loop_manifold_fan_around_vert_next(
+void BKE_mesh_loop_manifold_fan_around_vert_next(
const MLoop *mloops, const MPoly *mpolys,
const int *loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index,
const MLoop **r_mlfan_curr, int *r_mlfan_curr_index, int *r_mlfan_vert_index, int *r_mpfan_curr_index)
@@ -930,7 +952,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, NULL);
/* We know there is only one loop in this space, no need to create a linklist in this case... */
- BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, false);
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, NULL, true);
if (clnors_data) {
BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor);
@@ -1063,7 +1085,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
if (lnors_spacearr) {
/* Assign current lnor space to current 'vertex' loop. */
- BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, true);
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, NULL, false);
if (me_curr != me_org) {
/* We store here all edges-normalized vectors processed. */
BLI_stack_push(edge_vectors, vec_curr);
@@ -1081,7 +1103,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
copy_v3_v3(vec_prev, vec_curr);
/* Find next loop of the smooth fan. */
- loop_manifold_fan_around_vert_next(
+ BKE_mesh_loop_manifold_fan_around_vert_next(
mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
&mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
@@ -1218,7 +1240,7 @@ static bool loop_split_generator_check_cyclic_smooth_fan(
while (true) {
/* Find next loop of the smooth fan. */
- loop_manifold_fan_around_vert_next(
+ BKE_mesh_loop_manifold_fan_around_vert_next(
mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
&mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
@@ -1475,7 +1497,7 @@ void BKE_mesh_normals_loop_split(
r_lnors_spacearr = &_lnors_spacearr;
}
if (r_lnors_spacearr) {
- BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops);
+ BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops, MLNOR_SPACEARR_LOOP_INDEX);
}
/* Init data common to all tasks. */
@@ -1589,6 +1611,8 @@ static void mesh_normals_loop_custom_set(
}
}
+ BLI_assert(lnors_spacearr.data_type == MLNOR_SPACEARR_LOOP_INDEX);
+
/* Now, check each current smooth fan (one lnor space per smooth fan!), and if all its matching custom lnors
* are not (enough) equal, add sharp edges as needed.
* This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans matching
@@ -1612,7 +1636,7 @@ static void mesh_normals_loop_custom_set(
if (!BLI_BITMAP_TEST(done_loops, i)) {
/* Notes:
- * * In case of mono-loop smooth fan, loops is NULL, so everything is fine (we have nothing to do).
+ * * In case of mono-loop smooth fan, we have nothing to do.
* * Loops in this linklist are ordered (in reversed order compared to how they were discovered by
* BKE_mesh_normals_loop_split(), but this is not a problem). Which means if we find a
* mismatching clnor, we know all remaining loops will have to be in a new, different smooth fan/
@@ -1620,6 +1644,11 @@ static void mesh_normals_loop_custom_set(
* * In smooth fan case, we compare each clnor against a ref one, to avoid small differences adding
* up into a real big one in the end!
*/
+ if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
+ BLI_BITMAP_ENABLE(done_loops, i);
+ continue;
+ }
+
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
MLoop *prev_ml = NULL;
const float *org_nor = NULL;
@@ -1667,9 +1696,6 @@ static void mesh_normals_loop_custom_set(
medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
}
}
-
- /* For single loops, where lnors_spacearr.lspacearr[i]->loops is NULL. */
- BLI_BITMAP_ENABLE(done_loops, i);
}
}
@@ -1699,7 +1725,15 @@ static void mesh_normals_loop_custom_set(
* computed 2D factors).
*/
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
- if (loops) {
+ if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
+ BLI_assert(GET_INT_FROM_POINTER(loops) == i);
+ const int nidx = use_vertices ? (int)mloops[i].v : i;
+ float *nor = r_custom_loopnors[nidx];
+
+ BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
+ BLI_BITMAP_DISABLE(done_loops, i);
+ }
+ else {
int nbr_nors = 0;
float avg_nor[3];
short clnor_data_tmp[2], *clnor_data;
@@ -1726,13 +1760,6 @@ static void mesh_normals_loop_custom_set(
clnor_data[1] = clnor_data_tmp[1];
}
}
- else {
- const int nidx = use_vertices ? (int)mloops[i].v : i;
- float *nor = r_custom_loopnors[nidx];
-
- BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
- BLI_BITMAP_DISABLE(done_loops, i);
- }
}
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index d178b48ab60..9a927bd4701 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -597,9 +597,11 @@ static void bm_mesh_edges_sharp_tag(
bm->elem_index_dirty &= ~BM_EDGE;
}
-/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not.
- * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */
-static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
+/**
+ * Check whether given loop is part of an unknown-so-far cyclic smooth fan, or not.
+ * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once.
+ */
+bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
{
BMLoop *lfan_pivot_next = l_curr;
BMEdge *e_next = l_curr->e;
@@ -665,7 +667,7 @@ static void bm_mesh_loops_calc_normals(
r_lnors_spacearr = &_lnors_spacearr;
}
if (r_lnors_spacearr) {
- BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop);
+ BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
}
@@ -700,7 +702,7 @@ static void bm_mesh_loops_calc_normals(
* However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop()
* is quite cheap in term of CPU cycles, so really think it's not worth it. */
if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
- (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !bm_mesh_loop_check_cyclic_smooth_fan(l_curr)))
+ (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !BM_loop_check_cyclic_smooth_fan(l_curr)))
{
}
else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
@@ -734,7 +736,7 @@ static void bm_mesh_loops_calc_normals(
BKE_lnor_space_define(lnor_space, r_lnos[l_curr_index], vec_curr, vec_prev, NULL);
/* We know there is only one loop in this space, no need to create a linklist in this case... */
- BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, false);
+ BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, l_curr, true);
if (has_clnors) {
short (*clnor)[2] = clnors_data ? &clnors_data[l_curr_index] :
@@ -853,7 +855,7 @@ static void bm_mesh_loops_calc_normals(
if (r_lnors_spacearr) {
/* Assign current lnor space to current 'vertex' loop. */
- BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, true);
+ BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, lfan_pivot, false);
if (e_next != e_org) {
/* We store here all edges-normalized vectors processed. */
BLI_stack_push(edge_vectors, vec_next);
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 8326e82af00..10f024423aa 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -52,6 +52,9 @@ void BM_loops_calc_normal_vcos(
const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
struct MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset);
+bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr);
+
+
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle);
void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index 0f3240946fd..a139f0e3c87 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -478,9 +478,9 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
/* At this point, our value has changed, try to interpret it with python (if str is not empty!). */
if (n->str[0]) {
const float val_prev = n->val[idx];
+ double val;
#ifdef WITH_PYTHON
Scene *sce = CTX_data_scene(C);
- double val;
char str_unit_convert[NUM_STR_REP_LEN * 6]; /* Should be more than enough! */
const char *default_unit = NULL;
@@ -506,8 +506,9 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
n->val_flag[idx] |= NUM_INVALID;
}
#else /* Very unlikely, but does not harm... */
- n->val[idx] = (float)atof(n->str);
- (void)C;
+ val = atof(n->str);
+ n->val[idx] = (float)val;
+ UNUSED_VARS(C);
#endif /* WITH_PYTHON */
if (n->val_flag[idx] & NUM_NEGATE) {
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 9b384709f35..ebc4c704adf 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -1,11 +1,10 @@
/*
-
* ***** 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.
+ * 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
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 4cdca043448..8c0f78a9824 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -497,6 +497,8 @@ static void wm_file_read_post(bContext *C, const bool is_startup_file, const boo
BPY_python_reset(C);
addons_loaded = true;
}
+#else
+ UNUSED_VARS(use_userdef);
#endif /* WITH_PYTHON */
WM_operatortype_last_properties_clear_all();
diff --git a/tests/python/alembic_tests.py b/tests/python/alembic_tests.py
index 96a68de9801..b9dc78a821f 100755
--- a/tests/python/alembic_tests.py
+++ b/tests/python/alembic_tests.py
@@ -28,37 +28,17 @@ import sys
import tempfile
import unittest
+from modules.test_utils import (with_tempdir,
+ AbstractBlenderRunnerTest,
+ )
-def with_tempdir(wrapped):
- """Creates a temporary directory for the function, cleaning up after it returns normally.
-
- When the wrapped function raises an exception, the contents of the temporary directory
- remain available for manual inspection.
-
- The wrapped function is called with an extra positional argument containing
- the pathlib.Path() of the temporary directory.
- """
-
- @functools.wraps(wrapped)
- def decorator(*args, **kwargs):
- dirname = tempfile.mkdtemp(prefix='blender-alembic-test')
- try:
- retval = wrapped(*args, pathlib.Path(dirname), **kwargs)
- except:
- print('Exception in %s, not cleaning up temporary directory %s' % (wrapped, dirname))
- raise
- else:
- shutil.rmtree(dirname)
- return retval
-
- return decorator
class AbcPropError(Exception):
"""Raised when AbstractAlembicTest.abcprop() finds an error."""
-class AbstractAlembicTest(unittest.TestCase):
+class AbstractAlembicTest(AbstractBlenderRunnerTest):
@classmethod
def setUpClass(cls):
import re
@@ -74,37 +54,6 @@ class AbstractAlembicTest(unittest.TestCase):
# 'abcls' array notation, like "name[16]"
cls.abcls_array = re.compile(r'^(?P<name>[^\[]+)(\[(?P<arraysize>\d+)\])?$')
- def run_blender(self, filepath: str, python_script: str, timeout: int=300) -> str:
- """Runs Blender by opening a blendfile and executing a script.
-
- Returns Blender's stdout + stderr combined into one string.
-
- :param filepath: taken relative to self.testdir.
- :param timeout: in seconds
- """
-
- blendfile = self.testdir / filepath
-
- command = (
- self.blender,
- '--background',
- '-noaudio',
- '--factory-startup',
- '--enable-autoexec',
- str(blendfile),
- '-E', 'CYCLES',
- '--python-exit-code', '47',
- '--python-expr', python_script,
- )
-
- proc = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
- timeout=timeout)
- output = proc.stdout.decode('utf8')
- if proc.returncode:
- self.fail('Error %d running Blender:\n%s' % (proc.returncode, output))
-
- return output
-
def abcprop(self, filepath: pathlib.Path, proppath: str) -> dict:
"""Uses abcls to obtain compound property values from an Alembic object.
diff --git a/tests/python/modules/test_utils.py b/tests/python/modules/test_utils.py
new file mode 100755
index 00000000000..489f36c913f
--- /dev/null
+++ b/tests/python/modules/test_utils.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+# ##### 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 #####
+
+# <pep8 compliant>
+
+import argparse
+import functools
+import shutil
+import pathlib
+import re
+import subprocess
+import sys
+import tempfile
+import unittest
+
+
+def with_tempdir(wrapped):
+ """Creates a temporary directory for the function, cleaning up after it returns normally.
+
+ When the wrapped function raises an exception, the contents of the temporary directory
+ remain available for manual inspection.
+
+ The wrapped function is called with an extra positional argument containing
+ the pathlib.Path() of the temporary directory.
+ """
+
+ @functools.wraps(wrapped)
+ def decorator(*args, **kwargs):
+ dirname = tempfile.mkdtemp(prefix='blender-alembic-test')
+ try:
+ retval = wrapped(*args, pathlib.Path(dirname), **kwargs)
+ except:
+ print('Exception in %s, not cleaning up temporary directory %s' % (wrapped, dirname))
+ raise
+ else:
+ shutil.rmtree(dirname)
+ return retval
+
+ return decorator
+
+
+class AbstractBlenderRunnerTest(unittest.TestCase):
+ """Base class for all test suites which needs to run Blender"""
+
+ @classmethod
+ def setUpClass(cls):
+ global args
+ cls.blender = args.blender
+ cls.testdir = pathlib.Path(args.testdir)
+
+ def run_blender(self, filepath: str, python_script: str, timeout: int=300) -> str:
+ """Runs Blender by opening a blendfile and executing a script.
+
+ Returns Blender's stdout + stderr combined into one string.
+
+ :param filepath: taken relative to self.testdir.
+ :param timeout: in seconds
+ """
+
+ blendfile = self.testdir / filepath
+
+ command = (
+ self.blender,
+ '--background',
+ '-noaudio',
+ '--factory-startup',
+ '--enable-autoexec',
+ str(blendfile),
+ '-E', 'CYCLES',
+ '--python-exit-code', '47',
+ '--python-expr', python_script,
+ )
+
+ proc = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ timeout=timeout)
+ output = proc.stdout.decode('utf8')
+ if proc.returncode:
+ self.fail('Error %d running Blender:\n%s' % (proc.returncode, output))
+
+ return output
+