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:
authorInes Almeida <britalmeida@gmail.com>2015-01-13 14:04:25 +0300
committerInes Almeida <britalmeida@gmail.com>2015-01-13 14:04:25 +0300
commitcb61c5aeee94af943b0306550daef45c2018126a (patch)
treedbb2a9b5600bc53de35162e79091772bff1b6f8b
parentd7cabe7d6f4519856969137df415692e16a5372d (diff)
parent117edbbf881be1764db852d9805c523590a19f84 (diff)
Merge branch 'master' into soc-2014-bgesoc-2014-bge
-rw-r--r--intern/cycles/bvh/bvh.cpp23
-rw-r--r--intern/cycles/bvh/bvh_build.cpp154
-rw-r--r--intern/cycles/bvh/bvh_build.h10
-rw-r--r--intern/cycles/bvh/bvh_params.h3
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_shadow.h9
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_subsurface.h44
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_traversal.h101
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_volume.h68
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_shadow.h7
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_subsurface.h45
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_traversal.h82
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_volume.h66
-rw-r--r--intern/cycles/kernel/kernel_types.h7
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm3
-rw-r--r--release/datafiles/colormanagement/config.ocio2
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py27
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py20
-rw-r--r--release/scripts/startup/bl_ui/space_info.py10
-rw-r--r--release/scripts/templates_py/operator_modal_view3d_raycast.py4
-rw-r--r--source/blender/blenkernel/BKE_customdata.h6
-rw-r--r--source/blender/blenkernel/BKE_data_transfer.h (renamed from source/blender/blenkernel/BKE_object_data_transfer.h)2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt4
-rw-r--r--source/blender/blenkernel/intern/armature.c52
-rw-r--r--source/blender/blenkernel/intern/constraint.c5
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c (renamed from source/blender/blenkernel/intern/object_data_transfer.c)4
-rw-r--r--source/blender/blenkernel/intern/deform.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c7
-rw-r--r--source/blender/blenkernel/intern/object.c91
-rw-r--r--source/blender/blenlib/BLI_linklist_stack.h32
-rw-r--r--source/blender/blenlib/BLI_math_geom.h7
-rw-r--r--source/blender/blenlib/intern/math_geom.c93
-rw-r--r--source/blender/blenlib/intern/math_geom_inline.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c3
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c29
-rw-r--r--source/blender/editors/include/ED_render.h2
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/UI_interface_icons.h3
-rw-r--r--source/blender/editors/interface/interface_icons.c23
-rw-r--r--source/blender/editors/interface/interface_panel.c10
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c26
-rw-r--r--source/blender/editors/object/object_data_transfer.c2
-rw-r--r--source/blender/editors/render/render_preview.c5
-rw-r--r--source/blender/editors/screen/screen_edit.c26
-rw-r--r--source/blender/editors/space_file/file_draw.c18
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h24
-rw-r--r--source/blender/makesdna/DNA_screen_types.h16
-rw-r--r--source/blender/makesrna/intern/rna_ID.c35
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c38
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c11
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c2
-rw-r--r--source/blender/render/intern/source/convertblender.c13
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c12
-rw-r--r--source/blender/windowmanager/intern/wm_files.c19
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c88
55 files changed, 996 insertions, 408 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index ac2762b80bd..5fc4ddb3a0e 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -504,12 +504,20 @@ RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_
void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
{
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1)
+ if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
/* object */
- pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, leaf->m_visibility, leaf->m_visibility);
- else
- /* triangle */
- pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, leaf->m_lo, leaf->m_hi, leaf->m_visibility, leaf->m_visibility);
+ pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0,
+ leaf->m_visibility, leaf->m_visibility);
+ }
+ else {
+ int prim_type = leaf->num_triangles() ? pack.prim_type[leaf->m_lo] : 0;
+ /* Triangle/curve primitive leaf. */
+ pack_node(e.idx, leaf->m_bounds, leaf->m_bounds,
+ leaf->m_lo, leaf->m_hi,
+ leaf->m_visibility,
+ prim_type);
+ }
+
}
void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1)
@@ -657,7 +665,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
visibility |= ob->visibility;
}
- pack_node(idx, bbox, bbox, c0, c1, visibility, visibility);
+ pack_node(idx, bbox, bbox, c0, c1, visibility, data[3].w);
}
else {
/* refit inner node, set bbox from children */
@@ -700,6 +708,9 @@ void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
data[6].y = __int_as_float(leaf->m_hi);
}
data[6].z = __uint_as_float(leaf->m_visibility);
+ if(leaf->num_triangles() != 0) {
+ data[6].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
+ }
memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE);
}
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 5547229a910..da263c4945e 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -34,6 +34,21 @@
CCL_NAMESPACE_BEGIN
+#if !defined(__KERNEL_SSE2__)
+/* TODO(sergey): Move to some generic header so all code
+ * can use bitscan on non-SSE processors.
+ */
+ccl_device_inline int bitscan(int value)
+{
+ assert(value != 0);
+ int bit = 0;
+ while (value >>= 1) {
+ ++bit;
+ }
+ return bit;
+}
+#endif
+
/* BVH Build Task */
class BVHBuildTask : public Task {
@@ -449,61 +464,119 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
}
}
-BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
+BVHNode *BVHBuild::create_primitive_leaf_node(const int *p_type,
+ const int *p_index,
+ const int *p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start,
+ int num)
{
- vector<int>& p_type = prim_type;
- vector<int>& p_index = prim_index;
- vector<int>& p_object = prim_object;
- BoundBox bounds = BoundBox::empty;
- int num = 0, ob_num = 0;
- uint visibility = 0;
+ for(int i = 0; i < num; ++i) {
+ if(start + i == prim_index.size()) {
+ assert(params.use_spatial_split);
+ prim_type.push_back(p_type[i]);
+ prim_index.push_back(p_index[i]);
+ prim_object.push_back(p_object[i]);
+ }
+ else {
+ prim_type[start + i] = p_type[i];
+ prim_index[start + i] = p_index[i];
+ prim_object[start + i] = p_object[i];
+ }
+ }
+ return new LeafNode(bounds, visibility, start, start + num);
+}
+BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
+{
+#define MAX_LEAF_SIZE 8
+ int p_num[PRIMITIVE_NUM_TOTAL] = {0};
+ int p_type[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ int p_index[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ int p_object[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ uint visibility[PRIMITIVE_NUM_TOTAL] = {0};
+ /* NOTE: Keep initializtion in sync with actual number of primitives. */
+ BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty};
+ int ob_num = 0;
+
+ /* Fill in per-type type/index array. */
for(int i = 0; i < range.size(); i++) {
BVHReference& ref = references[range.start() + i];
-
if(ref.prim_index() != -1) {
- if(range.start() + num == prim_index.size()) {
- assert(params.use_spatial_split);
-
- p_type.push_back(ref.prim_type());
- p_index.push_back(ref.prim_index());
- p_object.push_back(ref.prim_object());
- }
- else {
- p_type[range.start() + num] = ref.prim_type();
- p_index[range.start() + num] = ref.prim_index();
- p_object[range.start() + num] = ref.prim_object();
- }
-
- bounds.grow(ref.bounds());
- visibility |= objects[ref.prim_object()]->visibility;
- num++;
+ int type_index = bitscan(ref.prim_type() & PRIMITIVE_ALL);
+ int idx = p_num[type_index];
+ p_type[type_index][idx] = ref.prim_type();
+ p_index[type_index][idx] = ref.prim_index();
+ p_object[type_index][idx] = ref.prim_object();
+ ++p_num[type_index];
+
+ bounds[type_index].grow(ref.bounds());
+ visibility[type_index] |= objects[ref.prim_object()]->visibility;
}
else {
- if(ob_num < i)
+ if(ob_num < i) {
references[range.start() + ob_num] = ref;
+ }
ob_num++;
}
}
- BVHNode *leaf = NULL;
-
- if(num > 0) {
- leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num);
+ /* Create leaf nodes for every existing primitive. */
+ BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL};
+ int num_leaves = 0;
+ int start = range.start();
+ for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
+ if(p_num[i] != 0) {
+ leaves[num_leaves] = create_primitive_leaf_node(p_type[i],
+ p_index[i],
+ p_object[i],
+ bounds[i],
+ visibility[i],
+ start,
+ p_num[i]);
+ ++num_leaves;
+ start += p_num[i];
+ }
+ }
- if(num == range.size())
- return leaf;
+ /* Create leaf node for object. */
+ if(num_leaves == 0 || ob_num) {
+ /* Only create object leaf nodes if there are objects or no other
+ * nodes created.
+ */
+ const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
+ leaves[num_leaves] = create_object_leaf_nodes(ref, start, ob_num);
+ ++num_leaves;
}
- /* while there may be multiple triangles in a leaf, for object primitives
- * we want there to be the only one, so we keep splitting */
- const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
- BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num);
-
- if(leaf)
- return new InnerNode(range.bounds(), leaf, oleaf);
- else
- return oleaf;
+ if(num_leaves == 1) {
+ /* Simplest case: single leaf, just return it.
+ * In all the rest cases we'll be creating intermediate inner node with
+ * an appropriate bounding box.
+ */
+ return leaves[0];
+ }
+ else if(num_leaves == 2) {
+ return new InnerNode(range.bounds(), leaves[0], leaves[1]);
+ }
+ else if(num_leaves == 3) {
+ BoundBox inner_bounds = merge(bounds[1], bounds[2]);
+ BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]);
+ return new InnerNode(range.bounds(), leaves[0], inner);
+ } else /*if(num_leaves == 4)*/ {
+ /* Shpuld be doing more branches if more primitive types added. */
+ assert(num_leaves == 4);
+ BoundBox inner_bounds_a = merge(bounds[0], bounds[1]);
+ BoundBox inner_bounds_b = merge(bounds[2], bounds[3]);
+ BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]);
+ BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]);
+ return new InnerNode(range.bounds(), inner_a, inner_b);
+ }
+#undef AMX_LEAF_SIZE
}
/* Tree Rotations */
@@ -588,4 +661,3 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
}
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index a6b9916de9b..294c5a1758d 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -70,6 +70,15 @@ protected:
BVHNode *create_leaf_node(const BVHRange& range);
BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num);
+ /* Leaf node type splitting. */
+ BVHNode *create_primitive_leaf_node(const int *p_type,
+ const int *p_index,
+ const int *p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start,
+ int nun);
+
bool range_within_max_leaf_size(const BVHRange& range);
/* threads */
@@ -116,4 +125,3 @@ protected:
CCL_NAMESPACE_END
#endif /* __BVH_BUILD_H__ */
-
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index 43c2d9b2683..3fa6ebd75af 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -49,8 +49,6 @@ public:
/* QBVH */
int use_qbvh;
- int pad;
-
/* fixed parameters */
enum {
MAX_DEPTH = 64,
@@ -75,7 +73,6 @@ public:
top_level = false;
use_cache = false;
use_qbvh = false;
- pad = false;
}
/* SAH costs */
diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h
index 6dafd2c9fdc..193f49074a3 100644
--- a/intern/cycles/kernel/geom/geom_bvh_shadow.h
+++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h
@@ -206,7 +206,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
/* pop */
nodeAddr = traversalStack[stackPtr];
@@ -214,14 +216,15 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* primitive intersection */
while(primAddr < primAddr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+
bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
/* todo: specialized intersect functions which don't fill in
* isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
* might give a few % performance improvement */
- switch(type & PRIMITIVE_ALL) {
+ switch(p_type) {
case PRIMITIVE_TRIANGLE: {
hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
break;
diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
index ea9d7c07a72..290297ef5c5 100644
--- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h
+++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
@@ -193,37 +193,43 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from the same object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
-
- if(tri_object != subsurface_object)
- continue;
-
- /* intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from the same object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object)
+ continue;
triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from the same object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object)
+ continue;
motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
}
+ break;
+ }
#endif
- default: {
- break;
- }
+ default: {
+ break;
}
}
}
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h
index b948ab8f5e4..0298e687de2 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h
@@ -254,62 +254,85 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- while(primAddr < primAddr2) {
- bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
- break;
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) {
+ /* shadow ray early termination */
+#if defined(__KERNEL_SSE2__)
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+#else
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+#endif
+ }
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
#endif
-#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- else
- hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- break;
- }
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ /* shadow ray early termination */
+#if defined(__KERNEL_SSE2__)
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+#else
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
#endif
- default: {
- hit = false;
- break;
+ }
}
+ break;
}
-
+#endif /* BVH_FEATURE(BVH_MOTION) */
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
+ isect->num_traversal_steps++;
#endif
-
- /* shadow ray early termination */
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ else
+ hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ if(hit) {
+ /* shadow ray early termination */
#if defined(__KERNEL_SSE2__)
- if(hit) {
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
-
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
- }
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
#else
- if(hit && visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
#endif
-
- primAddr++;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
}
}
#if BVH_FEATURE(BVH_INSTANCING)
diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h
index f1f2e6d1f46..0862812a170 100644
--- a/intern/cycles/kernel/geom/geom_bvh_volume.h
+++ b/intern/cycles/kernel/geom/geom_bvh_volume.h
@@ -194,49 +194,67 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from volume object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
-
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
-
- /* intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
- break;
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
}
+ break;
+ }
#endif
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
else
bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
- break;
}
+ break;
+ }
#endif
- default: {
- break;
- }
+ default: {
+ break;
}
}
}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h
index e493a3f51bd..e77e220c919 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h
@@ -216,6 +216,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(primAddr >= 0) {
#endif
int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
/* Pop. */
nodeAddr = traversalStack[stackPtr].addr;
@@ -223,14 +225,15 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Primitive intersection. */
while(primAddr < primAddr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+
bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
/* todo: specialized intersect functions which don't fill in
* isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
* might give a few % performance improvement */
- switch(type & PRIMITIVE_ALL) {
+ switch(p_type) {
case PRIMITIVE_TRIANGLE: {
hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
break;
diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
index 0154772988f..ef1754e711c 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
@@ -203,37 +203,44 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(primAddr >= 0) {
#endif
int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* Pop. */
nodeAddr = traversalStack[stackPtr].addr;
--stackPtr;
/* Primitive intersection. */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from the same object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
-
- if(tri_object != subsurface_object)
- continue;
-
- /* Intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* Intersect ray against primitive, */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from the same object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object) {
+ continue;
+ }
triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* Intersect ray against primitive. */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from the same object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object) {
+ continue;
+ }
motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
- }
-#endif
- default: {
- break;
}
+ break;
}
+#endif
+ default:
+ break;
}
}
#if BVH_FEATURE(BVH_INSTANCING)
diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
index 8d81f475848..64da51360de 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
@@ -275,6 +275,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(primAddr >= 0) {
#endif
int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* Pop. */
nodeAddr = traversalStack[stackPtr].addr;
@@ -282,49 +283,62 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
--stackPtr;
/* Primitive intersection. */
- while(primAddr < primAddr2) {
- bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
- break;
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_MOTION) */
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
else
hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- break;
+ if(hit) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
}
-#endif
- default: {
- hit = false;
- break;
- }
- }
-
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
-
- /* Shadow ray early termination. */
- if(hit) {
- tfar = ssef(isect->t);
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
+ break;
}
-
- primAddr++;
+#endif /* BVH_FEATURE(BVH_HAIR) */
}
}
#if BVH_FEATURE(BVH_INSTANCING)
diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h
index 9e6e7552b3f..a2a8d1a20ab 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_volume.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h
@@ -209,49 +209,65 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(primAddr >= 0) {
#endif
int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
/* Pop. */
nodeAddr = traversalStack[stackPtr].addr;
--stackPtr;
/* Primitive intersection. */
- for(; primAddr < primAddr2; primAddr++) {
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
-
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
-
- /* Intersect ray against primitive. */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
+ switch(p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
- break;
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
}
+ break;
+ }
#endif
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
else
bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
- break;
- }
-#endif
- default: {
- break;
}
+ break;
}
+#endif
}
}
#if BVH_FEATURE(BVH_INSTANCING)
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index aff9a001061..82619b3f854 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -481,7 +481,12 @@ typedef enum PrimitiveType {
PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE|PRIMITIVE_MOTION_TRIANGLE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE|PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE|PRIMITIVE_MOTION_CURVE),
- PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE)
+ PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE),
+
+ /* Total number of different primitives.
+ * NOTE: This is an actual value, not a bitflag.
+ */
+ PRIMITIVE_NUM_TOTAL = 4,
} PrimitiveType;
#define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << 16) | type)
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index 37fd4a36ea4..0b290c617a5 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -75,9 +75,10 @@ GHOST_ContextCGL::GHOST_ContextCGL(
GHOST_ContextCGL::~GHOST_ContextCGL()
{
if (m_openGLContext != nil) {
- if (m_openGLContext == [NSOpenGLContext currentContext])
+ if (m_openGLContext == [NSOpenGLContext currentContext]) {
[NSOpenGLContext clearCurrentContext];
[m_openGLView clearGLContext];
+ }
if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) {
assert(s_sharedCount > 0);
diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio
index 1d2c730ecab..1cf9a3bb36e 100644
--- a/release/datafiles/colormanagement/config.ocio
+++ b/release/datafiles/colormanagement/config.ocio
@@ -25,7 +25,7 @@ roles:
# Default color space sequencer is working in
default_sequencer: sRGB
- # Color spaces for color picking and exture painting (not internally supported yet)
+ # Color spaces for color picking and texture painting (not internally supported yet)
color_picking: Raw
texture_paint: Raw
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index b25024fca9b..ec4a395f1e1 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -63,10 +63,18 @@ def region_2d_to_vector_3d(region, rv3d, coord):
return view_vector
-def region_2d_to_origin_3d(region, rv3d, coord):
+def region_2d_to_origin_3d(region, rv3d, coord, clamp=None):
"""
Return the 3d view origin from the region relative 2d coords.
+ .. note::
+
+ Orthographic views have a less obvious origin, the far clip is used to define the viewport near/far extents.
+ Since far clip can be a very large value, the result may give with numeric precision issues.
+
+ To avoid this problem, you can optionally clamp the far clip to a smaller value
+ based on the data you're operating on.
+
:arg region: region of the 3D viewport, typically bpy.context.region.
:type region: :class:`bpy.types.Region`
:arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
@@ -74,6 +82,9 @@ def region_2d_to_origin_3d(region, rv3d, coord):
:arg coord: 2d coordinates relative to the region;
(event.mouse_region_x, event.mouse_region_y) for example.
:type coord: 2d vector
+ :arg clamp: Clamp the maximum far-clip value used.
+ (negative value will move the offset away from the view_location)
+ :type clamp: float or None
:return: The origin of the viewpoint in 3d space.
:rtype: :class:`mathutils.Vector`
"""
@@ -89,6 +100,20 @@ def region_2d_to_origin_3d(region, rv3d, coord):
origin_start = ((persinv.col[0].xyz * dx) +
(persinv.col[1].xyz * dy) +
viewinv.translation)
+
+ if clamp != 0.0:
+ if rv3d.view_perspective != 'CAMERA':
+ # this value is scaled to the far clip already
+ origin_offset = persinv.col[2].xyz
+ if clamp is not None:
+ if clamp < 0.0:
+ origin_offset.negate()
+ clamp = -clamp
+ if origin_offset.length > clamp:
+ origin_offset.length = clamp
+
+ origin_start -= origin_offset
+
return origin_start
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index e6b62cae6ef..0c5aae1de2f 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -768,9 +768,27 @@ class ConstraintButtonsPanel():
col = layout.column()
col.label(text="Chain Scaling:")
col.prop(con, "use_y_stretch")
- col.prop(con, "xz_scale_mode")
col.prop(con, "use_curve_radius")
+ layout.prop(con, "xz_scale_mode")
+
+ if con.xz_scale_mode == 'VOLUME_PRESERVE':
+ layout.prop(con, "bulge", text="Volume Variation")
+ split = layout.split()
+ col = split.column(align=True)
+ col.prop(con, "use_bulge_min", text="Volume Min")
+ sub = col.column()
+ sub.active = con.use_bulge_min
+ sub.prop(con, "bulge_min", text="")
+ col = split.column(align=True)
+ col.prop(con, "use_bulge_max", text="Volume Max")
+ sub = col.column()
+ sub.active = con.use_bulge_max
+ sub.prop(con, "bulge_max", text="")
+ col = layout.column()
+ col.active = con.use_bulge_min or con.use_bulge_max
+ col.prop(con, "bulge_smooth", text="Smooth")
+
def PIVOT(self, context, layout, con):
self.target_template(layout, con)
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 2b075128fef..b642b61fcdc 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -132,6 +132,7 @@ class INFO_MT_file(Menu):
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.link", text="Link", icon='LINK_BLEND')
layout.operator("wm.append", text="Append", icon='APPEND_BLEND')
+ layout.menu("INFO_MT_file_previews")
layout.separator()
@@ -195,6 +196,15 @@ class INFO_MT_file_external_data(Menu):
layout.operator("file.find_missing_files")
+class INFO_MT_file_previews(Menu):
+ bl_label = "Data Previews"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.previews_ensure")
+
+
class INFO_MT_game(Menu):
bl_label = "Game"
diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py
index 1aa13c90ca3..b72b2f76750 100644
--- a/release/scripts/templates_py/operator_modal_view3d_raycast.py
+++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py
@@ -14,10 +14,6 @@ def main(context, event, ray_max=1000.0):
view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
- if rv3d.view_perspective == 'ORTHO':
- # move ortho origin back
- ray_origin = ray_origin - (view_vector * (ray_max / 2.0))
-
ray_target = ray_origin + (view_vector * ray_max)
def visible_objects_and_duplis():
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 08edde1cec0..f11aad27e4b 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -373,10 +373,10 @@ void CustomData_external_reload(struct CustomData *data,
/* Mesh-to-mesh transfer data. */
struct MeshPairRemap;
-typedef struct CustomDataTransferLayerMap CustomDataTransferLayerMap;
+struct CustomDataTransferLayerMap;
typedef void (*cd_datatransfer_interp)(
- const CustomDataTransferLayerMap *laymap, void *dest,
+ const struct CustomDataTransferLayerMap *laymap, void *dest,
void **sources, const float *weights, const int count, const float mix_factor);
/**
@@ -423,7 +423,7 @@ enum {
};
typedef struct CustomDataTransferLayerMap {
- CustomDataTransferLayerMap *next, *prev;
+ struct CustomDataTransferLayerMap *next, *prev;
int data_type;
int mix_mode;
diff --git a/source/blender/blenkernel/BKE_object_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
index fe218901201..07ef16e8161 100644
--- a/source/blender/blenkernel/BKE_object_data_transfer.h
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenkernel/BKE_object_data_transfer.h
+/** \file blender/blenkernel/BKE_data_transfer.h
* \ingroup bke
*/
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 31e28f9e51b..c71595e7a3e 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -85,6 +85,7 @@ set(SRC
intern/curve.c
intern/customdata.c
intern/customdata_file.c
+ intern/data_transfer.c
intern/deform.c
intern/depsgraph.c
intern/displist.c
@@ -130,7 +131,6 @@ set(SRC
intern/nla.c
intern/node.c
intern/object.c
- intern/object_data_transfer.c
intern/object_deform.c
intern/object_dupli.c
intern/ocean.c
@@ -203,6 +203,7 @@ set(SRC
BKE_curve.h
BKE_customdata.h
BKE_customdata_file.h
+ BKE_data_transfer.h
BKE_deform.h
BKE_depsgraph.h
BKE_displist.h
@@ -239,7 +240,6 @@ set(SRC
BKE_nla.h
BKE_node.h
BKE_object.h
- BKE_object_data_transfer.h
BKE_object_deform.h
BKE_ocean.h
BKE_packedFile.h
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index df57db21e3b..03372b97049 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2166,9 +2166,9 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
mul_v3_fl(poseMat[2], scale);
break;
}
- case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC:
+ case CONSTRAINT_SPLINEIK_XZS_INVERSE:
{
- /* 'volume preservation' */
+ /* old 'volume preservation' method using the inverse scale */
float scale;
/* calculate volume preservation factor which is
@@ -2189,6 +2189,54 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
mul_v3_fl(poseMat[2], scale);
break;
}
+ case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC:
+ {
+ /* improved volume preservation based on the Stretch To constraint */
+ float final_scale;
+
+ /* as the basis for volume preservation, we use the inverse scale factor... */
+ if (fabsf(scaleFac) != 0.0f) {
+ /* NOTE: The method here is taken wholesale from the Stretch To constraint */
+ float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge);
+
+ if (bulge > 1.0f) {
+ if (ikData->flag & STRETCHTOCON_USE_BULGE_MAX) {
+ float bulge_max = max_ff(ikData->bulge_max, 1.0f);
+ float hard = min_ff(bulge, bulge_max);
+
+ float range = bulge_max - 1.0f;
+ float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
+ float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (0.5f * M_PI);
+
+ bulge = interpf(soft, hard, ikData->bulge_smooth);
+ }
+ }
+ if (bulge < 1.0f) {
+ if (ikData->flag & STRETCHTOCON_USE_BULGE_MIN) {
+ float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f);
+ float hard = max_ff(bulge, bulge_min);
+
+ float range = 1.0f - bulge_min;
+ float scale = (range > 0.0f) ? 1.0f / range : 0.0f;
+ float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (0.5f * M_PI);
+
+ bulge = interpf(soft, hard, ikData->bulge_smooth);
+ }
+ }
+
+ /* compute scale factor for xz axes from this value */
+ final_scale = sqrt(bulge);
+ }
+ else {
+ /* no scaling, so scale factor is simple */
+ final_scale = 1.0f;
+ }
+
+ /* apply the scaling (assuming normalised scale) */
+ mul_v3_fl(poseMat[0], final_scale);
+ mul_v3_fl(poseMat[2], final_scale);
+ break;
+ }
}
/* finally, multiply the x and z scaling by the radius of the curve too,
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 9072acd8b02..f591fe857f8 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -2722,7 +2722,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
}
if (bulge < 1.0f) {
if (data->flag & STRETCHTOCON_USE_BULGE_MIN) {
- float bulge_min = CLAMPIS(data->bulge_max, 0.0f, 1.0f);
+ float bulge_min = CLAMPIS(data->bulge_min, 0.0f, 1.0f);
float hard = max_ff(bulge, bulge_min);
float range = 1.0f - bulge_min;
@@ -3698,6 +3698,9 @@ static void splineik_new_data(void *cdata)
bSplineIKConstraint *data = (bSplineIKConstraint *)cdata;
data->chainlen = 1;
+ data->bulge = 1.0;
+ data->bulge_max = 1.0f;
+ data->bulge_min = 1.0f;
}
static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
diff --git a/source/blender/blenkernel/intern/object_data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 78a293c644e..b573d621052 100644
--- a/source/blender/blenkernel/intern/object_data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -25,7 +25,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/blenkernel/intern/object_data_transfer.c
+/** \file blender/blenkernel/intern/data_transfer.c
* \ingroup bke
*/
@@ -44,7 +44,7 @@
#include "BKE_context.h"
#include "BKE_customdata.h"
-#include "BKE_object_data_transfer.h"
+#include "BKE_data_transfer.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
#include "BKE_mesh_mapping.h"
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 4ed9278ab26..80db62801d6 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -52,7 +52,7 @@
#include "BLF_translation.h"
#include "BKE_customdata.h"
-#include "BKE_object_data_transfer.h"
+#include "BKE_data_transfer.h"
#include "BKE_deform.h" /* own include */
#include "BKE_mesh_mapping.h"
#include "BKE_object_deform.h"
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 4c9e44682c3..915abdb6766 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -896,13 +896,6 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
mvarray[loopstart[2].v].co
);
}
- else if (mpoly->totloop == 4) {
- return area_quad_v3(mvarray[loopstart[0].v].co,
- mvarray[loopstart[1].v].co,
- mvarray[loopstart[2].v].co,
- mvarray[loopstart[3].v].co
- );
- }
else {
int i;
MLoop *l_iter = loopstart;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index b158f7bec96..fb6b65d7a00 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -3507,6 +3507,88 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
return flag;
}
+/* Check of objects moves in time. */
+/* NOTE: This function is currently optimized for usage in combination
+ * with mti->canDeform, so modifiers can quickly check if their target
+ * objects moves (causing deformation motion blur) or not.
+ *
+ * This makes it possible to give some degree of false-positives here,
+ * but it's currently an acceptable tradeof between complexity and check
+ * speed. In combination with checks of modifier stack and real life usage
+ * percentage of false-positives shouldn't be that hight.
+ */
+static bool object_moves_in_time(Object *object)
+{
+ AnimData *adt = object->adt;
+ if (adt != NULL) {
+ /* If object has any sort of animation data assume it is moving. */
+ if (adt->action != NULL ||
+ !BLI_listbase_is_empty(&adt->nla_tracks) ||
+ !BLI_listbase_is_empty(&adt->drivers) ||
+ !BLI_listbase_is_empty(&adt->overrides))
+ {
+ return true;
+ }
+ }
+ if (!BLI_listbase_is_empty(&object->constraints)) {
+ return true;
+ }
+ if (object->parent != NULL) {
+ /* TODO(sergey): Do recursive check here? */
+ return true;
+ }
+ return false;
+}
+
+static bool constructive_modifier_is_deform_modified(ModifierData *md)
+{
+ /* TODO(sergey): Consider generalizing this a bit so all modifier logic
+ * is concentrated in MOD_{modifier}.c file,
+ */
+ if (md->type == eModifierType_Array) {
+ ArrayModifierData *amd = (ArrayModifierData *)md;
+ /* TODO(sergey): Check if curve is deformed. */
+ return (amd->start_cap != NULL && object_moves_in_time(amd->start_cap)) ||
+ (amd->end_cap != NULL && object_moves_in_time(amd->end_cap)) ||
+ (amd->curve_ob != NULL && object_moves_in_time(amd->curve_ob)) ||
+ (amd->offset_ob != NULL && object_moves_in_time(amd->offset_ob));
+ }
+ else if (md->type == eModifierType_Mirror) {
+ MirrorModifierData *mmd = (MirrorModifierData *)md;
+ return mmd->mirror_ob != NULL && object_moves_in_time(mmd->mirror_ob);
+ }
+ else if (md->type == eModifierType_Screw) {
+ ScrewModifierData *smd = (ScrewModifierData *)md;
+ return smd->ob_axis != NULL && object_moves_in_time(smd->ob_axis);
+ }
+ return false;
+}
+
+static bool modifiers_has_animation_check(Object *ob)
+{
+ /* TODO(sergey): This is a bit code duplication with depsgraph, but
+ * would be nicer to solve this as a part of new dependency graph
+ * work, so we avoid conflicts and so.
+ */
+ if (ob->adt != NULL) {
+ AnimData *adt = ob->adt;
+ FCurve *fcu;
+ if (adt->action != NULL) {
+ for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
+ return true;
+ }
+ }
+ }
+ for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+ if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/* test if object is affected by deforming modifiers (for motion blur). again
* most important is to avoid false positives, this is to skip computations
* and we can still if there was actual deformation afterwards */
@@ -3515,6 +3597,7 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
ModifierData *md;
VirtualModifierData virtualModifierData;
int flag = 0;
+ const bool is_modifier_animated = modifiers_has_animation_check(ob);
if (BKE_key_from_object(ob))
flag |= eModifierMode_Realtime | eModifierMode_Render;
@@ -3525,8 +3608,14 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
md = md->next)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ bool can_deform = mti->type == eModifierTypeType_OnlyDeform ||
+ is_modifier_animated;
+
+ if (!can_deform) {
+ can_deform = constructive_modifier_is_deform_modified(md);
+ }
- if (mti->type == eModifierTypeType_OnlyDeform) {
+ if (can_deform) {
if (!(flag & eModifierMode_Render) && modifier_isEnabled(scene, md, eModifierMode_Render))
flag |= eModifierMode_Render;
diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h
index 17d40e068b3..9ac233a8fa4 100644
--- a/source/blender/blenlib/BLI_linklist_stack.h
+++ b/source/blender/blenlib/BLI_linklist_stack.h
@@ -51,46 +51,46 @@
#define BLI_LINKSTACK_DECLARE(var, type) \
LinkNode *var; \
- BLI_mempool *_##var##_pool; \
- type _##var##_type
+ BLI_mempool *var##_pool_; \
+ type var##_type_
#define BLI_LINKSTACK_INIT(var) { \
var = NULL; \
- _##var##_pool = BLI_mempool_create(sizeof(LinkNode), 0, 64, BLI_MEMPOOL_NOP); \
+ var##_pool_ = BLI_mempool_create(sizeof(LinkNode), 0, 64, BLI_MEMPOOL_NOP); \
} (void)0
#define BLI_LINKSTACK_SIZE(var) \
- BLI_mempool_count(_##var##_pool)
+ BLI_mempool_count(var##_pool_)
/* check for typeof() */
#ifdef __GNUC__
#define BLI_LINKSTACK_PUSH(var, ptr) ( \
- CHECK_TYPE_INLINE(ptr, typeof(_##var##_type)), \
- BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool))
+ CHECK_TYPE_INLINE(ptr, typeof(var##_type_)), \
+ BLI_linklist_prepend_pool(&(var), ptr, var##_pool_))
#define BLI_LINKSTACK_POP(var) \
- (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL)
+ (var ? (typeof(var##_type_))BLI_linklist_pop_pool(&(var), var##_pool_) : NULL)
#define BLI_LINKSTACK_POP_DEFAULT(var, r) \
- (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : r)
+ (var ? (typeof(var##_type_))BLI_linklist_pop_pool(&(var), var##_pool_) : r)
#else /* non gcc */
#define BLI_LINKSTACK_PUSH(var, ptr) ( \
- BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool))
+ BLI_linklist_prepend_pool(&(var), ptr, var##_pool_))
#define BLI_LINKSTACK_POP(var) \
- (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL)
+ (var ? BLI_linklist_pop_pool(&(var), var##_pool_) : NULL)
#define BLI_LINKSTACK_POP_DEFAULT(var, r) \
- (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : r)
+ (var ? BLI_linklist_pop_pool(&(var), var##_pool_) : r)
#endif /* gcc check */
#define BLI_LINKSTACK_SWAP(var_a, var_b) { \
- CHECK_TYPE_PAIR(_##var_a##_type, _##var_b##_type); \
+ CHECK_TYPE_PAIR(var_a##_type_, var_b##_type_); \
SWAP(LinkNode *, var_a, var_b); \
- SWAP(BLI_mempool *, _##var_a##_pool, _##var_b##_pool); \
+ SWAP(BLI_mempool *, var_a##_pool_, var_b##_pool_); \
} (void)0
#define BLI_LINKSTACK_FREE(var) { \
- BLI_mempool_destroy(_##var##_pool); \
- _##var##_pool = NULL; (void)_##var##_pool; \
+ BLI_mempool_destroy(var##_pool_); \
+ var##_pool_ = NULL; (void)var##_pool_; \
var = NULL; (void)var; \
- (void)&(_##var##_type); \
+ (void)&(var##_type_); \
} (void)0
#include "BLI_linklist.h"
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index ee99f860a97..495aa6b2465 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -52,16 +52,23 @@ float normal_quad_v3(float r[3], const float a[3], const float b[3], const float
float normal_poly_v3(float r[3], const float verts[][3], unsigned int nr);
MINLINE float area_tri_v2(const float a[2], const float b[2], const float c[2]);
+MINLINE float area_squared_tri_v2(const float a[2], const float b[2], const float c[2]);
MINLINE float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2]);
float area_tri_v3(const float a[3], const float b[3], const float c[3]);
+float area_squared_tri_v3(const float a[3], const float b[3], const float c[3]);
float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]);
float area_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]);
+float area_squared_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]);
float area_poly_v3(const float verts[][3], unsigned int nr);
float area_poly_v2(const float verts[][2], unsigned int nr);
+float area_squared_poly_v3(const float verts[][3], unsigned int nr);
+float area_squared_poly_v2(const float verts[][2], unsigned int nr);
+float area_poly_signed_v2(const float verts[][2], unsigned int nr);
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3]);
void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3]);
MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2]);
+void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr);
float cross_poly_v2(const float verts[][2], unsigned int nr);
/********************************* Planes **********************************/
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 59d9cf85dec..05a527c4f7a 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -109,58 +109,44 @@ float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const flo
*/
float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr)
{
- const float *v_prev = verts[nr - 1];
- const float *v_curr = verts[0];
- unsigned int i;
-
- zero_v3(n);
-
- /* Newell's Method */
- for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) {
- add_newell_cross_v3_v3v3(n, v_prev, v_curr);
- }
-
+ cross_poly_v3(n, verts, nr);
return normalize_v3(n);
}
-/* only convex Quadrilaterals */
float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
- float len, vec1[3], vec2[3], n[3];
-
- sub_v3_v3v3(vec1, v2, v1);
- sub_v3_v3v3(vec2, v4, v1);
- cross_v3_v3v3(n, vec1, vec2);
- len = len_v3(n);
-
- sub_v3_v3v3(vec1, v4, v3);
- sub_v3_v3v3(vec2, v2, v3);
- cross_v3_v3v3(n, vec1, vec2);
- len += len_v3(n);
+ const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
+ return area_poly_v3(verts, 4);
+}
- return (len / 2.0f);
+float area_squared_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+{
+ const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}};
+ return area_squared_poly_v3(verts, 4);
}
/* Triangles */
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
{
- float vec1[3], vec2[3], n[3];
-
- sub_v3_v3v3(vec1, v3, v2);
- sub_v3_v3v3(vec2, v1, v2);
- cross_v3_v3v3(n, vec1, vec2);
+ float n[3];
+ cross_tri_v3(n, v1, v2, v3);
+ return len_v3(n) * 0.5f;
+}
- return len_v3(n) / 2.0f;
+float area_squared_tri_v3(const float v1[3], const float v2[3], const float v3[3])
+{
+ float n[3];
+ cross_tri_v3(n, v1, v2, v3);
+ mul_v3_fl(n, 0.5f);
+ return len_squared_v3(n);
}
float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3])
{
- float area, vec1[3], vec2[3], n[3];
+ float area, n[3];
- sub_v3_v3v3(vec1, v3, v2);
- sub_v3_v3v3(vec2, v1, v2);
- cross_v3_v3v3(n, vec1, vec2);
- area = len_v3(n) / 2.0f;
+ cross_tri_v3(n, v1, v2, v3);
+ area = len_v3(n) * 0.5f;
/* negate area for flipped triangles */
if (dot_v3v3(n, normal) < 0.0f)
@@ -172,7 +158,17 @@ float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3]
float area_poly_v3(const float verts[][3], unsigned int nr)
{
float n[3];
- return normal_poly_v3(n, verts, nr) * 0.5f;
+ cross_poly_v3(n, verts, nr);
+ return len_v3(n) * 0.5f;
+}
+
+float area_squared_poly_v3(const float verts[][3], unsigned int nr)
+{
+ float n[3];
+
+ cross_poly_v3(n, verts, nr);
+ mul_v3_fl(n, 0.5f);
+ return len_squared_v3(n);
}
/**
@@ -200,11 +196,36 @@ float cross_poly_v2(const float verts[][2], unsigned int nr)
return cross;
}
+void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr)
+{
+ const float *v_prev = verts[nr - 1];
+ const float *v_curr = verts[0];
+ unsigned int i;
+
+ zero_v3(n);
+
+ /* Newell's Method */
+ for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) {
+ add_newell_cross_v3_v3v3(n, v_prev, v_curr);
+ }
+}
+
float area_poly_v2(const float verts[][2], unsigned int nr)
{
return fabsf(0.5f * cross_poly_v2(verts, nr));
}
+float area_poly_signed_v2(const float verts[][2], unsigned int nr)
+{
+ return (0.5f * cross_poly_v2(verts, nr));
+}
+
+float area_squared_poly_v2(const float verts[][2], unsigned int nr)
+{
+ float area = area_poly_signed_v2(verts, nr);
+ return area * area;
+}
+
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
{
float a[3], b[3], c[3], c_len;
diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c
index 5a64ed63ecf..44b17681540 100644
--- a/source/blender/blenlib/intern/math_geom_inline.c
+++ b/source/blender/blenlib/intern/math_geom_inline.c
@@ -54,6 +54,12 @@ MINLINE float area_tri_v2(const float v1[2], const float v2[2], const float v3[2
return fabsf(area_tri_signed_v2(v1, v2, v3));
}
+MINLINE float area_squared_tri_v2(const float v1[2], const float v2[2], const float v3[2])
+{
+ float area = area_tri_signed_v2(v1, v2, v3);
+ return area * area;
+}
+
/****************************** Spherical Harmonics **************************/
MINLINE void zero_sh(float r[9])
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index f2c426133c2..e4aa4bb0c0e 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -214,9 +214,6 @@ float BM_face_calc_area(BMFace *f)
if (f->len == 3) {
area = area_tri_v3(verts[0], verts[1], verts[2]);
}
- else if (f->len == 4) {
- area = area_quad_v3(verts[0], verts[1], verts[2], verts[3]);
- }
else {
area = area_poly_v3((const float (*)[3])verts, f->len);
}
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index e7b65a10790..da1991a187d 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -236,6 +236,20 @@ static void bmo_region_extend_expand(
bmo_face_flag_set_flush(bm, f, SEL_FLAG, true);
}
}
+
+ /* handle wire edges (when stepping over faces) */
+ {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(e)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) {
+ BMO_elem_flag_enable(bm, e, SEL_FLAG);
+ BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
+ }
+ }
+ }
+ }
}
}
}
@@ -306,6 +320,21 @@ static void bmo_region_extend_contract(
break;
}
}
+
+ /* handle wire edges (when stepping over faces) */
+ if (!found) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(e)) {
+ if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
}
if (found) {
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index 32fa641e3ae..de3843c91eb 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -72,7 +72,7 @@ void ED_preview_init_dbase(void);
void ED_preview_free_dbase(void);
void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, struct ID *parent, struct MTex *slot, int sizex, int sizey, int method);
-void ED_preview_icon_render(const struct bContext *C, void *owner, struct ID *id, unsigned int *rect, int sizex, int sizey);
+void ED_preview_icon_render(struct Scene *scene, struct ID *id, unsigned int *rect, int sizex, int sizey);
void ED_preview_icon_job(const struct bContext *C, void *owner, struct ID *id, unsigned int *rect, int sizex, int sizey);
void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index ed2465647da..b790c656b61 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -107,6 +107,7 @@ void ED_screen_set_subwinactive(struct bContext *C, struct wmEvent *event);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh);
+void ED_screen_retore_temp_type(struct bContext *C, ScrArea *sa, bool is_screen_change);
ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type);
void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa);
void ED_screen_full_restore(struct bContext *C, ScrArea *sa);
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 2ba3d309aa7..74927428363 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -64,7 +64,8 @@ void UI_icons_init(int first_dyn_id);
int UI_icon_get_width(int icon_id);
int UI_icon_get_height(int icon_id);
-void UI_id_icon_render(const struct bContext *C, struct ID *id, const bool big, const bool use_job);
+void UI_id_icon_render(
+ const struct bContext *C, struct Scene *scene, struct ID *id, const bool big, const bool use_job);
void UI_icon_draw(float x, float y, int icon_id);
void UI_icon_draw_preview(float x, float y, int icon_id);
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index ac9abe8e781..679681cb372 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -931,7 +931,8 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
/* only called when icon has changed */
/* only call with valid pointer from UI_icon_draw */
-static void icon_set_image(const bContext *C, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job)
+static void icon_set_image(
+ const bContext *C, Scene *scene, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job)
{
if (!prv_img) {
if (G.debug & G_DEBUG)
@@ -946,8 +947,11 @@ static void icon_set_image(const bContext *C, ID *id, PreviewImage *prv_img, enu
ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
}
else {
+ if (!scene) {
+ scene = CTX_data_scene(C);
+ }
/* Immediate version */
- ED_preview_icon_render(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ ED_preview_icon_render(scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
}
}
@@ -1155,25 +1159,26 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al
}
}
-static void ui_id_preview_image_render_size(const bContext *C, ID *id, PreviewImage *pi, int size, const bool use_job)
+static void ui_id_preview_image_render_size(
+ const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job)
{
if ((pi->changed[size] || !pi->rect[size])) { /* changed only ever set by dynamic icons */
/* create the rect if necessary */
- icon_set_image(C, id, pi, size, use_job);
+ icon_set_image(C, scene, id, pi, size, use_job);
pi->changed[size] = 0;
}
}
-void UI_id_icon_render(const bContext *C, ID *id, const bool big, const bool use_job)
+void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job)
{
PreviewImage *pi = BKE_previewimg_get(id);
if (pi) {
if (big)
- ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_PREVIEW, use_job); /* bigger preview size */
+ ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_PREVIEW, use_job); /* bigger preview size */
else
- ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_ICON, use_job); /* icon size */
+ ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_ICON, use_job); /* icon size */
}
}
@@ -1189,7 +1194,7 @@ static void ui_id_brush_render(const bContext *C, ID *id)
/* check if rect needs to be created; changed
* only set by dynamic icons */
if ((pi->changed[i] || !pi->rect[i])) {
- icon_set_image(C, id, pi, i, true);
+ icon_set_image(C, NULL, id, pi, i, true);
pi->changed[i] = 0;
}
}
@@ -1265,7 +1270,7 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big)
case ID_LA: /* fall through */
iconid = BKE_icon_getid(id);
/* checks if not exists, or changed */
- UI_id_icon_render(C, id, big, true);
+ UI_id_icon_render(C, NULL, id, big, true);
break;
default:
break;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 5ccfa4193e9..e68c86353a3 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -753,9 +753,13 @@ static int find_highest_panel(const void *a1, const void *a2)
const PanelSort *ps1 = a1, *ps2 = a2;
/* stick uppermost header-less panels to the top of the region -
- * prevent them from being sorted */
- if (ps1->pa->sortorder < ps2->pa->sortorder && ps1->pa->type->flag & PNL_NO_HEADER) return -1;
-
+ * prevent them from being sorted (multiple header-less panels have to be sorted though) */
+ if (ps1->pa->type->flag & PNL_NO_HEADER && ps2->pa->type->flag & PNL_NO_HEADER) {
+ /* skip and check for ofs and sortorder below */
+ }
+ else if (ps1->pa->type->flag & PNL_NO_HEADER) return -1;
+ else if (ps2->pa->type->flag & PNL_NO_HEADER) return 1;
+
if (ps1->pa->ofsy + ps1->pa->sizey < ps2->pa->ofsy + ps2->pa->sizey) return 1;
else if (ps1->pa->ofsy + ps1->pa->sizey > ps2->pa->ofsy + ps2->pa->sizey) return -1;
else if (ps1->pa->sortorder > ps2->pa->sortorder) return 1;
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 7f20970cfb9..10541a6d02e 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -75,10 +75,16 @@
#define KMAXDIST 10 /* max mouse distance from edge before not detecting it */
+/* WARNING: knife float precision is fragile:
+ * be careful before making changes here see: (T43229, T42864, T42459, T41164).
+ */
#define KNIFE_FLT_EPS 0.00001f
#define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS)
#define KNIFE_FLT_EPSBIG 0.0005f
-#define KNIFE_FLT_EPS_PX 0.2f
+
+#define KNIFE_FLT_EPS_PX_VERT 0.5f
+#define KNIFE_FLT_EPS_PX_EDGE 0.05f
+#define KNIFE_FLT_EPS_PX_FACE 0.05f
typedef struct KnifeColors {
unsigned char line[3];
@@ -1318,7 +1324,6 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
float vert_tol, vert_tol_sq;
float line_tol, line_tol_sq;
float face_tol, face_tol_sq;
- float eps_scale, eps_scale_px;
int isect_kind;
unsigned int tot;
int i;
@@ -1426,19 +1431,10 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
/* Now go through the candidates and find intersections */
/* These tolerances, in screen space, are for intermediate hits, as ends are already snapped to screen */
- {
- /* Scale the epsilon by the zoom level
- * to compensate for projection imprecision, see T41164 */
- const float zoom_xy[2] = {
- kcd->vc.rv3d->winmat[0][0],
- kcd->vc.rv3d->winmat[1][1]};
- eps_scale = len_v2(zoom_xy);
- eps_scale_px = eps_scale * (kcd->is_interactive ? KNIFE_FLT_EPS_PX : KNIFE_FLT_EPSBIG);
- }
-
- vert_tol = eps_scale_px;
- line_tol = eps_scale_px;
- face_tol = max_ff(vert_tol, line_tol);
+
+ vert_tol = KNIFE_FLT_EPS_PX_VERT;
+ line_tol = KNIFE_FLT_EPS_PX_EDGE;
+ face_tol = KNIFE_FLT_EPS_PX_FACE;
vert_tol_sq = vert_tol * vert_tol;
line_tol_sq = line_tol * line_tol;
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index 71ad73ac420..95dc3de0b7f 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -41,7 +41,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
-#include "BKE_object_data_transfer.h"
+#include "BKE_data_transfer.h"
#include "BKE_DerivedMesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 8833d76fde2..ea80a07fdd4 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -1098,14 +1098,13 @@ static void icon_preview_free(void *customdata)
MEM_freeN(ip);
}
-void ED_preview_icon_render(const bContext *C, void *UNUSED(owner), ID *id, unsigned int *rect, int sizex, int sizey)
+void ED_preview_icon_render(Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey)
{
IconPreview ip = {0};
short stop = false, update = false;
float progress = 0.0f;
- /* customdata for preview thread */
- ip.scene = CTX_data_scene(C);
+ ip.scene = scene;
ip.owner = id;
ip.id = id;
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index c179cfc464c..3f814084238 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1748,6 +1748,13 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type)
}
}
+ if (sa && (sa->spacetype != type)) {
+ newsa->flag |= AREA_FLAG_TEMP_TYPE;
+ }
+ else {
+ newsa->flag &= ~AREA_FLAG_TEMP_TYPE;
+ }
+
ED_area_newspace(C, newsa, type);
return newsa;
@@ -1763,6 +1770,21 @@ void ED_screen_full_prevspace(bContext *C, ScrArea *sa)
ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED);
}
+void ED_screen_retore_temp_type(bContext *C, ScrArea *sa, bool is_screen_change)
+{
+ /* incase nether functions below run */
+ ED_area_tag_redraw(sa);
+
+ if (sa->flag & AREA_FLAG_TEMP_TYPE) {
+ ED_area_prevspace(C, sa);
+ sa->flag &= ~AREA_FLAG_TEMP_TYPE;
+ }
+
+ if (is_screen_change && sa->full) {
+ ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ }
+}
+
/* restore a screen / area back to default operation, after temp fullscreen modes */
void ED_screen_full_restore(bContext *C, ScrArea *sa)
{
@@ -1789,12 +1811,14 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa)
else
ED_screen_state_toggle(C, win, sa, state);
}
- else if (sl->spacetype == SPACE_FILE) {
+ else if (sa->flag & AREA_FLAG_TEMP_TYPE) {
ED_screen_full_prevspace(C, sa);
}
else {
ED_screen_state_toggle(C, win, sa, state);
}
+
+ sa->flag &= ~AREA_FLAG_TEMP_TYPE;
}
/* otherwise just tile the area again */
else {
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 5d0734db18b..3f3c14d3a7d 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -111,6 +111,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
ARegion *artmp;
+ const bool is_browse_only = (sfile->op == NULL);
/* Initialize UI block. */
BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
@@ -124,15 +125,22 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
available_w -= chan_offs;
}
}
-
+
/* Is there enough space for the execute / cancel buttons? */
- loadbutton = UI_fontstyle_string_width(params->title) + btn_margin;
- CLAMP_MIN(loadbutton, btn_minw);
- if (available_w <= loadbutton + separator + input_minw || params->title[0] == 0) {
+
+ if (is_browse_only) {
loadbutton = 0;
}
else {
+ loadbutton = UI_fontstyle_string_width(params->title) + btn_margin;
+ CLAMP_MIN(loadbutton, btn_minw);
+ if (available_w <= loadbutton + separator + input_minw) {
+ loadbutton = 0;
+ }
+ }
+
+ if (loadbutton) {
line1_w -= (loadbutton + separator);
line2_w = line1_w;
}
@@ -145,7 +153,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar)
else {
line2_w -= (fnumbuttons + separator);
}
-
+
/* Text input fields for directory and file. */
if (available_w > 0) {
int overwrite_alert = file_draw_check_exists(sfile);
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index fb33879e2c1..86991245068 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -173,6 +173,12 @@ typedef struct bSplineIKConstraint {
/* settings */
short flag; /* general settings for constraint */
short xzScaleMode; /* method used for determining the x & z scaling of the bones */
+
+ /* volume preservation settings */
+ float bulge;
+ float bulge_min;
+ float bulge_max;
+ float bulge_smooth;
} bSplineIKConstraint;
@@ -680,15 +686,19 @@ typedef enum eKinematic_Flags {
/* bSplineIKConstraint->flag */
typedef enum eSplineIK_Flags {
/* chain has been attached to spline */
- CONSTRAINT_SPLINEIK_BOUND = (1<<0),
+ CONSTRAINT_SPLINEIK_BOUND = (1 << 0),
/* root of chain is not influenced by the constraint */
- CONSTRAINT_SPLINEIK_NO_ROOT = (1<<1),
+ CONSTRAINT_SPLINEIK_NO_ROOT = (1 << 1),
/* bones in the chain should not scale to fit the curve */
- CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1<<2),
+ CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1 << 2),
/* evenly distribute the bones along the path regardless of length */
- CONSTRAINT_SPLINEIK_EVENSPLITS = (1<<3),
+ CONSTRAINT_SPLINEIK_EVENSPLITS = (1 << 3),
/* don't adjust the x and z scaling of the bones by the curve radius */
- CONSTRAINT_SPLINEIK_NO_CURVERAD = (1<<4)
+ CONSTRAINT_SPLINEIK_NO_CURVERAD = (1 << 4),
+
+ /* for "volumetric" xz scale mode, limit the minimum or maximum scale values */
+ CONSTRAINT_SPLINEIK_USE_BULGE_MIN = (1 << 5),
+ CONSTRAINT_SPLINEIK_USE_BULGE_MAX = (1 << 6),
} eSplineIK_Flags;
/* bSplineIKConstraint->xzScaleMode */
@@ -698,7 +708,9 @@ typedef enum eSplineIK_XZScaleModes {
/* bones in the chain should take their x/z scales from the original scaling */
CONSTRAINT_SPLINEIK_XZS_ORIGINAL = 1,
/* x/z scales are the inverse of the y-scale */
- CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 2
+ CONSTRAINT_SPLINEIK_XZS_INVERSE = 2,
+ /* x/z scales are computed using a volume preserving technique (from Stretch To constraint) */
+ CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 3
} eSplineIK_XZScaleModes;
/* MinMax (floor) flags */
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 47a08c62f95..941a7d020bc 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -272,12 +272,16 @@ typedef struct ARegion {
// #define WIN_EQUAL 3 // UNUSED
/* area->flag */
-#define HEADER_NO_PULLDOWN (1 << 0)
-#define AREA_FLAG_DRAWJOINTO (1 << 1)
-#define AREA_FLAG_DRAWJOINFROM (1 << 2)
-#define AREA_TEMP_INFO (1 << 3)
-#define AREA_FLAG_DRAWSPLIT_H (1 << 4)
-#define AREA_FLAG_DRAWSPLIT_V (1 << 5)
+enum {
+ HEADER_NO_PULLDOWN = (1 << 0),
+ AREA_FLAG_DRAWJOINTO = (1 << 1),
+ AREA_FLAG_DRAWJOINFROM = (1 << 2),
+ AREA_TEMP_INFO = (1 << 3),
+ AREA_FLAG_DRAWSPLIT_H = (1 << 4),
+ AREA_FLAG_DRAWSPLIT_V = (1 << 5),
+ /* used to check if we should switch back to prevspace (of a different type) */
+ AREA_FLAG_TEMP_TYPE = (1 << 6),
+};
#define EDGEWIDTH 1
#define AREAGRID 4
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 51d81295f8c..009e3799c49 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -64,6 +64,7 @@ EnumPropertyItem id_type_items[] = {
{ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""},
{ID_MB, "META", ICON_META_DATA, "MetaBall", ""},
{ID_ME, "MESH", ICON_MESH_DATA, "Mesh", ""},
+ {ID_MC, "MOVIECLIP", ICON_CLIP, "MovieClip", ""},
{ID_NT, "NODETREE", ICON_NODETREE, "NodeTree", ""},
{ID_OB, "OBJECT", ICON_OBJECT_DATA, "Object", ""},
{ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""},
@@ -71,12 +72,12 @@ EnumPropertyItem id_type_items[] = {
{ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""},
{ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""},
{ID_SCR, "SCREEN", ICON_SPLITSCREEN, "Screen", ""},
+ {ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""},
{ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""},
- {ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""},
{ID_TXT, "TEXT", ICON_TEXT, "Text", ""},
{ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""},
- {ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
{ID_WM, "WINDOWMANAGER", ICON_FULLSCREEN, "Window Manager", ""},
+ {ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -141,23 +142,23 @@ short RNA_type_to_ID_code(StructRNA *type)
if (RNA_struct_is_a(type, &RNA_Lattice)) return ID_LT;
if (RNA_struct_is_a(type, &RNA_Material)) return ID_MA;
if (RNA_struct_is_a(type, &RNA_MetaBall)) return ID_MB;
- if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT;
+ if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC;
if (RNA_struct_is_a(type, &RNA_Mesh)) return ID_ME;
+ if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
+ if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT;
if (RNA_struct_is_a(type, &RNA_Object)) return ID_OB;
if (RNA_struct_is_a(type, &RNA_ParticleSettings)) return ID_PA;
+ if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
+ if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
if (RNA_struct_is_a(type, &RNA_Scene)) return ID_SCE;
if (RNA_struct_is_a(type, &RNA_Screen)) return ID_SCR;
- if (RNA_struct_is_a(type, &RNA_Speaker)) return ID_SPK;
if (RNA_struct_is_a(type, &RNA_Sound)) return ID_SO;
- if (RNA_struct_is_a(type, &RNA_Text)) return ID_TXT;
+ if (RNA_struct_is_a(type, &RNA_Speaker)) return ID_SPK;
if (RNA_struct_is_a(type, &RNA_Texture)) return ID_TE;
+ if (RNA_struct_is_a(type, &RNA_Text)) return ID_TXT;
if (RNA_struct_is_a(type, &RNA_VectorFont)) return ID_VF;
if (RNA_struct_is_a(type, &RNA_World)) return ID_WO;
if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM;
- if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC;
- if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK;
- if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL;
- if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC;
return 0;
}
@@ -180,23 +181,23 @@ StructRNA *ID_code_to_RNA_type(short idcode)
case ID_LT: return &RNA_Lattice;
case ID_MA: return &RNA_Material;
case ID_MB: return &RNA_MetaBall;
- case ID_NT: return &RNA_NodeTree;
+ case ID_MC: return &RNA_MovieClip;
case ID_ME: return &RNA_Mesh;
+ case ID_MSK: return &RNA_Mask;
+ case ID_NT: return &RNA_NodeTree;
case ID_OB: return &RNA_Object;
case ID_PA: return &RNA_ParticleSettings;
+ case ID_PAL: return &RNA_Palette;
+ case ID_PC: return &RNA_PaintCurve;
case ID_SCE: return &RNA_Scene;
case ID_SCR: return &RNA_Screen;
- case ID_SPK: return &RNA_Speaker;
case ID_SO: return &RNA_Sound;
- case ID_TXT: return &RNA_Text;
+ case ID_SPK: return &RNA_Speaker;
case ID_TE: return &RNA_Texture;
+ case ID_TXT: return &RNA_Text;
case ID_VF: return &RNA_VectorFont;
- case ID_WO: return &RNA_World;
case ID_WM: return &RNA_WindowManager;
- case ID_MC: return &RNA_MovieClip;
- case ID_MSK: return &RNA_Mask;
- case ID_PAL: return &RNA_Palette;
- case ID_PC: return &RNA_PaintCurve;
+ case ID_WO: return &RNA_World;
default: return &RNA_ID;
}
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 77355dbad0e..b6845b1df2e 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -1388,7 +1388,7 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0, 1.0f);
- RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "");
+ RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
@@ -2272,8 +2272,10 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
{CONSTRAINT_SPLINEIK_XZS_NONE, "NONE", 0, "None", "Don't scale the X and Z axes (Default)"},
{CONSTRAINT_SPLINEIK_XZS_ORIGINAL, "BONE_ORIGINAL", 0, "Bone Original",
"Use the original scaling of the bones"},
+ {CONSTRAINT_SPLINEIK_XZS_INVERSE, "INVERSE_PRESERVE", 0, "Inverse Scale",
+ "Scale of the X and Z axes is the inverse of the Y-Scale"},
{CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC, "VOLUME_PRESERVE", 0, "Volume Preservation",
- "Scale of the X and Z axes is the inverse of the Y-Scale"},
+ "Scale of the X and Z axes are adjusted to preserve the volume of the bones"},
{0, NULL, 0, NULL, NULL}
};
@@ -2333,12 +2335,44 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
"on top of XZ Scale mode");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ /* xz scaling mode */
prop = RNA_def_property(srna, "xz_scale_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "xzScaleMode");
RNA_def_property_enum_items(prop, splineik_xz_scale_mode);
RNA_def_property_ui_text(prop, "XZ Scale Mode",
"Method used for determining the scaling of the X and Z axes of the bones");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ /* volume presevation for "volumetric" scale mode */
+ prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 100.f);
+ RNA_def_property_ui_text(prop, "Volume Variation", "Factor between volume variation and stretching");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "use_bulge_min", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MIN);
+ RNA_def_property_ui_text(prop, "Use Volume Variation Minimum", "Use lower limit for volume variation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "use_bulge_max", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MAX);
+ RNA_def_property_ui_text(prop, "Use Volume Variation Maximum", "Use upper limit for volume variation");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_min", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Minimum", "Minimum volume stretching factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_max", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 1.0, 100.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Maximum", "Maximum volume stretching factor");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_pivot(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 03e73ec186a..9554b219da9 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -43,7 +43,7 @@
#include "BLF_translation.h"
#include "BKE_animsys.h"
-#include "BKE_object_data_transfer.h"
+#include "BKE_data_transfer.h"
#include "BKE_DerivedMesh.h"
#include "BKE_dynamicpaint.h"
#include "BKE_mesh_mapping.h"
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 7ad7f129218..8eed482327d 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2200,13 +2200,20 @@ static void rna_def_space_view3d(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "persmat");
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX: for now, it's too risky for users to do this */
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
- RNA_def_property_ui_text(prop, "Perspective Matrix", "Current perspective matrix of the 3D region");
+ RNA_def_property_ui_text(prop, "Perspective Matrix",
+ "Current perspective matrix (``window_matrix * view_matrix``)");
+
+ prop = RNA_def_property(srna, "window_matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_float_sdna(prop, NULL, "winmat");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_ui_text(prop, "Window Matrix", "Current window matrix");
prop = RNA_def_property(srna, "view_matrix", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_float_sdna(prop, NULL, "viewmat");
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_float_funcs(prop, NULL, "rna_RegionView3D_view_matrix_set", NULL);
- RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix of the 3D region");
+ RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "view_perspective", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index 06f9d274576..2dca3218e41 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -37,7 +37,7 @@
#include "DNA_object_types.h"
#include "BKE_customdata.h"
-#include "BKE_object_data_transfer.h"
+#include "BKE_data_transfer.h"
#include "BKE_DerivedMesh.h"
#include "BKE_library.h"
#include "BKE_mesh_mapping.h"
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index c7170cfa4b4..35878f664ea 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -2721,12 +2721,13 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset)
vlr->v4= NULL;
/* to prevent float accuracy issues, we calculate normal in local object space (not world) */
- if (area_tri_v3(co3, co2, co1)>FLT_EPSILON) {
- if (negative_scale)
- normal_tri_v3(tmp, co1, co2, co3);
- else
- normal_tri_v3(tmp, co3, co2, co1);
- add_v3_v3(n, tmp);
+ if (normal_tri_v3(tmp, co1, co2, co3) > FLT_EPSILON) {
+ if (negative_scale == false) {
+ add_v3_v3(n, tmp);
+ }
+ else {
+ sub_v3_v3(n, tmp);
+ }
}
vlr->mat= matar[ dl->col ];
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index e7b3de74a5c..1fc1348385b 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1707,16 +1707,12 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand
/* remlink now, for load file case before removing*/
BLI_remlink(handlers, handler);
-
+
if (val != EVT_FILESELECT_EXTERNAL_CANCEL) {
- if (screen != handler->filescreen) {
- ED_screen_full_prevspace(C, CTX_wm_area(C));
- }
- else {
- ED_area_prevspace(C, CTX_wm_area(C));
- }
+ ScrArea *sa = CTX_wm_area(C);
+ ED_screen_retore_temp_type(C, sa, screen != handler->filescreen);
}
-
+
wm_handler_op_context(C, handler);
/* needed for UI_popup_menu_reports */
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index fabb69b8eff..c1c31f6795d 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -101,7 +101,6 @@
#include "GHOST_Path-api.h"
#include "UI_interface.h"
-#include "UI_interface_icons.h"
#include "UI_view2d.h"
#include "GPU_draw.h"
@@ -895,24 +894,6 @@ bool write_crash_blend(void)
}
}
-static void UNUSED_FUNCTION(wm_ensure_previews)(bContext *C, Main *mainvar)
-{
- ListBase *lb[] = {&mainvar->mat, &mainvar->tex, &mainvar->image, &mainvar->world, &mainvar->lamp, NULL};
- ID *id;
- int i;
-
- for (i = 0; lb[i]; i++) {
- for (id = lb[i]->first; id; id = id->next) {
- /* Only preview non-library datablocks, lib ones do not pertain to this .blend file!
- * Same goes for ID with no user. */
- if (!id->lib && (id->us != 0)) {
- UI_id_icon_render(C, id, false, false);
- UI_id_icon_render(C, id, true, false);
- }
- }
- }
-}
-
/**
* \see #wm_homefile_write_exec wraps #BLO_write_file in a similar way.
*/
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 5b944a7b1ec..02a029fc3f3 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -61,6 +61,7 @@
#include "BLI_blenlib.h"
#include "BLI_dial.h"
#include "BLI_dynstr.h" /*for WM_operator_pystring */
+#include "BLI_linklist_stack.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -76,6 +77,7 @@
#include "BKE_idprop.h"
#include "BKE_image.h"
#include "BKE_library.h"
+#include "BKE_library_query.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_material.h"
@@ -105,6 +107,7 @@
#include "RNA_enum_types.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "UI_resources.h"
#include "WM_api.h"
@@ -4705,6 +4708,90 @@ static void WM_OT_dependency_relations(wmOperatorType *ot)
ot->exec = dependency_relations_exec;
}
+/* *************************** Mat/tex/etc. previews generation ************* */
+
+typedef struct PreviewsIDEnsureStack {
+ Scene *scene;
+
+ BLI_LINKSTACK_DECLARE(id_stack, ID *);
+} PreviewsIDEnsureStack;
+
+static void previews_id_ensure(bContext *C, Scene *scene, ID *id)
+{
+ BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA));
+
+ /* Only preview non-library datablocks, lib ones do not pertain to this .blend file!
+ * Same goes for ID with no user. */
+ if (!id->lib && (id->us != 0)) {
+ UI_id_icon_render(C, scene, id, false, false);
+ UI_id_icon_render(C, scene, id, true, false);
+ }
+}
+
+static bool previews_id_ensure_callback(void *todo_v, ID **idptr, int UNUSED(cd_flag))
+{
+ PreviewsIDEnsureStack *todo = todo_v;
+ ID *id = *idptr;
+
+ if (id && (id->flag & LIB_DOIT)) {
+ if (ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)) {
+ previews_id_ensure(NULL, todo->scene, id);
+ }
+ id->flag &= ~LIB_DOIT; /* Tag the ID as done in any case. */
+ BLI_LINKSTACK_PUSH(todo->id_stack, id);
+ }
+
+ return true;
+}
+
+static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ ListBase *lb[] = {&bmain->mat, &bmain->tex, &bmain->image, &bmain->world, &bmain->lamp, NULL};
+ PreviewsIDEnsureStack preview_id_stack;
+ Scene *scene;
+ ID *id;
+ int i;
+
+ /* We use LIB_DOIT to check whether we have already handled a given ID or not. */
+ BKE_main_id_flag_all(bmain, LIB_DOIT, true);
+
+ BLI_LINKSTACK_INIT(preview_id_stack.id_stack);
+
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
+ preview_id_stack.scene = scene;
+ id = (ID *)scene;
+
+ do {
+ /* This will loop over all IDs linked by current one, render icons for them if needed,
+ * and add them to 'todo' preview_id_stack. */
+ BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_stack, IDWALK_READONLY);
+ } while((id = BLI_LINKSTACK_POP(preview_id_stack.id_stack)));
+ }
+
+ BLI_LINKSTACK_FREE(preview_id_stack.id_stack);
+
+ /* Check a last time for ID not used (fake users only, in theory), and
+ * do our best for those, using current scene... */
+ for (i = 0; lb[i]; i++) {
+ for (id = lb[i]->first; id; id = id->next) {
+ previews_id_ensure(C, NULL, id);
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void WM_OT_previews_ensure(wmOperatorType *ot)
+{
+ ot->name = "Refresh DataBlock Previews";
+ ot->idname = "WM_OT_previews_ensure";
+ ot->description = "Ensure datablock previews are available and up-to-date "
+ "(to be saved in .blend file, only for some types like materials, textures, etc.)";
+
+ ot->exec = previews_ensure_exec;
+}
+
/* ******************************************************* */
static void operatortype_ghash_free_cb(wmOperatorType *ot)
@@ -4768,6 +4855,7 @@ void wm_operatortype_init(void)
#if defined(WIN32)
WM_operatortype_append(WM_OT_console_toggle);
#endif
+ WM_operatortype_append(WM_OT_previews_ensure);
}
/* circleselect-like modal operators */