diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 0e264a752d51..d99e66f78717 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -112,8 +112,8 @@ def parse_header_file(filename, define): chroot_name = 'buildbot_' + deb_name + '_i686' cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64' targets = ['player', 'blender', 'cuda'] - cmake_extra_options.extend(["-DCMAKE_C_COMPILER=/usr/bin/gcc-6", - "-DCMAKE_CXX_COMPILER=/usr/bin/g++-6"]) + cmake_extra_options.extend(["-DCMAKE_C_COMPILER=/usr/bin/gcc-7", + "-DCMAKE_CXX_COMPILER=/usr/bin/g++-7"]) cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file)) diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 3b0e8f52c83e..7ad3bab1557e 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -1639,6 +1639,11 @@ def write_sphinx_conf_py(basepath): fw("version = '%s - API'\n" % BLENDER_VERSION_DOTS) fw("release = '%s - API'\n" % BLENDER_VERSION_DOTS) + # Quiet file not in table-of-contents warnings. + fw("exclude_patterns = [\n") + fw(" 'include__bmesh.rst',\n") + fw("]\n\n") + if ARGS.sphinx_theme != 'default': fw("html_theme = '%s'\n" % ARGS.sphinx_theme) @@ -1659,6 +1664,24 @@ def write_sphinx_conf_py(basepath): fw("}\n\n") fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n") + + # Workaround for useless links leading to compile errors + # See https://github.com/sphinx-doc/sphinx/issues/3866 + fw(r""" +from sphinx.domains.python import PythonDomain + +class PatchedPythonDomain(PythonDomain): + def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): + if 'refspecific' in node: + del node['refspecific'] + return super(PatchedPythonDomain, self).resolve_xref( + env, fromdocname, builder, typ, target, node, contnode) + +def setup(sphinx): + sphinx.override_domain(PatchedPythonDomain) +""") + # end workaround + file.close() @@ -1697,9 +1720,6 @@ def write_rst_contents(basepath): for info, info_desc in INFO_DOCS: fw(" %s <%s>\n\n" % (info_desc, info)) fw("\n") - fw("- :ref:`Blender/Python Add-on Tutorial: a step by step guide on") - fw(" how to write an add-on from scratch `\n") - fw("\n") fw(title_string("Application Modules", "=", double=True)) fw(".. toctree::\n") diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 175bd6b9737d..9ed16aceb55d 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -220,7 +220,9 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass) #ifdef __SHADOW_TRICKS__ L->path_total = make_float3(0.0f, 0.0f, 0.0f); L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f); - L->shadow_color = make_float3(0.0f, 0.0f, 0.0f); + L->shadow_background_color = make_float3(0.0f, 0.0f, 0.0f); + L->shadow_radiance_sum = make_float3(0.0f, 0.0f, 0.0f); + L->shadow_throughput = 0.0f; #endif #ifdef __DENOISING_FEATURES__ @@ -680,11 +682,12 @@ ccl_device_inline float3 path_radiance_sum_shadowcatcher(KernelGlobals *kg, const float shadow = path_radiance_sum_shadow(L); float3 L_sum; if(kernel_data.background.transparent) { - *alpha = 1.0f-shadow; - L_sum = make_float3(0.0f, 0.0f, 0.0f); + *alpha = 1.0f - L->shadow_throughput * shadow; + L_sum = L->shadow_radiance_sum; } else { - L_sum = L->shadow_color * shadow; + L_sum = L->shadow_background_color * L->shadow_throughput * shadow + + L->shadow_radiance_sum; } return L_sum; } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index fc093ad83194..c340b3bc9685 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -643,11 +643,16 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg, #ifdef __SHADOW_TRICKS__ if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) { if(state.flag & PATH_RAY_CAMERA) { - state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY | PATH_RAY_STORE_SHADOW_INFO); + state.flag |= (PATH_RAY_SHADOW_CATCHER | + PATH_RAY_SHADOW_CATCHER_ONLY | + PATH_RAY_STORE_SHADOW_INFO); state.catcher_object = sd.object; if(!kernel_data.background.transparent) { - L->shadow_color = indirect_background(kg, &emission_sd, &state, &ray); + L->shadow_background_color = + indirect_background(kg, &emission_sd, &state, &ray); } + L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L); + L->shadow_throughput = average(throughput); } } else { diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index 10816d3e5d1f..77d4f1df4472 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -499,13 +499,16 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg, #ifdef __SHADOW_TRICKS__ if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) { - if(state.flag & PATH_RAY_CAMERA) { - state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY | PATH_RAY_STORE_SHADOW_INFO); - state.catcher_object = sd.object; - if(!kernel_data.background.transparent) { - L->shadow_color = indirect_background(kg, &emission_sd, &state, &ray); - } + state.flag |= (PATH_RAY_SHADOW_CATCHER | + PATH_RAY_SHADOW_CATCHER_ONLY | + PATH_RAY_STORE_SHADOW_INFO); + state.catcher_object = sd.object; + if(!kernel_data.background.transparent) { + L->shadow_background_color = + indirect_background(kg, &emission_sd, &state, &ray); } + L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L); + L->shadow_throughput = average(throughput); } else { state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 34affab1b9d0..37af98b32c7a 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -515,7 +515,13 @@ typedef ccl_addr_space struct PathRadiance { float3 path_total_shaded; /* Color of the background on which shadow is alpha-overed. */ - float3 shadow_color; + float3 shadow_background_color; + + /* Path radiance sum and throughput at the moment when ray hits shadow + * catcher object. + */ + float3 shadow_radiance_sum; + float shadow_throughput; #endif #ifdef __DENOISING_FEATURES__ diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h index 670a557f084d..fec671be0167 100644 --- a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h +++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h @@ -125,13 +125,21 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( #ifdef __SHADOW_TRICKS__ if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { if(state->flag & PATH_RAY_CAMERA) { - state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY | PATH_RAY_STORE_SHADOW_INFO); + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + state->flag |= (PATH_RAY_SHADOW_CATCHER | + PATH_RAY_SHADOW_CATCHER_ONLY | + PATH_RAY_STORE_SHADOW_INFO); state->catcher_object = sd->object; if(!kernel_data.background.transparent) { - PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - L->shadow_color = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray); + L->shadow_background_color = indirect_background( + kg, + &kernel_split_state.sd_DL_shadow[ray_index], + state, + ray); } + L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L); + L->shadow_throughput = average(throughput); } } else { diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index a91983c001cd..ab614b8f4609 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -2641,7 +2641,7 @@ static void statvis_calc_distort( vertexCos[BM_elem_index_get(l_iter->next->v)]); } else { - BM_loop_calc_face_normal(l_iter, no_corner); + BM_loop_calc_face_normal_safe(l_iter, no_corner); } /* simple way to detect (what is most likely) concave */ if (dot_v3v3(f_no, no_corner) < 0.0f) { diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 347640aae0d0..86c24307ae2f 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -1395,9 +1395,9 @@ static float voronoi_CrS(float x, float y, float z) static float cellNoiseU(float x, float y, float z) { /* avoid precision issues on unit coordinates */ - x = (x + 0.000001f)*0.999999f; - y = (y + 0.000001f)*0.999999f; - z = (z + 0.000001f)*0.999999f; + x = (x + 0.000001f)*1.00001f; + y = (y + 0.000001f)*1.00001f; + z = (z + 0.000001f)*1.00001f; int xi = (int)(floor(x)); int yi = (int)(floor(y)); @@ -1417,9 +1417,9 @@ float cellNoise(float x, float y, float z) void cellNoiseV(float x, float y, float z, float ca[3]) { /* avoid precision issues on unit coordinates */ - x = (x + 0.000001f)*0.999999f; - y = (y + 0.000001f)*0.999999f; - z = (z + 0.000001f)*0.999999f; + x = (x + 0.000001f)*1.00001f; + y = (y + 0.000001f)*1.00001f; + z = (z + 0.000001f)*1.00001f; int xi = (int)(floor(x)); int yi = (int)(floor(y)); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index f5c14304ea33..668fb9982548 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1511,12 +1511,11 @@ float BM_loop_calc_face_angle(const BMLoop *l) * Calculate the normal at this loop corner or fallback to the face normal on straight lines. * * \param l The loop to calculate the normal at + * \param epsilon: Value to avoid numeric errors (1e-5f works well). * \param r_normal Resulting normal */ -void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) +float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3]) { -#define FEPSILON 1e-5f - /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line) * from zero value, because it does not normalize both vectors before making crossproduct. * Instead of adding two costly normalize computations, just check ourselves for colinear case. */ @@ -1525,20 +1524,55 @@ void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) sub_v3_v3v3(v1, l->prev->v->co, l->v->co); sub_v3_v3v3(v2, l->next->v->co, l->v->co); - const float fac = (v2[0] == 0.0f) ? ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0]; + const float fac = + ((v2[0] == 0.0f) ? + ((v2[1] == 0.0f) ? + ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0]); mul_v3_v3fl(v_tmp, v2, fac); sub_v3_v3(v_tmp, v1); - if (fac != 0.0f && !is_zero_v3(v1) && len_manhattan_v3(v_tmp) > FEPSILON) { + if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) { /* Not co-linear, we can compute crossproduct and normalize it into normal. */ cross_v3_v3v3(r_normal, v1, v2); - normalize_v3(r_normal); + return normalize_v3(r_normal); } else { copy_v3_v3(r_normal, l->f->no); + return 0.0f; } +} + +/** + * #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon. + * + * Since this doesn't scale baed on triangle size, fixed value works well. + */ +float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) +{ + return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal); +} -#undef FEPSILON +/** + * \brief BM_loop_calc_face_normal + * + * Calculate the normal at this loop corner or fallback to the face normal on straight lines. + * + * \param l The loop to calculate the normal at + * \param r_normal Resulting normal + * \return The length of the cross product (double the area). + */ +float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) +{ + float v1[3], v2[3]; + sub_v3_v3v3(v1, l->prev->v->co, l->v->co); + sub_v3_v3v3(v2, l->next->v->co, l->v->co); + + cross_v3_v3v3(r_normal, v1, v2); + const float len = normalize_v3(r_normal); + if (UNLIKELY(len == 0.0f)) { + copy_v3_v3(r_normal, l->f->no); + } + return len; } /** diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 903fdc59cb8d..83977fa8be03 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -113,7 +113,9 @@ BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq); float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3]) ATTR_NONNULL(); void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]); void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]); diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index cca0f7387cd3..d8f83d786b46 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -839,7 +839,7 @@ void BM_mesh_calc_uvs_grid( const float dx = 1.0f / (float)(x_segments - 1); const float dy = 1.0f / (float)(y_segments - 1); float x = 0.0f; - float y = 0.0f; + float y = dy; int loop_index; @@ -854,16 +854,16 @@ void BM_mesh_calc_uvs_grid( switch (loop_index) { case 0: - x += dx; + y -= dy; break; case 1: - y += dy; + x += dx; break; case 2: - x -= dx; + y += dy; break; case 3: - y -= dy; + x -= dx; break; default: break; diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index 3bff20e846b1..b3d512204bea 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -530,7 +530,7 @@ void AnimationExporter::dae_baked_animation(std::vector &fra, Object *ob_ addSampler(sampler); - std::string target = translate_id(bone_name) + "/transform"; + std::string target = get_joint_id(bone, ob_arm) + "/transform"; addChannel(COLLADABU::URI(empty, sampler_id), target); closeAnimation(); diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index aafd7ebb1f96..be01f8cbe692 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -895,7 +895,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *even case PADENTER: case LEFTMOUSE: case MIDDLEMOUSE: - if (WM_modal_tweak_exit(event, mm->event_type)) { + if (WM_event_is_modal_tweak_exit(event, mm->event_type)) { ed_marker_move_exit(C, op); WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index a6de1b284b79..68bd8ff27b1d 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -446,6 +446,9 @@ BMVert *EDBM_vert_find_nearest_ex( unsigned int index; BMVert *eve; + /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ + ED_view3d_backbuf_validate(vc); + index = ED_view3d_backbuf_sample_rect( vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; @@ -630,7 +633,8 @@ BMEdge *EDBM_edge_find_nearest_ex( float dist_test = 0.0f; unsigned int index; BMEdge *eed; - + + /* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */ ED_view3d_backbuf_validate(vc); index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 4d7d7df0d2fa..47a3f79b0b4c 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -923,8 +923,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) cent[2] = 0.0f; - cu->xof = cu->xof - (cent[0] / cu->fsize); - cu->yof = cu->yof - (cent[1] / cu->fsize); + cu->xof = cu->xof - cent[0]; + cu->yof = cu->yof - cent[1]; tot_change++; cu->id.tag |= LIB_TAG_DOIT; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index c99d9add4322..27e19ca1fc33 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2260,25 +2260,28 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op) BLI_dlrbTree_linkedlist_sync(&keys); /* find matching keyframe in the right direction */ - do { - if (next) - ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra); - else - ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra); - - if (ak) { - if (CFRA != (int)ak->cfra) { - /* this changes the frame, so set the frame and we're done */ - CFRA = (int)ak->cfra; - done = true; + if (next) + ak = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra); + else + ak = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra); + + while ((ak != NULL) && (done == false)) { + if (CFRA != (int)ak->cfra) { + /* this changes the frame, so set the frame and we're done */ + CFRA = (int)ak->cfra; + done = true; + } + else { + /* take another step... */ + if (next) { + ak = ak->next; } else { - /* make this the new starting point for the search */ - cfra = ak->cfra; + ak = ak->prev; } } - } while ((ak != NULL) && (done == false)); - + } + /* free temp stuff */ BLI_dlrbTree_free(&keys); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index d0f1cc99b8d9..b43581170d0f 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -3712,8 +3712,12 @@ static void project_paint_prepare_all_faces( } /* don't allow using the same inage for painting and stencilling */ - if (slot->ima == ps->stencil_ima) + if (slot->ima == ps->stencil_ima) { + /* While this shouldn't be used, face-winding reads all polys. + * It's less trouble to set all faces to valid UV's, avoiding NULL checks all over. */ + ps->dm_mloopuv[lt->poly] = mloopuv_base; continue; + } tpage = slot->ima; } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 3ae4a233353e..e63569ac3867 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3512,7 +3512,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) bool proxy_50 = RNA_boolean_get(op->ptr, "proxy_50"); bool proxy_75 = RNA_boolean_get(op->ptr, "proxy_75"); bool proxy_100 = RNA_boolean_get(op->ptr, "proxy_100"); - bool override = RNA_boolean_get(op->ptr, "override"); + bool overwrite = RNA_boolean_get(op->ptr, "overwrite"); bool turnon = true; if (ed == NULL || !(proxy_25 || proxy_50 || proxy_75 || proxy_100)) { @@ -3548,7 +3548,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) else seq->strip->proxy->build_size_flags &= ~SEQ_PROXY_IMAGE_SIZE_100; - if (!override) + if (!overwrite) seq->strip->proxy->build_flags |= SEQ_PROXY_SKIP_EXISTING; else seq->strip->proxy->build_flags &= ~SEQ_PROXY_SKIP_EXISTING; @@ -3580,7 +3580,7 @@ void SEQUENCER_OT_enable_proxies(wmOperatorType *ot) RNA_def_boolean(ot->srna, "proxy_50", false, "50%", ""); RNA_def_boolean(ot->srna, "proxy_75", false, "75%", ""); RNA_def_boolean(ot->srna, "proxy_100", false, "100%", ""); - RNA_def_boolean(ot->srna, "override", false, "Override", ""); + RNA_def_boolean(ot->srna, "overwrite", false, "Overwrite", ""); } /* change ops */ diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 542dc410bc3f..c6b73056a9a1 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -674,16 +674,6 @@ static int walkEnd(bContext *C, WalkInfo *walk) return OPERATOR_CANCELLED; } -static bool wm_event_is_last_mousemove(const wmEvent *event) -{ - while ((event = event->next)) { - if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - return false; - } - } - return true; -} - static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event) { if (event->type == TIMER && event->customdata == walk->timer) { @@ -736,7 +726,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent } else #endif - if (wm_event_is_last_mousemove(event)) { + if (WM_event_is_last_mousemove(event)) { wmWindow *win = CTX_wm_window(C); #ifdef __APPLE__ diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index fa17ab34cf99..9e94b2835d5e 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -138,85 +138,53 @@ struct SnapObjectContext { /** Common utilities * \{ */ -struct SnapObject { - struct SnapObject *next, *prev; - bool use_obedit; - struct Object *ob; - float obmat[4][4]; -}; +typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data); /** * Walks through all objects in the scene to create the list of objets to snap. * * \param sctx: Snap context to store data. * \param snap_select : from enum SnapSelect. - * \param use_object_edit_cage : Uses the coordinates of BMesh(if any) to do the snapping. - * + * \param obedit : Object Edited to use its coordinates of BMesh(if any) to do the snapping. */ -static void create_object_list( +static void iter_snap_objects( SnapObjectContext *sctx, - const SnapSelect snap_select, const bool use_object_edit_cage, ListBase *r_obj_list) + const SnapSelect snap_select, + Object *obedit, + IterSnapObjsCallback sob_callback, + void *data) { - r_obj_list->first = r_obj_list->last = NULL; - - Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL; - - bool ignore_object_selected = false, ignore_object_active = false; - switch (snap_select) { - case SNAP_ALL: - break; - case SNAP_NOT_SELECTED: - ignore_object_selected = true; - break; - case SNAP_NOT_ACTIVE: - ignore_object_active = true; - break; - } - + Base *base_act = sctx->scene->basact; /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA * which makes the loop skip it, even the derived mesh will never change * * To solve that problem, we do it first as an exception. * */ - Base *base_act = sctx->scene->basact; if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) { - struct SnapObject *sobj = MEM_mallocN(sizeof(*sobj), __func__); - sobj->use_obedit = false; - sobj->ob = base_act->object; - copy_m4_m4(sobj->obmat, sobj->ob->obmat); - BLI_addtail(r_obj_list, sobj); + sob_callback(sctx, false, base_act->object, base_act->object->obmat, data); } for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) { if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) && (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && - - !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) || - (ignore_object_active && base == base_act))) + !((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL))) || + (snap_select == SNAP_NOT_ACTIVE && base == base_act))) { - Object *ob = base->object; - - if (ob->transflag & OB_DUPLI) { + bool use_obedit; + Object *obj = base->object; + if (obj->transflag & OB_DUPLI) { DupliObject *dupli_ob; - ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob); - + ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, obj); for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { - struct SnapObject *sobj = MEM_mallocN(sizeof(*sobj), __func__); - sobj->use_obedit = obedit && dupli_ob->ob->data == obedit->data; - sobj->ob = sobj->use_obedit ? obedit : dupli_ob->ob;; - copy_m4_m4(sobj->obmat, dupli_ob->mat); - BLI_addtail(r_obj_list, sobj); + use_obedit = obedit && dupli_ob->ob->data == obedit->data; + sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data); } - free_object_duplilist(lb); } - struct SnapObject *sobj = MEM_mallocN(sizeof(*sobj), __func__); - sobj->use_obedit = obedit && ob->data == obedit->data; - sobj->ob = sobj->use_obedit ? obedit : ob; - copy_m4_m4(sobj->obmat, sobj->ob->obmat); - BLI_addtail(r_obj_list, sobj); + use_obedit = obedit && obj->data == obedit->data; + sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data); } } } @@ -262,17 +230,6 @@ MINLINE float depth_get(const float co[3], const float ray_start[3], const float return dot_v3v3(dvec, ray_dir); } -static float UNUSED_FUNCTION(dist_aabb_to_plane)( - const float bbmin[3], const float bbmax[3], - const float plane_co[3], const float plane_no[3]) -{ - const float local_bvmin[3] = { - (plane_no[0] < 0) ? bbmax[0] : bbmin[0], - (plane_no[1] < 0) ? bbmax[1] : bbmin[1], - (plane_no[2] < 0) ? bbmax[2] : bbmin[2], - }; - return depth_get(local_bvmin, plane_co, plane_no); -} static bool walk_parent_bvhroot_cb(const BVHTreeAxisRange *bounds, void *userdata) { @@ -285,6 +242,7 @@ static bool walk_parent_bvhroot_cb(const BVHTreeAxisRange *bounds, void *userdat return false; } + static bool isect_ray_bvhroot_v3(struct BVHTree *tree, const float ray_start[3], const float ray_dir[3], float *depth) { BVHTreeRay ray; @@ -612,8 +570,7 @@ static bool raycastEditMesh( } SnapObjectData_EditMesh *sod = NULL; - - BVHTreeFromEditMesh *treedata; + BVHTreeFromEditMesh *treedata = NULL; void **sod_p; if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { @@ -822,6 +779,37 @@ static bool raycastObj( } +struct RaycastObjUserData { + const float *ray_orig; + const float *ray_start; + const float *ray_dir; + const float *depth_range; + unsigned int ob_index; + /* read/write args */ + float *ray_depth; + /* return args */ + float *r_loc; + float *r_no; + int *r_index; + Object **r_ob; + float (*r_obmat)[4]; + ListBase *r_hit_list; + bool ret; +}; + +static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) +{ + struct RaycastObjUserData *dt = data; + dt->ret |= raycastObj( + sctx, + dt->ray_orig, dt->ray_start, dt->ray_dir, dt->depth_range, + ob, obmat, dt->ob_index++, is_obedit, + dt->ray_depth, + dt->r_loc, dt->r_no, dt->r_index, + dt->r_ob, dt->r_obmat, + dt->r_hit_list); +} + /** * Main RayCast Function * ====================== @@ -862,24 +850,27 @@ static bool raycastObjects( Object **r_ob, float r_obmat[4][4], ListBase *r_hit_list) { - bool retval = false; - - unsigned int ob_index = 0; - - ListBase obj_list; - create_object_list(sctx, snap_select, use_object_edit_cage, &obj_list); + Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL; - for (struct SnapObject *sobj = obj_list.first; sobj; sobj = sobj->next) { - retval |= raycastObj( - sctx, - ray_orig, ray_start, ray_dir, depth_range, - sobj->ob, sobj->obmat, ob_index++, sobj->use_obedit, - ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); - } + struct RaycastObjUserData data = { + .ray_orig = ray_orig, + .ray_start = ray_start, + .ray_dir = ray_dir, + .depth_range = depth_range, + .ob_index = 0, + .ray_depth = ray_depth, + .r_loc = r_loc, + .r_no = r_no, + .r_index = r_index, + .r_ob = r_ob, + .r_obmat = r_obmat, + .r_hit_list = r_hit_list, + .ret = false, + }; - BLI_freelistN(&obj_list); + iter_snap_objects(sctx, snap_select, obedit, raycast_obj_cb, &data); - return retval; + return data.ret; } @@ -1848,8 +1839,7 @@ static bool snapEditMesh( float local_scale = normalize_v3(ray_normal_local); SnapObjectData_EditMesh *sod = NULL; - - BVHTreeFromEditMesh *treedata; + BVHTreeFromEditMesh *treedata = NULL; void **sod_p; if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { @@ -2052,6 +2042,33 @@ static bool snapObject( } +struct SnapObjUserData { + SnapData *snapdata; + /* read/write args */ + float *ray_depth; + float *dist_px; + /* return args */ + float *r_loc; + float *r_no; + Object **r_ob; + float (*r_obmat)[4]; + bool ret; +}; + +static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) +{ + struct SnapObjUserData *dt = data; + dt->ret |= snapObject( + sctx, dt->snapdata, + ob, obmat, is_obedit, + /* read/write args */ + dt->ray_depth, dt->dist_px, + /* return args */ + dt->r_loc, dt->r_no, + dt->r_ob, dt->r_obmat); +} + + /** * Main Snapping Function * ====================== @@ -2089,21 +2106,22 @@ static bool snapObjectsRay( float r_loc[3], float r_no[3], Object **r_ob, float r_obmat[4][4]) { - bool retval = false; - - ListBase obj_list; - create_object_list(sctx, snap_select, use_object_edit_cage, &obj_list); + Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL; - for (struct SnapObject *sobj = obj_list.first; sobj; sobj = sobj->next) { - retval |= snapObject( - sctx, snapdata, sobj->ob, sobj->obmat, sobj->use_obedit, - ray_depth, dist_px, - r_loc, r_no, r_ob, r_obmat); - } + struct SnapObjUserData data = { + .snapdata = snapdata, + .ray_depth = ray_depth, + .dist_px = dist_px, + .r_loc = r_loc, + .r_no = r_no, + .r_ob = r_ob, + .r_obmat = r_obmat, + .ret = false, + }; - BLI_freelistN(&obj_list); + iter_snap_objects(sctx, snap_select, obedit, sanp_obj_cb, &data); - return retval; + return data.ret; } /** \} */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 193b006cf0de..d7361f5a2596 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1136,8 +1136,13 @@ static void uv_select_linked(Scene *scene, Image *ima, BMEditMesh *em, const flo BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ - /* use winding so we don't consider overlapping islands as connected, see T44320 */ - vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, true); + /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320 + * this made *every* projection split the island into front/back islands. + * Keep 'use_winding' to false, see: T50970. + * + * Better solve this by having a delimit option for select-linked operator, + * keeping island-select working as is. */ + vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false); if (vmap == NULL) return; diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index 6ea311b2c7bc..f837789914e0 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -217,9 +217,27 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3]) // nr = copy_m4_m3(ikmat, ik_mat); if (pchan->parent) - mul_m4_series(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat); + mul_m4_m4m4(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat); else - mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, ikmat); + copy_m4_m4(pchan->pose_mat, pchan->chan_mat); + +#ifdef USE_NONUNIFORM_SCALE + /* apply IK mat, but as if the bones have uniform scale since the IK solver + * is not aware of non-uniform scale */ + float scale[3]; + mat4_to_size(scale, pchan->pose_mat); + normalize_v3_length(pchan->pose_mat[0], scale[1]); + normalize_v3_length(pchan->pose_mat[2], scale[1]); +#endif + + mul_m4_m4m4(pchan->pose_mat, pchan->pose_mat, ikmat); + +#ifdef USE_NONUNIFORM_SCALE + float ik_scale[3]; + mat3_to_size(ik_scale, ik_mat); + normalize_v3_length(pchan->pose_mat[0], scale[0] * ik_scale[0]); + normalize_v3_length(pchan->pose_mat[2], scale[2] * ik_scale[2]); +#endif /* calculate head */ copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]); @@ -308,6 +326,10 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) /* change length based on bone size */ length = bone->length * len_v3(R_bonemat[1]); + /* basis must be pure rotation */ + normalize_m3(R_bonemat); + normalize_m3(R_parmat); + /* compute rest basis and its inverse */ copy_m3_m3(rest_basis, bone->bone_mat); transpose_m3_m3(irest_basis, bone->bone_mat); @@ -317,11 +339,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) mul_m3_m3m3(full_basis, iR_parmat, R_bonemat); mul_m3_m3m3(basis, irest_basis, full_basis); - /* basis must be pure rotation */ - normalize_m3(basis); - /* transform offset into local bone space */ - normalize_m3(iR_parmat); mul_m3_v3(iR_parmat, start); IK_SetTransform(seg, start, rest_basis, basis, length); @@ -545,18 +563,6 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan tree->pchan[a]->flag |= POSE_CHAIN; } -#ifdef USE_NONUNIFORM_SCALE - float (*pchan_scale_data)[3] = MEM_mallocN(sizeof(float[3]) * tree->totchannel, __func__); - - for (a = 0; a < tree->totchannel; a++) { - mat4_to_size(pchan_scale_data[a], tree->pchan[a]->pose_mat); - - /* make uniform at y scale since this controls the length */ - normalize_v3_length(tree->pchan[a]->pose_mat[0], pchan_scale_data[a][1]); - normalize_v3_length(tree->pchan[a]->pose_mat[2], pchan_scale_data[a][1]); - } -#endif - /* 5. execute the IK solver */ execute_posetree(scene, ob, tree); @@ -571,14 +577,6 @@ void iksolver_execute_tree(struct Scene *scene, Object *ob, bPoseChannel *pchan where_is_ik_bone(tree->pchan[a], tree->basis_change[a]); } -#ifdef USE_NONUNIFORM_SCALE - for (a = 0; a < tree->totchannel; a++) { - normalize_v3_length(tree->pchan[a]->pose_mat[0], pchan_scale_data[a][0]); - normalize_v3_length(tree->pchan[a]->pose_mat[2], pchan_scale_data[a][2]); - } - MEM_freeN(pchan_scale_data); -#endif - /* 7. and free */ BLI_remlink(&pchan_root->iktree, tree); free_posetree(tree); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index c0f2dbd07068..7a978c358108 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3926,12 +3926,18 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); + RNA_def_property_ui_text(prop, "DPI", + "DPI for addons to use when drawing custom user interface elements. Controlled by " + "operating system settings and Blender UI scale, with a reference value of 72 DPI. " + "Note that since this value includes a user defined scale, it is not always the " + "actual monitor DPI"); prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_float_sdna(prop, NULL, "pixelsize"); - RNA_def_property_ui_text(prop, "Pixel Size", ""); + RNA_def_property_ui_text(prop, "Pixel Size", + "Suggested line thickness and point size in pixels, for addons drawing custom user " + "interface elements. Controlled by operating system settings and Blender UI scale"); prop = RNA_def_property(srna, "font_path_ui", PROP_STRING, PROP_FILEPATH); RNA_def_property_string_sdna(prop, NULL, "font_path_ui"); diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index ed2752d83723..7ab6447d21a1 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -248,8 +248,17 @@ PyObject *bpy_text_reimport(PyObject *module, int *found) if ((name = PyModule_GetName(module)) == NULL) return NULL; - if ((filepath = (char *)PyModule_GetFilename(module)) == NULL) - return NULL; + { + PyObject *module_file = PyModule_GetFilenameObject(module); + if (module_file == NULL) { + return NULL; + } + filepath = (char *)_PyUnicode_AsString(module_file); + Py_DECREF(module_file); + if (filepath == NULL) { + return NULL; + } + } /* look up the text object */ text = BLI_findstring(&maggie->text, BLI_path_basename(filepath), offsetof(ID, name) + 2); diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 2e789d6d4b3e..861e2dbb0df4 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -300,7 +300,14 @@ void PyC_FileAndNum(const char **filename, int *lineno) if (mod_name) { PyObject *mod = PyDict_GetItem(PyImport_GetModuleDict(), mod_name); if (mod) { - *filename = PyModule_GetFilename(mod); + PyObject *mod_file = PyModule_GetFilenameObject(mod); + if (mod_file) { + *filename = _PyUnicode_AsString(mod_name); + Py_DECREF(mod_file); + } + else { + PyErr_Clear(); + } } /* unlikely, fallback */ diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 54eddcd88467..a51fb8b8cf4a 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -872,6 +872,7 @@ static void bpy_module_delay_init(PyObject *bpy_proxy) BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs)); BLI_path_cwd(filename_abs, sizeof(filename_abs)); + Py_DECREF(filename_obj); argv[0] = filename_abs; argv[1] = NULL; diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index c7787ba96829..362c0281b363 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -2697,7 +2697,8 @@ PyDoc_STRVAR(BPy_EnumProperty_doc, " :icon: An icon string identifier or integer icon value\n" " (e.g. returned by :class:`bpy.types.UILayout.icon`)\n" " :number: Unique value used as the identifier for this item (stored in file data).\n" -" Use when the identifier may need to change.\n" +" Use when the identifier may need to change. If the *ENUM_FLAG* option is used,\n" +" the values are bitmasks and should be powers of two.\n" "\n" " When an item only contains 4 items they define ``(identifier, name, description, number)``.\n" "\n" diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 60a39b24208f..a91c30c28075 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -187,8 +187,9 @@ struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase /* mouse */ void WM_event_add_mousemove(struct bContext *C); -bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event); +bool WM_event_is_modal_tweak_exit(const struct wmEvent *event, int tweak_event); bool WM_event_is_absolute(const struct wmEvent *event); +bool WM_event_is_last_mousemove(const struct wmEvent *event); #ifdef WITH_INPUT_NDOF /* 3D mouse */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index f26ee0e73ec7..32f978ae891e 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -615,6 +615,16 @@ bool WM_event_is_absolute(const wmEvent *event) return (event->tablet_data != NULL); } +bool WM_event_is_last_mousemove(const wmEvent *event) +{ + while ((event = event->next)) { + if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + return false; + } + } + return true; +} + #ifdef WITH_INPUT_NDOF void WM_ndof_deadzone_set(float deadzone) { @@ -2852,7 +2862,7 @@ void WM_event_add_mousemove(bContext *C) /* for modal callbacks, check configuration for how to interpret exit with tweaks */ -bool WM_modal_tweak_exit(const wmEvent *event, int tweak_event) +bool WM_event_is_modal_tweak_exit(const wmEvent *event, int tweak_event) { /* if the release-confirm userpref setting is enabled, * tweak events can be canceled when mouse is released diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index f939df4a4db7..5d471a96b465 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -379,6 +379,11 @@ void WM_window_set_dpi(wmWindow *win) { int auto_dpi = GHOST_GetDPIHint(win->ghostwin); + /* Clamp auto DPI to 96, since our font/interface drawing does not work well + * with lower sizes. The main case we are interested in supporting is higher + * DPI. If a smaller UI is desired it is still possible to adjust UI scale. */ + auto_dpi = MAX2(auto_dpi, 96); + /* Lazily init UI scale size, preserving backwards compatibility by * computing UI scale from ratio of previous DPI and auto DPI */ if (U.ui_scale == 0) { diff --git a/tests/python/bl_load_py_modules.py b/tests/python/bl_load_py_modules.py index 4935491a6bee..80933cd5b611 100644 --- a/tests/python/bl_load_py_modules.py +++ b/tests/python/bl_load_py_modules.py @@ -38,7 +38,7 @@ 'io_import_dxf', # Because of cydxfentity.so dependency # The unpacked wheel is only loaded when actually used, not directly on import: - "io_blend_utils/blender_bam-unpacked.whl", + os.path.join("io_blend_utils", "blender_bam-unpacked.whl"), } # Some modules need to add to the `sys.path`.