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:
authorDalai Felinto <dfelinto@gmail.com>2015-04-06 16:37:12 +0300
committerDalai Felinto <dfelinto@gmail.com>2015-04-06 16:37:12 +0300
commit3519a9f5179132251d60cd7660e8b257f41de76d (patch)
treebe6b81d2c439249af96b8b28b5013dcbb735b937
parentbdf398daa805cc233d5cdf1a08bf6f71f0d5f994 (diff)
parent74df307ca43df14b759fd9eb6a049a6c5d90dcda (diff)
Merge remote-tracking branch 'origin/master' into multiviewmultiview
-rw-r--r--intern/cycles/blender/blender_sync.cpp33
-rw-r--r--intern/cycles/blender/blender_sync.h3
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h161
-rw-r--r--intern/cycles/kernel/geom/geom_volume.h2
-rw-r--r--intern/cycles/render/nodes.cpp13
-rw-r--r--intern/cycles/util/util_math_fast.h4
-rw-r--r--release/scripts/startup/bl_ui/space_image.py4
-rw-r--r--source/blender/blenkernel/intern/deform.c8
-rw-r--r--source/blender/blenkernel/intern/icons.c8
-rw-r--r--source/blender/blenkernel/intern/treehash.c10
-rw-r--r--source/blender/blenlib/BLI_ghash.h1
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c54
-rw-r--r--source/blender/blenlib/intern/scanfill_utils.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c5
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c25
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c36
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c4
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c2
-rw-r--r--source/blender/editors/mesh/mesh_ops.c2
-rw-r--r--source/blender/editors/screen/area.c6
-rw-r--r--source/blender/editors/space_graph/graph_select.c18
-rw-r--r--source/blender/editors/space_image/image_ops.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c3
-rw-r--r--source/blender/editors/transform/transform.c13
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c8
-rw-r--r--source/blender/modifiers/intern/MOD_build.c42
-rw-r--r--source/blender/render/intern/source/render_texture.c13
-rw-r--r--source/blender/render/intern/source/shadeinput.c2
-rw-r--r--source/blender/render/intern/source/zbuf.c48
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c12
-rw-r--r--source/blender/windowmanager/intern/wm_window.c15
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp10
34 files changed, 343 insertions, 270 deletions
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 2ed61860066..aaf7d7d58ef 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -150,6 +150,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void *
sync_integrator();
sync_film();
sync_shaders();
+ sync_images();
sync_curve_settings();
mesh_synced.clear(); /* use for objects and motion sync */
@@ -360,6 +361,38 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
}
}
+/* Images */
+void BlenderSync::sync_images()
+{
+ /* Sync is a convention for this API, but currently it frees unused buffers. */
+
+ const bool is_interface_locked = b_engine.render() &&
+ b_engine.render().use_lock_interface();
+ if(is_interface_locked == false && BlenderSession::headless == false) {
+ /* If interface is not locked, it's possible image is needed for
+ * the display.
+ */
+ return;
+ }
+ /* Free buffers used by images which are not needed for render. */
+ BL::BlendData::images_iterator b_image;
+ for(b_data.images.begin(b_image);
+ b_image != b_data.images.end();
+ ++b_image)
+ {
+ /* TODO(sergey): Consider making it an utility function to check
+ * whether image is considered builtin.
+ */
+ const bool is_builtin = b_image->packed_file() ||
+ b_image->source() == BL::Image::source_GENERATED ||
+ b_image->source() == BL::Image::source_MOVIE;
+ if(is_builtin == false) {
+ b_image->buffers_free();
+ }
+ /* TODO(sergey): Free builtin images not used by any shader. */
+ }
+}
+
/* Scene Parameters */
SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background, bool is_cpu)
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 2c2e41fbca2..5fbf2c3011f 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -95,6 +95,9 @@ private:
/* particles */
bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object);
+ /* Images. */
+ void sync_images();
+
/* util */
void find_shader(BL::ID id, vector<uint>& used_shaders, int default_shader);
bool BKE_object_is_modified(BL::Object b_ob);
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 71086f2e764..32cf36abd27 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -35,79 +35,7 @@
CCL_NAMESPACE_BEGIN
-/* Approximate erf and erfinv implementations.
- * Implementation comes straight from Wikipedia:
- *
- * http://en.wikipedia.org/wiki/Error_function
- *
- * Some constants are baked into the code.
- */
-
-ccl_device_inline float approx_erff_do(float x)
-{
- /* Such a clamp doesn't give much distortion to the output value
- * and gives quite a few of the speedup.
- */
- if(x > 3.0f) {
- return 1.0f;
- }
- float t = 1.0f / (1.0f + 0.47047f*x);
- return (1.0f -
- t*(0.3480242f + t*(-0.0958798f + t*0.7478556f)) * expf(-x*x));
-}
-
-ccl_device_inline float approx_erff(float x)
-{
- if(x >= 0.0f) {
- return approx_erff_do(x);
- }
- else {
- return -approx_erff_do(-x);
- }
-}
-
-ccl_device_inline float approx_erfinvf_do(float x)
-{
- if(x <= 0.7f) {
- const float x2 = x * x;
- const float a1 = 0.886226899f;
- const float a2 = -1.645349621f;
- const float a3 = 0.914624893f;
- const float a4 = -0.140543331f;
- const float b1 = -2.118377725f;
- const float b2 = 1.442710462f;
- const float b3 = -0.329097515f;
- const float b4 = 0.012229801f;
- return x * (((a4 * x2 + a3) * x2 + a2) * x2 + a1) /
- ((((b4 * x2 + b3) * x2 + b2) * x2 + b1) * x2 + 1.0f);
- }
- else {
- const float c1 = -1.970840454f;
- const float c2 = -1.624906493f;
- const float c3 = 3.429567803f;
- const float c4 = 1.641345311f;
- const float d1 = 3.543889200f;
- const float d2 = 1.637067800f;
- const float z = sqrtf(-logf((1.0f - x) * 0.5f));
- return (((c4 * z + c3) * z + c2) * z + c1) /
- ((d2 * z + d1) * z + 1.0f);
- }
-}
-
-ccl_device_inline float approx_erfinvf(float x)
-{
- if(x >= 0.0f) {
- return approx_erfinvf_do(x);
- }
- else {
- return -approx_erfinvf_do(-x);
- }
-}
-
-/* Beckmann and GGX microfacet importance sampling from:
- *
- * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals.
- * E. Heitz and E. d'Eon, EGSR 2014 */
+/* Beckmann and GGX microfacet importance sampling. */
ccl_device_inline void microfacet_beckmann_sample_slopes(
KernelGlobals *kg,
@@ -128,64 +56,71 @@ ccl_device_inline void microfacet_beckmann_sample_slopes(
/* precomputations */
const float tan_theta_i = sin_theta_i/cos_theta_i;
const float inv_a = tan_theta_i;
- const float a = 1.0f/inv_a;
- const float erf_a = approx_erff(a);
- const float exp_a2 = expf(-a*a);
+ const float cot_theta_i = 1.0f/tan_theta_i;
+ const float erf_a = fast_erff(cot_theta_i);
+ const float exp_a2 = expf(-cot_theta_i*cot_theta_i);
const float SQRT_PI_INV = 0.56418958354f;
const float Lambda = 0.5f*(erf_a - 1.0f) + (0.5f*SQRT_PI_INV)*(exp_a2*inv_a);
const float G1 = 1.0f/(1.0f + Lambda); /* masking */
*G1i = G1;
-#if 0
- const float C = 1.0f - G1 * erf_a;
-
- /* sample slope X */
- if(randu < C) {
- /* rescale randu */
- randu = randu / C;
- const float w_1 = 0.5f * SQRT_PI_INV * sin_theta_i * exp_a2;
- const float w_2 = cos_theta_i * (0.5f - 0.5f*erf_a);
- const float p = w_1 / (w_1 + w_2);
+#if defined(__KERNEL_GPU__)
+ /* Based on paper from Wenzel Jakob
+ * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
+ *
+ * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
+ *
+ * Reformulation from OpenShadingLanguage which avoids using inverse
+ * trigonometric functions.
+ */
- if(randu < p) {
- randu = randu / p;
- *slope_x = -sqrtf(-logf(randu*exp_a2));
- }
- else {
- randu = (randu - p) / (1.0f - p);
- *slope_x = approx_erfinvf(randu - 1.0f - randu*erf_a);
- }
+ /* Sample slope X.
+ *
+ * Compute a coarse approximation using the approximation:
+ * exp(-ierf(x)^2) ~= 1 - x * x
+ * solve y = 1 + b + K * (1 - b * b)
+ */
+ float K = tan_theta_i * SQRT_PI_INV;
+ float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
+ float y_exact = randu * (1.0f + erf_a + K * exp_a2);
+ float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
+
+ /* Perform newton step to refine toward the true root. */
+ float inv_erf = fast_ierff(b);
+ float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ /* Check if we are close enough already,
+ * this also avoids NaNs as we get close to the root.
+ */
+ if(fabsf(value) > 1e-6f) {
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */
+ inv_erf = fast_ierff(b);
+ value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */
+ /* Compute the slope from the refined value. */
+ *slope_x = fast_ierff(b);
}
else {
- /* rescale randu */
- randu = (randu - C) / (1.0f - C);
- *slope_x = approx_erfinvf((-1.0f + 2.0f*randu)*erf_a);
-
- const float p = (-(*slope_x)*sin_theta_i + cos_theta_i) / (2.0f*cos_theta_i);
-
- if(randv > p) {
- *slope_x = -(*slope_x);
- randv = (randv - p) / (1.0f - p);
- }
- else
- randv = randv / p;
+ /* We are close enough already. */
+ *slope_x = inv_erf;
}
-
- /* sample slope Y */
- *slope_y = approx_erfinvf(2.0f*randv - 1.0f);
+ *slope_y = fast_ierff(2.0f*randv - 1.0f);
#else
- /* use precomputed table, because it better preserves stratification
- * of the random number pattern */
+ /* Use precomputed table on CPU, it gives better perfomance. */
int beckmann_table_offset = kernel_data.tables.beckmann_offset;
*slope_x = lookup_table_read_2D(kg, randu, cos_theta_i,
beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE);
- *slope_y = approx_erfinvf(2.0f*randv - 1.0f);
+ *slope_y = fast_ierff(2.0f*randv - 1.0f);
#endif
-
}
+/* GGX microfacet importance sampling from:
+ *
+ * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals.
+ * E. Heitz and E. d'Eon, EGSR 2014
+ */
+
ccl_device_inline void microfacet_ggx_sample_slopes(
const float cos_theta_i, const float sin_theta_i,
float randu, float randv, float *slope_x, float *slope_y,
diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h
index c33509fbf4f..c72afa2a3a4 100644
--- a/intern/cycles/kernel/geom/geom_volume.h
+++ b/intern/cycles/kernel/geom/geom_volume.h
@@ -60,7 +60,7 @@ ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd,
#endif
if(dx) *dx = 0.0f;
- if(dx) *dy = 0.0f;
+ if(dy) *dy = 0.0f;
/* todo: support float textures to lower memory usage for single floats */
return average(float4_to_float3(r));
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index a62634efa42..40bb82c6330 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -2248,10 +2248,15 @@ void GeometryNode::compile(SVMCompiler& compiler)
out = output("Pointiness");
if(!out->links.empty()) {
compiler.stack_assign(out);
- compiler.add_node(attr_node,
- ATTR_STD_POINTINESS,
- out->stack_offset,
- NODE_ATTR_FLOAT);
+ if(compiler.output_type() != SHADER_TYPE_VOLUME) {
+ compiler.add_node(attr_node,
+ ATTR_STD_POINTINESS,
+ out->stack_offset,
+ NODE_ATTR_FLOAT);
+ }
+ else {
+ compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), out->stack_offset);
+ }
}
}
diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h
index 4ad81e9c015..1acceee22a5 100644
--- a/intern/cycles/util/util_math_fast.h
+++ b/intern/cycles/util/util_math_fast.h
@@ -539,7 +539,7 @@ ccl_device float fast_safe_powf(float x, float y)
* bsdf_microfaset.h.
*/
-ccl_device float fast_erff(float x)
+ccl_device_inline float fast_erff(float x)
{
/* Examined 1082130433 values of erff on [0,4]: 1.93715e-06 max error. */
/* Abramowitz and Stegun, 7.1.28. */
@@ -570,7 +570,7 @@ ccl_device_inline float fast_erfcf(float x)
return 1.0f - fast_erff(x);
}
-ccl_device float fast_ierff(float x)
+ccl_device_inline float fast_ierff(float x)
{
/* From: Approximating the erfinv function by Mike Giles. */
/* To avoid trouble at the limit, clamp input to 1-eps. */
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 0af8b79b1e2..a1101bb3efb 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -629,6 +629,8 @@ class IMAGE_PT_view_properties(Panel):
sima = context.space_data
ima = sima.image
+
+ show_render = sima.show_render
show_uvedit = sima.show_uvedit
show_maskedit = sima.show_maskedit
uvedit = sima.uv_editor
@@ -673,7 +675,7 @@ class IMAGE_PT_view_properties(Panel):
sub.active = uvedit.show_stretch
sub.row().prop(uvedit, "draw_stretch_type", expand=True)
- if ima:
+ if show_render and ima:
layout.separator()
render_slot = ima.render_slots.active
layout.prop(render_slot, "name", text="Slot Name")
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 350b19b0250..72133cf6460 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -982,7 +982,7 @@ void BKE_defvert_extract_vgroup_to_vertweights(
}
}
else {
- fill_vn_fl(r_weights, invert_vgroup ? 1.0f : 0.0f, num_verts);
+ fill_vn_fl(r_weights, num_verts, invert_vgroup ? 1.0f : 0.0f);
}
}
@@ -1008,7 +1008,7 @@ void BKE_defvert_extract_vgroup_to_edgeweights(
MEM_freeN(tmp_weights);
}
else {
- fill_vn_fl(r_weights, 0.0f, num_edges);
+ fill_vn_fl(r_weights, num_edges, 0.0f);
}
}
@@ -1031,7 +1031,7 @@ void BKE_defvert_extract_vgroup_to_loopweights(
MEM_freeN(tmp_weights);
}
else {
- fill_vn_fl(r_weights, 0.0f, num_loops);
+ fill_vn_fl(r_weights, num_loops, 0.0f);
}
}
@@ -1060,7 +1060,7 @@ void BKE_defvert_extract_vgroup_to_polyweights(
MEM_freeN(tmp_weights);
}
else {
- fill_vn_fl(r_weights, 0.0f, num_polys);
+ fill_vn_fl(r_weights, num_polys, 0.0f);
}
}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 8bda957f187..d3225f3fa35 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -311,16 +311,14 @@ Icon *BKE_icon_get(int icon_id)
void BKE_icon_set(int icon_id, struct Icon *icon)
{
- Icon *old_icon = NULL;
+ void **val_p;
- old_icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
-
- if (old_icon) {
+ if (BLI_ghash_ensure_p(gIcons, SET_INT_IN_POINTER(icon_id), &val_p)) {
printf("BKE_icon_set: Internal error, icon already set: %d\n", icon_id);
return;
}
- BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), icon);
+ *val_p = icon;
}
void BKE_icon_delete(struct ID *id)
diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c
index 866502c4ae1..43eeae7329e 100644
--- a/source/blender/blenkernel/intern/treehash.c
+++ b/source/blender/blenkernel/intern/treehash.c
@@ -129,11 +129,13 @@ void *BKE_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore
void BKE_treehash_add_element(void *treehash, TreeStoreElem *elem)
{
- TseGroup *group = BLI_ghash_lookup(treehash, elem);
- if (!group) {
- group = tse_group_create();
- BLI_ghash_insert(treehash, elem, group);
+ TseGroup *group;
+ void **val_p;
+
+ if (!BLI_ghash_ensure_p(treehash, elem, &val_p)) {
+ *val_p = tse_group_create();
}
+ group = *val_p;
tse_group_add(group, elem);
}
diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h
index 16d18ef1315..a00ddeefb2b 100644
--- a/source/blender/blenlib/BLI_ghash.h
+++ b/source/blender/blenlib/BLI_ghash.h
@@ -79,6 +79,7 @@ bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfre
void *BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
void *BLI_ghash_lookup_default(GHash *gh, const void *key, void *val_default) ATTR_WARN_UNUSED_RESULT;
void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT;
+bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT;
bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp);
void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp,
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index f2705c79574..dae7af6a927 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -162,7 +162,7 @@ BLI_INLINE unsigned int ghash_bucket_index(GHash *gh, const unsigned int hash)
#ifdef GHASH_USE_MODULO_BUCKETS
return hash % gh->nbuckets;
#else
- return full_hash & gh->bucket_mask;
+ return hash & gh->bucket_mask;
#endif
}
@@ -445,19 +445,35 @@ BLI_INLINE void ghash_insert_ex(
}
/**
+ * Insert function that takes a pre-allocated entry.
+ */
+BLI_INLINE void ghash_insert_ex_keyonly_entry(
+ GHash *gh, void *key, const unsigned int bucket_index,
+ Entry *e)
+{
+ BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
+
+ e->next = gh->buckets[bucket_index];
+ e->key = key;
+ gh->buckets[bucket_index] = e;
+
+ ghash_buckets_expand(gh, ++gh->nentries, false);
+}
+
+/**
* Insert function that doesn't set the value (use for GSet)
*/
BLI_INLINE void ghash_insert_ex_keyonly(
GHash *gh, void *key, const unsigned int bucket_index)
{
- GSetEntry *e = BLI_mempool_alloc(gh->entrypool);
+ Entry *e = BLI_mempool_alloc(gh->entrypool);
BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0));
BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0);
e->next = gh->buckets[bucket_index];
e->key = key;
- gh->buckets[bucket_index] = (Entry *)e;
+ gh->buckets[bucket_index] = e;
ghash_buckets_expand(gh, ++gh->nentries, false);
}
@@ -498,7 +514,7 @@ BLI_INLINE bool ghash_insert_safe_keyonly(GHash *gh, void *key, const bool overr
{
const unsigned int hash = ghash_keyhash(gh, key);
const unsigned int bucket_index = ghash_bucket_index(gh, hash);
- GSetEntry *e = ghash_lookup_entry_ex(gh, key, bucket_index);
+ Entry *e = ghash_lookup_entry_ex(gh, key, bucket_index);
BLI_assert((gh->flag & GHASH_FLAG_IS_GSET) != 0);
@@ -721,6 +737,36 @@ void **BLI_ghash_lookup_p(GHash *gh, const void *key)
}
/**
+ * Ensure \a key is exists in \a gh.
+ *
+ * This handles the common situation where the caller needs ensure a key is added to \a gh,
+ * constructing a new value in the case the key isn't found.
+ * Otherwise use the existing value.
+ *
+ * Such situations typically incur multiple lookups, however this function
+ * avoids them by ensuring the key is added,
+ * returning a pointer to the value so it can be used or initialized by the caller.
+ *
+ * \returns true when the value didn't need to be added.
+ * (when false, the caller _must_ initialize the value).
+ */
+bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val)
+{
+ const unsigned int hash = ghash_keyhash(gh, key);
+ const unsigned int bucket_index = ghash_bucket_index(gh, hash);
+ GHashEntry *e = (GHashEntry *)ghash_lookup_entry_ex(gh, key, bucket_index);
+ const bool haskey = (e != NULL);
+
+ if (!haskey) {
+ e = BLI_mempool_alloc(gh->entrypool);
+ ghash_insert_ex_keyonly_entry(gh, key, bucket_index, (Entry *)e);
+ }
+
+ *r_val = &e->val;
+ return haskey;
+}
+
+/**
* Remove \a key from \a gh, or return false if the key wasn't found.
*
* \param key The key to remove.
diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c
index a606ac41aa1..d0420a30448 100644
--- a/source/blender/blenlib/intern/scanfill_utils.c
+++ b/source/blender/blenlib/intern/scanfill_utils.c
@@ -112,11 +112,13 @@ void BLI_scanfill_view3d_dump(ScanFillContext *sf_ctx)
static ListBase *edge_isect_ls_ensure(GHash *isect_hash, ScanFillEdge *eed)
{
ListBase *e_ls;
- e_ls = BLI_ghash_lookup(isect_hash, eed);
- if (e_ls == NULL) {
- e_ls = MEM_callocN(sizeof(ListBase), __func__);
- BLI_ghash_insert(isect_hash, eed, e_ls);
+ void **val_p;
+
+ if (!BLI_ghash_ensure_p(isect_hash, eed, &val_p)) {
+ *val_p = MEM_callocN(sizeof(ListBase), __func__);
}
+ e_ls = *val_p;
+
return e_ls;
}
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 158c2aa4263..c53b7f939c9 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -836,14 +836,15 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o
BMLogVert *lv;
unsigned int v_id = bm_log_vert_id_get(log, v);
void *key = SET_UINT_IN_POINTER(v_id);
+ void **val_p;
/* Find or create the BMLogVert entry */
if ((lv = BLI_ghash_lookup(entry->added_verts, key))) {
bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
}
- else if (!BLI_ghash_haskey(entry->modified_verts, key)) {
+ else if (!BLI_ghash_ensure_p(entry->modified_verts, key, &val_p)) {
lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
- BLI_ghash_insert(entry->modified_verts, key, lv);
+ *val_p = lv;
}
}
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
index c695d4c1774..0c0bb892f7b 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.c
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -534,12 +534,13 @@ static void bm_uuidwalk_pass_add(
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
/* fill verts_new */
+ void **val_p;
if (!BLI_ghash_haskey(uuidwalk->verts_uuid, l_iter->v) &&
- !BLI_ghash_haskey(verts_uuid_pass, l_iter->v) &&
+ !BLI_ghash_ensure_p(verts_uuid_pass, l_iter->v, &val_p) &&
(bm_vert_is_uuid_connect(uuidwalk, l_iter->v) == true))
{
const UUID_Int uuid = bm_uuidwalk_calc_vert_uuid(uuidwalk, l_iter->v);
- BLI_ghash_insert(verts_uuid_pass, l_iter->v, (void *)uuid);
+ *val_p = (void *)uuid;
}
/* fill faces_step_next */
@@ -667,13 +668,15 @@ static bool bm_uuidwalk_facestep_begin(
if (!BLI_ghash_haskey(uuidwalk->faces_uuid, f)) {
const UUID_Int uuid = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
UUIDFaceStepItem *fstep_item;
+ void **val_p;
ok = true;
- fstep_item = BLI_ghash_lookup(uuidwalk->cache.faces_from_uuid, (void *)uuid);
- if (UNLIKELY(fstep_item == NULL)) {
- fstep_item = BLI_mempool_alloc(uuidwalk->step_pool_items);
- BLI_ghash_insert(uuidwalk->cache.faces_from_uuid, (void *)uuid, fstep_item);
+ if (BLI_ghash_ensure_p(uuidwalk->cache.faces_from_uuid, (void *)uuid, &val_p)) {
+ fstep_item = *val_p;
+ }
+ else {
+ fstep_item = *val_p = BLI_mempool_alloc(uuidwalk->step_pool_items);
/* add to start, so its handled on the next round of passes */
BLI_addhead(&fstep->items, fstep_item);
@@ -1111,9 +1114,10 @@ static BMEdge *bm_face_region_pivot_edge_find(
if (bm_edge_is_region_boundary(e)) {
unsigned int j;
for (j = 0; j < 2; j++) {
- if (!BLI_ghash_haskey(gh, (&e->v1)[j])) {
+ void **val_p;
+ if (!BLI_ghash_ensure_p(gh, (&e->v1)[j], &val_p)) {
SUID_Int v_id = bm_face_region_vert_boundary_id((&e->v1)[j]);
- BLI_ghash_insert(gh, (&e->v1)[j], (void *)v_id);
+ *val_p = (void *)v_id;
BLI_LINKSTACK_PUSH(vert_queue_prev, (&e->v1)[j]);
vert_queue_used += 1;
}
@@ -1137,10 +1141,11 @@ static BMEdge *bm_face_region_pivot_edge_find(
if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
BMVert *v_other = BM_edge_other_vert(e, v);
if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
- if (!BLI_ghash_haskey(gh, v_other)) {
+ void **val_p;
+ if (!BLI_ghash_ensure_p(gh, v_other, &val_p)) {
/* add as negative, so we know not to read from them this pass */
const SUID_Int v_id_other = -bm_face_region_vert_pass_id(gh, v_other);
- BLI_ghash_insert(gh, v_other, (void *)v_id_other);
+ *val_p = (void *)v_id_other;
BLI_LINKSTACK_PUSH(vert_queue_next, v_other);
vert_queue_used += 1;
}
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 93a485423c0..d4d601b1e8d 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -60,6 +60,7 @@
#include "BIF_glutil.h"
#include "ED_gpencil.h"
+#include "ED_screen.h"
#include "ED_view3d.h"
#include "UI_interface_icons.h"
@@ -1047,8 +1048,17 @@ static void gp_draw_data_layers(bGPdata *gpd, int offsx, int offsy, int winx, in
}
/* draw a short status message in the top-right corner */
-static void gp_draw_status_text(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int UNUSED(cfra), int UNUSED(dflag))
+static void gp_draw_status_text(bGPdata *gpd, ARegion *ar)
{
+ rcti rect;
+
+ /* Cannot draw any status text when drawing OpenGL Renders */
+ if (G.f & G_RENDER_OGL)
+ return;
+
+ /* Get bounds of region - Necessary to avoid problems with region overlap */
+ ED_region_visible_rect(ar, &rect);
+
/* for now, this should only be used to indicate when we are in stroke editmode */
if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
const char *printable = IFACE_("GPencil Stroke Editing");
@@ -1057,8 +1067,8 @@ static void gp_draw_status_text(bGPdata *gpd, int offsx, int offsy, int winx, in
BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]);
- xco = offsx + (winx - U.widget_unit) - (int)printable_size[0];
- yco = offsy + (winy - U.widget_unit);
+ xco = (rect.xmax - U.widget_unit) - (int)printable_size[0];
+ yco = (rect.ymax - U.widget_unit);
/* text label */
UI_ThemeColor(TH_TEXT_HI);
@@ -1107,16 +1117,6 @@ static void gp_draw_data(bGPdata *gpd, int offsx, int offsy, int winx, int winy,
glDisable(GL_BLEND); // alpha blending
glDisable(GL_LINE_SMOOTH); // smooth lines
- /* Draw status text:
- * - This cannot be drawn when doing OpenGL "renders" and also when "only render" is enabled
- * - NOSTATUS should also catch all the other cases where the we are drawing into the "wrong"
- * coordinate space (e.g. 3D, View 2D, etc.)
- */
- /* XXX: Reinstate the "draw info" flag into the UI? */
- if ((dflag & GP_DRAWDATA_NOSTATUS) == 0 && (G.f & G_RENDER_OGL) == 0) {
- gp_draw_status_text(gpd, offsx, offsy, winx, winy, cfra, dflag);
- }
-
/* restore initial gl conditions */
glLineWidth(1.0);
glPointSize(1.0);
@@ -1243,6 +1243,11 @@ void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d)
/* draw it! */
if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS);
gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype);
+
+ /* draw status text (if in screen/pixel-space) */
+ if (onlyv2d == false) {
+ gp_draw_status_text(gpd, ar);
+ }
}
/* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly
@@ -1293,6 +1298,11 @@ void ED_gpencil_draw_view3d(Scene *scene, View3D *v3d, ARegion *ar, bool only3d)
/* draw it! */
gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype);
+
+ /* draw status text (if in screen/pixel-space) */
+ if (only3d == false) {
+ gp_draw_status_text(gpd, ar);
+ }
}
void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 96f9b87611f..f5847a9d701 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -277,10 +277,6 @@ static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
eyedropper_cancel(C, op);
return OPERATOR_CANCELLED;
case LEFTMOUSE:
- /* two release events are sent on KM_CLICK, so ignore second one */
- if (event->click_type == KM_CLICK) {
- break;
- }
if (event->val == KM_RELEASE) {
if (eye->accum_tot == 0) {
eyedropper_color_sample(C, eye, event->x, event->y);
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 9b1b0b915c1..5c7efcc40da 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -510,7 +510,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
float min[3], max[3];
bool done = false;
bool use_proj;
-
+
em_setup_viewcontext(C, &vc);
ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 126d1cb0ad9..79eec57712f 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -407,7 +407,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
/* Vertex Slide */
WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0);
/* use KM_CLICK because same key is used for tweaks */
- kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0);
+ kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_RELEASE, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "rotate_source", true);
kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "rotate_source", false);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 3b9e2188d41..d786c0cfc36 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -772,7 +772,7 @@ static void region_azone_tab_plus(ScrArea *sa, AZone *az, ARegion *ar)
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
+ add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0;
az->x1 = ar->winrct.xmax - 2.5f * AZONEPAD_TAB_PLUSW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - 1.5f * AZONEPAD_TAB_PLUSW;
@@ -817,7 +817,7 @@ static void region_azone_tab(ScrArea *sa, AZone *az, ARegion *ar)
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
+ add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0;
az->x1 = ar->winrct.xmax - 2 * AZONEPAD_TABW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - AZONEPAD_TABW;
@@ -862,7 +862,7 @@ static void region_azone_tria(ScrArea *sa, AZone *az, ARegion *ar)
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- if (ar->winrct.ymax == sa->totrct.ymin) add = 1; else add = 0;
+ add = (ar->winrct.ymax == sa->totrct.ymin) ? 1 : 0;
az->x1 = ar->winrct.xmax - 2 * AZONEPAD_TRIAW;
az->y1 = ar->winrct.ymax - add;
az->x2 = ar->winrct.xmax - AZONEPAD_TRIAW;
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 78dbae7618b..28107337084 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -1089,6 +1089,8 @@ typedef struct tNearestVertInfo {
short hpoint; /* the handle index that we hit (eHandleIndex) */
short sel; /* whether the handle is selected or not */
int dist; /* distance from mouse to vert */
+
+ eAnim_ChannelType ctype; /* type of animation channel this FCurve comes from */
} tNearestVertInfo;
/* Tags for the type of graph vert that we have */
@@ -1116,7 +1118,7 @@ static bool fcurve_handle_sel_check(SpaceIpo *sipo, BezTriple *bezt)
/* check if the given vertex is within bounds or not */
// TODO: should we return if we hit something?
static void nearest_fcurve_vert_store(
- ListBase *matches, View2D *v2d, FCurve *fcu,
+ ListBase *matches, View2D *v2d, FCurve *fcu, eAnim_ChannelType ctype,
BezTriple *bezt, FPoint *fpt, short hpoint, const int mval[2], float unit_scale)
{
/* Keyframes or Samples? */
@@ -1149,6 +1151,8 @@ static void nearest_fcurve_vert_store(
/* store values */
nvi->fcu = fcu;
+ nvi->ctype = ctype;
+
nvi->bezt = bezt;
nvi->hpoint = hpoint;
nvi->dist = dist;
@@ -1190,29 +1194,29 @@ static void get_nearest_fcurve_verts_list(bAnimContext *ac, const int mval[2], L
FCurve *fcu = (FCurve *)ale->key_data;
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag);
-
+
/* apply NLA mapping to all the keyframes */
if (adt)
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
-
+
if (fcu->bezt) {
BezTriple *bezt1 = fcu->bezt, *prevbezt = NULL;
int i;
for (i = 0; i < fcu->totvert; i++, prevbezt = bezt1, bezt1++) {
/* keyframe */
- nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale);
+ nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_KEY, mval, unit_scale);
/* handles - only do them if they're visible */
if (fcurve_handle_sel_check(sipo, bezt1) && (fcu->totvert > 1)) {
/* first handle only visible if previous segment had handles */
if ((!prevbezt && (bezt1->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
- nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale);
+ nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_LEFT, mval, unit_scale);
}
/* second handle only visible if this segment is bezier */
if (bezt1->ipo == BEZT_IPO_BEZ) {
- nearest_fcurve_vert_store(matches, v2d, fcu, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale);
+ nearest_fcurve_vert_store(matches, v2d, fcu, ale->type, bezt1, NULL, NEAREST_HANDLE_RIGHT, mval, unit_scale);
}
}
}
@@ -1405,7 +1409,7 @@ static void mouse_graph_keys(bAnimContext *ac, const int mval[2], short select_m
/* needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY) otherwise the active flag won't be set [#26452] */
if (nvi->fcu->flag & FCURVE_SELECTED) {
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
- ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, ANIMTYPE_FCURVE);
+ ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nvi->fcu, nvi->ctype);
}
/* free temp sample data for filtering */
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index ddbe501e6ef..6a5462bff45 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2950,8 +2950,11 @@ static int image_sample_modal(bContext *C, wmOperator *op, const wmEvent *event)
switch (event->type) {
case LEFTMOUSE:
case RIGHTMOUSE: // XXX hardcoded
+ if (event->val == KM_RELEASE) {
image_sample_exit(C, op);
return OPERATOR_CANCELLED;
+ }
+ break;
case MOUSEMOVE:
image_sample_apply(C, op, event);
break;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 51a2d0510d8..95a1ab87348 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1488,14 +1488,15 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax,
short xminc, yminc, xmaxc, ymaxc, xs, ys;
/* clip */
- if (xmin < 0) xminc = 0; else xminc = xmin;
- if (xmax >= vc->ar->winx) xmaxc = vc->ar->winx - 1; else xmaxc = xmax;
- if (xminc > xmaxc) return NULL;
+ xminc = max_ii(xmin, 0);
+ yminc = max_ii(ymin, 0);
+ xmaxc = min_ii(xmax, vc->ar->winx - 1);
+ ymaxc = min_ii(ymax, vc->ar->winy - 1);
+
+ if (UNLIKELY((xminc > xmaxc) || (yminc > ymaxc))) {
+ return NULL;
+ }
- if (ymin < 0) yminc = 0; else yminc = ymin;
- if (ymax >= vc->ar->winy) ymaxc = vc->ar->winy - 1; else ymaxc = ymax;
- if (yminc > ymaxc) return NULL;
-
ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect);
view3d_validate_backbuf(vc);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 671fc682409..236fefc7088 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -4701,16 +4701,24 @@ bool ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d,
bglMats mats; /* ZBuffer depth vars */
float depth_close;
double cent[2], p[3];
+ int margin_arr[] = {0, 2, 4};
+ int i;
+ bool depth_ok = false;
/* Get Z Depths, needed for perspective, nice for ortho */
bgl_get_mats(&mats);
ED_view3d_draw_depth(scene, ar, v3d, alphaoverride);
- depth_close = view_autodist_depth_margin(ar, mval, 4);
+ /* Attempt with low margin's first */
+ i = 0;
+ do {
+ depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize);
+ depth_ok = (depth_close != FLT_MAX);
+ } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
- if (depth_close != FLT_MAX) {
- cent[0] = (double)mval[0];
- cent[1] = (double)mval[1];
+ if (depth_ok) {
+ cent[0] = (double)mval[0] + 0.5;
+ cent[1] = (double)mval[1] + 0.5;
if (gluUnProject(cent[0], cent[1], depth_close,
mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
@@ -4761,8 +4769,8 @@ bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_world
if (depth == FLT_MAX)
return false;
- cent[0] = (double)mval[0];
- cent[1] = (double)mval[1];
+ cent[0] = (double)mval[0] + 0.5;
+ cent[1] = (double)mval[1] + 0.5;
bgl_get_mats(&mats);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index c5425f238cc..6ba3a2850cc 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -236,7 +236,8 @@ void view3d_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "VIEW3D_OT_navigate", FKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_ANY, KM_ANY, 0);
+ /* value is set to KM_NOTHING to avoid conflicts with click type (see T44251) */
+ WM_keymap_verify_item(keymap, "VIEW3D_OT_smoothview", TIMER1, KM_NOTHING, KM_ANY, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEPAN, 0, 0, 0);
WM_keymap_add_item(keymap, "VIEW3D_OT_rotate", MOUSEROTATE, 0, 0, 0);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index c8d81383d79..161b8ca232d 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -866,10 +866,10 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf)
keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items);
/* items for modal map */
- WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CANCEL);
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CANCEL);
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_RELEASE, KM_ANY, 0, TFM_MODAL_CONFIRM);
WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, TFM_MODAL_TRANSLATE);
WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE);
@@ -5266,9 +5266,10 @@ static void slide_origdata_create_data_vert(
loop_weights = BLI_array_alloca(loop_weights, l_num);
for (j = 0; j < l_num; j++) {
BMLoop *l = BM_iter_step(&liter);
- if (!BLI_ghash_haskey(sod->origfaces, l->f)) {
+ void **val_p;
+ if (!BLI_ghash_ensure_p(sod->origfaces, l->f, &val_p)) {
BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true);
- BLI_ghash_insert(sod->origfaces, l->f, f_copy);
+ *val_p = f_copy;
}
loop_weights[j] = BM_loop_calc_face_angle(l);
}
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 52e8562f0b2..47be7bec432 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -288,6 +288,11 @@ static void rna_Image_filepath_from_user(Image *image, ImageUser *image_user, ch
BKE_image_user_file_path(image_user, image, filepath);
}
+static void rna_Image_buffers_free(Image *image)
+{
+ BKE_image_free_buffers(image);
+}
+
#else
void RNA_api_image(StructRNA *srna)
@@ -374,6 +379,9 @@ void RNA_api_image(StructRNA *srna)
RNA_def_property_flag(parm, PROP_THICK_WRAP); /* needed for string return value */
RNA_def_function_output(func, parm);
+ func = RNA_def_function(srna, "buffers_free", "rna_Image_buffers_free");
+ RNA_def_function_ui_description(func, "Free the image buffers from memory");
+
/* TODO, pack/unpack, maybe should be generic functions? */
}
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index 1dc1a1f8d64..96337c33373 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -131,6 +131,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
MPoly *mpoly, *mp;
MLoop *ml, *mloop;
MEdge *medge;
+ uintptr_t hash_num, hash_num_alt;
if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE) {
BLI_array_randomize(faceMap, sizeof(*faceMap),
@@ -142,40 +143,44 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
*/
mpoly = mpoly_src;
mloop = mloop_src;
+ hash_num = 0;
for (i = 0; i < numFaces_dst; i++) {
mp = mpoly + faceMap[i];
ml = mloop + mp->loopstart;
for (j = 0; j < mp->totloop; j++, ml++) {
- if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v)))
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(ml->v),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ void **val_p;
+ if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(ml->v), &val_p)) {
+ *val_p = (void *)hash_num;
+ hash_num++;
+ }
}
-
+
numLoops_dst += mp->totloop;
}
+ BLI_assert(hash_num == BLI_ghash_size(vertHash));
/* get the set of edges that will be in the new mesh (i.e. all edges
* that have both verts in the new mesh)
*/
medge = medge_src;
- for (i = 0; i < numEdge_src; i++) {
+ hash_num = 0;
+ hash_num_alt = 0;
+ for (i = 0; i < numEdge_src; i++, hash_num_alt++) {
MEdge *me = medge + i;
if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1)) &&
BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2)))
{
- j = BLI_ghash_size(edgeHash);
-
- BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(j),
- SET_INT_IN_POINTER(i));
- BLI_ghash_insert(edgeHash2, SET_INT_IN_POINTER(i),
- SET_INT_IN_POINTER(j));
+ BLI_ghash_insert(edgeHash, (void *)hash_num, (void *)hash_num_alt);
+ BLI_ghash_insert(edgeHash2, (void *)hash_num_alt, (void *)hash_num);
+ hash_num++;
}
}
}
else if (numEdges_dst) {
MEdge *medge, *me;
+ uintptr_t hash_num;
if (bmd->flag & MOD_BUILD_FLAG_RANDOMIZE)
BLI_array_randomize(edgeMap, sizeof(*edgeMap),
@@ -185,17 +190,22 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
* mapped to the new indices
*/
medge = medge_src;
+ hash_num = 0;
+ BLI_assert(hash_num == BLI_ghash_size(vertHash));
for (i = 0; i < numEdges_dst; i++) {
+ void **val_p;
me = medge + edgeMap[i];
- if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v1))) {
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v1),
- SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(me->v1), &val_p)) {
+ *val_p = (void *)hash_num;
+ hash_num++;
}
- if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me->v2))) {
- BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(me->v2), SET_INT_IN_POINTER(BLI_ghash_size(vertHash)));
+ if (!BLI_ghash_ensure_p(vertHash, SET_INT_IN_POINTER(me->v2), &val_p)) {
+ *val_p = (void *)hash_num;
+ hash_num++;
}
}
+ BLI_assert(hash_num == BLI_ghash_size(vertHash));
/* get the set of edges that will be in the new mesh */
for (i = 0; i < numEdges_dst; i++) {
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index dc8c714bea5..c6a80c822a3 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -1348,7 +1348,7 @@ int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct Image
/* fact = texture strength, facg = button strength value */
void texture_rgb_blend(float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype)
{
- float facm, col;
+ float facm;
switch (blendtype) {
case MTEX_BLEND:
@@ -1435,13 +1435,10 @@ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], floa
case MTEX_LIGHT:
fact*= facg;
-
- col= fact*tex[0];
- if (col > out[0]) in[0]= col; else in[0]= out[0];
- col= fact*tex[1];
- if (col > out[1]) in[1]= col; else in[1]= out[1];
- col= fact*tex[2];
- if (col > out[2]) in[2]= col; else in[2]= out[2];
+
+ in[0] = max_ff(fact * tex[0], out[0]);
+ in[1] = max_ff(fact * tex[1], out[1]);
+ in[2] = max_ff(fact * tex[2], out[2]);
break;
case MTEX_BLEND_HUE:
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 01055d87a38..9ea7cb62c58 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -633,7 +633,7 @@ void shade_input_calc_viewco(ShadeInput *shi, float x, float y, float z, float v
dyco[2] = 0.0f;
if (dxyview) {
- if (co[2] != 0.0f) fac = 1.0f / co[2]; else fac = 0.0f;
+ fac = (co[2] != 0.0f) ? (1.0f / co[2]) : 0.0f;
dxyview[0] = -R.viewdx * fac;
dxyview[1] = -R.viewdy * fac;
}
diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c
index 9d2bc8f5ba1..b6628796e0d 100644
--- a/source/blender/render/intern/source/zbuf.c
+++ b/source/blender/render/intern/source/zbuf.c
@@ -330,8 +330,8 @@ static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
if (my2<my0) return;
@@ -1073,8 +1073,8 @@ static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1196,8 +1196,8 @@ static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1324,8 +1324,8 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int UNUSED(obi), int UNUSED(zvlnr),
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1426,8 +1426,8 @@ void zspan_scanconvert_strand(ZSpan *zspan, void *handle, float *v1, float *v2,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1513,7 +1513,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
float x0, y0, x1, y1, x2, y2, z0, z1, z2;
float u, v, uxd, uyd, vxd, vyd, uy0, vy0, xx1;
const float *span1, *span2;
- int x, y, sn1, sn2, rectx= zspan->rectx, my0, my2;
+ int i, j, x, y, sn1, sn2, rectx = zspan->rectx, my0, my2;
/* init */
zbuf_init_span(zspan);
@@ -1526,8 +1526,8 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
@@ -1574,7 +1574,7 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
span2= zspan->span1+my2;
}
- for (y=my2; y>=my0; y--, span1--, span2--) {
+ for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) {
sn1= floor(*span1);
sn2= floor(*span2);
@@ -1583,14 +1583,12 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
if (sn2>=rectx) sn2= rectx-1;
if (sn1<0) sn1= 0;
- u= (double)sn1*uxd + uy0;
- v= (double)sn1*vxd + vy0;
-
- for (x= sn1; x<=sn2; x++, u+=uxd, v+=vxd)
- func(handle, x, y, u, v);
+ u = (((double)sn1 * uxd) + uy0) - (i * uyd);
+ v = (((double)sn1 * vxd) + vy0) - (i * vyd);
- uy0 -= uyd;
- vy0 -= vyd;
+ for (j = 0, x = sn1; x <= sn2; j++, x++) {
+ func(handle, x, y, u + (j * uxd), v + (j * vxd));
+ }
}
}
@@ -2482,8 +2480,8 @@ static void zbuffill_sss(ZSpan *zspan, int obi, int zvlnr,
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
if (my2<my0) return;
@@ -2683,8 +2681,8 @@ static void zbuf_fill_in_rgba(ZSpan *zspan, DrawBufPixel *col, float *v1, float
/* clipped */
if (zspan->minp2==NULL || zspan->maxp2==NULL) return;
- if (zspan->miny1 < zspan->miny2) my0= zspan->miny2; else my0= zspan->miny1;
- if (zspan->maxy1 > zspan->maxy2) my2= zspan->maxy2; else my2= zspan->maxy1;
+ my0 = max_ii(zspan->miny1, zspan->miny2);
+ my2 = min_ii(zspan->maxy1, zspan->maxy2);
// printf("my %d %d\n", my0, my2);
if (my2<my0) return;
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 8c013eb7cd4..225e3138859 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2994,7 +2994,7 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
* - #KM_PRESS && time since first #KM_PRESS > U.click_timeout --> send #KM_HOLD
* - #KM_PRESS after a #KM_RELEASE && time since previous #KM_PRESS < U.dbl_click_time --> send #KM_DBL_CLICK
*
- * \note: only #KM_DBL_CLICK is handled here, rest in #wm_window_event_clicktype_init (wm_window.c)
+ * \note: only #KM_DBL_CLICK and #KM_CLICK are handled here, #KM_HOLD in #wm_window_event_clicktype_init (wm_window.c)
*/
static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *event_state)
{
@@ -3025,6 +3025,16 @@ static void wm_event_clicktype_init(wmWindow *win, wmEvent *event, wmEvent *even
}
}
+ /* click */
+ if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) {
+ if (event->val == KM_RELEASE) {
+ click_type = KM_CLICK;
+ if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) {
+ printf("%s Send click event\n", __func__);
+ }
+ }
+ }
+
if (click_type != event->click_type) {
event_state->click_type = event->click_type = click_type;
}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 61bddb144ae..4b98f8bf71d 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1107,9 +1107,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
}
/**
- * #KM_DBL_CLICK is set in wm_event_clicktype_init (wm_event_system.c)
- * Normally, this should be there too, but for #KM_CLICK/#KM_HOLD, we need a
- * time precision of a few milliseconds, which we can't get from there
+ * #KM_DBL_CLICK and #KM_CLICK are set in wm_event_clicktype_init (wm_event_system.c)
+ * Normally, #KM_HOLD should be there too, but we need a time precision of a few
+ * milliseconds for it, which we can't get from there
*/
static void wm_window_event_clicktype_init(const bContext *C)
{
@@ -1150,14 +1150,7 @@ static void wm_window_event_clicktype_init(const bContext *C)
/* the actual test */
if ((PIL_check_seconds_timer() - event->click_time) * 1000 <= U.click_timeout) {
- /* for any reason some X11 systems send two release events triggering two KM_CLICK
- * events - making the rules more strict by checking for prevval resolves this */
- if (event->val == KM_RELEASE && event->prevval != KM_RELEASE) {
- click_type = KM_CLICK;
- if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS)) {
- printf("%s Send click event\n", __func__);
- }
- }
+ /* sending of KM_CLICK is handled in wm_event_clicktype_init (wm_event_system.c) */
}
else if (event->is_key_pressed) {
click_type = KM_HOLD;
diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
index 0eec86987be..f65b0ac0f4f 100644
--- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp
@@ -223,6 +223,11 @@ bool KX_ObjectActuator::Update()
else if (m_bitLocalFlag.CharacterMotion) {
MT_Vector3 dir = m_dloc;
+ if (m_bitLocalFlag.DLoc) {
+ MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation();
+ dir = basis * dir;
+ }
+
if (m_bitLocalFlag.AddOrSetCharLoc) {
MT_Vector3 old_dir = character->GetWalkDirection();
@@ -236,11 +241,6 @@ bool KX_ObjectActuator::Update()
}
// We always want to set the walk direction since a walk direction of (0, 0, 0) should stop the character
- if (m_bitLocalFlag.DLoc)
- {
- MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation();
- dir = basis*dir;
- }
character->SetWalkDirection(dir/parent->GetScene()->GetPhysicsEnvironment()->GetNumTimeSubSteps());
if (!m_bitLocalFlag.ZeroDRot)