diff options
author | Campbell Barton <ideasman42@gmail.com> | 2016-07-18 12:25:44 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2016-07-18 12:25:44 +0300 |
commit | 9186b9ae4806f4bbc1a14417c408e844f8e8cc1a (patch) | |
tree | 117bbd4ace75825e3a65f0ba2a447509bde0df85 | |
parent | cfbd605567f48229a923df382baf6db98fbafc61 (diff) | |
parent | 9946cca14676bf07b3c7c103e99033fe1e4e423e (diff) |
Merge branch 'master' into blender2.8
176 files changed, 2458 insertions, 1611 deletions
diff --git a/.gitmodules b/.gitmodules index 132f6cffada..0b8228e3f14 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,7 @@ path = release/datafiles/locale url = ../blender-translations.git ignore = all +[submodule "source/tools"] + path = source/tools + url = ../blender-dev-tools.git + ignore = all diff --git a/GNUmakefile b/GNUmakefile index d9c895c214a..1fda1a25a92 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -182,14 +182,20 @@ help: .FORCE @echo " * package_archive - build an archive package" @echo "" @echo "Testing Targets (not associated with building blender)" - @echo " * test - run ctest, currently tests import/export, operator execution and that python modules load" - @echo " * test_cmake - runs our own cmake file checker which detects errors in the cmake file list definitions" - @echo " * test_pep8 - checks all python script are pep8 which are tagged to use the stricter formatting" + @echo " * test - run ctest, currently tests import/export," + @echo " operator execution and that python modules load" + @echo " * test_cmake - runs our own cmake file checker" + @echo " which detects errors in the cmake file list definitions" + @echo " * test_pep8 - checks all python script are pep8" + @echo " which are tagged to use the stricter formatting" @echo " * test_deprecated - checks for deprecation tags in our code which may need to be removed" - @echo " * test_style_c - checks C/C++ conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" + @echo " * test_style_c - checks C/C++ conforms with blenders style guide:" + @echo " http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" @echo " * test_style_c_qtc - same as test_style but outputs QtCreator tasks format" - @echo " * test_style_osl - checks OpenShadingLanguage conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" - @echo " * test_style_osl_qtc - checks OpenShadingLanguage conforms with blenders style guide: http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" + @echo " * test_style_osl - checks OpenShadingLanguage conforms with blenders style guide:" + @echo " http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" + @echo " * test_style_osl_qtc - checks OpenShadingLanguage conforms with blenders style guide:" + @echo " http://wiki.blender.org/index.php/Dev:Doc/CodeStyle" @echo "" @echo "Static Source Code Checking (not associated with building blender)" @echo " * check_cppcheck - run blender source through cppcheck (C & C++)" @@ -405,7 +411,8 @@ update: .FORCE # Simple version of ./doc/python_api/sphinx_doc_gen.sh with no PDF generation. doc_py: .FORCE - "$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python doc/python_api/sphinx_doc_gen.py + "$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup \ + --python doc/python_api/sphinx_doc_gen.py cd doc/python_api ; sphinx-build -b html sphinx-in sphinx-out @echo "docs written into: '$(BLENDER_DIR)/doc/python_api/sphinx-out/contents.html'" @@ -414,7 +421,8 @@ doc_doxy: .FORCE @echo "docs written into: '$(BLENDER_DIR)/doc/doxygen/html/index.html'" doc_dna: .FORCE - "$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup --python doc/blender_file_format/BlendFileDnaExporter_25.py + "$(BUILD_DIR)/bin/blender" --background -noaudio --factory-startup \ + --python doc/blender_file_format/BlendFileDnaExporter_25.py @echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'" doc_man: .FORCE diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index d29f086069a..5ffd6c4e7f4 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -196,8 +196,33 @@ function(blender_source_group endfunction() +# Support per-target CMake flags +# Read from: CMAKE_C_FLAGS_**** (made upper case) when set. +# +# 'name' should alway match the target name, +# use this macro before add_library or add_executable. +# +# Optionally takes an arg passed to set(), eg PARENT_SCOPE. +macro(add_cc_flags_custom_test + name + ) + + string(TOUPPER ${name} _name_upper) + if(DEFINED CMAKE_C_FLAGS_${_name_upper}) + message(STATUS "Using custom CFLAGS: CMAKE_C_FLAGS_${_name_upper} in \"${CMAKE_CURRENT_SOURCE_DIR}\"") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${_name_upper}}" ${ARGV1}) + endif() + if(DEFINED CMAKE_CXX_FLAGS_${_name_upper}) + message(STATUS "Using custom CXXFLAGS: CMAKE_CXX_FLAGS_${_name_upper} in \"${CMAKE_CURRENT_SOURCE_DIR}\"") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${_name_upper}}" ${ARGV1}) + endif() + unset(_name_upper) + +endmacro() + + # only MSVC uses SOURCE_GROUP -function(blender_add_lib_nolist +function(blender_add_lib__impl name sources includes @@ -225,6 +250,18 @@ function(blender_add_lib_nolist endfunction() +function(blender_add_lib_nolist + name + sources + includes + includes_sys + ) + + add_cc_flags_custom_test(${name} PARENT_SCOPE) + + blender_add_lib__impl(${name} "${sources}" "${includes}" "${includes_sys}") +endfunction() + function(blender_add_lib name sources @@ -232,7 +269,9 @@ function(blender_add_lib includes_sys ) - blender_add_lib_nolist(${name} "${sources}" "${includes}" "${includes_sys}") + add_cc_flags_custom_test(${name} PARENT_SCOPE) + + blender_add_lib__impl(${name} "${sources}" "${includes}" "${includes_sys}") set_property(GLOBAL APPEND PROPERTY BLENDER_LINK_LIBS ${name}) endfunction() diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index bf84517a082..04feb979165 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -503,6 +503,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Use BVH spatial splits: longer builder time, faster render", default=False, ) + cls.debug_use_hair_bvh = BoolProperty( + name="Use Hair BVH", + description="Use special type BVH optimized for hair. Uses more ram but renders faster", + default=True, + ) cls.tile_order = EnumProperty( name="Tile Order", description="Tile order for rendering", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 3c9c83fec42..6faec5e013b 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -401,6 +401,7 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): col.label(text="Acceleration structure:") col.prop(cscene, "debug_use_spatial_splits") + col.prop(cscene, "debug_use_hair_bvh") class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index a7ede3094ac..be395b9f253 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -484,6 +484,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene, SceneParams::BVH_STATIC); params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits"); + params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh"); if(background && params.shadingsystem != SHADINGSYSTEM_OSL) params.persistent_data = r.use_persistent_data(); diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index e92526ac1c4..1bb3e95c810 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -463,8 +463,7 @@ void RegularBVH::pack_aligned_inner(const BVHStackEntry& e, pack_aligned_node(e.idx, e0.node->m_bounds, e1.node->m_bounds, e0.encodeIdx(), e1.encodeIdx(), - e0.node->m_visibility & ~PATH_RAY_NODE_UNALIGNED, - e1.node->m_visibility & ~PATH_RAY_NODE_UNALIGNED); + e0.node->m_visibility, e1.node->m_visibility); } void RegularBVH::pack_aligned_node(int idx, @@ -475,7 +474,8 @@ void RegularBVH::pack_aligned_node(int idx, { int4 data[BVH_NODE_SIZE] = { - make_int4(visibility0, visibility1, c0, c1), + make_int4(visibility0 & ~PATH_RAY_NODE_UNALIGNED, + visibility1 & ~PATH_RAY_NODE_UNALIGNED, c0, c1), make_int4(__float_as_int(b0.min.x), __float_as_int(b1.min.x), __float_as_int(b0.max.x), __float_as_int(b1.max.x)), make_int4(__float_as_int(b0.min.y), __float_as_int(b1.min.y), __float_as_int(b0.max.y), __float_as_int(b1.max.y)), make_int4(__float_as_int(b0.min.z), __float_as_int(b1.min.z), __float_as_int(b0.max.z), __float_as_int(b1.max.z)), @@ -688,9 +688,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility leaf_data[0].y = __int_as_float(c1); leaf_data[0].z = __uint_as_float(visibility); leaf_data[0].w = __uint_as_float(data[0].w); - memcpy(&pack.leaf_nodes[idx * BVH_NODE_LEAF_SIZE], - leaf_data, - sizeof(float4)*BVH_NODE_LEAF_SIZE); + memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_NODE_LEAF_SIZE); } else { int4 *data = &pack.nodes[idx]; diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index afe21c49730..50490f3a20e 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -795,7 +795,7 @@ public: bool load_binary(const string& /*kernel_path*/, const string& clbin, - string custom_kernel_build_options, + const string& custom_kernel_build_options, cl_program *program, const string *debug_src = NULL) { @@ -848,7 +848,7 @@ public: } bool build_kernel(cl_program *kernel_program, - string custom_kernel_build_options, + const string& custom_kernel_build_options, const string *debug_src = NULL) { string build_options; @@ -881,30 +881,39 @@ public: return true; } - bool compile_kernel(const string& kernel_path, - string source, - string custom_kernel_build_options, + bool compile_kernel(const string& kernel_name, + const string& kernel_path, + const string& source, + const string& custom_kernel_build_options, cl_program *kernel_program, const string *debug_src = NULL) { - /* we compile kernels consisting of many files. unfortunately opencl + /* We compile kernels consisting of many files. unfortunately OpenCL * kernel caches do not seem to recognize changes in included files. - * so we force recompile on changes by adding the md5 hash of all files */ - source = path_source_replace_includes(source, kernel_path); + * so we force recompile on changes by adding the md5 hash of all files. + */ + string inlined_source = path_source_replace_includes(source, + kernel_path); - if(debug_src) - path_write_text(*debug_src, source); + if(debug_src) { + path_write_text(*debug_src, inlined_source); + } - size_t source_len = source.size(); - const char *source_str = source.c_str(); + size_t source_len = inlined_source.size(); + const char *source_str = inlined_source.c_str(); - *kernel_program = clCreateProgramWithSource(cxContext, 1, &source_str, &source_len, &ciErr); + *kernel_program = clCreateProgramWithSource(cxContext, + 1, + &source_str, + &source_len, + &ciErr); - if(opencl_error(ciErr)) + if(opencl_error(ciErr)) { return false; + } double starttime = time_dt(); - printf("Compiling OpenCL kernel ...\n"); + printf("Compiling %s OpenCL kernel ...\n", kernel_name.c_str()); /* TODO(sergey): Report which kernel is being compiled * as well (megakernel or which of split kernels etc..). */ @@ -1004,7 +1013,8 @@ public: string init_kernel_source = "#include \"kernels/opencl/kernel.cl\" // " + kernel_md5 + "\n"; /* If does not exist or loading binary failed, compile kernel. */ - if(!compile_kernel(kernel_path, + if(!compile_kernel("base_kernel", + kernel_path, init_kernel_source, build_flags, &cpProgram, @@ -1694,7 +1704,8 @@ public: string init_kernel_source = "#include \"kernels/opencl/kernel.cl\" // " + kernel_md5 + "\n"; /* If does not exist or loading binary failed, compile kernel. */ - if(!compile_kernel(kernel_path, + if(!compile_kernel("mega_kernel", + kernel_path, init_kernel_source, custom_kernel_build_options, &path_trace_program, @@ -2078,30 +2089,33 @@ public: /* TODO(sergey): Seems really close to load_kernel(), * could it be de-duplicated? */ - bool load_split_kernel(string kernel_path, - string kernel_init_source, - string clbin, - string custom_kernel_build_options, + bool load_split_kernel(const string& kernel_name, + const string& kernel_path, + const string& kernel_init_source, + const string& clbin, + const string& custom_kernel_build_options, cl_program *program, const string *debug_src = NULL) { - if(!opencl_version_check()) + if(!opencl_version_check()) { return false; + } - clbin = path_user_get(path_join("cache", clbin)); + string cache_clbin = path_user_get(path_join("cache", clbin)); /* If exists already, try use it. */ - if(path_exists(clbin) && load_binary(kernel_path, - clbin, - custom_kernel_build_options, - program, - debug_src)) + if(path_exists(cache_clbin) && load_binary(kernel_path, + cache_clbin, + custom_kernel_build_options, + program, + debug_src)) { /* Kernel loaded from binary. */ } else { /* If does not exist or loading binary failed, compile kernel. */ - if(!compile_kernel(kernel_path, + if(!compile_kernel(kernel_name, + kernel_path, kernel_init_source, custom_kernel_build_options, program, @@ -2110,7 +2124,7 @@ public: return false; } /* Save binary for reuse. */ - if(!save_binary(program, clbin)) { + if(!save_binary(program, cache_clbin)) { return false; } } @@ -2208,7 +2222,10 @@ public: clsrc = path_user_get(path_join("cache", clsrc)); \ debug_src = &clsrc; \ } \ - if(!load_split_kernel(kernel_path, kernel_init_source, clbin, \ + if(!load_split_kernel(#name, \ + kernel_path, \ + kernel_init_source, \ + clbin, \ build_options, \ &GLUE(name, _program), \ debug_src)) \ diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h index 1869457f0c3..b27afaa9869 100644 --- a/intern/cycles/kernel/bvh/bvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h @@ -283,7 +283,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, return true; } /* if maximum number of hits reached, block all light */ - else if(*num_hits == max_hits) { + else if(*num_hits >= max_hits) { return true; } diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h index b5405e8e57b..d7f6bf86c71 100644 --- a/intern/cycles/kernel/bvh/bvh_volume_all.h +++ b/intern/cycles/kernel/bvh/bvh_volume_all.h @@ -206,7 +206,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_INSTANCING) num_hits_in_instance++; #endif - if(num_hits == max_hits) { + if(num_hits >= max_hits) { #if BVH_FEATURE(BVH_INSTANCING) # if BVH_FEATURE(BVH_MOTION) float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir)); @@ -252,7 +252,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, # if BVH_FEATURE(BVH_INSTANCING) num_hits_in_instance++; # endif - if(num_hits == max_hits) { + if(num_hits >= max_hits) { # if BVH_FEATURE(BVH_INSTANCING) # if BVH_FEATURE(BVH_MOTION) float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir)); diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h index 34753ff067d..eb98eaf7455 100644 --- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h @@ -366,7 +366,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, return true; } /* if maximum number of hits reached, block all light */ - else if(*num_hits == max_hits) { + else if(*num_hits >= max_hits) { return true; } diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h index a877e5bb341..90cad9d91c0 100644 --- a/intern/cycles/kernel/bvh/qbvh_volume_all.h +++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h @@ -273,7 +273,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_INSTANCING) num_hits_in_instance++; #endif - if(num_hits == max_hits) { + if(num_hits >= max_hits) { #if BVH_FEATURE(BVH_INSTANCING) # if BVH_FEATURE(BVH_MOTION) float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir)); @@ -312,7 +312,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, # if BVH_FEATURE(BVH_INSTANCING) num_hits_in_instance++; # endif - if(num_hits == max_hits) { + if(num_hits >= max_hits) { # if BVH_FEATURE(BVH_INSTANCING) # if BVH_FEATURE(BVH_MOTION) float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir)); diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index aa21633070a..7bf7c2806d4 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -615,6 +615,36 @@ ccl_device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */ } +ccl_device_inline float bsdf_beckmann_G1(float alpha, float cos_n) +{ + cos_n *= cos_n; + float invA = alpha * safe_sqrtf((1.0f - cos_n) / cos_n); + if(invA < 0.625f) { + return 1.0f; + } + + float a = 1.0f / invA; + return ((2.181f*a + 3.535f)*a) / ((2.577f*a + 2.276f)*a + 1.0f); +} + +ccl_device_inline float bsdf_beckmann_aniso_G1(float alpha_x, float alpha_y, float cos_n, float cos_phi, float sin_phi) +{ + cos_n *= cos_n; + sin_phi *= sin_phi; + cos_phi *= cos_phi; + alpha_x *= alpha_x; + alpha_y *= alpha_y; + + float alphaO2 = (cos_phi*alpha_x + sin_phi*alpha_y) / (cos_phi + sin_phi); + float invA = safe_sqrtf(alphaO2 * (1 - cos_n) / cos_n); + if(invA < 0.625f) { + return 1.0f; + } + + float a = 1.0f / invA; + return ((2.181f*a + 3.535f)*a) / ((2.577f*a + 2.276f)*a + 1.0f); +} + ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { float alpha_x = sc->data0; @@ -646,10 +676,8 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */ - float ao = 1 / (alpha_x * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + G1o = bsdf_beckmann_G1(alpha_x, cosNO); + G1i = bsdf_beckmann_G1(alpha_x, cosNI); } else { /* anisotropic */ @@ -668,24 +696,8 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4); /* G1(i,m) and G1(o,m) */ - float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO); - float cosPhiO = dot(I, X); - float sinPhiO = dot(I, Y); - - float alphaO2 = (cosPhiO*cosPhiO)*(alpha_x*alpha_x) + (sinPhiO*sinPhiO)*(alpha_y*alpha_y); - alphaO2 /= cosPhiO*cosPhiO + sinPhiO*sinPhiO; - - float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI); - float cosPhiI = dot(omega_in, X); - float sinPhiI = dot(omega_in, Y); - - float alphaI2 = (cosPhiI*cosPhiI)*(alpha_x*alpha_x) + (sinPhiI*sinPhiI)*(alpha_y*alpha_y); - alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI; - - float ao = 1 / (safe_sqrtf(alphaO2 * tanThetaO2)); - float ai = 1 / (safe_sqrtf(alphaI2 * tanThetaI2)); - G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y)); + G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y)); } float G = G1o * G1i; @@ -740,10 +752,8 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4); /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */ - float ao = 1 / (alpha_x * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO))); - float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f; - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + float G1o = bsdf_beckmann_G1(alpha_x, cosNO); + float G1i = bsdf_beckmann_G1(alpha_x, cosNI); float G = G1o * G1i; /* probability */ @@ -820,8 +830,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl float cosNI = dot(N, *omega_in); /* eq. 26, 27: now calculate G1(i,m) */ - float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + G1i = bsdf_beckmann_G1(alpha_x, cosNI); } else { /* anisotropic distribution */ @@ -836,16 +845,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4); /* G1(i,m) */ - float cosNI = dot(N, *omega_in); - float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI); - float cosPhiI = dot(*omega_in, X); - float sinPhiI = dot(*omega_in, Y); - - float alphaI2 = (cosPhiI*cosPhiI)*(alpha_x*alpha_x) + (sinPhiI*sinPhiI)*(alpha_y*alpha_y); - alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI; - - float ai = 1 / (safe_sqrtf(alphaI2 * tanThetaI2)); - G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, dot(*omega_in, N), dot(*omega_in, X), dot(*omega_in, Y)); } float G = G1o * G1i; @@ -906,8 +906,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl float cosNI = dot(N, *omega_in); /* eq. 26, 27: now calculate G1(i,m) */ - float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI))); - float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f; + float G1i = bsdf_beckmann_G1(alpha_x, cosNI); float G = G1o * G1i; /* eq. 21 */ diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index 6060d7d8ccb..51b12fe4e45 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -348,11 +348,7 @@ ccl_device int bsdf_microfacet_multi_ggx_common_setup(ShaderClosure *sc) ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(ShaderClosure *sc) { -#ifdef __KERNEL_OPENCL__ - if(all(sc->T == 0.0f)) -#else - if(sc->T == make_float3(0.0f, 0.0f, 0.0f)) -#endif + if(is_zero(sc->T)) sc->T = make_float3(1.0f, 0.0f, 0.0f); return bsdf_microfacet_multi_ggx_common_setup(sc); diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h index 89b1998d1ce..b0c5280b6cb 100644 --- a/intern/cycles/kernel/closure/bsdf_util.h +++ b/intern/cycles/kernel/closure/bsdf_util.h @@ -80,7 +80,7 @@ ccl_device float fresnel_dielectric( return 1; // total internal reflection } else { - float dnp = sqrtf(arg); + float dnp = max(sqrtf(arg), 1e-7f); float nK = (neta * cos)- dnp; *T = -(neta * I)+(nK * Nn); #ifdef __RAY_DIFFERENTIALS__ diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h index fc081bda525..720ee6a1f5c 100644 --- a/intern/cycles/kernel/geom/geom_triangle_intersect.h +++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h @@ -255,6 +255,13 @@ ccl_device_inline void triangle_intersect_subsurface( /* Normalize U, V, W, and T. */ const float inv_det = 1.0f / det; + const float t = T * inv_det; + for(int i = min(max_hits, ss_isect->num_hits); i >= 0; --i) { + if(ss_isect->hits[i].t == t) { + return; + } + } + ss_isect->num_hits++; int hit; @@ -277,7 +284,7 @@ ccl_device_inline void triangle_intersect_subsurface( isect->type = PRIMITIVE_TRIANGLE; isect->u = U * inv_det; isect->v = V * inv_det; - isect->t = T * inv_det; + isect->t = t; /* Record geometric normal. */ /* TODO(sergey): Use float4_to_float3() on just an edges. */ diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h index db2fc84834a..d1576754d2e 100644 --- a/intern/cycles/kernel/kernel_shadow.h +++ b/intern/cycles/kernel/kernel_shadow.h @@ -75,7 +75,12 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ShaderData *shadow_sd, } uint num_hits; - blocked = scene_intersect_shadow_all(kg, ray, hits, max_hits, &num_hits); + if(max_hits == 0) { + blocked = true; + num_hits = 0; + } else { + blocked = scene_intersect_shadow_all(kg, ray, hits, max_hits, &num_hits); + } /* if no opaque surface found but we did find transparent hits, shade them */ if(!blocked && num_hits > 0) { diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 27fed89fdf7..276b6f26f5e 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -312,7 +312,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st /* apply normal map */ float3 B = sign * cross(normal, tangent); - N = normalize(color.x * tangent + color.y * B + color.z * normal); + N = safe_normalize(color.x * tangent + color.y * B + color.z * normal); /* transform to world space */ object_normal_transform(kg, sd, &N); @@ -330,14 +330,18 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st if(space == NODE_NORMAL_MAP_OBJECT || space == NODE_NORMAL_MAP_BLENDER_OBJECT) object_normal_transform(kg, sd, &N); else - N = normalize(N); + N = safe_normalize(N); } float strength = stack_load_float(stack, strength_offset); if(strength != 1.0f) { strength = max(strength, 0.0f); - N = normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength); + N = safe_normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength); + } + + if(is_zero(N)) { + N = ccl_fetch(sd, N); } stack_store_float3(stack, normal_offset, N); diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index 2a10eb474a4..63914e57319 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -176,7 +176,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene max_samples = max(max_samples, volume_samples); } - max_samples *= (max_bounce + transparent_max_bounce + 3); + max_samples *= (max_bounce + transparent_max_bounce + 3 + BSSRDF_MAX_HITS); int dimensions = PRNG_BASE_NUM + max_samples*PRNG_BOUNCE_NUM; dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS); diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 661719ed545..8b0ed9f77b2 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -588,7 +588,8 @@ void Mesh::compute_bvh(DeviceScene *dscene, BVHParams bparams; bparams.use_spatial_split = params->use_bvh_spatial_split; bparams.use_qbvh = params->use_qbvh; - bparams.use_unaligned_nodes = dscene->data.bvh.have_curves; + bparams.use_unaligned_nodes = dscene->data.bvh.have_curves && + params->use_bvh_unaligned_nodes; delete bvh; bvh = BVH::create(bparams, objects); @@ -1222,7 +1223,8 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene * bparams.top_level = true; bparams.use_qbvh = scene->params.use_qbvh; bparams.use_spatial_split = scene->params.use_bvh_spatial_split; - bparams.use_unaligned_nodes = dscene->data.bvh.have_curves; + bparams.use_unaligned_nodes = dscene->data.bvh.have_curves && + scene->params.use_bvh_unaligned_nodes; delete bvh; bvh = BVH::create(bparams, scene->objects); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 15b55d17301..a8fd9da9ced 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1576,7 +1576,9 @@ RGBToBWNode::RGBToBWNode() { } -bool RGBToBWNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool RGBToBWNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { if(all_inputs_constant()) { optimized->set(linear_rgb_to_gray(color)); @@ -1661,7 +1663,9 @@ ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool auto special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT; } -bool ConvertNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool ConvertNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { /* proxy nodes should have been removed at this point */ assert(special_type != SHADER_SPECIAL_TYPE_PROXY); @@ -2362,7 +2366,9 @@ void EmissionNode::compile(OSLCompiler& compiler) compiler.add(this, "node_emission"); } -bool EmissionNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *) +bool EmissionNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput * /*optimized*/) { ShaderInput *color_in = input("Color"); ShaderInput *strength_in = input("Strength"); @@ -2412,7 +2418,9 @@ void BackgroundNode::compile(OSLCompiler& compiler) compiler.add(this, "node_background"); } -bool BackgroundNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *) +bool BackgroundNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput * /*optimized*/) { ShaderInput *color_in = input("Color"); ShaderInput *strength_in = input("Strength"); @@ -3380,7 +3388,9 @@ ValueNode::ValueNode() { } -bool ValueNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool ValueNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { optimized->set(value); return true; @@ -3416,7 +3426,9 @@ ColorNode::ColorNode() { } -bool ColorNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool ColorNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { optimized->set(value); return true; @@ -3499,7 +3511,9 @@ void MixClosureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_mix_closure"); } -bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *) +bool MixClosureNode::constant_fold(ShaderGraph *graph, + ShaderOutput * /*socket*/, + ShaderInput * /*optimized*/) { ShaderInput *fac_in = input("Fac"); ShaderInput *closure1_in = input("Closure1"); @@ -3589,7 +3603,9 @@ InvertNode::InvertNode() { } -bool InvertNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *optimized) +bool InvertNode::constant_fold(ShaderGraph *graph, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { ShaderInput *fac_in = input("Fac"); ShaderInput *color_in = input("Color"); @@ -3697,7 +3713,9 @@ void MixNode::compile(OSLCompiler& compiler) compiler.add(this, "node_mix"); } -bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *optimized) +bool MixNode::constant_fold(ShaderGraph *graph, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { ShaderInput *fac_in = input("Fac"); ShaderInput *color1_in = input("Color1"); @@ -3774,7 +3792,9 @@ CombineRGBNode::CombineRGBNode() { } -bool CombineRGBNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool CombineRGBNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { if(all_inputs_constant()) { optimized->set(make_float3(r, g, b)); @@ -3829,7 +3849,9 @@ CombineXYZNode::CombineXYZNode() { } -bool CombineXYZNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool CombineXYZNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { if(all_inputs_constant()) { optimized->set(make_float3(x, y, z)); @@ -3884,7 +3906,9 @@ CombineHSVNode::CombineHSVNode() { } -bool CombineHSVNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool CombineHSVNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { if(all_inputs_constant()) { optimized->set(hsv_to_rgb(make_float3(h, s, v))); @@ -3932,7 +3956,9 @@ GammaNode::GammaNode() { } -bool GammaNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool GammaNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { if(all_inputs_constant()) { optimized->set(svm_math_gamma_color(color, gamma)); @@ -3979,7 +4005,9 @@ BrightContrastNode::BrightContrastNode() { } -bool BrightContrastNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool BrightContrastNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { if(all_inputs_constant()) { optimized->set(svm_brightness_contrast(color, bright, contrast)); @@ -4029,7 +4057,9 @@ SeparateRGBNode::SeparateRGBNode() { } -bool SeparateRGBNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) +bool SeparateRGBNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput *socket, + ShaderInput *optimized) { if(all_inputs_constant()) { for(int channel = 0; channel < 3; channel++) { @@ -4088,7 +4118,9 @@ SeparateXYZNode::SeparateXYZNode() { } -bool SeparateXYZNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) +bool SeparateXYZNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput *socket, + ShaderInput *optimized) { if(all_inputs_constant()) { for(int channel = 0; channel < 3; channel++) { @@ -4147,7 +4179,9 @@ SeparateHSVNode::SeparateHSVNode() { } -bool SeparateHSVNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) +bool SeparateHSVNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput *socket, + ShaderInput *optimized) { if(all_inputs_constant()) { float3 hsv = rgb_to_hsv(color); @@ -4546,7 +4580,9 @@ BlackbodyNode::BlackbodyNode() { } -bool BlackbodyNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool BlackbodyNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { if(all_inputs_constant()) { optimized->set(svm_math_blackbody_color(temperature)); @@ -4655,7 +4691,9 @@ MathNode::MathNode() { } -bool MathNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized) +bool MathNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput * /*socket*/, + ShaderInput *optimized) { if(all_inputs_constant()) { float value = svm_math(type, value1, value2); @@ -4717,7 +4755,9 @@ VectorMathNode::VectorMathNode() { } -bool VectorMathNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized) +bool VectorMathNode::constant_fold(ShaderGraph * /*graph*/, + ShaderOutput *socket, + ShaderInput *optimized) { float value; float3 vector; @@ -4873,7 +4913,9 @@ void BumpNode::compile(OSLCompiler& compiler) compiler.add(this, "node_bump"); } -bool BumpNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *) +bool BumpNode::constant_fold(ShaderGraph *graph, + ShaderOutput * /*socket*/, + ShaderInput * /*optimized*/) { ShaderInput *height_in = input("Height"); ShaderInput *normal_in = input("Normal"); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index ff1f678c2d2..662d87e8b6b 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -184,7 +184,7 @@ void Object::apply_transform(bool apply_to_motion) } /* tfm is not reset to identity, all code that uses it needs to check the - transform_applied boolean */ + * transform_applied boolean */ } void Object::tag_update(Scene *scene) diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 925e84ad96d..5abcbfcdaad 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -136,6 +136,7 @@ public: BVH_NUM_TYPES, } bvh_type; bool use_bvh_spatial_split; + bool use_bvh_unaligned_nodes; bool use_qbvh; bool persistent_data; @@ -144,6 +145,7 @@ public: shadingsystem = SHADINGSYSTEM_SVM; bvh_type = BVH_DYNAMIC; use_bvh_spatial_split = false; + use_bvh_unaligned_nodes = true; use_qbvh = false; persistent_data = false; } @@ -152,6 +154,7 @@ public: { return !(shadingsystem == params.shadingsystem && bvh_type == params.bvh_type && use_bvh_spatial_split == params.use_bvh_spatial_split + && use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes && use_qbvh == params.use_qbvh && persistent_data == params.persistent_data); } }; diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h index deb2013daae..d3960deb3b4 100644 --- a/intern/cycles/util/util_math_fast.h +++ b/intern/cycles/util/util_math_fast.h @@ -547,6 +547,9 @@ ccl_device_inline float fast_erff(float x) const float a5 = 0.0002765672f; const float a6 = 0.0000430638f; const float a = fabsf(x); + if(a >= 12.3f) { + return copysignf(1.0f, x); + } const float b = 1.0f - (1.0f - a); /* Crush denormals. */ const float r = madd(madd(madd(madd(madd(madd(a6, b, a5), b, a4), b, a3), b, a2), b, a1), b, 1.0f); const float s = r * r; /* ^2 */ diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 55d013f6e5f..6f349543eed 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -1985,9 +1985,8 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType, ); } #endif -/* +/** * These callbacks can be used for debugging, so we can breakpoint on an X11 error. - * * Dummy function to get around IO Handler exiting if device invalid * Basically it will not crash blender now if you have a X device that diff --git a/intern/guardedalloc/test/simpletest/memtest.c b/intern/guardedalloc/test/simpletest/memtest.c index 841b47bd4f1..79d55dd02cc 100644 --- a/intern/guardedalloc/test/simpletest/memtest.c +++ b/intern/guardedalloc/test/simpletest/memtest.c @@ -26,7 +26,6 @@ */ /** - * Copyright (C) 2001 NaN Technologies B.V. * Simple test of memory. */ diff --git a/intern/libmv/libmv/multiview/projection.h b/intern/libmv/libmv/multiview/projection.h index 3220bc2dbbc..8f304f31ec6 100644 --- a/intern/libmv/libmv/multiview/projection.h +++ b/intern/libmv/libmv/multiview/projection.h @@ -122,7 +122,7 @@ inline void Project(const Mat34 &P, const Vec3 &X, Vec3 *x) { inline void Project(const Mat34 &P, const Vec3 &X, Vec2 *x) { Vec3 hx; - Project(P, X, x); + Project(P, X, &hx); *x = hx.head<2>() / hx(2); } diff --git a/intern/libmv/libmv/numeric/numeric.h b/intern/libmv/libmv/numeric/numeric.h index 20a4a29e5ba..a42dab8c7a2 100644 --- a/intern/libmv/libmv/numeric/numeric.h +++ b/intern/libmv/libmv/numeric/numeric.h @@ -148,7 +148,7 @@ using Eigen::Matrix; // A = U * diag(s) * VT // template <typename TMat, typename TVec> -inline void SVD(TMat *A, Vec *s, Mat *U, Mat *VT) { +inline void SVD(TMat * /*A*/, Vec * /*s*/, Mat * /*U*/, Mat * /*VT*/) { assert(0); } diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc index 3fadde68d32..0ad72c88a12 100644 --- a/intern/opensubdiv/opensubdiv_converter.cc +++ b/intern/opensubdiv/opensubdiv_converter.cc @@ -332,7 +332,6 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopolog else { /* Special handle of non-manifold vertex. */ for (int i = 0; i < num_vert_edges; ++i) { - bool start_found = false; edge_start = vert_edges[i]; IndexArray edge_faces = getBaseEdgeFaces(refiner, edge_start); if (edge_faces.size() == 1) { @@ -343,14 +342,10 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopolog face_edges = getBaseFaceEdges(refiner, face_start); face_vert_start = findInArray(face_verts, vert); if (edge_start == face_edges[face_vert_start]) { - start_found = true; break; } } } - if (start_found) { - break; - } /* Reset indices for sanity check below. */ face_start = edge_start = face_vert_start = -1; } diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index af8431ba1dc..33af812b6c4 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -125,7 +125,7 @@ class DATA_PT_shape_curve(CurveButtonsPanel, Panel): col.prop(curve, "use_fill_deform") if is_curve: - col.label(text="Path / Curve-Deform:") + col.label(text="Path/Curve-Deform:") sub = col.column() subsub = sub.row() subsub.prop(curve, "use_radius") diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 7e6067192f4..0a8920dff59 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -151,21 +151,16 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col = split.column() col.label(text="Operation:") col.prop(md, "operation", text="") + row = layout.row() + row.label("Solver:") + row.prop(md, "solver", expand=True) col = split.column() col.label(text="Object:") col.prop(md, "object", text="") - """ - layout.prop(md, "use_bmesh") - if md.use_bmesh: - box = layout.box() - box.label("BMesh Options:") - box.prop(md, "use_bmesh_separate") - box.prop(md, "use_bmesh_dissolve") - box.prop(md, "use_bmesh_connect_regions") - box.prop(md, "threshold") - """ + if md.solver == 'BMESH': + layout.prop(md, "double_threshold") def BUILD(self, layout, ob, md): split = layout.split() diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 8bb3cf2814c..58bb956f653 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -950,7 +950,7 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel): class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel): bl_space_type = 'CLIP_EDITOR' bl_region_type = 'UI' - bl_label = "Proxy / Timecode" + bl_label = "Proxy/Timecode" bl_options = {'DEFAULT_CLOSED'} def draw_header(self, context): diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 539ee7a6af4..4d1b9104344 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -972,7 +972,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): - bl_label = "Proxy / Timecode" + bl_label = "Proxy/Timecode" @classmethod def poll(cls, context): diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 06abb869b4f..f6cbd2c444a 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -488,7 +488,7 @@ class USERPREF_PT_system(Panel): col.separator() - col.label(text="Sequencer / Clip Editor:") + col.label(text="Sequencer/Clip Editor:") # currently disabled in the code # col.prop(system, "prefetch_frames") col.prop(system, "memory_cache_limit") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 882c3e82001..38f7675b070 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -364,6 +364,7 @@ class VIEW3D_MT_snap(Menu): layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid") layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor").use_offset = False layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Offset)").use_offset = True + layout.operator("view3d.snap_selected_to_active", text="Selection to Active") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index b2b4d4fa148..1879a35aa35 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1582,7 +1582,7 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel): class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel): bl_category = "Tools" - bl_label = "Symmetry / Lock" + bl_label = "Symmetry/Lock" bl_options = {'DEFAULT_CLOSED'} @classmethod diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 5874f95502b..ac9b0b6fb10 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -63,7 +63,7 @@ struct bAction *BKE_action_copy(struct Main *bmain, struct bAction *src); /* Deallocate all of the Action's data, but not the Action itself */ void BKE_action_free(struct bAction *act); -void BKE_action_make_local(struct Main *bmain, struct bAction *act); +void BKE_action_make_local(struct Main *bmain, struct bAction *act, const bool force_local); /* Action API ----------------- */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 326c335338f..bfd4a7e3dd8 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -76,7 +76,7 @@ struct bArmature *BKE_armature_from_object(struct Object *ob); int BKE_armature_bonelist_count(struct ListBase *lb); void BKE_armature_bonelist_free(struct ListBase *lb); void BKE_armature_free(struct bArmature *arm); -void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm); +void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool force_local); struct bArmature *BKE_armature_copy(struct Main *bmain, struct bArmature *arm); /* Bounding box. */ diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index c7116bf2ef6..4be4d95490b 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -45,7 +45,7 @@ void BKE_brush_init(struct Brush *brush); struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode); struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode); struct Brush *BKE_brush_copy(struct Main *bmain, struct Brush *brush); -void BKE_brush_make_local(struct Main *bmain, struct Brush *brush); +void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool force_local); void BKE_brush_unlink(struct Main *bmain, struct Brush *brush); void BKE_brush_free(struct Brush *brush); diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 97f4b30894b..3ae0e0e1111 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -53,7 +53,7 @@ struct GPUFXSettings; void BKE_camera_init(struct Camera *cam); void *BKE_camera_add(struct Main *bmain, const char *name); struct Camera *BKE_camera_copy(struct Main *bmain, struct Camera *cam); -void BKE_camera_make_local(struct Main *bmain, struct Camera *cam); +void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool force_local); void BKE_camera_free(struct Camera *ca); /* Camera Usage */ diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 89dbe246910..c2a0404e96e 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -71,7 +71,7 @@ void BKE_curve_editfont_free(struct Curve *cu); void BKE_curve_init(struct Curve *cu); struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type); struct Curve *BKE_curve_copy(struct Main *bmain, struct Curve *cu); -void BKE_curve_make_local(struct Main *bmain, struct Curve *cu); +void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool force_local); short BKE_curve_type_get(struct Curve *cu); void BKE_curve_type_test(struct Object *ob); void BKE_curve_curve_dimension_update(struct Curve *cu); diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 763a3874d4e..7839b9e2154 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -55,7 +55,7 @@ void BKE_icons_init(int first_dyn_id); /* return icon id for library object or create new icon if not found */ int BKE_icon_id_ensure(struct ID *id); -int BKE_icon_preview_ensure(struct PreviewImage *preview); +int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview); /* retrieve icon for id */ struct Icon *BKE_icon_get(int icon_id); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 0895feef983..db73b42d894 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -108,7 +108,7 @@ struct anim *openanim_noload(const char *name, int flags, int streamindex, char void BKE_image_de_interlace(struct Image *ima, int odd); -void BKE_image_make_local(struct Main *bmain, struct Image *ima); +void BKE_image_make_local(struct Main *bmain, struct Image *ima, const bool force_local); void BKE_image_tag_time(struct Image *ima); diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index f30f9eac4e8..e590ff148d7 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -53,7 +53,6 @@ void BKE_key_free_nolib(struct Key *key); struct Key *BKE_key_add(struct ID *id); struct Key *BKE_key_copy(struct Main *bmain, struct Key *key); struct Key *BKE_key_copy_nolib(struct Key *key); -void BKE_key_make_local(struct Main *bmain, struct Key *key); void BKE_key_sort(struct Key *key); void key_curve_position_weights(float t, float data[4], int type); diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 49b43550e67..dc977eabbb1 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -46,7 +46,7 @@ void BKE_lamp_init(struct Lamp *la); struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT; struct Lamp *BKE_lamp_copy(struct Main *bmain, struct Lamp *la) ATTR_WARN_UNUSED_RESULT; struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT; -void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la); +void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool force_local); void BKE_lamp_free(struct Lamp *la); void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime); diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 606df9dcec8..4f72bbecff4 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -49,7 +49,7 @@ void BKE_lattice_init(struct Lattice *lt); struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name); struct Lattice *BKE_lattice_copy(struct Main *bmain, struct Lattice *lt); void BKE_lattice_free(struct Lattice *lt); -void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt); +void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool force_local); void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du); struct LatticeDeformData; diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index cb39b2e53ee..b6a91caee4e 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -80,7 +80,7 @@ void id_us_min(struct ID *id); void id_fake_user_set(struct ID *id); void id_fake_user_clear(struct ID *id); -bool id_make_local(struct Main *bmain, struct ID *id, bool test); +bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local); bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop); bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test); void id_sort_by_name(struct ListBase *lb, struct ID *id); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 0bc54ee4a16..bbe104cd6ee 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -57,7 +57,7 @@ struct Material *BKE_material_add(struct Main *bmain, const char *name); struct Material *BKE_material_copy(struct Main *bmain, struct Material *ma); struct Material *localize_material(struct Material *ma); struct Material *give_node_material(struct Material *ma); /* returns node material or self */ -void BKE_material_make_local(struct Main *bmain, struct Material *ma); +void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool force_local); /* UNUSED */ // void automatname(struct Material *); diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 42704c1b2db..191e8721099 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -43,7 +43,7 @@ void BKE_mball_init(struct MetaBall *mb); struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name); struct MetaBall *BKE_mball_copy(struct Main *bmain, struct MetaBall *mb); -void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb); +void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool force_local); bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2); bool BKE_mball_is_basis(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index d3bb34d7a41..ef8d1c98318 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -91,7 +91,7 @@ struct Mesh *BKE_mesh_copy(struct Main *bmain, struct Mesh *me); void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd); void BKE_mesh_ensure_skin_customdata(struct Mesh *me); -void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me); +void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool force_local); void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]); void BKE_mesh_texspace_calc(struct Mesh *me); float (*BKE_mesh_orco_verts_get(struct Object *ob))[3]; diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b44cb226f0d..647b96fb9ae 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -346,7 +346,7 @@ void ntreeUserDecrefID(struct bNodeTree *ntree); struct bNodeTree *ntreeFromID(struct ID *id); -void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist); +void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist, const bool force_local); struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type); bool ntreeHasType(const struct bNodeTree *ntree, int type); bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 2c4df9620c2..8811f358cd3 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -104,7 +104,7 @@ struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene); struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches); struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob); -void BKE_object_make_local(struct Main *bmain, struct Object *ob); +void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool force_local); bool BKE_object_is_libdata(struct Object *ob); bool BKE_object_obdata_is_libdata(struct Object *ob); @@ -203,8 +203,6 @@ void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); -void BKE_object_eval_proxy_backlink(struct EvaluationContext *eval_ctx, struct Object *ob); - void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h index 89b948a2126..fb730d95b92 100644 --- a/source/blender/blenkernel/BKE_speaker.h +++ b/source/blender/blenkernel/BKE_speaker.h @@ -34,7 +34,7 @@ struct Speaker; void BKE_speaker_init(struct Speaker *spk); void *BKE_speaker_add(struct Main *bmain, const char *name); struct Speaker *BKE_speaker_copy(struct Main *bmain, struct Speaker *spk); -void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk); +void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool force_local); void BKE_speaker_free(struct Speaker *spk); #endif diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 52b1906a78b..b853ebd4793 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -71,7 +71,7 @@ void BKE_texture_default(struct Tex *tex); struct Tex *BKE_texture_copy(struct Main *bmain, struct Tex *tex); struct Tex *BKE_texture_add(struct Main *bmain, const char *name); struct Tex *BKE_texture_localize(struct Tex *tex); -void BKE_texture_make_local(struct Main *bmain, struct Tex *tex); +void BKE_texture_make_local(struct Main *bmain, struct Tex *tex, const bool force_local); void BKE_texture_type_set(struct Tex *tex, int type); void BKE_texture_mtex_default(struct MTex *mtex); diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h index da5cca09b27..8b8dac4ab22 100644 --- a/source/blender/blenkernel/BKE_world.h +++ b/source/blender/blenkernel/BKE_world.h @@ -41,7 +41,7 @@ void BKE_world_init(struct World *wrld); struct World *add_world(struct Main *bmian, const char *name); struct World *BKE_world_copy(struct Main *bmain, struct World *wrld); struct World *localize_world(struct World *wrld); -void BKE_world_make_local(struct Main *bmain, struct World *wrld); +void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool force_local); #endif diff --git a/source/blender/blenkernel/intern/CCGSubSurf_util.c b/source/blender/blenkernel/intern/CCGSubSurf_util.c index 9af69115559..c7ef528c02f 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_util.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_util.c @@ -184,7 +184,7 @@ int ccg_ehashIterator_isStopped(EHashIterator *ehi) } /** - * Standard allocator implementarion. + * Standard allocator implementation. */ static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes) diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index f7ff1261c8a..fa49797126d 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -95,11 +95,11 @@ bAction *add_empty_action(Main *bmain, const char name[]) /* .................................. */ // does copy_fcurve... -void BKE_action_make_local(Main *bmain, bAction *act) +void BKE_action_make_local(Main *bmain, bAction *act, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -110,7 +110,7 @@ void BKE_action_make_local(Main *bmain, bAction *act) BKE_library_ID_test_usages(bmain, act, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &act->id); BKE_id_expand_local(&act->id); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 7f10f6833db..fa156e95d46 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -399,8 +399,8 @@ static void make_local_strips(ListBase *strips) NlaStrip *strip; for (strip = strips->first; strip; strip = strip->next) { - if (strip->act) BKE_action_make_local(G.main, strip->act); - if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target); + if (strip->act) BKE_action_make_local(G.main, strip->act, false); + if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target, false); make_local_strips(&strip->strips); } @@ -412,10 +412,10 @@ void BKE_animdata_make_local(AnimData *adt) NlaTrack *nlt; /* Actions - Active and Temp */ - if (adt->action) BKE_action_make_local(G.main, adt->action); - if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact); + if (adt->action) BKE_action_make_local(G.main, adt->action, false); + if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact, false); /* Remaps */ - if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target); + if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target, false); /* Drivers */ /* TODO: need to remap the ID-targets too? */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 5f564e1c4d2..53e28177bdf 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -144,11 +144,11 @@ void BKE_armature_free(bArmature *arm) } } -void BKE_armature_make_local(Main *bmain, bArmature *arm) +void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -159,7 +159,7 @@ void BKE_armature_make_local(Main *bmain, bArmature *arm) BKE_library_ID_test_usages(bmain, arm, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &arm->id); BKE_id_expand_local(&arm->id); diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index ece17335fa0..aebd564ca58 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -224,7 +224,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos } /* make a new Spline-IK chain, and store it in the IK chains */ - /* TODO: we should check if there is already an IK chain on this, since that would take presidence... */ + /* TODO: we should check if there is already an IK chain on this, since that would take precedence... */ { /* make new tree */ tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree"); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 20621feac6c..3d9cabdc15d 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -219,11 +219,11 @@ void BKE_brush_free(Brush *brush) BKE_previewimg_free(&(brush->preview)); } -void BKE_brush_make_local(Main *bmain, Brush *brush) +void BKE_brush_make_local(Main *bmain, Brush *brush, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -234,12 +234,12 @@ void BKE_brush_make_local(Main *bmain, Brush *brush) if (brush->clone.image) { /* Special case: ima always local immediately. Clone image should only have one user anyway. */ - id_make_local(bmain, &brush->clone.image->id, false); + id_make_local(bmain, &brush->clone.image->id, false, false); } BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &brush->id); BKE_id_expand_local(&brush->id); diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index ae7aac8b54f..cd085816b4d 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -107,11 +107,11 @@ Camera *BKE_camera_copy(Main *bmain, Camera *cam) return camn; } -void BKE_camera_make_local(Main *bmain, Camera *cam) +void BKE_camera_make_local(Main *bmain, Camera *cam, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -122,7 +122,7 @@ void BKE_camera_make_local(Main *bmain, Camera *cam) BKE_library_ID_test_usages(bmain, cam, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &cam->id); BKE_id_expand_local(&cam->id); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 0e634e21ea3..693e7eb0c80 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -215,11 +215,11 @@ Curve *BKE_curve_copy(Main *bmain, Curve *cu) return cun; } -void BKE_curve_make_local(Main *bmain, Curve *cu) +void BKE_curve_make_local(Main *bmain, Curve *cu, const bool force_local) { bool is_local = false, is_lib = false; - /* - when there are only lib users: don't do + /* - only lib users: do nothing (unless force_local is set) * - when there are only local users: set flag * - mixed: do a copy */ @@ -230,12 +230,9 @@ void BKE_curve_make_local(Main *bmain, Curve *cu) BKE_library_ID_test_usages(bmain, cu, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &cu->id); - if (cu->key) { - BKE_key_make_local(bmain, cu->key); - } BKE_id_expand_local(&cu->id); } else { diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index f3e86b44459..63055dc0646 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -423,10 +423,26 @@ void BKE_icon_changed(int id) } } -int BKE_icon_id_ensure(struct ID *id) +static int icon_id_ensure_create_icon(struct ID *id) { Icon *new_icon = NULL; + new_icon = MEM_mallocN(sizeof(Icon), __func__); + + new_icon->obj = id; + new_icon->type = GS(id->name); + + /* next two lines make sure image gets created */ + new_icon->drawinfo = NULL; + new_icon->drawinfo_free = NULL; + + BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon); + + return id->icon_id; +} + +int BKE_icon_id_ensure(struct ID *id) +{ if (!id || G.background) return 0; @@ -440,32 +456,39 @@ int BKE_icon_id_ensure(struct ID *id) return 0; } - new_icon = MEM_mallocN(sizeof(Icon), __func__); - - new_icon->obj = id; - new_icon->type = GS(id->name); - - /* next two lines make sure image gets created */ - new_icon->drawinfo = NULL; - new_icon->drawinfo_free = NULL; + /* Ensure we synchronize ID icon_id with its previewimage if it has one. */ + PreviewImage **p_prv = BKE_previewimg_id_get_p(id); + if (p_prv && *p_prv) { + BLI_assert(ELEM((*p_prv)->icon_id, 0, id->icon_id)); + (*p_prv)->icon_id = id->icon_id; + } - BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon); - - return id->icon_id; + return icon_id_ensure_create_icon(id); } /** * Return icon id of given preview, or create new icon if not found. */ -int BKE_icon_preview_ensure(PreviewImage *preview) +int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) { Icon *new_icon = NULL; if (!preview || G.background) return 0; - if (preview->icon_id) + if (id) { + BLI_assert(BKE_previewimg_id_ensure(id) == preview); + } + + if (preview->icon_id) { + BLI_assert(!id || !id->icon_id || id->icon_id == preview->icon_id); return preview->icon_id; + } + + if (id && id->icon_id) { + preview->icon_id = id->icon_id; + return preview->icon_id; + } preview->icon_id = get_next_free_id(); @@ -474,6 +497,12 @@ int BKE_icon_preview_ensure(PreviewImage *preview) return 0; } + /* Ensure we synchronize ID icon_id with its previewimage if available, and generate suitable 'ID' icon. */ + if (id) { + id->icon_id = preview->icon_id; + return icon_id_ensure_create_icon(id); + } + new_icon = MEM_mallocN(sizeof(Icon), __func__); new_icon->obj = preview; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f6f38977402..ae3163d388e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -469,11 +469,11 @@ Image *BKE_image_copy(Main *bmain, Image *ima) return nima; } -void BKE_image_make_local(Main *bmain, Image *ima) +void BKE_image_make_local(Main *bmain, Image *ima, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -484,7 +484,7 @@ void BKE_image_make_local(Main *bmain, Image *ima) BKE_library_ID_test_usages(bmain, ima, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &ima->id); BKE_id_expand_local(&ima->id); @@ -1118,8 +1118,11 @@ int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options) return IMB_FTYPE_DPX; #endif #ifdef WITH_OPENJPEG - else if (imtype == R_IMF_IMTYPE_JP2) + else if (imtype == R_IMF_IMTYPE_JP2) { + r_options->flag |= JP2_JP2; + r_options->quality = 90; return IMB_FTYPE_JP2; + } #endif else { r_options->quality = 90; diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index e59facd3c39..a524f927cad 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -203,18 +203,6 @@ Key *BKE_key_copy_nolib(Key *key) return keyn; } -void BKE_key_make_local(Main *bmain, Key *key) -{ - /* Note that here for now we simply just make it local... - * Sounds fishy behavior, but since skeys are not *real* IDs... */ - - if (!ID_IS_LINKED_DATABLOCK(key)) { - return; - } - - id_clear_lib_data(bmain, &key->id); -} - /* Sort shape keys and Ipo curves after a change. This assumes that at most * one key was moved, which is a valid assumption for the places it's * currently being called. diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 003b154a70b..c224b5ca0a7 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -172,11 +172,11 @@ Lamp *localize_lamp(Lamp *la) return lan; } -void BKE_lamp_make_local(Main *bmain, Lamp *la) +void BKE_lamp_make_local(Main *bmain, Lamp *la, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -187,7 +187,7 @@ void BKE_lamp_make_local(Main *bmain, Lamp *la) BKE_library_ID_test_usages(bmain, la, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &la->id); BKE_id_expand_local(&la->id); diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 67f49266efc..c2675fabe3b 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -330,11 +330,11 @@ void BKE_lattice_free(Lattice *lt) } -void BKE_lattice_make_local(Main *bmain, Lattice *lt) +void BKE_lattice_make_local(Main *bmain, Lattice *lt, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -345,12 +345,9 @@ void BKE_lattice_make_local(Main *bmain, Lattice *lt) BKE_library_ID_test_usages(bmain, lt, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, <->id); - if (lt->key) { - BKE_key_make_local(bmain, lt->key); - } BKE_id_expand_local(<->id); } else { diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 978f1acefba..9b9b80a2ecc 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -270,7 +270,7 @@ void BKE_id_expand_local(ID *id) /* calls the appropriate make_local method for the block, unless test. Returns true * if the block can be made local. */ -bool id_make_local(Main *bmain, ID *id, bool test) +bool id_make_local(Main *bmain, ID *id, const bool test, const bool force_local) { if (id->tag & LIB_TAG_INDIRECT) return false; @@ -281,45 +281,44 @@ bool id_make_local(Main *bmain, ID *id, bool test) case ID_LI: return false; /* can't be linked */ case ID_OB: - if (!test) BKE_object_make_local(bmain, (Object *)id); + if (!test) BKE_object_make_local(bmain, (Object *)id, force_local); return true; case ID_ME: - if (!test) BKE_mesh_make_local(bmain, (Mesh *)id); + if (!test) BKE_mesh_make_local(bmain, (Mesh *)id, force_local); return true; case ID_CU: - if (!test) BKE_curve_make_local(bmain, (Curve *)id); + if (!test) BKE_curve_make_local(bmain, (Curve *)id, force_local); return true; case ID_MB: - if (!test) BKE_mball_make_local(bmain, (MetaBall *)id); + if (!test) BKE_mball_make_local(bmain, (MetaBall *)id, force_local); return true; case ID_MA: - if (!test) BKE_material_make_local(bmain, (Material *)id); + if (!test) BKE_material_make_local(bmain, (Material *)id, force_local); return true; case ID_TE: - if (!test) BKE_texture_make_local(bmain, (Tex *)id); + if (!test) BKE_texture_make_local(bmain, (Tex *)id, force_local); return true; case ID_IM: - if (!test) BKE_image_make_local(bmain, (Image *)id); + if (!test) BKE_image_make_local(bmain, (Image *)id, force_local); return true; case ID_LT: - if (!test) BKE_lattice_make_local(bmain, (Lattice *)id); + if (!test) BKE_lattice_make_local(bmain, (Lattice *)id, force_local); return true; case ID_LA: - if (!test) BKE_lamp_make_local(bmain, (Lamp *)id); + if (!test) BKE_lamp_make_local(bmain, (Lamp *)id, force_local); return true; case ID_CA: - if (!test) BKE_camera_make_local(bmain, (Camera *)id); + if (!test) BKE_camera_make_local(bmain, (Camera *)id, force_local); return true; case ID_SPK: - if (!test) BKE_speaker_make_local(bmain, (Speaker *)id); + if (!test) BKE_speaker_make_local(bmain, (Speaker *)id, force_local); return true; case ID_IP: return false; /* deprecated */ case ID_KE: - if (!test) BKE_key_make_local(bmain, (Key *)id); - return true; + return false; /* can't be linked */ case ID_WO: - if (!test) BKE_world_make_local(bmain, (World *)id); + if (!test) BKE_world_make_local(bmain, (World *)id, force_local); return true; case ID_SCR: return false; /* can't be linked */ @@ -332,16 +331,16 @@ bool id_make_local(Main *bmain, ID *id, bool test) case ID_GR: return false; /* not implemented */ case ID_AR: - if (!test) BKE_armature_make_local(bmain, (bArmature *)id); + if (!test) BKE_armature_make_local(bmain, (bArmature *)id, force_local); return true; case ID_AC: - if (!test) BKE_action_make_local(bmain, (bAction *)id); + if (!test) BKE_action_make_local(bmain, (bAction *)id, force_local); return true; case ID_NT: - if (!test) ntreeMakeLocal(bmain, (bNodeTree *)id, true); + if (!test) ntreeMakeLocal(bmain, (bNodeTree *)id, true, force_local); return true; case ID_BR: - if (!test) BKE_brush_make_local(bmain, (Brush *)id); + if (!test) BKE_brush_make_local(bmain, (Brush *)id, force_local); return true; case ID_WM: return false; /* can't be linked */ @@ -1455,6 +1454,7 @@ bool new_id(ListBase *lb, ID *id, const char *tname) void id_clear_lib_data_ex(Main *bmain, ID *id, bool id_in_mainlist) { bNodeTree *ntree = NULL; + Key *key = NULL; BKE_id_lib_local_paths(bmain, id->lib, id); @@ -1465,13 +1465,14 @@ void id_clear_lib_data_ex(Main *bmain, ID *id, bool id_in_mainlist) if (id_in_mainlist) new_id(which_libbase(bmain, GS(id->name)), id, NULL); - /* internal bNodeTree blocks inside ID types below - * also stores id->lib, make sure this stays in sync. - */ - ntree = ntreeFromID(id); + /* Internal bNodeTree blocks inside datablocks also stores id->lib, make sure this stays in sync. */ + if ((ntree = ntreeFromID(id))) { + id_clear_lib_data_ex(bmain, &ntree->id, false); /* Datablocks' nodetree is never in Main. */ + } - if (ntree) { - ntreeMakeLocal(bmain, ntree, false); + /* Same goes for shapekeys. */ + if ((key = BKE_key_from_id(id))) { + id_clear_lib_data_ex(bmain, &key->id, id_in_mainlist); /* sigh, why are keys in Main? */ } if (GS(id->name) == ID_OB) { @@ -1585,14 +1586,8 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged { if (lib == NULL || id->lib == lib) { if (id->lib) { - /* for Make Local > All we should be calling id_make_local, - * but doing that breaks append (see #36003 and #36006), we - * we should make it work with all datablocks and id.us==0 */ - id_clear_lib_data(bmain, id); /* sets 'id->tag' */ - - /* why sort alphabetically here but not in - * id_clear_lib_data() ? - campbell */ - id_sort_by_name(lbarray[a], id); + /* In this specific case, we do want to make ID local even if it has no local usage yet... */ + id_make_local(bmain, id, false, true); } else { id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 17811893c03..2ae369fdd1b 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -285,11 +285,11 @@ Material *localize_material(Material *ma) return man; } -void BKE_material_make_local(Main *bmain, Material *ma) +void BKE_material_make_local(Main *bmain, Material *ma, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -300,7 +300,7 @@ void BKE_material_make_local(Main *bmain, Material *ma) BKE_library_ID_test_usages(bmain, ma, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &ma->id); BKE_id_expand_local(&ma->id); diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 9a0a6e3540c..aeb38b3bd1d 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -127,11 +127,11 @@ MetaBall *BKE_mball_copy(Main *bmain, MetaBall *mb) return mbn; } -void BKE_mball_make_local(Main *bmain, MetaBall *mb) +void BKE_mball_make_local(Main *bmain, MetaBall *mb, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -142,7 +142,7 @@ void BKE_mball_make_local(Main *bmain, MetaBall *mb) BKE_library_ID_test_usages(bmain, mb, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &mb->id); BKE_id_expand_local(&mb->id); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 787b9905734..b2f57328df3 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -555,11 +555,11 @@ BMesh *BKE_mesh_to_bmesh( return bm; } -void BKE_mesh_make_local(Main *bmain, Mesh *me) +void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -570,12 +570,9 @@ void BKE_mesh_make_local(Main *bmain, Mesh *me) BKE_library_ID_test_usages(bmain, me, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &me->id); - if (me->key) { - BKE_key_make_local(bmain, me->key); - } BKE_id_expand_local(&me->id); } else { @@ -2227,7 +2224,6 @@ Mesh *BKE_mesh_new_from_object( { Mesh *tmpmesh; Curve *tmpcu = NULL, *copycu; - Object *tmpobj = NULL; int render = settings == eModifierMode_Render, i; int cage = !apply_modifiers; @@ -2242,7 +2238,7 @@ Mesh *BKE_mesh_new_from_object( int uv_from_orco; /* copies object and modifiers (but not the data) */ - tmpobj = BKE_object_copy_ex(bmain, ob, true); + Object *tmpobj = BKE_object_copy_ex(bmain, ob, true); tmpcu = (Curve *)tmpobj->data; id_us_min(&tmpcu->id); @@ -2443,7 +2439,7 @@ Mesh *BKE_mesh_new_from_object( } /* make sure materials get updated in object */ - test_object_materials(tmpobj ? tmpobj : ob, &tmpmesh->id); + test_object_materials(ob, &tmpmesh->id); return tmpmesh; } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 296a00388c4..eec09973a82 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1211,7 +1211,6 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool ski } else { newtree = BKE_libblock_copy_nolib(&ntree->id, true); - newtree->id.lib = NULL; /* same as owning datablock id.lib */ } id_us_plus((ID *)newtree->gpd); @@ -1951,11 +1950,11 @@ bNodeTree *ntreeFromID(ID *id) } } -void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist) +void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist, const bool force_local) { bool is_lib = false, is_local = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -1966,7 +1965,7 @@ void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist) BKE_library_ID_test_usages(bmain, ntree, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist); BKE_id_expand_local(&ntree->id); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 00c25bed1f7..5d654515fc8 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1023,11 +1023,11 @@ Object *BKE_object_copy(Main *bmain, Object *ob) return BKE_object_copy_ex(bmain, ob, false); } -void BKE_object_make_local(Main *bmain, Object *ob) +void BKE_object_make_local(Main *bmain, Object *ob, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -1038,7 +1038,7 @@ void BKE_object_make_local(Main *bmain, Object *ob) BKE_library_ID_test_usages(bmain, ob, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &ob->id); BKE_id_expand_local(&ob->id); diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index b5cb59da7d2..b8cb8955672 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -300,10 +300,3 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME); } - -void BKE_object_eval_proxy_backlink(EvaluationContext *UNUSED(eval_ctx), Object *ob) -{ - if (ob->proxy) { - ob->proxy->proxy_from = ob; - } -} diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 572d23b39c7..d284548d6bc 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1103,7 +1103,7 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame) Base *BKE_scene_base_add(Scene *sce, Object *ob) { - Base *b = MEM_callocN(sizeof(*b), "BKE_scene_base_add"); + Base *b = MEM_callocN(sizeof(*b), __func__); BLI_addhead(&sce->base, b); b->object = ob; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 3de4a426973..ce7c520438a 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -123,28 +123,34 @@ static ImBuf *prepare_effect_imbufs(const SeqRenderData *context, ImBuf *ibuf1, out = IMB_allocImBuf(x, y, 32, IB_rect); } - if (ibuf1 && !ibuf1->rect_float && out->rect_float) { - BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true); - } - if (ibuf2 && !ibuf2->rect_float && out->rect_float) { - BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true); - } - if (ibuf3 && !ibuf3->rect_float && out->rect_float) { - BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true); - } + if (out->rect_float) { + if (ibuf1 && !ibuf1->rect_float) { + BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true); + } + + if (ibuf2 && !ibuf2->rect_float) { + BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true); + } + + if (ibuf3 && !ibuf3->rect_float) { + BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true); + } - if (ibuf1 && !ibuf1->rect && !out->rect_float) { - IMB_rect_from_float(ibuf1); - } - if (ibuf2 && !ibuf2->rect && !out->rect_float) { - IMB_rect_from_float(ibuf2); - } - if (ibuf3 && !ibuf3->rect && !out->rect_float) { - IMB_rect_from_float(ibuf3); + IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name); } + else { + if (ibuf1 && !ibuf1->rect) { + IMB_rect_from_float(ibuf1); + } - if (out->rect_float) - IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name); + if (ibuf2 && !ibuf2->rect) { + IMB_rect_from_float(ibuf2); + } + + if (ibuf3 && !ibuf3->rect) { + IMB_rect_from_float(ibuf3); + } + } /* If effect only affecting a single channel, forward input's metadata to the output. */ if (ibuf1 != NULL && ibuf1 == ibuf2 && ibuf2 == ibuf3) { diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 5ef502e0182..2f497d807e4 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1308,41 +1308,40 @@ StripElem *BKE_sequencer_give_stripelem(Sequence *seq, int cfra) static int evaluate_seq_frame_gen(Sequence **seq_arr, ListBase *seqbase, int cfra, int chanshown) { - Sequence *seq; - Sequence *effect_inputs[MAXSEQ + 1]; - int i, totseq = 0, num_effect_inputs = 0; + /* Use arbitrary sized linked list, the size could be over MAXSEQ. */ + LinkNodePair effect_inputs = {NULL, NULL}; + int totseq = 0; memset(seq_arr, 0, sizeof(Sequence *) * (MAXSEQ + 1)); - seq = seqbase->first; - while (seq) { - if (seq->startdisp <= cfra && seq->enddisp > cfra) { + for (Sequence *seq = seqbase->first; seq; seq = seq->next) { + if ((seq->startdisp <= cfra) && (seq->enddisp > cfra)) { if ((seq->type & SEQ_TYPE_EFFECT) && !(seq->flag & SEQ_MUTE)) { + if (seq->seq1) { - effect_inputs[num_effect_inputs++] = seq->seq1; + BLI_linklist_append_alloca(&effect_inputs, seq->seq1); } if (seq->seq2) { - effect_inputs[num_effect_inputs++] = seq->seq2; + BLI_linklist_append_alloca(&effect_inputs, seq->seq2); } if (seq->seq3) { - effect_inputs[num_effect_inputs++] = seq->seq3; + BLI_linklist_append_alloca(&effect_inputs, seq->seq3); } } seq_arr[seq->machine] = seq; totseq++; } - seq = seq->next; } /* Drop strips which are used for effect inputs, we don't want * them to blend into render stack in any other way than effect * string rendering. */ - for (i = 0; i < num_effect_inputs; i++) { - seq = effect_inputs[i]; + for (LinkNode *seq_item = effect_inputs.list; seq_item; seq_item = seq_item->next) { + Sequence *seq = seq_item->link; /* It's possible that effetc strip would be placed to the same * 'machine' as it's inputs. We don't want to clear such strips * from the stack. @@ -1826,8 +1825,10 @@ static void seq_proxy_build_frame( IMB_freeImBuf(ibuf); } -/* returns whether the file this context would read from even exist, if not, don't create the context -*/ +/** + * Returns whether the file this context would read from even exist, + * if not, don't create the context + */ static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, const int view_id) { if ((scene->r.scemode & R_MULTIVIEW) == 0) @@ -1862,8 +1863,9 @@ static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, con return false; } -/** This returns the maximum possible number of required contexts -*/ +/** + * This returns the maximum possible number of required contexts + */ static int seq_proxy_context_count(Sequence *seq, Scene *scene) { int num_views = 1; diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c index a91d8657179..c027f3b38ca 100644 --- a/source/blender/blenkernel/intern/speaker.c +++ b/source/blender/blenkernel/intern/speaker.c @@ -85,11 +85,11 @@ Speaker *BKE_speaker_copy(Main *bmain, Speaker *spk) return spkn; } -void BKE_speaker_make_local(Main *bmain, Speaker *spk) +void BKE_speaker_make_local(Main *bmain, Speaker *spk, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -100,7 +100,7 @@ void BKE_speaker_make_local(Main *bmain, Speaker *spk) BKE_library_ID_test_usages(bmain, spk, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &spk->id); BKE_id_expand_local(&spk->id); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index b0d19320230..f73dbd8078f 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -3472,7 +3472,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, if (!flush && compareDrawOptions) { /* also compare draw options and flush buffer if they're different - * need for face selection highlight in edit mode */ + * need for face selection highlight in edit mode */ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0; } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index dcd60aaa702..155c7f04e53 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -917,11 +917,11 @@ Tex *BKE_texture_localize(Tex *tex) /* ------------------------------------------------------------------------- */ -void BKE_texture_make_local(Main *bmain, Tex *tex) +void BKE_texture_make_local(Main *bmain, Tex *tex, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -932,7 +932,7 @@ void BKE_texture_make_local(Main *bmain, Tex *tex) BKE_library_ID_test_usages(bmain, tex, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &tex->id); BKE_id_expand_local(&tex->id); diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 9795a8174f8..277aeaa7e42 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -176,11 +176,11 @@ World *localize_world(World *wrld) return wrldn; } -void BKE_world_make_local(Main *bmain, World *wrld) +void BKE_world_make_local(Main *bmain, World *wrld, const bool force_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ @@ -191,7 +191,7 @@ void BKE_world_make_local(Main *bmain, World *wrld) BKE_library_ID_test_usages(bmain, wrld, &is_local, &is_lib); - if (is_local) { + if (force_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &wrld->id); BKE_id_expand_local(&wrld->id); diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index b4a465bbc74..0b1b4d8ee8c 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -42,7 +42,7 @@ extern "C" { #endif /* for tables, button in UI, etc */ -#define BLENDER_MAX_THREADS 64 +#define BLENDER_MAX_THREADS 1024 struct ListBase; struct TaskScheduler; diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index 4bd404e5d73..d48e9fbddde 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -32,7 +32,6 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" -#include "BLI_memarena.h" #include "BLI_heap.h" #include "BLI_strict_flags.h" @@ -44,15 +43,37 @@ struct HeapNode { unsigned int index; }; +struct HeapNode_Chunk { + struct HeapNode_Chunk *prev; + unsigned int size; + unsigned int bufsize; + struct HeapNode buf[0]; +}; + +/** + * Number of nodes to include per #HeapNode_Chunk when no reserved size is passed, + * or we allocate past the reserved number. + * + * \note Optimize number for 64kb allocs. + */ +#define HEAP_CHUNK_DEFAULT_NUM \ + ((MEM_SIZE_OPTIMAL((1 << 16) - sizeof(struct HeapNode_Chunk))) / sizeof(HeapNode)) + struct Heap { unsigned int size; unsigned int bufsize; - MemArena *arena; - HeapNode *freenodes; HeapNode **tree; + + struct { + /* Always keep at least one chunk (never NULL) */ + struct HeapNode_Chunk *chunk; + /* when NULL, allocate a new chunk */ + HeapNode *free; + } nodes; }; -/* internal functions */ +/** \name Internal Functions + * \{ */ #define HEAP_PARENT(i) (((i) - 1) >> 1) #define HEAP_LEFT(i) (((i) << 1) + 1) @@ -92,11 +113,13 @@ static void heap_down(Heap *heap, unsigned int i) smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i])) ? l : i; - if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest])) + if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest])) { smallest = r; + } - if (smallest == i) + if (smallest == i) { break; + } heap_swap(heap, i, smallest); i = smallest; @@ -108,25 +131,74 @@ static void heap_up(Heap *heap, unsigned int i) while (i > 0) { const unsigned int p = HEAP_PARENT(i); - if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) + if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) { break; - + } heap_swap(heap, p, i); i = p; } } +/** \} */ -/***/ + +/** \name Internal Memory Management + * \{ */ + +static struct HeapNode_Chunk *heap_node_alloc_chunk( + unsigned int tot_nodes, struct HeapNode_Chunk *chunk_prev) +{ + struct HeapNode_Chunk *chunk = MEM_mallocN( + sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * tot_nodes), __func__); + chunk->prev = chunk_prev; + chunk->bufsize = tot_nodes; + chunk->size = 0; + return chunk; +} + +static struct HeapNode *heap_node_alloc(Heap *heap) +{ + HeapNode *node; + + if (heap->nodes.free) { + node = heap->nodes.free; + heap->nodes.free = heap->nodes.free->ptr; + } + else { + struct HeapNode_Chunk *chunk = heap->nodes.chunk; + if (UNLIKELY(chunk->size == chunk->bufsize)) { + struct HeapNode_Chunk *chunk_next = heap_node_alloc_chunk(HEAP_CHUNK_DEFAULT_NUM, chunk); + chunk = chunk_next; + } + node = &chunk->buf[chunk->size++]; + } + + return node; +} + +static void heap_node_free(Heap *heap, HeapNode *node) +{ + node->ptr = heap->nodes.free; + heap->nodes.free = node; +} + +/** \} */ + + +/** \name Public Heap API + * \{ */ /* use when the size of the heap is known in advance */ Heap *BLI_heap_new_ex(unsigned int tot_reserve) { - Heap *heap = (Heap *)MEM_callocN(sizeof(Heap), __func__); + Heap *heap = MEM_mallocN(sizeof(Heap), __func__); /* ensure we have at least one so we can keep doubling it */ + heap->size = 0; heap->bufsize = MAX2(1u, tot_reserve); - heap->tree = (HeapNode **)MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); - heap->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "heap arena"); + heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); + + heap->nodes.chunk = heap_node_alloc_chunk((tot_reserve > 1) ? tot_reserve : HEAP_CHUNK_DEFAULT_NUM, NULL); + heap->nodes.free = NULL; return heap; } @@ -146,8 +218,15 @@ void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) } } + struct HeapNode_Chunk *chunk = heap->nodes.chunk; + do { + struct HeapNode_Chunk *chunk_prev; + chunk_prev = chunk->prev; + MEM_freeN(chunk); + chunk = chunk_prev; + } while (chunk); + MEM_freeN(heap->tree); - BLI_memarena_free(heap->arena); MEM_freeN(heap); } @@ -160,10 +239,16 @@ void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp) ptrfreefp(heap->tree[i]->ptr); } } - heap->size = 0; - BLI_memarena_clear(heap->arena); - heap->freenodes = NULL; + + /* Remove all except the last chunk */ + while (heap->nodes.chunk->prev) { + struct HeapNode_Chunk *chunk_prev = heap->nodes.chunk->prev; + MEM_freeN(heap->nodes.chunk); + heap->nodes.chunk = chunk_prev; + } + heap->nodes.chunk->size = 0; + heap->nodes.free = NULL; } HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) @@ -175,13 +260,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree)); } - if (heap->freenodes) { - node = heap->freenodes; - heap->freenodes = heap->freenodes->ptr; - } - else { - node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof(*node)); - } + node = heap_node_alloc(heap); node->ptr = ptr; node->value = value; @@ -217,8 +296,7 @@ void *BLI_heap_popmin(Heap *heap) BLI_assert(heap->size != 0); - heap->tree[0]->ptr = heap->freenodes; - heap->freenodes = heap->tree[0]; + heap_node_free(heap, heap->tree[0]); if (--heap->size) { heap_swap(heap, 0, heap->size); @@ -254,3 +332,4 @@ void *BLI_heap_node_ptr(HeapNode *node) return node->ptr; } +/** \} */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 5d0de6526b6..a7c625b0842 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -907,7 +907,10 @@ static void decode_blender_header(FileData *fd) } } -static int read_file_dna(FileData *fd) +/** + * \return Success if the file is read correctly, else set \a r_error_message. + */ +static bool read_file_dna(FileData *fd, const char **r_error_message) { BHead *bhead; @@ -915,20 +918,25 @@ static int read_file_dna(FileData *fd) if (bhead->code == DNA1) { const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0; - fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap, true); + fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap, true, r_error_message); if (fd->filesdna) { fd->compflags = DNA_struct_get_compareflags(fd->filesdna, fd->memsdna); /* used to retrieve ID names from (bhead+1) */ fd->id_name_offs = DNA_elem_offset(fd->filesdna, "ID", "char", "name[]"); + + return true; + } + else { + return false; } - return 1; } else if (bhead->code == ENDB) break; } - return 0; + *r_error_message = "Missing DNA block"; + return false; } static int *read_file_thumbnail(FileData *fd) @@ -1070,13 +1078,9 @@ static FileData *filedata_new(void) fd->filedes = -1; fd->gzfiledes = NULL; - - /* XXX, this doesn't need to be done all the time, - * but it keeps us re-entrant, remove once we have - * a lib that provides a nice lock. - zr - */ - fd->memsdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false); - + + fd->memsdna = DNA_sdna_current_get(); + fd->datamap = oldnewmap_new(); fd->globmap = oldnewmap_new(); fd->libmap = oldnewmap_new(); @@ -1089,8 +1093,11 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports) decode_blender_header(fd); if (fd->flags & FD_FLAGS_FILE_OK) { - if (!read_file_dna(fd)) { - BKE_reportf(reports, RPT_ERROR, "Failed to read blend file '%s', incomplete", fd->relabase); + const char *error_message = NULL; + if (read_file_dna(fd, &error_message) == false) { + BKE_reportf(reports, RPT_ERROR, + "Failed to read blend file '%s': %s", + fd->relabase, error_message); blo_freefiledata(fd); fd = NULL; } @@ -1267,9 +1274,7 @@ void blo_freefiledata(FileData *fd) // Free all BHeadN data blocks BLI_freelistN(&fd->listbase); - - if (fd->memsdna) - DNA_sdna_free(fd->memsdna); + if (fd->filesdna) DNA_sdna_free(fd->filesdna); if (fd->compflags) @@ -1842,7 +1847,7 @@ void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd) /* ********** END OLD POINTERS ****************** */ /* ********** READ FILE ****************** */ -static void switch_endian_structs(struct SDNA *filesdna, BHead *bhead) +static void switch_endian_structs(const struct SDNA *filesdna, BHead *bhead) { int blocksize, nblocks; char *data; @@ -2137,6 +2142,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p } prv->gputexture[i] = NULL; } + prv->icon_id = 0; } return prv; @@ -2705,7 +2711,7 @@ static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } -/* singe node tree (also used for material/scene trees), ntree is not NULL */ +/* Single node tree (also used for material/scene trees), ntree is not NULL */ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree) { bNode *node; @@ -2748,22 +2754,6 @@ static void lib_link_nodetree(FileData *fd, Main *main) } } -/* get node tree stored locally in other IDs */ -static bNodeTree *nodetree_from_id(ID *id) -{ - if (!id) - return NULL; - switch (GS(id->name)) { - case ID_SCE: return ((Scene *)id)->nodetree; - case ID_MA: return ((Material *)id)->nodetree; - case ID_WO: return ((World *)id)->nodetree; - case ID_LA: return ((Lamp *)id)->nodetree; - case ID_TE: return ((Tex *)id)->nodetree; - case ID_LS: return ((FreestyleLineStyle *)id)->nodetree; - } - return NULL; -} - /* updates group node socket identifier so that * external links to/from the group node are preserved. */ @@ -5957,11 +5947,9 @@ static void lib_link_screen(FileData *fd, Main *main) snode->id = newlibadr(fd, sc->id.lib, snode->id); snode->from = newlibadr(fd, sc->id.lib, snode->from); - ntree = nodetree_from_id(snode->id); - if (ntree) - snode->nodetree = ntree; - else { - snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree); + if (snode->id) { + ntree = ntreeFromID(snode->id); + snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree); } for (path = snode->treepath.first; path; path = path->next) { @@ -6341,11 +6329,11 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc snode->id = restore_pointer_by_name(id_map, snode->id, USER_REAL); snode->from = restore_pointer_by_name(id_map, snode->from, USER_IGNORE); - ntree = nodetree_from_id(snode->id); - if (ntree) - snode->nodetree = ntree; - else - snode->nodetree = restore_pointer_by_name(id_map, (ID*)snode->nodetree, USER_REAL); + if (snode->id) { + ntree = ntreeFromID(snode->id); + snode->nodetree = ntree ? ntree : + restore_pointer_by_name(id_map, (ID *)snode->nodetree, USER_REAL); + } for (path = snode->treepath.first; path; path = path->next) { if (path == snode->treepath.first) { diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 42728fd406f..b054cd0031d 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -74,7 +74,7 @@ typedef struct FileData { // general reading variables struct SDNA *filesdna; - struct SDNA *memsdna; + const struct SDNA *memsdna; char *compflags; /* array of eSDNA_StructCompare */ int fileversion; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index d631e1507e3..81b61f399c9 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1130,5 +1130,18 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "float", "double_threshold")) { + Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + ModifierData *md; + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Boolean) { + BooleanModifierData *bmd = (BooleanModifierData *)md; + bmd->double_threshold = 1e-6f; + } + } + } + } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 9c7aa87f3cc..c9f4858e545 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -301,7 +301,7 @@ static void ww_handle_init(eWriteWrapType ww_type, WriteWrap *r_ww) typedef struct { - struct SDNA *sdna; + const struct SDNA *sdna; unsigned char *buf; MemFile *compare, *current; @@ -323,7 +323,7 @@ static WriteData *writedata_new(WriteWrap *ww) { WriteData *wd = MEM_callocN(sizeof(*wd), "writedata"); - wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false); + wd->sdna = DNA_sdna_current_get(); wd->ww = ww; @@ -355,8 +355,6 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen) static void writedata_free(WriteData *wd) { - DNA_sdna_free(wd->sdna); - MEM_freeN(wd->buf); MEM_freeN(wd); } @@ -2042,7 +2040,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase) mesh->edit_btmesh = NULL; /* now fill in polys to mfaces */ - /* XXX This breaks writing desing, by using temp allocated memory, which will likely generate + /* XXX This breaks writing design, by using temp allocated memory, which will likely generate * duplicates in stored 'old' addresses. * This is very bad, but do not see easy way to avoid this, aside from generating those data * outside of save process itself. diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c index 3eb6fe0cb97..241086fbf02 100644 --- a/source/blender/bmesh/operators/bmo_connect_pair.c +++ b/source/blender/bmesh/operators/bmo_connect_pair.c @@ -125,7 +125,7 @@ typedef struct PathLinkState { /** \name Min Dist Dir Util - + * * Simply getting the closest intersecting vert/edge is _not_ good enough. see T43792 * we need to get the closest in both directions since the absolute closest may be a dead-end. * diff --git a/source/blender/bmesh/operators/bmo_normals.c b/source/blender/bmesh/operators/bmo_normals.c index f0738303d5c..73dbee25be3 100644 --- a/source/blender/bmesh/operators/bmo_normals.c +++ b/source/blender/bmesh/operators/bmo_normals.c @@ -86,7 +86,7 @@ static int recalc_face_normals_find_index(BMesh *bm, BMFace **faces, const int f int f_start_index; int i; - /* Search for the best loop. Members are comapred in-order defined here. */ + /* Search for the best loop. Members are compared in-order defined here. */ struct { /* Squared distance from the center to the loops vertex 'l->v'. * The normalized direction between the center and this vertex is also used for the dot-products below. */ diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index f06f299d381..226f319cefd 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -904,6 +904,7 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia i++; } } + // EMISSION // color if (ef->getEmission().isColor()) { @@ -919,8 +920,22 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia i++; } } - - if (ef->getOpacity().isTexture()) { + + // TRANSPARENT + // color + if (ef->getOpacity().isColor()) { + col = ef->getTransparent().getColor(); + float alpha = ef->getTransparency().getFloatValue(); + if (col.isValid()) { + alpha *= col.getAlpha(); // Assuming A_ONE opaque mode + } + if (col.isValid() || alpha < 1.0) { + ma->alpha = alpha; + ma->mode |= MA_ZTRANSP | MA_TRANSP; + } + } + // texture + else if (ef->getOpacity().isTexture()) { COLLADAFW::Texture ctex = ef->getOpacity().getTexture(); mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); if (mtex != NULL) { @@ -930,22 +945,7 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia ma->mode |= MA_ZTRANSP | MA_TRANSP; } } - // TRANSPARENT - // color -#if 0 - if (ef->getOpacity().isColor()) { - // XXX don't know what to do here - } - // texture - else if (ef->getOpacity().isTexture()) { - ctex = ef->getOpacity().getTexture(); - if (mtex != NULL) mtex->mapto &= MAP_ALPHA; - else { - mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); - if (mtex != NULL) mtex->mapto = MAP_ALPHA; - } - } -#endif + material_texture_mapping_map[ma] = texindex_texarray_map; } diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 13dc1eda580..76b51148509 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -30,6 +30,7 @@ #include <set> #include "COLLADASWEffectProfile.h" +#include "COLLADAFWColorOrTexture.h" #include "EffectExporter.h" #include "DocumentExporter.h" @@ -217,9 +218,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob) // transparency if (ma->mode & MA_TRANSP) { // Tod: because we are in A_ONE mode transparency is calculated like this: - ep.setTransparency(ma->alpha, false, "transparency"); - // cot = getcol(1.0f, 1.0f, 1.0f, 1.0f); - // ep.setTransparent(cot); + cot = getcol(1.0f, 1.0f, 1.0f, ma->alpha); + ep.setTransparent(cot); + ep.setOpaque(COLLADASW::EffectProfile::A_ONE); } // emission diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp index b271604f839..98aa85f8a9b 100644 --- a/source/blender/collada/ErrorHandler.cpp +++ b/source/blender/collada/ErrorHandler.cpp @@ -79,7 +79,7 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) COLLADASaxFWL::SaxFWLError *saxFWLError = (COLLADASaxFWL::SaxFWLError *) error; /* * Accept non critical errors as warnings (i.e. texture not found) - * This makes the importer more gracefull, so it now imports what makes sense. + * This makes the importer more graceful, so it now imports what makes sense. */ if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) { isError = false; diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 649c86edd25..abe5130b9c1 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -539,8 +539,8 @@ void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::str } /* If numeric layers and labeled layers are used in parallel (unlikely), - we get a potential mixup. Just leave as is for now. - */ + * we get a potential mixup. Just leave as is for now. + */ this->bone_layers = bc_set_layer(this->bone_layers, pos); } diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index d6e5fdf86bb..caafdfe8f0c 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -1,5 +1,4 @@ /* - * Copyright 2012, Blender Foundation. * * This program is free software; you can redistribute it and/or diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 6bf9dbe3e54..9364c86196e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -294,15 +294,16 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene) for (Base *base = (Base *)scene->base.first; base; base = base->next) { Object *ob = base->object; + /* object itself */ + build_object(scene, base, ob); + /* object that this is a proxy for */ // XXX: the way that proxies work needs to be completely reviewed! if (ob->proxy) { ob->proxy->proxy_from = ob; + build_object(scene, base, ob->proxy); } - /* object itself */ - build_object(scene, base, ob); - /* Object dupligroup. */ if (ob->dup_group) { build_group(scene, base, ob->dup_group); @@ -395,12 +396,12 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) { if (ob->id.tag & LIB_TAG_DOIT) { IDDepsNode *id_node = m_graph->find_id_node(&ob->id); - id_node->layers = base->lay; + id_node->layers |= base->lay; return; } IDDepsNode *id_node = add_id_node(&ob->id); - id_node->layers = base->lay; + id_node->layers |= base->lay; ob->customdata_mask = 0; /* standard components */ @@ -439,7 +440,7 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) } case OB_ARMATURE: /* Pose */ - if (ob->id.lib != NULL && ob->proxy_from != NULL) { + if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from != NULL) { build_proxy_rig(ob); } else { @@ -478,12 +479,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) if (ob->gpd) { build_gpencil(ob->gpd); } - - if (ob->proxy != NULL) { - add_operation_node(&ob->id, DEPSNODE_TYPE_PROXY, DEPSOP_TYPE_POST, - function_bind(BKE_object_eval_proxy_backlink, _1, ob), - DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); - } } void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 9ca42e1e7d5..72005880161 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -264,18 +264,12 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) for (Base *base = (Base *)scene->base.first; base; base = base->next) { Object *ob = base->object; - /* Object that this is a proxy for. - * Just makes sure backlink is correct. - */ - if (ob->proxy) { - ob->proxy->proxy_from = ob; - } - /* object itself */ build_object(bmain, scene, ob); /* object that this is a proxy for */ if (ob->proxy) { + ob->proxy->proxy_from = ob; build_object(bmain, scene, ob->proxy); /* TODO(sergey): This is an inverted relation, matches old depsgraph * behavior and need to be investigated if it still need to be inverted. @@ -439,7 +433,7 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o } case OB_ARMATURE: /* Pose */ - if (ob->id.lib != NULL && ob->proxy_from != NULL) { + if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from != NULL) { build_proxy_rig(ob); } else { @@ -919,6 +913,12 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) } } else { + if (dtar->id == id) { + /* Ignore input dependency if we're driving properties of the same ID, + * otherwise we'll be ending up in a cyclic dependency here. + */ + continue; + } /* resolve path to get node */ RNAPathKey target_key(dtar->id, dtar->rna_path ? dtar->rna_path : ""); add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[RNA Target -> Driver]"); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 9ba0b61a4f1..f9e1504b3ce 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -85,9 +85,6 @@ static void flush_init_func(void *data_v, int i) id_node->done = 0; comp_node->done = 0; node->scheduled = false; - if (comp_node->type == DEPSNODE_TYPE_PROXY) { - node->flag |= DEPSOP_FLAG_NEEDS_UPDATE; - } } /* Flush updates from tagged nodes outwards until all affected nodes diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc index 12d5ee00a63..db807d22b89 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node.cc @@ -181,6 +181,11 @@ void IDDepsNode::init(const ID *id, const string &UNUSED(subdata)) this->layers = (1 << 20) - 1; this->eval_flags = 0; + /* For object we initialize layers to layer from base. */ + if (GS(id) == ID_OB) { + this->layers = 0; + } + components = BLI_ghash_new(id_deps_node_hash_key, id_deps_node_hash_key_cmp, "Depsgraph id components hash"); diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 6306926e0b2..6979a324b69 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -424,7 +424,9 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone for (curBone = bones->first; curBone; curBone = curBone->next) { eBone = MEM_callocN(sizeof(EditBone), "make_editbone"); - /* Copy relevant data from bone to eBone */ + /* Copy relevant data from bone to eBone + * Keep selection logic in sync with ED_armature_sync_selection. + */ eBone->parent = parent; BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name)); eBone->flag = curBone->flag; @@ -435,11 +437,11 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone eBone->flag |= BONE_TIPSEL; if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { eBone->parent->flag |= BONE_TIPSEL; - eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */ - } - else { - eBone->flag |= BONE_ROOTSEL; } + + /* For connected bones, take care when changing the selection when we have a connected parent, + * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */ + eBone->flag |= BONE_ROOTSEL; } else { /* if the bone is not selected, but connected to its parent diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 81e2558e765..602e203a381 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -325,18 +325,18 @@ bool ANIM_driver_vars_paste(struct ReportList *reports, struct FCurve *fcu, bool /* Notes: * - All the defines for this (User-Pref settings and Per-Scene settings) * are defined in DNA_userdef_types.h - * - Scene settings take presidence over those for userprefs, with old files + * - Scene settings take precedence over those for userprefs, with old files * inheriting userpref settings for the scene settings * - "On/Off + Mode" are stored per Scene, but "settings" are currently stored * as userprefs */ /* Auto-Keying macros for use by various tools */ -/* check if auto-keyframing is enabled (per scene takes presidence) */ +/* check if auto-keyframing is enabled (per scene takes precedence) */ #define IS_AUTOKEY_ON(scene) ((scene) ? (scene->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON)) -/* check the mode for auto-keyframing (per scene takes presidence) */ +/* check the mode for auto-keyframing (per scene takes precedence) */ #define IS_AUTOKEY_MODE(scene, mode) ((scene) ? (scene->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode)) -/* check if a flag is set for auto-keyframing (per scene takes presidence) */ +/* check if a flag is set for auto-keyframing (per scene takes precedence) */ #define IS_AUTOKEY_FLAG(scene, flag) \ ((scene) ? \ ((scene->toolsettings->autokey_flag & AUTOKEY_FLAG_##flag) || (U.autokey_flag & AUTOKEY_FLAG_##flag)) \ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index b09284aa759..48c1e2d1996 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -208,6 +208,7 @@ eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const fl eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); +bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]); bool ED_view3d_win_to_ray( const struct ARegion *ar, const struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3], const bool do_clip); @@ -218,6 +219,7 @@ void ED_view3d_global_to_vector(const struct RegionView3D *rv3d, const float coo void ED_view3d_win_to_3d(const struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]); void ED_view3d_win_to_3d_int(const struct ARegion *ar, const float depth_pt[3], const int mval[2], float out[3]); void ED_view3d_win_to_delta(const struct ARegion *ar, const float mval[2], float out[3], const float zfac); +void ED_view3d_win_to_origin(const struct ARegion *ar, const float mval[2], float out[3]); void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], float out[3]); bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_end[3], const bool do_clip); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index ba7240be5d8..cbe8654ceb6 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1138,7 +1138,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but, * as new items are added to the menu later on. It also optimises efficiency - * a radial menu is best kept symmetrical, with as large an angle between * items as possible, so that the gestural mouse movements can be fast and inexact. - + * * It starts off with two opposite sides for the first two items * then joined by the one below for the third (this way, even with three items, * the menu seems to still be 'in order' reading left to right). Then the fourth is diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 0a0ecf93d17..11703208b2a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1057,7 +1057,9 @@ static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block) } } -static bool ui_multibut_states_tag(uiBut *but_active, uiHandleButtonData *data, const wmEvent *event) +static bool ui_multibut_states_tag( + uiBut *but_active, + uiHandleButtonData *data, const wmEvent *event) { uiBut *but; float seg[2][2]; @@ -1668,7 +1670,9 @@ static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent return BLI_rcti_isect_pt(&rect, x, y); } -static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static bool ui_but_drag_init( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { /* prevent other WM gestures to start while we try to drag */ WM_gestures_remove(C); @@ -1740,11 +1744,16 @@ static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data, } } else { - wmDrag *drag; + wmDrag *drag = WM_event_start_drag( + C, but->icon, but->dragtype, but->dragpoin, + ui_but_value_get(but), WM_DRAG_NOP); - drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_but_value_get(but), WM_DRAG_NOP); - if (but->imb) - WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect)); + if (but->imb) { + WM_event_drag_image( + drag, but->imb, but->imb_scale, + BLI_rctf_size_x(&but->rect), + BLI_rctf_size_y(&but->rect)); + } } return true; } @@ -1872,11 +1881,15 @@ static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to) /* (3) add a new controller */ if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, &props_ptr) & OPERATOR_FINISHED) { cont = (bController *)ob->controllers.last; - cont->type = CONT_LOGIC_AND; /* Quick fix to make sure we always have an AND controller. It might be nicer to make sure the operator gives us the right one though... */ + /* Quick fix to make sure we always have an AND controller. + * It might be nicer to make sure the operator gives us the right one though... */ + cont->type = CONT_LOGIC_AND; /* (4) link the sensor->controller->actuator */ tmp_but = MEM_callocN(sizeof(uiBut), "uiBut"); - UI_but_link_set(tmp_but, (void **)&cont, (void ***)&(cont->links), &(cont->totlinks), from->link->tocode, (int)to->hardmin); + UI_but_link_set( + tmp_but, (void **)&cont, (void ***)&(cont->links), + &cont->totlinks, from->link->tocode, (int)to->hardmin); tmp_but->hardmin = from->link->tocode; tmp_but->poin = (char *)cont; @@ -3180,7 +3193,9 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa } -static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static void ui_do_but_textedit( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int retval = WM_UI_HANDLER_CONTINUE; bool changed = false, inbox = false, update = false; @@ -3233,7 +3248,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle if (data->searchbox) inbox = ui_searchbox_inside(data->searchbox, event->x, event->y); - /* for double click: we do a press again for when you first click on button (selects all text, no cursor pos) */ + /* for double click: we do a press again for when you first click on button + * (selects all text, no cursor pos) */ if (event->val == KM_PRESS || event->val == KM_DBL_CLICK) { float mx, my; @@ -3477,7 +3493,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle ED_region_tag_redraw(data->region); } -static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static void ui_do_but_textedit_select( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my, retval = WM_UI_HANDLER_CONTINUE; @@ -3682,7 +3700,9 @@ static uiBut *ui_but_list_row_text_activate( /* ***************** events for different button types *************** */ -static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_BUT( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (event->type == LEFTMOUSE && event->val == KM_PRESS) { @@ -3713,7 +3733,9 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_HOTKEYEVT( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { @@ -3776,7 +3798,9 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_KEYEVT( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { @@ -3802,7 +3826,9 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_TEX( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) { @@ -3830,7 +3856,9 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_SEARCH_UNLINK( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { uiButExtraIconType extra_icon_type; @@ -3877,7 +3905,9 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa return ui_do_but_TEX(C, block, but, data, event); } -static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_TOG( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { #ifdef USE_DRAG_TOGGLE if (data->state == BUTTON_STATE_HIGHLIGHT) { @@ -3944,7 +3974,9 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_EXIT( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { @@ -4092,7 +4124,7 @@ static float ui_numedit_apply_snap( static bool ui_numedit_but_NUM( uiBut *but, uiHandleButtonData *data, - int mx, + int mx, const bool is_motion, const enum eSnapType snap, float fac) { float deler, tempf, softmin, softmax, softrange; @@ -4100,8 +4132,10 @@ static bool ui_numedit_but_NUM( bool changed = false; const bool is_float = ui_but_is_float(but); - /* prevent unwanted drag adjustments */ - if (ui_but_dragedit_update_mval(data, mx) == false) { + /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */ + if ((is_motion || data->draglock) && + (ui_but_dragedit_update_mval(data, mx) == false)) + { return changed; } @@ -4242,7 +4276,9 @@ static bool ui_numedit_but_NUM( return changed; } -static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_NUM( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; /* mouse location scaled to fit the UI */ int screen_mx, screen_my; /* mouse location kept at screen pixel coords */ @@ -4324,6 +4360,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } } else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) { + const bool is_motion = (event->type == MOUSEMOVE); const enum eSnapType snap = ui_event_to_snap(event); float fac; @@ -4335,8 +4372,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton fac = 1.0f; if (event->shift) fac /= 10.0f; - if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), snap, fac)) + if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), is_motion, snap, fac)) { ui_numedit_apply(C, block, but, data); + } #ifdef USE_DRAG_MULTINUM else if (data->multi_data.has_mbuts) { if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) { @@ -4430,7 +4468,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton static bool ui_numedit_but_SLI( uiBut *but, uiHandleButtonData *data, - int mx, const bool is_horizontal, + int mx, const bool is_horizontal, const bool is_motion, const bool snap, const bool shift) { float deler, f, tempf, softmin, softmax, softrange; @@ -4440,8 +4478,9 @@ static bool ui_numedit_but_SLI( /* note, 'offs' is really from the widget drawing rounded corners see 'widget_numslider' */ float offs; - /* prevent unwanted drag adjustments */ + /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */ if ((but->type != UI_BTYPE_SCROLL) && + (is_motion || data->draglock) && (ui_but_dragedit_update_mval(data, mx) == false)) { return changed; @@ -4541,7 +4580,9 @@ static bool ui_numedit_but_SLI( return changed; } -static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_SLI( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my, click = 0; int retval = WM_UI_HANDLER_CONTINUE; @@ -4634,12 +4675,14 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } } else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) { + const bool is_motion = (event->type == MOUSEMOVE); #ifdef USE_DRAG_MULTINUM data->multi_data.drag_dir[0] += abs(data->draglastx - mx); data->multi_data.drag_dir[1] += abs(data->draglasty - my); #endif - if (ui_numedit_but_SLI(but, data, mx, true, event->ctrl != 0, event->shift != 0)) + if (ui_numedit_but_SLI(but, data, mx, true, is_motion, event->ctrl != 0, event->shift != 0)) { ui_numedit_apply(C, block, but, data); + } #ifdef USE_DRAG_MULTINUM else if (data->multi_data.has_mbuts) { @@ -4722,7 +4765,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton return retval; } -static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_SCROLL( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my /*, click = 0 */; int retval = WM_UI_HANDLER_CONTINUE; @@ -4765,8 +4810,10 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { - if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, false, false)) + const bool is_motion = (event->type == MOUSEMOVE); + if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, is_motion, false, false)) { ui_numedit_apply(C, block, but, data); + } } retval = WM_UI_HANDLER_BREAK; @@ -4775,7 +4822,9 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut return retval; } -static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_GRIP( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; int retval = WM_UI_HANDLER_CONTINUE; @@ -4826,7 +4875,9 @@ static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButto return retval; } -static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_LISTROW( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { /* hack to pass on ctrl+click and double click to overlapping text @@ -4846,7 +4897,9 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, return ui_do_but_EXIT(C, but, data, event); } -static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_BLOCK( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { @@ -5021,7 +5074,9 @@ static void ui_palette_set_active(uiBut *but) } } -static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_COLOR( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { /* first handle click on icondrag type button */ @@ -5154,7 +5209,9 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_UNITVEC(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_UNITVEC( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -5431,7 +5488,9 @@ static void ui_ndofedit_but_HSVCUBE( ui_but_v3_set(but, data->vec); } -static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_HSVCUBE( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -5693,7 +5752,9 @@ static void ui_ndofedit_but_HSVCIRCLE( } -static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_HSVCIRCLE( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; @@ -5821,7 +5882,9 @@ static bool ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int m return changed; } -static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_COLORBAND( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { ColorBand *coba; CBData *cbd; @@ -5997,7 +6060,9 @@ static bool ui_numedit_but_CURVE( return changed; } -static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_CURVE( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my, a; bool changed = false; @@ -6165,7 +6230,9 @@ static bool ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int m return changed; } -static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_HISTOGRAM( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -6238,7 +6305,9 @@ static bool ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx return changed; } -static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_WAVEFORM( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -6292,7 +6361,9 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_LINK( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { VECCOPY2D(but->linkto, event->mval); @@ -6355,7 +6426,9 @@ static bool ui_numedit_but_TRACKPREVIEW( return changed; } -static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_TRACKPREVIEW( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -6851,7 +6924,8 @@ static bool ui_but_menu(bContext *C, uiBut *but) WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), + uiItemFullO(layout, "WM_OT_doc_view", + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); /* XXX inactive option, not for public! */ @@ -6860,7 +6934,8 @@ static bool ui_but_menu(bContext *C, uiBut *but) RNA_string_set(&ptr_props, "doc_id", buf); RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); - uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); + uiItemFullO(layout, "WM_OT_doc_edit", + "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); #endif } } @@ -7440,7 +7515,8 @@ static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y) /** * Can we mouse over the button or is it hidden/disabled/layout. - * Note: ctrl is kind of a hack currently, so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed. + * \note ctrl is kind of a hack currently, + * so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed. */ static bool ui_but_is_interactive(const uiBut *but, const bool labeledit) { @@ -7634,7 +7710,9 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s if (but->block->auto_open == true) { /* test for toolbox */ time = 1; } - else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) || but->block->auto_open == true) { + else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) || + (but->block->auto_open == true)) + { time = 5 * U.menuthreshold2; } else if (U.uiflag & USER_MENUOPENAUTO) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index c1d7a9ada96..3660160a98c 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1061,6 +1061,9 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) } } +static void ui_id_preview_image_render_size( + const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job); + void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big) { Icon *icon = BKE_icon_get(icon_id); @@ -1076,22 +1079,19 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi } if (di) { - if (di->type == ICON_TYPE_PREVIEW) { - PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; - - if (prv) { - const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; - - if (!prv->use_deferred || prv->rect[size] || (prv->flag[size] & PRV_USER_EDITED)) { - return; + switch (di->type) { + case ICON_TYPE_PREVIEW: + { + ID *id = (icon->type != 0) ? icon->obj : NULL; + PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj; + + if (prv) { + const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; + + if (id || prv->use_deferred) { + ui_id_preview_image_render_size(C, NULL, id, prv, size, true); + } } - - icon_create_rect(prv, size); - - /* Always using job (background) version. */ - ED_preview_icon_job(C, prv, NULL, prv->rect[size], prv->w[size], prv->h[size]); - - prv->flag[size] &= ~PRV_CHANGED; } } } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 01b10b7b032..1af6d902b18 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -416,7 +416,7 @@ bool UI_context_copy_to_selected_list( if ((id_data == NULL) || (id_data->tag & LIB_TAG_DOIT) == 0 || - ID_IS_LINKED_DATABLOCK(id_data->lib) || + ID_IS_LINKED_DATABLOCK(id_data) || (GS(id_data->name) != id_code)) { BLI_remlink(&lb, link); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 575b32e81e8..d4205c50ddc 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -110,7 +110,7 @@ bool ui_but_menu_step_poll(const uiBut *but) { BLI_assert(but->type == UI_BTYPE_MENU); - /* currenly only RNA buttons */ + /* currently only RNA buttons */ return ((but->menu_step_func != NULL) || (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM)); } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 7cc7b540cc0..3af25ba8894 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -301,7 +301,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; case UI_ID_LOCAL: if (id) { - if (id_make_local(CTX_data_main(C), id, false)) { + if (id_make_local(CTX_data_main(C), id, false, false)) { /* reassign to get get proper updates/notifiers */ idptr = RNA_property_pointer_get(&template->ptr, template->prop); RNA_property_pointer_set(&template->ptr, template->prop, idptr); @@ -453,7 +453,7 @@ static void template_ID( else { but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local")); - if (!id_make_local(CTX_data_main(C), id, true /* test */) || (idfrom && idfrom->lib)) + if (!id_make_local(CTX_data_main(C), id, true /* test */, false) || (idfrom && idfrom->lib)) UI_but_flag_enable(but, UI_BUT_DISABLED); } diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 69588928253..281a8b2a02d 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -563,7 +563,7 @@ static BMEdge *bm_face_split_edge_find( if (UNLIKELY(BM_edge_exists(v_pivot, l_iter->e->v1) || BM_edge_exists(v_pivot, l_iter->e->v2))) { - /* very unlikley but will cause complications splicing the verts together, + /* very unlikely but will cause complications splicing the verts together, * so just skip this case */ ok = false; } diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index e3e5863dc0e..2cdb00286aa 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -395,7 +395,7 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs, * return an un-ordered array of loop pairs * use for rebuilding face-fill * - * \note the method currenly used fails for edges with 3+ face users and gives + * \note the method currently used fails for edges with 3+ face users and gives * nasty holes in the mesh, there isnt a good way of knowing ahead of time * which loops will be split apart (its possible to figure out but quite involved). * So for now this is a known limitation of current rip-fill option. diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index bcdd170c53c..0fe43c44d7d 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -440,7 +440,7 @@ static int group_link_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* Early return check, if the object is already in group - * we could sckip all the dependency check and just consider + * we could skip all the dependency check and just consider * operator is finished. */ if (BKE_group_object_exists(group, ob)) { diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 55eb30ac2de..d8b0767562c 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2103,11 +2103,11 @@ static void make_local_makelocalmaterial(Material *ma) AnimData *adt; int b; - id_make_local(G.main, &ma->id, false); + id_make_local(G.main, &ma->id, false, false); for (b = 0; b < MAX_MTEX; b++) if (ma->mtex[b] && ma->mtex[b]->tex) - id_make_local(G.main, &ma->mtex[b]->tex->id, false); + id_make_local(G.main, &ma->mtex[b]->tex->id, false, false); adt = BKE_animdata_from_id(&ma->id); if (adt) BKE_animdata_make_local(adt); @@ -2235,7 +2235,7 @@ static int make_local_exec(bContext *C, wmOperator *op) } if (ob->id.lib) - id_make_local(bmain, &ob->id, false); + id_make_local(bmain, &ob->id, false, false); } CTX_DATA_END; @@ -2257,7 +2257,7 @@ static int make_local_exec(bContext *C, wmOperator *op) id = ob->data; if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) { - id_make_local(bmain, id, false); + id_make_local(bmain, id, false, false); adt = BKE_animdata_from_id(id); if (adt) BKE_animdata_make_local(adt); @@ -2289,7 +2289,7 @@ static int make_local_exec(bContext *C, wmOperator *op) for (b = 0; b < MAX_MTEX; b++) if (la->mtex[b] && la->mtex[b]->tex) - id_make_local(bmain, &la->mtex[b]->tex->id, false); + id_make_local(bmain, &la->mtex[b]->tex->id, false, false); } else { for (a = 0; a < ob->totcol; a++) { diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 8501cea4e00..7db32957b42 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -538,7 +538,6 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel /* can be NULL if parent in other scene */ if (baspar && BASE_SELECTABLE(v3d, baspar)) { - ED_base_object_select(basact, BA_DESELECT); ED_base_object_select(baspar, BA_SELECT); ED_base_object_activate(C, baspar); changed = true; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 6e8aaebcccc..ad41fb23a69 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -3538,8 +3538,10 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr) return BLI_natstrcmp(def_a->name, def_b->name); } -/* Sorts the weight groups according to the bone hierarchy of the - associated armature (similar to how bones are ordered in the Outliner) */ +/** + * Sorts the weight groups according to the bone hierarchy of the + * associated armature (similar to how bones are ordered in the Outliner) + */ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) { if (bonebase == NULL) { diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 1203889cf0e..8c5d25ad44d 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -1482,7 +1482,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C) void render_view3d_update(RenderEngine *engine, const bContext *C) { /* this shouldn't be needed and causes too many database rebuilds, but we - * aren't actually tracking updates for all relevent datablocks so this is + * aren't actually tracking updates for all relevant datablocks so this is * a catch-all for updates */ engine->update_flag |= RE_ENGINE_UPDATE_DATABASE; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 6ed969cb270..d60c8e8dbd9 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -183,8 +183,8 @@ BLI_INLINE unsigned char f_to_char(const float val) /* to avoid locking in tile initialization */ #define TILE_PENDING SET_INT_IN_POINTER(-1) -/* This is mainly a convenience struct used so we can keep an array of images we use - * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread +/* This is mainly a convenience struct used so we can keep an array of images we use - + * their imbufs, etc, in 1 array, When using threads this array is copied for each thread * because 'partRedrawRect' and 'touch' values would not be thread safe */ typedef struct ProjPaintImage { Image *ima; @@ -202,7 +202,7 @@ typedef struct ProjPaintImage { */ typedef struct ProjStrokeHandle { /* Support for painting from multiple views at once, - * currently used to impliment symmetry painting, + * currently used to implement symmetry painting, * we can assume at least the first is set while painting. */ struct ProjPaintState *ps_views[8]; int ps_views_tot; @@ -2174,7 +2174,7 @@ static void project_bucket_clip_face( if ((*tot) < 3) { /* no intersections to speak of, but more probable is that all face is just outside the - * rectangle and culled due to float precision issues. Since above teste have failed, + * rectangle and culled due to float precision issues. Since above tests have failed, * just dump triangle as is for painting */ *tot = 0; copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index aa17cb02fe5..1431958501d 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -491,31 +491,30 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float } /* Returns zero if no sculpt changes should be made, non-zero otherwise */ -static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outpressure, - const PaintSample *sample, PaintMode mode) +static bool paint_smooth_stroke( + PaintStroke *stroke, const PaintSample *sample, PaintMode mode, + float r_mouse[2], float *r_pressure) { if (paint_supports_smooth_stroke(stroke->brush, mode)) { float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d; - float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u; - float dx = stroke->last_mouse_position[0] - sample->mouse[0]; - float dy = stroke->last_mouse_position[1] - sample->mouse[1]; + float u = stroke->brush->smooth_stroke_factor; /* If the mouse is moving within the radius of the last move, * don't update the mouse position. This allows sharp turns. */ - if (dx * dx + dy * dy < radius * radius) - return 0; + if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < SQUARE(radius)) { + return false; + } - output[0] = sample->mouse[0] * v + stroke->last_mouse_position[0] * u; - output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u; - *outpressure = sample->pressure * v + stroke->last_pressure * u; + interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u); + *r_pressure = interpf(sample->pressure, stroke->last_pressure, u); } else { - output[0] = sample->mouse[0]; - output[1] = sample->mouse[1]; - *outpressure = sample->pressure; + r_mouse[0] = sample->mouse[0]; + r_mouse[1] = sample->mouse[1]; + *r_pressure = sample->pressure; } - return 1; + return true; } static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure) @@ -1190,7 +1189,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) /* airbrush */ ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer)) { - if (paint_smooth_stroke(stroke, mouse, &pressure, &sample_average, mode)) { + if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) { if (stroke->stroke_started) { if (paint_space_stroke_enabled(br, mode)) { if (paint_space_stroke(C, op, mouse, pressure)) diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index e874a969963..f21f62cc141 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2379,9 +2379,8 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P swap_m4m4(vc->rv3d->persmat, mat); /* calculate pivot for rotation around seletion if needed */ - if (U.uiflag & USER_ORBIT_SELECTION) { - paint_last_stroke_update(scene, vc->ar, mval); - } + /* also needed for "View Selected" on last stroke */ + paint_last_stroke_update(scene, vc->ar, mval); DAG_id_tag_update(ob->data, 0); ED_region_tag_redraw(vc->ar); @@ -2842,9 +2841,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P } /* calculate pivot for rotation around seletion if needed */ - if (U.uiflag & USER_ORBIT_SELECTION) { - paint_last_stroke_update(scene, vc->ar, mval); - } + /* also needed for "View Selected" on last stroke */ + paint_last_stroke_update(scene, vc->ar, mval); ED_region_tag_redraw(vc->ar); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index cc7531b9783..1305b76b5ad 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1145,7 +1145,9 @@ static void calc_area_normal_and_center( /* Return modified brush strength. Includes the direction of the brush, positive * values pull vertices, negative values push. Uses tablet pressure and a * special multiplier found experimentally to scale the strength factor. */ -static float brush_strength(const Sculpt *sd, const StrokeCache *cache, const float feather, const UnifiedPaintSettings *ups) +static float brush_strength( + const Sculpt *sd, const StrokeCache *cache, + const float feather, const UnifiedPaintSettings *ups) { const Scene *scene = cache->vc->scene; const Brush *brush = BKE_paint_brush((Paint *)&sd->paint); @@ -3985,7 +3987,9 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss) } /* Initialize the stroke cache invariants from operator properties */ -static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2]) +static void sculpt_update_cache_invariants( + bContext *C, Sculpt *sd, SculptSession *ss, + wmOperator *op, const float mouse[2]) { StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache"); Scene *scene = CTX_data_scene(C); @@ -4448,7 +4452,9 @@ static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin) } } -static float sculpt_raycast_init(ViewContext *vc, const float mouse[2], float ray_start[3], float ray_end[3], float ray_normal[3], bool original) +static float sculpt_raycast_init( + ViewContext *vc, const float mouse[2], + float ray_start[3], float ray_end[3], float ray_normal[3], bool original) { float obimat[4][4]; float dist; @@ -4956,8 +4962,9 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss) cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id); } - ss->cd_vert_node_offset = CustomData_get_n_offset(&ss->bm->vdata, CD_PROP_INT, - cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT)); + ss->cd_vert_node_offset = CustomData_get_n_offset( + &ss->bm->vdata, CD_PROP_INT, + cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT)); ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY; @@ -4967,8 +4974,9 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss) cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id); } - ss->cd_face_node_offset = CustomData_get_n_offset(&ss->bm->pdata, CD_PROP_INT, - cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT)); + ss->cd_face_node_offset = CustomData_get_n_offset( + &ss->bm->pdata, CD_PROP_INT, + cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT)); ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY; } @@ -5667,7 +5675,8 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX, "Location", "Screen Coordinates of sampling", 0, SHRT_MAX); + RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX, + "Location", "Screen Coordinates of sampling", 0, SHRT_MAX); } diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 1ff656243d6..14d0f909d23 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -634,7 +634,7 @@ typedef struct PrefetchQueue { short render_size, render_flag; /* If true prefecthing goes forward in time, - * othwewise it goes backwards in time (starting from current frame). + * otherwise it goes backwards in time (starting from current frame). */ bool forward; diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index b837e516422..ae91a466495 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -826,7 +826,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0) // return; - /* No curve to modify/visualise the result? + /* No curve to modify/visualize the result? * => We still want to show the 1-1 default... */ if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 06caf930988..1538842b139 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1061,6 +1061,12 @@ typedef struct ImageOpenData { ImageFormatData im_format; } ImageOpenData; +typedef struct ImageFrameRange { + struct ImageFrameRange *next, *prev; + ListBase frames; + char filepath[FILE_MAX]; +} ImageFrameRange; + typedef struct ImageFrame { struct ImageFrame *next, *prev; int framenr; @@ -1086,10 +1092,10 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op) * \param frames [out] the list of frame numbers found in the files matching the first one by name * \param path [out] the full path of the first file in the list of image files */ -static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *path, const size_t maxlen) +static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all) { char dir[FILE_MAXDIR]; - bool is_first_entry = true; + ImageFrameRange *frame_range = NULL; RNA_string_get(ptr, "directory", dir); RNA_BEGIN (ptr, itemptr, "files") @@ -1101,29 +1107,26 @@ static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *p ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame"); /* use the first file in the list as base filename */ - if (is_first_entry) { - BLI_join_dirfile(path, maxlen, dir, filename); - frame->framenr = BLI_stringdec(filename, base_head, base_tail, &digits); - BLI_addtail(frames, frame); - is_first_entry = false; + frame->framenr = BLI_stringdec(filename, head, tail, &digits); + + /* still in the same sequence */ + if ((frame_range != NULL) && + (STREQLEN(base_head, head, FILE_MAX)) && + (STREQLEN(base_tail, tail, FILE_MAX))) + { + /* pass */ } else { - frame->framenr = BLI_stringdec(filename, head, tail, &digits); + /* start a new frame range */ + frame_range = MEM_callocN(sizeof(*frame_range), __func__); + BLI_join_dirfile(frame_range->filepath, sizeof(frame_range->filepath), dir, filename); + BLI_addtail(frames_all, frame_range); - /* still in the same sequence */ - if ((STREQLEN(base_head, head, FILE_MAX)) && - (STREQLEN(base_tail, tail, FILE_MAX))) - { - BLI_addtail(frames, frame); - } - else { - /* different file base name found, is ignored */ - MEM_freeN(filename); - MEM_freeN(frame); - break; - } + BLI_strncpy(base_head, head, sizeof(base_head)); + BLI_strncpy(base_tail, tail, sizeof(base_tail)); } + BLI_addtail(&frame_range->frames, frame); MEM_freeN(filename); } RNA_END @@ -1164,6 +1167,52 @@ static int image_sequence_get_len(ListBase *frames, int *ofs) return 0; } +static Image *image_open_single( + wmOperator *op, const char *filepath, const char *relbase, + bool is_relative_path, bool use_multiview, int frame_seq_len) +{ + bool exists = false; + Image *ima = NULL; + + errno = 0; + ima = BKE_image_load_exists_ex(filepath, &exists); + + if (!ima) { + if (op->customdata) MEM_freeN(op->customdata); + BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", + filepath, errno ? strerror(errno) : TIP_("unsupported image format")); + return NULL; + } + + if (!exists) { + /* only image path after save, never ibuf */ + if (is_relative_path) { + BLI_path_rel(ima->name, relbase); + } + + /* handle multiview images */ + if (use_multiview) { + ImageOpenData *iod = op->customdata; + ImageFormatData *imf = &iod->im_format; + + ima->flag |= IMA_USE_VIEWS; + ima->views_format = imf->views_format; + *ima->stereo3d_format = imf->stereo3d_format; + } + else { + ima->flag &= ~IMA_USE_VIEWS; + BKE_image_free_views(ima); + } + + if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) { + ima->source = IMA_SRC_SEQUENCE; + } + } + + return ima; +} + + static int image_open_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1174,70 +1223,60 @@ static int image_open_exec(bContext *C, wmOperator *op) ImageOpenData *iod = op->customdata; PointerRNA idptr; Image *ima = NULL; - char path[FILE_MAX]; + char filepath[FILE_MAX]; int frame_seq_len = 0; int frame_ofs = 1; - bool exists = false; const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); + const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview"); - RNA_string_get(op->ptr, "filepath", path); + if (!op->customdata) + image_open_init(C, op); + + RNA_string_get(op->ptr, "filepath", filepath); if (RNA_struct_property_is_set(op->ptr, "directory") && RNA_struct_property_is_set(op->ptr, "files")) { - /* only to pass to imbuf */ - char path_full[FILE_MAX]; - BLI_strncpy(path_full, path, sizeof(path_full)); - BLI_path_abs(path_full, G.main->name); + bool was_relative = BLI_path_is_rel(filepath); + ListBase frame_ranges_all; - if (!IMB_isanim(path_full)) { - bool was_relative = BLI_path_is_rel(path); - ListBase frames; + BLI_listbase_clear(&frame_ranges_all); + image_sequence_get_frame_ranges(op->ptr, &frame_ranges_all); + for (ImageFrameRange *frame_range = frame_ranges_all.first; frame_range; frame_range = frame_range->next) { + int frame_range_ofs; + int frame_range_seq_len = image_sequence_get_len(&frame_range->frames, &frame_range_ofs); + BLI_freelistN(&frame_range->frames); - BLI_listbase_clear(&frames); - image_sequence_get_frames(op->ptr, &frames, path, sizeof(path)); - frame_seq_len = image_sequence_get_len(&frames, &frame_ofs); - BLI_freelistN(&frames); + char filepath_range[FILE_MAX]; + BLI_strncpy(filepath_range, frame_range->filepath, sizeof(filepath_range)); if (was_relative) { - BLI_path_rel(path, G.main->name); + BLI_path_rel(filepath_range, bmain->name); } - } - } - - errno = 0; - ima = BKE_image_load_exists_ex(path, &exists); + Image *ima_range = image_open_single( + op, filepath_range, bmain->name, + is_relative_path, use_multiview, frame_range_seq_len); - if (!ima) { - if (op->customdata) MEM_freeN(op->customdata); - BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", - path, errno ? strerror(errno) : TIP_("unsupported image format")); - return OPERATOR_CANCELLED; - } - - if (!op->customdata) - image_open_init(C, op); - - /* handle multiview images */ - if (RNA_boolean_get(op->ptr, "use_multiview")) { - ImageFormatData *imf = &iod->im_format; - - ima->flag |= IMA_USE_VIEWS; - ima->views_format = imf->views_format; - *ima->stereo3d_format = imf->stereo3d_format; + /* take the first image */ + if ((ima == NULL) && ima_range) { + ima = ima_range; + frame_seq_len = frame_range_seq_len; + frame_ofs = frame_range_ofs; + } + } + BLI_freelistN(&frame_ranges_all); } else { - ima->flag &= ~IMA_USE_VIEWS; - BKE_image_free_views(ima); + /* for drag & drop etc. */ + ima = image_open_single( + op, filepath, bmain->name, + is_relative_path, use_multiview, 1); } - /* only image path after save, never ibuf */ - if (is_relative_path) { - if (!exists) { - BLI_path_rel(ima->name, bmain->name); - } + if (ima == NULL) { + return OPERATOR_CANCELLED; } /* hook into UI */ @@ -1245,11 +1284,8 @@ static int image_open_exec(bContext *C, wmOperator *op) if (iod->pprop.prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer also increases user, so this compensates it */ id_us_min(&ima->id); - if ((frame_seq_len > 1) && ima->source == IMA_SRC_FILE) { - ima->source = IMA_SRC_SEQUENCE; - } RNA_id_pointer_create(&ima->id, &idptr); RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, idptr); RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 7b7ea180604..14efd4338b4 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1234,106 +1234,106 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_DOT); break; } } - else if (GS(tselem->id->name) == ID_OB) { - Object *ob = (Object *)tselem->id; - switch (ob->type) { - case OB_LAMP: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break; - case OB_MESH: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break; - case OB_CAMERA: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break; - case OB_CURVE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break; - case OB_MBALL: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break; - case OB_LATTICE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break; - case OB_ARMATURE: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break; - case OB_FONT: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break; - case OB_SURF: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break; - case OB_SPEAKER: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break; - case OB_EMPTY: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break; - + else if (tselem->id) { + if (GS(tselem->id->name) == ID_OB) { + Object *ob = (Object *)tselem->id; + switch (ob->type) { + case OB_LAMP: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break; + case OB_MESH: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break; + case OB_CAMERA: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break; + case OB_CURVE: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break; + case OB_MBALL: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break; + case OB_LATTICE: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break; + case OB_ARMATURE: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break; + case OB_FONT: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break; + case OB_SURF: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break; + case OB_SPEAKER: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break; + case OB_EMPTY: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break; + } } - } - else { - switch (GS(tselem->id->name)) { - case ID_SCE: - tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break; - case ID_ME: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break; - case ID_CU: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break; - case ID_MB: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break; - case ID_LT: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break; - case ID_LA: - { - Lamp *la = (Lamp *)tselem->id; - - switch (la->type) { - case LA_LOCAL: - tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break; - case LA_SUN: - tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break; - case LA_SPOT: - tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break; - case LA_HEMI: - tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break; - case LA_AREA: - tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break; - default: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break; + else { + switch (GS(tselem->id->name)) { + case ID_SCE: + tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break; + case ID_ME: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break; + case ID_CU: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break; + case ID_MB: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break; + case ID_LT: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break; + case ID_LA: + { + Lamp *la = (Lamp *)tselem->id; + switch (la->type) { + case LA_LOCAL: + tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break; + case LA_SUN: + tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break; + case LA_SPOT: + tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break; + case LA_HEMI: + tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break; + case LA_AREA: + tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break; + default: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break; + } + break; } - break; + case ID_MA: + tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break; + case ID_TE: + tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break; + case ID_IM: + tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break; + case ID_SPK: + case ID_SO: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break; + case ID_AR: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break; + case ID_CA: + tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break; + case ID_KE: + tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break; + case ID_WO: + tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break; + case ID_AC: + tselem_draw_icon_uibut(&arg, ICON_ACTION); break; + case ID_NLA: + tselem_draw_icon_uibut(&arg, ICON_NLA); break; + case ID_TXT: + tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break; + case ID_GR: + tselem_draw_icon_uibut(&arg, ICON_GROUP); break; + case ID_LI: + if (tselem->id->tag & LIB_TAG_MISSING) { + tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN); + } + else if (((Library *)tselem->id)->parent) { + tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT); + } + else { + tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); + } + break; + case ID_LS: + tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break; + case ID_GD: + tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break; } - case ID_MA: - tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break; - case ID_TE: - tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break; - case ID_IM: - tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break; - case ID_SPK: - case ID_SO: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break; - case ID_AR: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break; - case ID_CA: - tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break; - case ID_KE: - tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break; - case ID_WO: - tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break; - case ID_AC: - tselem_draw_icon_uibut(&arg, ICON_ACTION); break; - case ID_NLA: - tselem_draw_icon_uibut(&arg, ICON_NLA); break; - case ID_TXT: - tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break; - case ID_GR: - tselem_draw_icon_uibut(&arg, ICON_GROUP); break; - case ID_LI: - if (tselem->id->tag & LIB_TAG_MISSING) { - tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN); - } - else if (((Library *)tselem->id)->parent) { - tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT); - } - else { - tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); - } - break; - case ID_LS: - tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break; - case ID_GD: - tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break; } } } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index f3235d07757..111e60e5159 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -439,7 +439,7 @@ static void id_local_cb( Main *bmain = CTX_data_main(C); /* if the ID type has no special local function, * just clear the lib */ - if (id_make_local(bmain, tselem->id, false) == false) { + if (id_make_local(bmain, tselem->id, false, false) == false) { id_clear_lib_data(bmain, tselem->id); } } @@ -516,23 +516,16 @@ static void group_linkobs2scene_cb( Group *group = (Group *)tselem->id; GroupObject *gob; Base *base; - + for (gob = group->gobject.first; gob; gob = gob->next) { base = BKE_scene_base_find(scene, gob->ob); - if (base) { - base->object->flag |= SELECT; - base->flag |= SELECT; - } - else { + if (!base) { /* link to scene */ - base = MEM_callocN(sizeof(Base), "add_base"); - BLI_addhead(&scene->base, base); - base->lay = gob->ob->lay; - gob->ob->flag |= SELECT; - base->flag = gob->ob->flag; - base->object = gob->ob; + base = BKE_scene_base_add(scene, gob->ob); id_lib_extern((ID *)gob->ob); /* in case these are from a linked group */ } + base->object->flag |= SELECT; + base->flag |= SELECT; } } diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index c11a4d2e5a3..ede6b7ce469 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -1071,7 +1071,7 @@ static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const { bool is_type_set = RNA_struct_property_is_set(op->ptr, "type"); int type = -1; - int prop_flag = SEQPROP_ENDFRAME; + int prop_flag = SEQPROP_ENDFRAME | SEQPROP_NOPATHS; if (is_type_set) { type = RNA_enum_get(op->ptr, "type"); @@ -1106,9 +1106,6 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - WM_operator_properties_filesel( - ot, 0, FILE_SPECIAL, FILE_OPENFILE, - WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME); RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type"); RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color", diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 2b0bd7690e2..83fde34fcde 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -3075,7 +3075,9 @@ static int viewselected_exec(bContext *C, wmOperator *op) else if (BKE_paint_select_face_test(ob)) { ok = paintface_minmax(ob, min, max); } - else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) { + else if (ob && + (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) + { BKE_paint_stroke_get_average(scene, ob, min); copy_v3_v3(max, min); ok = true; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 2d050c4fa95..c5026fbb32b 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -274,6 +274,7 @@ bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]); void VIEW3D_OT_snap_selected_to_grid(struct wmOperatorType *ot); void VIEW3D_OT_snap_selected_to_cursor(struct wmOperatorType *ot); +void VIEW3D_OT_snap_selected_to_active(struct wmOperatorType *ot); void VIEW3D_OT_snap_cursor_to_grid(struct wmOperatorType *ot); void VIEW3D_OT_snap_cursor_to_center(struct wmOperatorType *ot); void VIEW3D_OT_snap_cursor_to_selected(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 1c84ce3c985..b273f46fca3 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -214,6 +214,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid); WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor); + WM_operatortype_append(VIEW3D_OT_snap_selected_to_active); WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid); WM_operatortype_append(VIEW3D_OT_snap_cursor_to_center); WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index ac05853e6d0..7448d4c658e 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -312,25 +312,9 @@ static void view3d_win_to_ray_segment( if (!r_ray_co) r_ray_co = _ray_co; if (!r_ray_dir) r_ray_dir = _ray_dir; + ED_view3d_win_to_origin(ar, mval, r_ray_co); ED_view3d_win_to_vector(ar, mval, r_ray_dir); - if (rv3d->is_persp) { - copy_v3_v3(r_ray_co, rv3d->viewinv[3]); - } - else { - r_ray_co[0] = 2.0f * mval[0] / ar->winx - 1.0f; - r_ray_co[1] = 2.0f * mval[1] / ar->winy - 1.0f; - - if (rv3d->persp == RV3D_CAMOB) { - r_ray_co[2] = -1.0f; - } - else { - r_ray_co[2] = 0.0f; - } - - mul_project_m4_v3(rv3d->persinv, r_ray_co); - } - if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) { end_offset = v3d->far / 2.0f; start_offset = -end_offset; @@ -347,7 +331,7 @@ static void view3d_win_to_ray_segment( } } -BLI_INLINE bool view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3]) +bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3]) { if ((rv3d->rflag & RV3D_CLIPPING) && (clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6, @@ -384,7 +368,7 @@ bool ED_view3d_win_to_ray_ex( /* bounds clipping */ if (do_clip) { - return view3d_clip_segment(ar->regiondata, r_ray_start, ray_end); + return ED_view3d_clip_segment(ar->regiondata, r_ray_start, ray_end); } return true; @@ -549,6 +533,37 @@ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3] } /** + * Calculate a 3d origin from 2d window coordinates. + * \note Orthographic views have a less obvious origin, + * Since far clip can be a very large value resulting in numeric precision issues, + * the origin in this case is close to zero coordinate. + * + * \param ar The region (used for the window width and height). + * \param mval The area relative 2d location (such as event->mval converted to floats). + * \param out The resulting normalized world-space direction vector. + */ +void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3]) +{ + RegionView3D *rv3d = ar->regiondata; + if (rv3d->is_persp) { + copy_v3_v3(out, rv3d->viewinv[3]); + } + else { + out[0] = 2.0f * mval[0] / ar->winx - 1.0f; + out[1] = 2.0f * mval[1] / ar->winy - 1.0f; + + if (rv3d->persp == RV3D_CAMOB) { + out[2] = -1.0f; + } + else { + out[2] = 0.0f; + } + + mul_project_m4_v3(rv3d->persinv, out); + } +} + +/** * Calculate a 3d direction vector from 2d window coordinates. * This direction vector starts and the view in the direction of the 2d window coordinates. * In orthographic view all window coordinates yield the same vector. @@ -599,7 +614,7 @@ bool ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2 /* bounds clipping */ if (do_clip) { - return view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end); + return ED_view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end); } return true; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index e8e7d3c62fb..5dd69cc66eb 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -44,6 +44,7 @@ #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_object.h" +#include "BKE_report.h" #include "BKE_tracking.h" #include "WM_api.h" @@ -204,7 +205,7 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot) /* *************************************************** */ -static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) +static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); @@ -213,15 +214,10 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) TransVertStore tvs = {NULL}; TransVert *tv; float imat[3][3], bmat[3][3]; - const float *cursor_global; float center_global[3]; float offset_global[3]; int a; - const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); - - cursor_global = ED_view3d_cursor3d_get(scene, v3d); - if (use_offset) { if ((v3d && v3d->around == V3D_AROUND_ACTIVE) && snap_calc_active_center(C, true, center_global)) @@ -231,11 +227,11 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) else { snap_curs_to_sel_ex(C, center_global); } - sub_v3_v3v3(offset_global, cursor_global, center_global); + sub_v3_v3v3(offset_global, snap_target_global, center_global); } if (obedit) { - float cursor_local[3]; + float snap_target_local[3]; if (ED_transverts_check_obedit(obedit)) ED_transverts_create_from_obedit(&tvs, obedit, 0); @@ -246,8 +242,8 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) invert_m3_m3(imat, bmat); /* get the cursor in object space */ - sub_v3_v3v3(cursor_local, cursor_global, obedit->obmat[3]); - mul_m3_v3(imat, cursor_local); + sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]); + mul_m3_v3(imat, snap_target_local); if (use_offset) { float offset_local[3]; @@ -262,7 +258,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) else { tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { - copy_v3_v3(tv->loc, cursor_local); + copy_v3_v3(tv->loc, snap_target_local); } } @@ -274,10 +270,10 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) bPoseChannel *pchan; bArmature *arm = obact->data; - float cursor_local[3]; + float snap_target_local[3]; invert_m4_m4(obact->imat, obact->obmat); - mul_v3_m4v3(cursor_local, obact->imat, cursor_global); + mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global); for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { if ((pchan->bone->flag & BONE_SELECTED) && @@ -311,7 +307,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose); } else { - BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose); + BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose); } /* copy new position */ @@ -367,7 +363,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); } else { - copy_v3_v3(cursor_parent, cursor_global); + copy_v3_v3(cursor_parent, snap_target_global); } sub_v3_v3(cursor_parent, ob->obmat[3]); @@ -401,6 +397,18 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op) +{ + const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); + + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + + const float *snap_target_global = ED_view3d_cursor3d_get(scene, v3d); + + return snap_selected_to_location(C, snap_target_global, use_offset); +} + void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) { /* identifiers */ @@ -409,7 +417,7 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) ot->idname = "VIEW3D_OT_snap_selected_to_cursor"; /* api callbacks */ - ot->exec = snap_sel_to_curs_exec; + ot->exec = snap_selected_to_cursor_exec; ot->poll = ED_operator_view3d_active; /* flags */ @@ -419,6 +427,34 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", ""); } +static int snap_selected_to_active_exec(bContext *C, wmOperator *op) +{ + float snap_target_global[3]; + + if (snap_calc_active_center(C, false, snap_target_global) == false) { + BKE_report(op->reports, RPT_ERROR, "No active element found!"); + return OPERATOR_CANCELLED; + } + + return snap_selected_to_location(C, snap_target_global, false); +} + +void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Snap Selection to Active"; + ot->description = "Snap selected item(s) to the active item"; + ot->idname = "VIEW3D_OT_snap_selected_to_active"; + + /* api callbacks */ + ot->exec = snap_selected_to_active_exec; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + /* *************************************************** */ static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index ed6d49da681..724eba160a0 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -110,6 +110,12 @@ struct SnapObjectContext { }; +enum eViewProj { + VIEW_PROJ_NONE = -1, + VIEW_PROJ_ORTHO = 0, + VIEW_PROJ_PERSP = -1, +}; + static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt); @@ -137,10 +143,6 @@ struct RayCastAll_Data { Object *ob; unsigned int ob_uuid; - /* DerivedMesh only */ - DerivedMesh *dm; - const struct MLoopTri *dm_looptri; - /* output data */ ListBase *hit_list; bool retval; @@ -218,76 +220,177 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH /* -------------------------------------------------------------------- */ -/** \name Internal Object Snapping API +/** \Common utilities * \{ */ + +/** + * Struct that kepts basic information about a BVHTree build from a editmesh. + */ +typedef struct BVHTreeFromMeshType { + void *userdata; + char type; +} BVHTreeFromMeshType; + +typedef struct PreDefProject { + float pmat[4][4]; /* perspective matrix multiplied by object matrix */ + float win_half[2]; + float dist_px_sq; +} PreDefProject; + +static void precalc_project( + PreDefProject *projectdefs, const ARegion *ar, + const float dist_px, float obmat[4][4]) +{ + float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat; + if (obmat) { + mul_m4_m4m4(projectdefs->pmat, pmat, obmat); + } + else { + copy_m4_m4(projectdefs->pmat, pmat); + } + projectdefs->win_half[0] = ar->winx / 2; + projectdefs->win_half[1] = ar->winy / 2; + projectdefs->dist_px_sq = SQUARE(dist_px); +} + +/** + * From a threshold (maximum distance to snap in pixels) returns: + * + * - The *real* distance (3D) if you are in orthographic-view. + * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view. + */ +static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px) +{ + const RegionView3D *rv3d = ar->regiondata; + if (ar->winx >= ar->winy) + return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0]; + else + return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1]; +} + +static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index) +{ + switch (meshdata->type) { + case SNAP_MESH: + { + BVHTreeFromMesh *data = meshdata->userdata; + const MVert *vert = data->vert; + return vert[index].co; + } + case SNAP_EDIT_MESH: + { + BVHTreeFromEditMesh *data = meshdata->userdata; + BMVert *eve = BM_vert_at_index(data->em->bm, index); + return eve->co; + } + } + return NULL; +} + +static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3]) +{ + switch (meshdata->type) { + case SNAP_MESH: + { + BVHTreeFromMesh *data = meshdata->userdata; + const MVert *vert = data->vert; + normal_short_to_float_v3(r_no, vert->no); + break; + } + case SNAP_EDIT_MESH: + { + BVHTreeFromEditMesh *data = meshdata->userdata; + BMVert *eve = BM_vert_at_index(data->em->bm, index); + copy_v3_v3(r_no, eve->no); + break; + } + } +} + +static void get_edge_verts( + const BVHTreeFromMeshType *meshdata, const int index, + const float *v_pair[2]) +{ + switch (meshdata->type) { + case SNAP_MESH: + { + BVHTreeFromMesh *data = meshdata->userdata; + + const MVert *vert = data->vert; + const MEdge *edge = data->edge + index; + + v_pair[0] = vert[edge->v1].co; + v_pair[1] = vert[edge->v2].co; + break; + } + case SNAP_EDIT_MESH: + { + BVHTreeFromEditMesh *data = meshdata->userdata; + BMEdge *eed = BM_edge_at_index(data->em->bm, index); + + v_pair[0] = eed->v1->co; + v_pair[1] = eed->v2->co; + break; + } + } +} + #define V3_MUL_ELEM(a, b) \ (a)[0] * (b)[0], \ (a)[1] * (b)[1], \ (a)[2] * (b)[2] -static bool test_vert( - const float vco[3], const float vno[3], const float ray_co[3], const float ray_dir[3], - const float ray_depth_range[2], const float scale[3], const bool is_persp, +static bool test_vert_dist( + const float vco[3], const float ray_co[3], const float ray_dir[3], + const float ray_depth_range[2], const float scale[3], /* read/write args */ float *ray_depth, float *dist_to_ray_sq, /* return args */ - float r_co[3], float r_no[3]) + float r_co[3]) { const float vco_sc[3] = {V3_MUL_ELEM(vco, scale)}; - const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; + const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)}; - float depth; - float dist_sq = dist_squared_to_ray_v3(co_sc, dir_sc, vco_sc, &depth); + float depth, dist_sq; + dist_sq = dist_squared_to_ray_v3(origin_sc, dir_sc, vco_sc, &depth); if (depth < ray_depth_range[0]) { return false; } - if (is_persp) { - dist_sq /= SQUARE(depth); - } - if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) { *dist_to_ray_sq = dist_sq; copy_v3_v3(r_co, vco); - if (vno) { - copy_v3_v3(r_no, vno); - } - *ray_depth = depth; return true; } return false; } -static bool test_edge( +static bool test_edge_dist( const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3], - const float ray_depth_range[2], const float scale[3], const bool is_persp, + const float ray_depth_range[2], const float scale[3], /* read/write args */ float *ray_depth, float *dist_to_ray_sq, /* return args */ - float r_co[3], float r_no[3]) + float r_co[3]) { const float v1_sc[3] = {V3_MUL_ELEM(v1, scale)}; const float v2_sc[3] = {V3_MUL_ELEM(v2, scale)}; const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)}; - float tmp_co[3], depth; - float dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth); + float tmp_co[3], depth, dist_sq; + dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth); if (depth < ray_depth_range[0]) { return false; } - if (is_persp) { - dist_sq /= SQUARE(depth); - } - if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) { *dist_to_ray_sq = dist_sq; @@ -297,10 +400,6 @@ static bool test_edge( copy_v3_v3(r_co, tmp_co); - if (r_no) { - sub_v3_v3v3(r_no, v1, v2); - } - *ray_depth = depth; return true; } @@ -309,50 +408,369 @@ static bool test_edge( #undef V3_MUL_ELEM +static bool test_projected_vert_dist( + PreDefProject *projectdefs, + const float co[3], const enum eViewProj view_proj, + const float mval[2], const float depth_range[2], + float r_co[3]) +{ + float depth; + float(*pmat)[4] = projectdefs->pmat; + if (view_proj == VIEW_PROJ_PERSP) { + depth = mul_project_m4_v3_zfac(pmat, co); + if (depth < depth_range[0] || depth > depth_range[1]) { + return false; + } + } + + float co2d[2] = { + (dot_m4_v3_row_x(pmat, co) + pmat[3][0]), + (dot_m4_v3_row_y(pmat, co) + pmat[3][1]), + }; + + if (view_proj == VIEW_PROJ_PERSP) { + mul_v2_fl(co2d, 1 / depth); + } + + co2d[0] += 1.0f; + co2d[1] += 1.0f; + co2d[0] *= projectdefs->win_half[0]; + co2d[1] *= projectdefs->win_half[1]; + + const float dist_sq = len_squared_v2v2(mval, co2d); + if (dist_sq < projectdefs->dist_px_sq) { + copy_v3_v3(r_co, co); + projectdefs->dist_px_sq = dist_sq; + return true; + } + return false; +} + +static bool test_projected_edge_dist( + PreDefProject *projectdefs, + const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3], + const enum eViewProj view_proj, const float mval[2], const float depth_range[2], + float r_co[3]) +{ + + float tmp_co[3], depth; + dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth); + return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \Walk DFS + * \{ */ +typedef struct Object_Nearest2dPrecalc { + float ray_origin_local[3]; + float ray_direction_local[3]; + float ray_inv_dir[3]; + + PreDefProject projectdefs; + float mval[2]; + bool sign[3]; + bool r_axis_closest[3]; + float depth_range[2]; + + void *userdata; + int index; + float co[3]; + float no[3]; +} Object_Nearest2dPrecalc; + + +static void nearest2d_precalc( + Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar, + const float dist_px, float obmat[4][4], + const float ray_origin_local[3], const float ray_direction_local[3], + const float mval[2], const float depth_range[2]) +{ + precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat); + copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local); + copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local); + copy_v2_v2(neasrest_precalc->mval, mval); + copy_v2_v2(neasrest_precalc->depth_range, depth_range); + + for (int i = 0; i < 3; i++) { + neasrest_precalc->ray_inv_dir[i] = + (neasrest_precalc->ray_direction_local[i] != 0.0f) ? + (1.0f / neasrest_precalc->ray_direction_local[i]) : FLT_MAX; + neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f); + neasrest_precalc->r_axis_closest[i] = true; + } +} + +static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data) +{ + Object_Nearest2dPrecalc *data = user_data; + float local_bvmin[3], local_bvmax[3]; + if (data->sign[0]) { + local_bvmin[0] = bounds[0].max; + local_bvmax[0] = bounds[0].min; + } + else { + local_bvmin[0] = bounds[0].min; + local_bvmax[0] = bounds[0].max; + } + if (data->sign[1]) { + local_bvmin[1] = bounds[1].max; + local_bvmax[1] = bounds[1].min; + } + else { + local_bvmin[1] = bounds[1].min; + local_bvmax[1] = bounds[1].max; + } + if (data->sign[2]) { + local_bvmin[2] = bounds[2].max; + local_bvmax[2] = bounds[2].min; + } + else { + local_bvmin[2] = bounds[2].min; + local_bvmax[2] = bounds[2].max; + } + + const float tmin[3] = { + (local_bvmin[0] - data->ray_origin_local[0]) * data->ray_inv_dir[0], + (local_bvmin[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1], + (local_bvmin[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2], + }; + const float tmax[3] = { + (local_bvmax[0] - data->ray_origin_local[0]) * data->ray_inv_dir[0], + (local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1], + (local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2], + }; + float va[3], vb[3]; + float rtmin, rtmax; + int main_axis; + + if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) { + rtmax = tmax[0]; + va[0] = vb[0] = local_bvmax[0]; + main_axis = 3; + data->r_axis_closest[0] = data->sign[0]; + } + else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { + rtmax = tmax[1]; + va[1] = vb[1] = local_bvmax[1]; + main_axis = 2; + data->r_axis_closest[1] = data->sign[1]; + } + else { + rtmax = tmax[2]; + va[2] = vb[2] = local_bvmax[2]; + main_axis = 1; + data->r_axis_closest[2] = data->sign[2]; + } + + if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { + rtmin = tmin[0]; + va[0] = vb[0] = local_bvmin[0]; + main_axis -= 3; + data->r_axis_closest[0] = !data->sign[0]; + } + else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { + rtmin = tmin[1]; + va[1] = vb[1] = local_bvmin[1]; + main_axis -= 1; + data->r_axis_closest[1] = !data->sign[1]; + } + else { + rtmin = tmin[2]; + va[2] = vb[2] = local_bvmin[2]; + main_axis -= 2; + data->r_axis_closest[2] = !data->sign[2]; + } + if (main_axis < 0) { + main_axis += 3; + } + + /* if rtmin < rtmax, ray intersect `AABB` */ + if (rtmin <= rtmax) { +#ifdef IGNORE_BEHIND_RAY + /* `if rtmax < depth_min`, the whole `AABB` is behind us */ + if (rtmax < min_depth) { + return fallback; + } +#endif + const float proj = rtmin * data->ray_direction_local[main_axis]; + data->r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj); + return true; + } +#ifdef IGNORE_BEHIND_RAY + /* `if rtmin < depth_min`, the whole `AABB` is behing us */ + else if (rtmin < min_depth) { + return fallback; + } +#endif + if (data->sign[main_axis]) { + va[main_axis] = local_bvmax[main_axis]; + vb[main_axis] = local_bvmin[main_axis]; + } + else { + va[main_axis] = local_bvmin[main_axis]; + vb[main_axis] = local_bvmax[main_axis]; + } + float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]); + + float (*pmat)[4] = data->projectdefs.pmat; + float depth_a = mul_project_m4_v3_zfac(pmat, va); + float depth_b = depth_a + pmat[main_axis][3] * scale; + + float va2d[2] = { + (dot_m4_v3_row_x(pmat, va) + pmat[3][0]), + (dot_m4_v3_row_y(pmat, va) + pmat[3][1]), + }; + float vb2d[2] = { + (va2d[0] + pmat[main_axis][0] * scale) / depth_b, + (va2d[1] + pmat[main_axis][1] * scale) / depth_b, + }; + + va2d[0] /= depth_a; + va2d[1] /= depth_a; + + va2d[0] += 1.0f; + va2d[1] += 1.0f; + vb2d[0] += 1.0f; + vb2d[1] += 1.0f; + + va2d[0] *= data->projectdefs.win_half[0]; + va2d[1] *= data->projectdefs.win_half[1]; + vb2d[0] *= data->projectdefs.win_half[0]; + vb2d[1] *= data->projectdefs.win_half[1]; + + //float dvec[2], edge[2], rdist; + //sub_v2_v2v2(dvec, data->mval, va2d); + //sub_v2_v2v2(edge, vb2d, va2d); + float rdist; + short dvec[2] = {data->mval[0] - va2d[0], data->mval[1] - va2d[1]}; + short edge[2] = {vb2d[0] - va2d[0], vb2d[1] - va2d[1]}; + float lambda = dvec[0] * edge[0] + dvec[1] * edge[1]; + if (lambda != 0.0f) { + lambda /= edge[0] * edge[0] + edge[1] * edge[1]; + if (lambda <= 0.0f) { + rdist = len_squared_v2v2(data->mval, va2d); + data->r_axis_closest[main_axis] = true; + } + else if (lambda >= 1.0f) { + rdist = len_squared_v2v2(data->mval, vb2d); + data->r_axis_closest[main_axis] = false; + } + else { + va2d[0] += edge[0] * lambda; + va2d[1] += edge[1] * lambda; + rdist = len_squared_v2v2(data->mval, va2d); + data->r_axis_closest[main_axis] = lambda < 0.5f; + } + } + else { + rdist = len_squared_v2v2(data->mval, va2d); + } + return rdist < data->projectdefs.dist_px_sq; +} + +static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata) +{ + struct Object_Nearest2dPrecalc *neasrest_precalc = userdata; + const float co[3] = { + (bounds[0].min + bounds[0].max) / 2, + (bounds[1].min + bounds[1].max) / 2, + (bounds[2].min + bounds[2].max) / 2, + }; + + /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP) + * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO), + * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/ + if (test_projected_vert_dist( + &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP, + neasrest_precalc->mval, neasrest_precalc->depth_range, + neasrest_precalc->co)) + { + copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no); + neasrest_precalc->index = index; + } + return true; +} + +static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata) +{ + struct Object_Nearest2dPrecalc *neasrest_precalc = userdata; + + const float *v_pair[2]; + get_edge_verts(neasrest_precalc->userdata, index, v_pair); + + /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP) + * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO), + * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/ + if (test_projected_edge_dist( + &neasrest_precalc->projectdefs, v_pair[0], v_pair[1], + neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local, + VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range, + neasrest_precalc->co)) + { + sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]); + neasrest_precalc->index = index; + } + return true; +} + +static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata) +{ + const bool *r_axis_closest = ((struct Object_Nearest2dPrecalc *)userdata)->r_axis_closest; + return r_axis_closest[axis]; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Internal Object Snapping API + * \{ */ + static bool snapArmature( - Object *ob, bArmature *arm, float obmat[4][4], - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2], + const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], + const short snap_to, const float origin[3], const float dir[3], + const float mval[2], const enum eViewProj view_proj, const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { - float imat[4][4]; - float ray_origin_local[3], ray_normal_local[3]; bool retval = false; - invert_m4_m4(imat, obmat); + float ray_start_local[3], ray_normal_local[3]; + if (snap_to != SCE_SNAP_MODE_VERTEX) { + float imat[4][4]; + invert_m4_m4(imat, obmat); - mul_v3_m4v3(ray_origin_local, imat, ray_origin); - mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal); + copy_v3_v3(ray_start_local, origin); + copy_v3_v3(ray_normal_local, dir); + mul_m4_v3(imat, ray_start_local); + mul_mat3_m4_v3(imat, ray_normal_local); + } - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); + PreDefProject projectdefs; + precalc_project(&projectdefs, ar, *dist_px, obmat); if (arm->edbo) { - EditBone *eBone; - - for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { + for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) { if (eBone->layer & arm->layer) { /* skip hidden or moving (selected) bones */ if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) { switch (snap_to) { case SCE_SNAP_MODE_VERTEX: - retval |= test_vert( - eBone->head, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); - retval |= test_vert( - eBone->tail, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, eBone->head, view_proj, mval, depth_range, r_loc); + retval |= test_projected_vert_dist( + &projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc); break; case SCE_SNAP_MODE_EDGE: - retval |= test_edge( - eBone->head, eBone->tail, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_edge_dist( + &projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local, + view_proj, mval, depth_range, r_loc); break; } } @@ -360,11 +778,8 @@ static bool snapArmature( } } else if (ob->pose && ob->pose->chanbase.first) { - bPoseChannel *pchan; - Bone *bone; - - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - bone = pchan->bone; + for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + Bone *bone = pchan->bone; /* skip hidden bones */ if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) { const float *head_vec = pchan->pose_head; @@ -372,26 +787,22 @@ static bool snapArmature( switch (snap_to) { case SCE_SNAP_MODE_VERTEX: - retval |= test_vert( - head_vec, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); - retval |= test_vert( - tail_vec, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, head_vec, view_proj, mval, depth_range, r_loc); + retval |= test_projected_vert_dist( + &projectdefs, tail_vec, view_proj, mval, depth_range, r_loc); break; case SCE_SNAP_MODE_EDGE: - retval |= test_edge( - head_vec, tail_vec, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_edge_dist( + &projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local, + view_proj, mval, depth_range, r_loc); break; } } } } if (retval) { + *dist_px = sqrtf(projectdefs.dist_px_sq); mul_m4_v3(obmat, r_loc); return true; } @@ -399,39 +810,26 @@ static bool snapArmature( } static bool snapCurve( - Object *ob, Curve *cu, float obmat[4][4], - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2], + const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4], + const short snap_to, const float mval[2], const enum eViewProj view_proj, + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { - float imat[4][4]; - float ray_origin_local[3], ray_normal_local[3]; bool retval = false; - int u; - - Nurb *nu; /* only vertex snapping mode (eg control points and handles) supported for now) */ if (snap_to != SCE_SNAP_MODE_VERTEX) { return retval; } - invert_m4_m4(imat, obmat); - - copy_v3_v3(ray_origin_local, ray_origin); - copy_v3_v3(ray_normal_local, ray_normal); - - mul_m4_v3(imat, ray_origin_local); - mul_mat3_m4_v3(imat, ray_normal_local); - - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); + PreDefProject projectdefs; + precalc_project(&projectdefs, ar, *dist_px, obmat); - for (nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { - for (u = 0; u < nu->pntsu; u++) { + for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { + for (int u = 0; u < nu->pntsu; u++) { switch (snap_to) { case SCE_SNAP_MODE_VERTEX: { @@ -441,26 +839,20 @@ static bool snapCurve( if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) { break; } - retval |= test_vert( - nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc); /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */ if (!(nu->bezt[u].f1 & SELECT) && !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) { - retval |= test_vert( - nu->bezt[u].vec[0], NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc); } if (!(nu->bezt[u].f3 & SELECT) && !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) { - retval |= test_vert( - nu->bezt[u].vec[2], NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc); } } else { @@ -468,26 +860,20 @@ static bool snapCurve( if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) { break; } - retval |= test_vert( - nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc); } } else { /* curve is not visible outside editmode if nurb length less than two */ if (nu->pntsu > 1) { if (nu->bezt) { - retval |= test_vert( - nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc); } else { - retval |= test_vert( - nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc); } } } @@ -499,6 +885,7 @@ static bool snapCurve( } } if (retval) { + *dist_px = sqrtf(projectdefs.dist_px_sq); mul_m4_v3(obmat, r_loc); return true; } @@ -507,11 +894,11 @@ static bool snapCurve( /* may extend later (for now just snaps to empty center) */ static bool snapEmpty( - Object *ob, float obmat[4][4], - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2], + const ARegion *ar, Object *ob, float obmat[4][4], + const short snap_to, const float mval[2], const enum eViewProj view_proj, + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { @@ -520,17 +907,19 @@ static bool snapEmpty( if (ob->transflag & OB_DUPLI) { return retval; } + /* for now only vertex supported */ switch (snap_to) { case SCE_SNAP_MODE_VERTEX: { - float ob_loc[3], ob_scale[3] = {1.0, 1.0, 1.0}; - copy_v3_v3(ob_loc, obmat[3]); - - retval |= test_vert( - ob_loc, NULL, ray_origin, ray_normal, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + PreDefProject projectdefs; + precalc_project(&projectdefs, ar, *dist_px, NULL); + float tmp_co[3]; + copy_v3_v3(tmp_co, obmat[3]); + if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) { + *dist_px = sqrtf(projectdefs.dist_px_sq); + retval = true; + } break; } default: @@ -541,19 +930,23 @@ static bool snapEmpty( } static bool snapCamera( - Scene *scene, Object *object, float obmat[4][4], - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2], + const SnapObjectContext *sctx, Object *object, float obmat[4][4], + const short snap_to, const float mval[2], const enum eViewProj view_proj, + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { + Scene *scene = sctx->scene; + + PreDefProject projectdefs; + precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL); + float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4]; bool retval = false; MovieClip *clip = BKE_object_movieclip_get(scene, object, false); MovieTracking *tracking; - float ray_origin_local[3], ray_normal_local[3]; if (clip == NULL) { return retval; @@ -584,9 +977,6 @@ static bool snapCamera( reconstructed_camera_imat[4][4]; float (*vertex_obmat)[4]; - copy_v3_v3(ray_origin_local, ray_origin); - copy_v3_v3(ray_normal_local, ray_normal); - if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, CFRA, reconstructed_camera_mat); @@ -603,26 +993,16 @@ static bool snapCamera( copy_v3_v3(bundle_pos, track->bundle_pos); if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { - mul_m4_v3(orig_camera_imat, ray_origin_local); - mul_mat3_m4_v3(orig_camera_imat, ray_normal_local); vertex_obmat = orig_camera_mat; } else { mul_m4_v3(reconstructed_camera_imat, bundle_pos); - mul_m4_v3(imat, ray_origin_local); - mul_mat3_m4_v3(imat, ray_normal_local); vertex_obmat = obmat; } - float ob_scale[3]; - mat4_to_size(ob_scale, vertex_obmat); - - retval |= test_vert( - bundle_pos, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); - - mul_m4_v3(vertex_obmat, r_loc); + mul_m4_v3(vertex_obmat, bundle_pos); + retval |= test_projected_vert_dist( + &projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc); } } @@ -632,7 +1012,11 @@ static bool snapCamera( break; } - return retval; + if (retval) { + *dist_px = sqrtf(projectdefs.dist_px_sq); + return true; + } + return false; } static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) @@ -643,44 +1027,45 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) struct NearestDM_Data { void *bvhdata; - bool is_persp; - const float *ray_depth_range; - + const float *depth_range; float *ray_depth; }; -static void test_vert_depth_cb( +static void test_vert_ray_dist_cb( void *userdata, const float origin[3], const float dir[3], const float scale[3], int index, BVHTreeNearest *nearest) { struct NearestDM_Data *ndata = userdata; - const BVHTreeFromMesh *data = ndata->bvhdata; - const MVert *vert = data->vert + index; + const struct BVHTreeFromMeshType *data = ndata->bvhdata; + + const float *co = get_vert_co(data, index); - if (test_vert( - vert->co, NULL, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp, - ndata->ray_depth, &nearest->dist_sq, - nearest->co, NULL)) + if (test_vert_dist( + co, origin, dir, ndata->depth_range, + scale, ndata->ray_depth, &nearest->dist_sq, + nearest->co)) { - normal_short_to_float_v3(nearest->no, vert->no); + copy_vert_no(data, index, nearest->no); nearest->index = index; } } -static void test_edge_depth_cb( +static void test_edge_ray_dist_cb( void *userdata, const float origin[3], const float dir[3], const float scale[3], int index, BVHTreeNearest *nearest) { struct NearestDM_Data *ndata = userdata; - const BVHTreeFromMesh *data = ndata->bvhdata; - const MVert *vert = data->vert; - const MEdge *edge = data->edge + index; - - if (test_edge( - vert[edge->v1].co, vert[edge->v2].co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp, - ndata->ray_depth, &nearest->dist_sq, - nearest->co, nearest->no)) + BVHTreeFromMeshType *data = ndata->bvhdata; + + const float *v_pair[2]; + get_edge_verts(data, index, v_pair); + + if (test_edge_dist( + v_pair[0], v_pair[1], origin, dir, ndata->depth_range, + scale, ndata->ray_depth, &nearest->dist_sq, + nearest->co)) { + sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]); nearest->index = index; } } @@ -688,10 +1073,11 @@ static void test_edge_depth_cb( static bool snapDerivedMesh( SnapObjectContext *sctx, Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index, - const short snap_to, const bool is_persp, bool do_bb, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2], + const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb, + const float ray_origin[3], const float ray_start[3], const float ray_normal[3], + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float r_no[3], int *r_index, ListBase *r_hit_list) @@ -703,7 +1089,7 @@ static bool snapDerivedMesh( return retval; } } - if (snap_to == SCE_SNAP_MODE_EDGE) { + else if (snap_to == SCE_SNAP_MODE_EDGE) { if (dm->getNumEdges(dm) == 0) { return retval; } @@ -715,7 +1101,7 @@ static bool snapDerivedMesh( } { - bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && sctx->use_v3d && !is_persp; + bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO); float imat[4][4]; float timat[3][3]; /* transpose inverse matrix for normals */ @@ -823,28 +1209,30 @@ static bool snapDerivedMesh( } } + if (!treedata || !treedata->tree) { + return retval; + } + if (snap_to == SCE_SNAP_MODE_FACE) { /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already * been *inside* boundbox, leading to snap failures (see T38409). * Note also ar might be null (see T38435), in this case we assume ray_start is ok! */ - if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */ + if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ if (need_ray_start_correction_init) { /* We *need* a reasonably valid len_diff in this case. * Use BHVTree to find the closest face from ray_start_local. */ - if (treedata && treedata->tree != NULL) { - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); - if (nearest.index != -1) { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - } + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); + if (nearest.index != -1) { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); } } float ray_org_local[3]; @@ -856,8 +1244,7 @@ static bool snapDerivedMesh( * away ray_start values (as returned in case of ortho view3d), see T38358. */ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, - len_diff + ray_depth_range[0]); + madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0]); local_depth -= len_diff; } else { @@ -874,24 +1261,19 @@ static bool snapDerivedMesh( data.local_scale = local_scale; data.ob = ob; data.ob_uuid = ob_index; - data.dm = dm; data.hit_list = r_hit_list; data.retval = retval; BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); retval = data.retval; } else { - BVHTreeRayHit hit; + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - hit.index = -1; - hit.dist = local_depth; - - if (treedata->tree && - BLI_bvhtree_ray_cast( + if (BLI_bvhtree_ray_cast( treedata->tree, ray_start_local, ray_normal_local, 0.0f, &hit, treedata->raycast_callback, treedata) != -1) { @@ -900,12 +1282,15 @@ static bool snapDerivedMesh( if (hit.dist <= *ray_depth) { *ray_depth = hit.dist; copy_v3_v3(r_loc, hit.co); - copy_v3_v3(r_no, hit.no); /* back to worldspace */ mul_m4_v3(obmat, r_loc); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } retval = true; @@ -917,51 +1302,78 @@ static bool snapDerivedMesh( } } else { - /* Vert & edge use nearly identical logic. */ - BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)); + const ARegion *ar = sctx->v3d_data.ar; float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); mul_m4_v3(imat, ray_org_local); - BVHTreeNearest nearest; + BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; - nearest.index = -1; - nearest.dist_sq = *dist_to_ray_sq; + if (view_proj == VIEW_PROJ_PERSP) { + Object_Nearest2dPrecalc neasrest_precalc; + neasrest_precalc.userdata = &treedata_type; + neasrest_precalc.index = -1; - struct NearestDM_Data userdata; - userdata.bvhdata = treedata; - userdata.is_persp = is_persp; - userdata.ray_depth_range = ray_depth_range; - userdata.ray_depth = ray_depth; + nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat, + ray_org_local, ray_normal_local, mval, depth_range); - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); + BVHTree_WalkLeafCallback cb_walk_leaf = + (snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - BVHTree_NearestToRayCallback callback = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - test_vert_depth_cb : test_edge_depth_cb; + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); - if (treedata->tree && - (is_persp ? - BLI_bvhtree_find_nearest_to_ray_angle( - treedata->tree, ray_org_local, ray_normal_local, - true, ob_scale, &nearest, callback, &userdata) : - BLI_bvhtree_find_nearest_to_ray( - treedata->tree, ray_org_local, ray_normal_local, - true, ob_scale, &nearest, callback, &userdata)) != -1) - { - copy_v3_v3(r_loc, nearest.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, nearest.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + if (neasrest_precalc.index != -1) { + copy_v3_v3(r_loc, neasrest_precalc.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest_precalc.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); + + retval = true; } - *dist_to_ray_sq = nearest.dist_sq; + } + else { + BVHTreeNearest nearest; - retval = true; + nearest.index = -1; + float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px); + nearest.dist_sq = SQUARE(dist_3d); + + + float ob_scale[3]; + mat4_to_size(ob_scale, obmat); + + struct NearestDM_Data userdata; + userdata.bvhdata = &treedata_type; + userdata.depth_range = depth_range; + userdata.ray_depth = ray_depth; + + BVHTree_NearestToRayCallback cb_test_ray_dist = + (snap_to == SCE_SNAP_MODE_VERTEX) ? + test_vert_ray_dist_cb : test_edge_ray_dist_cb; + + if (BLI_bvhtree_find_nearest_to_ray( + treedata->tree, ray_org_local, ray_normal_local, + false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1) + { + copy_v3_v3(r_loc, nearest.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, nearest.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + *dist_px *= sqrtf(nearest.dist_sq) / dist_3d; + + retval = true; + } } } @@ -975,47 +1387,14 @@ static bool snapDerivedMesh( return retval; } -static void test_bmvert_depth_cb( - void *userdata, const float origin[3], const float dir[3], - const float scale[3], int index, BVHTreeNearest *nearest) -{ - struct NearestDM_Data *ndata = userdata; - const BMEditMesh *em = ndata->bvhdata; - BMVert *eve = BM_vert_at_index(em->bm, index); - - if (test_vert( - eve->co, eve->no, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp, - ndata->ray_depth, &nearest->dist_sq, - nearest->co, nearest->no)) - { - nearest->index = index; - } -} - -static void test_bmedge_depth_cb( - void *userdata, const float origin[3], const float dir[3], - const float scale[3], int index, BVHTreeNearest *nearest) -{ - struct NearestDM_Data *ndata = userdata; - const BMEditMesh *em = ndata->bvhdata; - BMEdge *eed = BM_edge_at_index(em->bm, index); - - if (test_edge( - eed->v1->co, eed->v2->co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp, - ndata->ray_depth, &nearest->dist_sq, - nearest->co, nearest->no)) - { - nearest->index = index; - } -} - static bool snapEditMesh( SnapObjectContext *sctx, Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index, - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2], + const short snap_to, const float mval[2], const enum eViewProj view_proj, + const float ray_origin[3], const float ray_start[3], const float ray_normal[3], + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float r_no[3], int *r_index, ListBase *r_hit_list) @@ -1143,6 +1522,10 @@ static bool snapEditMesh( } } + if (!treedata || !treedata->tree) { + return retval; + } + if (snap_to == SCE_SNAP_MODE_FACE) { float ray_start_local[3]; copy_v3_v3(ray_start_local, ray_start); @@ -1160,35 +1543,32 @@ static bool snapEditMesh( * Note also ar might be null (see T38435), in this case we assume ray_start is ok! */ float len_diff = 0.0f; - if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */ + if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ /* We *need* a reasonably valid len_diff in this case. * Use BHVTree to find the closest face from ray_start_local. */ - if (treedata && treedata->tree != NULL) { - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - if (BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) - { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - float ray_org_local[3]; - - copy_v3_v3(ray_org_local, ray_origin); - mul_m4_v3(imat, ray_org_local); - - /* We pass a temp ray_start, set from object's boundbox, - * to avoid precision issues with very far away ray_start values - * (as returned in case of ortho view3d), see T38358. - */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, - len_diff + ray_depth_range[0]); - local_depth -= len_diff; - } + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + if (BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) + { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); + float ray_org_local[3]; + + copy_v3_v3(ray_org_local, ray_origin); + mul_m4_v3(imat, ray_org_local); + + /* We pass a temp ray_start, set from object's boundbox, + * to avoid precision issues with very far away ray_start values + * (as returned in case of ortho view3d), see T38358. + */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0]); + local_depth -= len_diff; } } if (r_hit_list) { @@ -1202,7 +1582,6 @@ static bool snapEditMesh( data.local_scale = local_scale; data.ob = ob; data.ob_uuid = ob_index; - data.dm = NULL; data.hit_list = r_hit_list; data.retval = retval; @@ -1213,13 +1592,9 @@ static bool snapEditMesh( retval = data.retval; } else { - BVHTreeRayHit hit; + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - hit.index = -1; - hit.dist = local_depth; - - if (treedata->tree && - BLI_bvhtree_ray_cast( + if (BLI_bvhtree_ray_cast( treedata->tree, ray_start_local, ray_normal_local, 0.0f, &hit, treedata->raycast_callback, treedata) != -1) { @@ -1228,12 +1603,15 @@ static bool snapEditMesh( if (hit.dist <= *ray_depth) { *ray_depth = hit.dist; copy_v3_v3(r_loc, hit.co); - copy_v3_v3(r_no, hit.no); /* back to worldspace */ mul_m4_v3(obmat, r_loc); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } retval = true; @@ -1245,51 +1623,78 @@ static bool snapEditMesh( } } else { - /* Vert & edge use nearly identical logic. */ - BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)); + const ARegion *ar = sctx->v3d_data.ar; float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); mul_m4_v3(imat, ray_org_local); - BVHTreeNearest nearest; + BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; - nearest.index = -1; - nearest.dist_sq = *dist_to_ray_sq; + if (view_proj == VIEW_PROJ_PERSP) { + Object_Nearest2dPrecalc neasrest_precalc; + neasrest_precalc.userdata = &treedata_type; + neasrest_precalc.index = -1; - struct NearestDM_Data userdata; - userdata.bvhdata = em; - userdata.is_persp = is_persp; - userdata.ray_depth_range = ray_depth_range; - userdata.ray_depth = ray_depth; + nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat, + ray_org_local, ray_normal_local, mval, depth_range); - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); + BVHTree_WalkLeafCallback cb_walk_leaf = + (snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - BVHTree_NearestToRayCallback callback = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - test_bmvert_depth_cb : test_bmedge_depth_cb; + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); - if (treedata->tree && - (is_persp ? - BLI_bvhtree_find_nearest_to_ray_angle( - treedata->tree, ray_org_local, ray_normal_local, - false, ob_scale, &nearest, callback, &userdata) : - BLI_bvhtree_find_nearest_to_ray( - treedata->tree, ray_org_local, ray_normal_local, - false, ob_scale, &nearest, callback, &userdata)) != -1) - { - copy_v3_v3(r_loc, nearest.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, nearest.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + if (neasrest_precalc.index != -1) { + copy_v3_v3(r_loc, neasrest_precalc.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest_precalc.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); + + retval = true; } - *dist_to_ray_sq = nearest.dist_sq; + } + else { + BVHTreeNearest nearest; - retval = true; + nearest.index = -1; + float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px); + nearest.dist_sq = SQUARE(dist_3d); + + + float ob_scale[3]; + mat4_to_size(ob_scale, obmat); + + struct NearestDM_Data userdata; + userdata.bvhdata = &treedata_type; + userdata.depth_range = depth_range; + userdata.ray_depth = ray_depth; + + BVHTree_NearestToRayCallback cb_test_ray_dist = + (snap_to == SCE_SNAP_MODE_VERTEX) ? + test_vert_ray_dist_cb : test_edge_ray_dist_cb; + + if (BLI_bvhtree_find_nearest_to_ray( + treedata->tree, ray_org_local, ray_normal_local, + false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1) + { + copy_v3_v3(r_loc, nearest.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, nearest.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + *dist_px *= sqrtf(nearest.dist_sq) / dist_3d; + + retval = true; + } } } @@ -1305,26 +1710,28 @@ static bool snapEditMesh( /** * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; - * \param ray_depth_range: - * - 0: distance from the ray_origin to the clipping plane min (can be negative). - * - 1: maximum distance, elements outside this are ignored. - * \param ray_depth: maximum depth allowed for r_co. * * \note Duplicate args here are documented at #snapObjectsRay */ static bool snapObject( SnapObjectContext *sctx, Object *ob, float obmat[4][4], const unsigned int ob_index, - bool use_obedit, const short snap_to, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2], + bool use_obedit, const short snap_to, const float mval[2], + const float ray_origin[3], const float ray_start[3], const float ray_normal[3], + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4], ListBase *r_hit_list) { - const bool is_persp = sctx->use_v3d && ((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp; + const enum eViewProj view_proj = + ((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE : + (((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO); + + const ARegion *ar = sctx->v3d_data.ar; + bool retval = false; if (ob->type == OB_MESH) { @@ -1334,9 +1741,9 @@ static bool snapObject( em = BKE_editmesh_from_object(ob); retval = snapEditMesh( sctx, ob, em, obmat, ob_index, - snap_to, is_persp, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + snap_to, mval, view_proj, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); } @@ -1353,42 +1760,43 @@ static bool snapObject( } retval = snapDerivedMesh( sctx, ob, dm, obmat, ob_index, - snap_to, is_persp, true, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + snap_to, mval, view_proj, true, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); dm->release(dm); } } - else if (ob->type == OB_ARMATURE) { - retval = snapArmature( - ob, ob->data, obmat, snap_to, is_persp, - ray_origin, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, - r_loc, r_no); - } - else if (ob->type == OB_CURVE) { - retval = snapCurve( - ob, ob->data, obmat, snap_to, is_persp, - ray_origin, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, - r_loc, r_no); - } - else if (ob->type == OB_EMPTY) { - retval = snapEmpty( - ob, obmat, snap_to, is_persp, - ray_origin, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, - r_loc, r_no); - } - else if (ob->type == OB_CAMERA) { - retval = snapCamera( - sctx->scene, ob, obmat, snap_to, is_persp, - ray_origin, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, - r_loc, r_no); + else if (snap_to != SCE_SNAP_MODE_FACE) { + if (ob->type == OB_ARMATURE) { + retval = snapArmature( + ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal, + mval, view_proj, depth_range, dist_px, + r_loc, r_no); + } + else if (ob->type == OB_CURVE) { + retval = snapCurve( + ar, ob, ob->data, obmat, snap_to, mval, view_proj, + depth_range, + dist_px, + r_loc, r_no); + } + else if (ob->type == OB_EMPTY) { + retval = snapEmpty( + ar, ob, obmat, snap_to, mval, view_proj, + depth_range, + dist_px, + r_loc, r_no); + } + else if (ob->type == OB_CAMERA) { + retval = snapCamera( + sctx, ob, obmat, snap_to, mval, view_proj, + depth_range, + dist_px, + r_loc, r_no); + } } if (retval) { @@ -1414,16 +1822,18 @@ static bool snapObject( * \param snap_select: from enum SnapSelect. * * \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping. + * \param mval: Mouse coords. + * When NULL, ray-casting is handled without any projection matrix correction. * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. * \param ray_start: ray_origin moved for the start clipping plane (clip_min). * \param ray_normal: Unit length direction of the ray. + * \param depth_range: distances of clipe plane min and clip plane max; * * Read/Write Args * --------------- * * \param ray_depth: maximum depth allowed for r_co, elements deeper than this value will be ignored. - * \param dist_to_ray_sq: Real distance (3D) or Tangent (view cone radius at distance 1.0) squared. - * resulting of the function #dist_px_to_dist3d_or_tangent. + * \param dist_px: Maximum threshold distance (in pixels). * * Output Args * ----------- @@ -1440,10 +1850,11 @@ static bool snapObject( static bool snapObjectsRay( SnapObjectContext *sctx, const unsigned short snap_to, const SnapSelect snap_select, - const bool use_object_edit_cage, + const bool use_object_edit_cage, const float mval[2], const float ray_origin[3], const float ray_start[3], const float ray_normal[3], + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4], @@ -1451,14 +1862,6 @@ static bool snapObjectsRay( { bool retval = false; - float dvec[3]; - sub_v3_v3v3(dvec, ray_start, ray_origin); - - const float ray_depth_range[2] = { - dot_v3v3(dvec, ray_normal), - *ray_depth, - }; - unsigned int ob_index = 0; Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL; Base *base_act = sctx->scene->basact; @@ -1493,9 +1896,9 @@ static bool snapObjectsRay( retval |= snapObject( sctx, dupli_snap, dupli_ob->mat, ob_index++, - use_obedit_dupli, snap_to, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + use_obedit_dupli, snap_to, mval, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1507,9 +1910,9 @@ static bool snapObjectsRay( retval |= snapObject( sctx, ob_snap, ob->obmat, ob_index++, - use_obedit, snap_to, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + use_obedit, snap_to, mval, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } } @@ -1616,13 +2019,12 @@ bool ED_transform_snap_object_project_ray_ex( float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4]) { - float dist_to_ray_sq = 0.0f; - + const float depth_range[2] = {0.0f, FLT_MAX}; return snapObjectsRay( sctx, - snap_to, params->snap_select, params->use_object_edit_cage, - ray_start, ray_start, ray_normal, - ray_depth, &dist_to_ray_sq, + snap_to, params->snap_select, params->use_object_edit_cage, NULL, + ray_start, ray_start, ray_normal, depth_range, + ray_depth, NULL, r_loc, r_no, r_index, r_ob, r_obmat, NULL); } @@ -1641,8 +2043,7 @@ bool ED_transform_snap_object_project_ray_all( float ray_depth, bool sort, ListBase *r_hit_list) { - float dist_to_ray_sq = 0.0f; - + const float depth_range[2] = {0.0f, FLT_MAX}; if (ray_depth == -1.0f) { ray_depth = BVH_RAYCAST_DIST_MAX; } @@ -1653,9 +2054,9 @@ bool ED_transform_snap_object_project_ray_all( bool retval = snapObjectsRay( sctx, - snap_to, params->snap_select, params->use_object_edit_cage, - ray_start, ray_start, ray_normal, - &ray_depth, &dist_to_ray_sq, + snap_to, params->snap_select, params->use_object_edit_cage, NULL, + ray_start, ray_start, ray_normal, depth_range, + &ray_depth, NULL, NULL, NULL, NULL, NULL, NULL, r_hit_list); @@ -1710,11 +2111,6 @@ bool ED_transform_snap_object_project_ray( ray_depth = &ray_depth_fallback; } - float no_fallback[3]; - if (r_no == NULL) { - r_no = no_fallback; - } - return transform_snap_context_project_ray_impl( sctx, params, @@ -1733,11 +2129,6 @@ static bool transform_snap_context_project_view3d_mixed_impl( float ray_depth = BVH_RAYCAST_DIST_MAX; bool is_hit = false; - float r_no_dummy[3]; - if (r_no == NULL) { - r_no = r_no_dummy; - } - const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE}; BLI_assert(snap_to_flag != 0); @@ -1764,21 +2155,6 @@ static bool transform_snap_context_project_view3d_mixed_impl( } /** - * From a threshold (maximum distance to snap in pixels) returns: - * - * - The *real* distance (3D) if you are in orthographic-view. - * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view. - */ -static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px) -{ - const RegionView3D *rv3d = ar->regiondata; - if (ar->winx >= ar->winy) - return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0]; - else - return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1]; -} - -/** * Convenience function for performing snapping. * * Given a 2D region value, snap to vert/edge/face. @@ -1814,55 +2190,37 @@ bool ED_transform_snap_object_project_view3d_ex( float *ray_depth, float r_loc[3], float r_no[3], int *r_index) { - float ray_start[3], ray_normal[3], ray_origin[3]; + float ray_origin[3], ray_start[3], ray_normal[3], depth_range[2], ray_end[3]; - float ray_depth_fallback; - if (ray_depth == NULL) { - ray_depth_fallback = BVH_RAYCAST_DIST_MAX; - ray_depth = &ray_depth_fallback; - } + const ARegion *ar = sctx->v3d_data.ar; + const RegionView3D *rv3d = ar->regiondata; - if (!ED_view3d_win_to_ray_ex( - sctx->v3d_data.ar, sctx->v3d_data.v3d, - mval, ray_origin, ray_normal, ray_start, true)) - { + ED_view3d_win_to_origin(ar, mval, ray_origin); + ED_view3d_win_to_vector(ar, mval, ray_normal); + + ED_view3d_clip_range_get( + sctx->v3d_data.v3d, sctx->v3d_data.ar->regiondata, + &depth_range[0], &depth_range[1], false); + + madd_v3_v3v3fl(ray_start, ray_origin, ray_normal, depth_range[0]); + madd_v3_v3v3fl(ray_end, ray_origin, ray_normal, depth_range[1]); + + if (!ED_view3d_clip_segment(rv3d, ray_start, ray_end)) { return false; } - float radius, dist_to_ray_sq = 0.0f; - if (dist_px) { - radius = dist_px_to_dist3d_or_tangent(sctx->v3d_data.ar, *dist_px); - /** - * Workaround to use of cone (Instead of project the radius on view plane): - * In perspective view, the radius of the cone may decrease depending on the ray direction. - * This is more evident with small values of the `Viewport lens angle`. - * The threshold becomes distorted that way. - */ - RegionView3D *rv3d = sctx->v3d_data.ar->regiondata; - if (rv3d->is_persp) { - float view_dir[3]; - negate_v3_v3(view_dir, rv3d->viewinv[2]); - normalize_v3(view_dir); - radius *= dot_v3v3(ray_normal, view_dir); - } - - dist_to_ray_sq = SQUARE(radius); + float ray_depth_fallback; + if (ray_depth == NULL) { + ray_depth_fallback = BVH_RAYCAST_DIST_MAX; + ray_depth = &ray_depth_fallback; } - if (snapObjectsRay( + return snapObjectsRay( sctx, snap_to, params->snap_select, params->use_object_edit_cage, - ray_origin, ray_start, ray_normal, - ray_depth, &dist_to_ray_sq, - r_loc, r_no, r_index, NULL, NULL, NULL)) - { - if (dist_px) { - *dist_px *= sqrtf(dist_to_ray_sq) / radius; - } - return true; - } - - return false; + mval, ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, + r_loc, r_no, r_index, NULL, NULL, NULL); } bool ED_transform_snap_object_project_view3d( diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index c663af0ccbb..370841327aa 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -916,7 +916,7 @@ void GPU_buffer_unlock(GPUBuffer *UNUSED(buffer), GPUBindingType binding) { int bindtypegl = gpu_binding_type_gl[binding]; /* note: this operation can fail, could return - * an error code from this function? */ + * an error code from this function? */ glUnmapBuffer(bindtypegl); glBindBuffer(bindtypegl, 0); } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 3ea64e1f6d5..1c2dbfb8085 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -802,7 +802,7 @@ static void **gpu_gen_cube_map(unsigned int *rect, float *frect, int rectw, int * | | | | * | NegZ | PosZ | PosY | * |______|______|______| - */ + */ if (use_high_bit_depth) { float (*frectb)[4] = (float(*)[4])frect; float (**fsides)[4] = (float(**)[4])sides; diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index b8a39c81122..d41573b681b 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -77,9 +77,10 @@ static struct GPUGlobal { GPUDeviceType device; GPUOSType os; GPUDriverType driver; - float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers - calculate dfdy in shader differently when drawing to an offscreen buffer. First - number is factor on screen and second is off-screen */ + /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers + * calculate dfdy in shader differently when drawing to an offscreen buffer. First + * number is factor on screen and second is off-screen */ + float dfdyfactors[2]; float max_anisotropy; } GG = {1, 0}; diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index ba78c347e99..24228c8d087 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1720,8 +1720,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) (GPU_link_changed(shi->refl) || ma->ref != 0.0f)) { if (world->aocolor != WO_AOPLAIN) { - if (!(is_zero_v3(&world->horr) & is_zero_v3(&world->zenr))) - { + if (!(is_zero_v3(&world->horr) & is_zero_v3(&world->zenr))) { GPUNodeLink *fcol, *f; GPU_link(mat, "math_multiply", shi->amb, shi->refl, &f); GPU_link(mat, "math_multiply", f, GPU_uniform(&world->ao_env_energy), &f); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 07bc2478837..d385e303a7c 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -42,7 +42,7 @@ * * I've tried to keep similar, if not exact names for the variables as * are presented in the paper. Where I've changed the concept slightly, - * as in stepsPerFrame comapred to the time step in the paper, I've used + * as in stepsPerFrame compared to the time step in the paper, I've used * variables with different names to minimize confusion. */ diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h index 77877f7bada..0e34792e624 100644 --- a/source/blender/makesdna/DNA_genfile.h +++ b/source/blender/makesdna/DNA_genfile.h @@ -76,13 +76,23 @@ enum eSDNA_StructCompare { struct SDNA *DNA_sdna_from_data( const void *data, const int datalen, - bool do_endian_swap, bool data_alloc); + bool do_endian_swap, bool data_alloc, + const char **r_error_message); void DNA_sdna_free(struct SDNA *sdna); -int DNA_struct_find_nr(struct SDNA *sdna, const char *str); -void DNA_struct_switch_endian(struct SDNA *oldsdna, int oldSDNAnr, char *data); -char *DNA_struct_get_compareflags(struct SDNA *sdna, struct SDNA *newsdna); -void *DNA_struct_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data); +/* Access for current Blender versions SDNA*/ +void DNA_sdna_current_init(void); +/* borrowed reference */ +const struct SDNA *DNA_sdna_current_get(void); +void DNA_sdna_current_free(void); + +int DNA_struct_find_nr_ex(const struct SDNA *sdna, const char *str, unsigned int *index_last); +int DNA_struct_find_nr(const struct SDNA *sdna, const char *str); +void DNA_struct_switch_endian(const struct SDNA *oldsdna, int oldSDNAnr, char *data); +char *DNA_struct_get_compareflags(const struct SDNA *sdna, const struct SDNA *newsdna); +void *DNA_struct_reconstruct( + const struct SDNA *newsdna, const struct SDNA *oldsdna, + char *compflags, int oldSDNAnr, int blocks, void *data); int DNA_elem_array_size(const char *str); int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name); diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 5d04fba776f..a6bbb40d826 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -639,8 +639,9 @@ typedef struct BooleanModifierData { struct Object *object; char operation; - char bm_flag, pad[2]; - float threshold; + char solver; + char pad[2]; + float double_threshold; } BooleanModifierData; typedef enum { @@ -649,13 +650,10 @@ typedef enum { eBooleanModifierOp_Difference = 2, } BooleanModifierOp; -/* temp bm_flag (debugging only) */ -enum { - eBooleanModifierBMeshFlag_Enabled = (1 << 0), - eBooleanModifierBMeshFlag_BMesh_Separate = (1 << 1), - eBooleanModifierBMeshFlag_BMesh_NoDissolve = (1 << 2), - eBooleanModifierBMeshFlag_BMesh_NoConnectRegions = (1 << 3), -}; +typedef enum { + eBooleanModifierSolver_Carve = 0, + eBooleanModifierSolver_BMesh = 1, +} BooleanSolver; typedef struct MDefInfluence { int vertex; diff --git a/source/blender/makesdna/DNA_sdna_types.h b/source/blender/makesdna/DNA_sdna_types.h index 791aca77558..bd8f23f30c1 100644 --- a/source/blender/makesdna/DNA_sdna_types.h +++ b/source/blender/makesdna/DNA_sdna_types.h @@ -35,17 +35,17 @@ # # typedef struct SDNA { - const char *data; /* full copy of 'encoded' data */ + const char *data; /* full copy of 'encoded' data (when data_alloc is set, otherwise borrowed). */ int datalen; /* length of data */ bool data_alloc; int nr_names; /* total number of struct members */ - const char **names; /* struct member names */ + const char **names; /* struct member names */ int pointerlen; /* size of a pointer in bytes */ int nr_types; /* number of basic types + struct types */ - char **types; /* type names */ + const char **types; /* type names */ short *typelens; /* type lengths */ int nr_structs; /* number of struct types */ @@ -57,11 +57,6 @@ typedef struct SDNA { struct GHash *structs_map; /* ghash for faster lookups, * requires WITH_DNA_GHASH to be used for now */ - - /* wrong place for this really, its a simple - * cache for findstruct_nr. - */ - int lastfind; } SDNA; # diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 0bb6e866bf4..8c758c33dc5 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -52,6 +52,8 @@ endif() # SRC_DNA_INC is defined in the parent dir +add_cc_flags_custom_test(makesdna) + add_executable(makesdna ${SRC} ${SRC_DNA_INC}) # Output dna.c diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 9135d7bab7d..4db98bda7dd 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -39,6 +39,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <limits.h> #include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN @@ -133,39 +134,6 @@ * */ -/* ************************* ENDIAN STUFF ********************** */ - -/** - * converts a short between big/little endian. - */ -static short le_short(short temp) -{ - short new; - char *rt = (char *)&temp, *rtn = (char *)&new; - - rtn[0] = rt[1]; - rtn[1] = rt[0]; - - return new; -} - -/** - * converts an int between big/little endian. - */ -static int le_int(int temp) -{ - int new; - char *rt = (char *)&temp, *rtn = (char *)&new; - - rtn[0] = rt[3]; - rtn[1] = rt[2]; - rtn[2] = rt[1]; - rtn[3] = rt[0]; - - return new; -} - - /* ************************* MAKE DNA ********************** */ /* allowed duplicate code from makesdna.c */ @@ -280,37 +248,16 @@ static void printstruct(SDNA *sdna, short strnr) #endif /** - * Returns a pointer to the start of the struct info for the struct with the specified name. - */ -static short *findstruct_name(SDNA *sdna, const char *str) -{ - int a; - short *sp = NULL; - - - for (a = 0; a < sdna->nr_structs; a++) { - - sp = sdna->structs[a]; - - if (strcmp(sdna->types[sp[0]], str) == 0) { - return sp; - } - } - - return NULL; -} - -/** * Returns the index of the struct info for the struct with the specified name. */ -int DNA_struct_find_nr(SDNA *sdna, const char *str) +int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last) { const short *sp = NULL; - if (sdna->lastfind < sdna->nr_structs) { - sp = sdna->structs[sdna->lastfind]; + if (*index_last < sdna->nr_structs) { + sp = sdna->structs[*index_last]; if (strcmp(sdna->types[sp[0]], str) == 0) { - return sdna->lastfind; + return *index_last; } } @@ -323,7 +270,7 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str) if (index_p) { a = GET_INT_FROM_POINTER(*index_p); - sdna->lastfind = a; + *index_last = a; } else { a = -1; @@ -339,7 +286,7 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str) sp = sdna->structs[a]; if (strcmp(sdna->types[sp[0]], str) == 0) { - sdna->lastfind = a; + *index_last = a; return a; } } @@ -348,26 +295,51 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str) #endif } +int DNA_struct_find_nr(const SDNA *sdna, const char *str) +{ + unsigned int index_last_dummy = UINT_MAX; + return DNA_struct_find_nr_ex(sdna, str, &index_last_dummy); +} + /* ************************* END DIV ********************** */ /* ************************* READ DNA ********************** */ +BLI_INLINE const char *pad_up_4(const char *ptr) +{ + return (const char *)((((uintptr_t)ptr) + 3) & ~3); +} + /** * In sdna->data the data, now we convert that to something understandable */ -static void init_structDNA(SDNA *sdna, bool do_endian_swap) +static bool init_structDNA( + SDNA *sdna, bool do_endian_swap, + const char **r_error_message) { int *data, *verg, gravity_fix = -1; - intptr_t nr; short *sp; - char str[8], *cp; + char str[8]; verg = (int *)str; data = (int *)sdna->data; + /* clear pointers incase of error */ + sdna->names = NULL; + sdna->types = NULL; + sdna->structs = NULL; +#ifdef WITH_DNA_GHASH + sdna->structs_map = NULL; +#endif + strcpy(str, "SDNA"); - if (*data == *verg) { - + if (*data != *verg) { + *r_error_message = "SDNA error in SDNA file"; + return false; + } + else { + const char *cp; + data++; /* load names array */ @@ -375,20 +347,21 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap) if (*data == *verg) { data++; - if (do_endian_swap) sdna->nr_names = le_int(*data); - else sdna->nr_names = *data; + sdna->nr_names = *data; + if (do_endian_swap) { + BLI_endian_switch_int32(&sdna->nr_names); + } data++; sdna->names = MEM_callocN(sizeof(void *) * sdna->nr_names, "sdnanames"); } else { - printf("NAME error in SDNA file\n"); - return; + *r_error_message = "NAME error in SDNA file"; + return false; } - nr = 0; cp = (char *)data; - while (nr < sdna->nr_names) { + for (int nr = 0; nr < sdna->nr_names; nr++) { sdna->names[nr] = cp; /* "float gravity [3]" was parsed wrong giving both "gravity" and @@ -403,32 +376,31 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap) while (*cp) cp++; cp++; - nr++; } - nr = (intptr_t)cp; /* prevent BUS error */ - nr = (nr + 3) & ~3; - cp = (char *)nr; + + cp = pad_up_4(cp); /* load type names array */ data = (int *)cp; strcpy(str, "TYPE"); if (*data == *verg) { data++; - - if (do_endian_swap) sdna->nr_types = le_int(*data); - else sdna->nr_types = *data; + + sdna->nr_types = *data; + if (do_endian_swap) { + BLI_endian_switch_int32(&sdna->nr_types); + } data++; sdna->types = MEM_callocN(sizeof(void *) * sdna->nr_types, "sdnatypes"); } else { - printf("TYPE error in SDNA file\n"); - return; + *r_error_message = "TYPE error in SDNA file"; + return false; } - nr = 0; cp = (char *)data; - while (nr < sdna->nr_types) { + for (int nr = 0; nr < sdna->nr_types; nr++) { sdna->types[nr] = cp; /* this is a patch, to change struct names without a conflict with SDNA */ @@ -441,11 +413,9 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap) while (*cp) cp++; cp++; - nr++; } - nr = (intptr_t)cp; /* prevent BUS error */ - nr = (nr + 3) & ~3; - cp = (char *)nr; + + cp = pad_up_4(cp); /* load typelen array */ data = (int *)cp; @@ -456,20 +426,14 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap) sdna->typelens = sp; if (do_endian_swap) { - short a, *spo = sp; - - a = sdna->nr_types; - while (a--) { - spo[0] = le_short(spo[0]); - spo++; - } + BLI_endian_switch_int16_array(sp, sdna->nr_types); } sp += sdna->nr_types; } else { - printf("TLEN error in SDNA file\n"); - return; + *r_error_message = "TLEN error in SDNA file"; + return false; } if (sdna->nr_types & 1) sp++; /* prevent BUS error */ @@ -479,74 +443,90 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap) if (*data == *verg) { data++; - if (do_endian_swap) sdna->nr_structs = le_int(*data); - else sdna->nr_structs = *data; + sdna->nr_structs = *data; + if (do_endian_swap) { + BLI_endian_switch_int32(&sdna->nr_structs); + } data++; sdna->structs = MEM_callocN(sizeof(void *) * sdna->nr_structs, "sdnastrcs"); } else { - printf("STRC error in SDNA file\n"); - return; + *r_error_message = "STRC error in SDNA file"; + return false; } - nr = 0; sp = (short *)data; - while (nr < sdna->nr_structs) { + for (int nr = 0; nr < sdna->nr_structs; nr++) { sdna->structs[nr] = sp; if (do_endian_swap) { short a; - sp[0] = le_short(sp[0]); - sp[1] = le_short(sp[1]); + BLI_endian_switch_int16(&sp[0]); + BLI_endian_switch_int16(&sp[1]); a = sp[1]; sp += 2; while (a--) { - sp[0] = le_short(sp[0]); - sp[1] = le_short(sp[1]); + BLI_endian_switch_int16(&sp[0]); + BLI_endian_switch_int16(&sp[1]); sp += 2; } } else { sp += 2 * sp[1] + 2; } - - nr++; } + } - /* finally pointerlen: use struct ListBase to test it, never change the size of it! */ - sp = findstruct_name(sdna, "ListBase"); - /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */ - - sdna->pointerlen = sdna->typelens[sp[0]] / 2; - - if (sp[1] != 2 || (sdna->pointerlen != 4 && sdna->pointerlen != 8)) { - printf("ListBase struct error! Needs it to calculate pointerize.\n"); - exit(1); - /* well, at least sizeof(ListBase) is error proof! (ton) */ - } - + { /* second part of gravity problem, setting "gravity" type to void */ if (gravity_fix > -1) { - for (nr = 0; nr < sdna->nr_structs; nr++) { + for (int nr = 0; nr < sdna->nr_structs; nr++) { sp = sdna->structs[nr]; if (strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0) sp[10] = SDNA_TYPE_VOID; } } + } #ifdef WITH_DNA_GHASH + { /* create a ghash lookup to speed up */ sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->nr_structs); - for (nr = 0; nr < sdna->nr_structs; nr++) { + for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) { sp = sdna->structs[nr]; - BLI_ghash_insert(sdna->structs_map, sdna->types[sp[0]], SET_INT_IN_POINTER(nr)); + BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], SET_INT_IN_POINTER(nr)); } + } #endif + + /* Calculate 'sdna->pointerlen' */ + { + intptr_t nr = DNA_struct_find_nr(sdna, "ListBase"); + + /* should never happen, only with corrupt file for example */ + if (UNLIKELY(nr == -1)) { + *r_error_message = "ListBase struct error! Not found."; + return false; + } + + /* finally pointerlen: use struct ListBase to test it, never change the size of it! */ + sp = sdna->structs[nr]; + /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */ + + sdna->pointerlen = sdna->typelens[sp[0]] / 2; + + if (sp[1] != 2 || (sdna->pointerlen != 4 && sdna->pointerlen != 8)) { + *r_error_message = "ListBase struct error! Needs it to calculate pointerize."; + /* well, at least sizeof(ListBase) is error proof! (ton) */ + return false; + } } + + return true; } /** @@ -554,11 +534,11 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap) */ SDNA *DNA_sdna_from_data( const void *data, const int datalen, - bool do_endian_swap, bool data_alloc) + bool do_endian_swap, bool data_alloc, + const char **r_error_message) { SDNA *sdna = MEM_mallocN(sizeof(*sdna), "sdna"); - - sdna->lastfind = 0; + const char *error_message = NULL; sdna->datalen = datalen; if (data_alloc) { @@ -571,9 +551,44 @@ SDNA *DNA_sdna_from_data( } sdna->data_alloc = data_alloc; - init_structDNA(sdna, do_endian_swap); - - return sdna; + + if (init_structDNA(sdna, do_endian_swap, &error_message)) { + return sdna; + } + else { + if (r_error_message == NULL) { + fprintf(stderr, "Error decoding blend file SDNA: %s\n", error_message); + } + else { + *r_error_message = error_message; + } + DNA_sdna_free(sdna); + return NULL; + } +} + +/** + * Using globals is acceptable here, the data is read-only and only changes between Blender versions. + * + * So it is safe to create once and reuse. + */ +static SDNA *g_sdna = NULL; + +void DNA_sdna_current_init(void) +{ + g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, NULL); +} + +const struct SDNA *DNA_sdna_current_get(void) +{ + BLI_assert(g_sdna != NULL); + return g_sdna; +} + +void DNA_sdna_current_free(void) +{ + DNA_sdna_free(g_sdna); + g_sdna = NULL; } /* ******************** END READ DNA ********************** */ @@ -623,7 +638,7 @@ static void recurs_test_compflags(const SDNA *sdna, char *compflags, int structn * - 1 Struct is the same (can be loaded with straight memory copy after any necessary endian conversion) * - 2 Struct is different in some way (needs to be copied/converted field by field) */ -char *DNA_struct_get_compareflags(SDNA *oldsdna, SDNA *newsdna) +char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna) { int a, b; const short *sp_old, *sp_new; @@ -640,14 +655,19 @@ char *DNA_struct_get_compareflags(SDNA *oldsdna, SDNA *newsdna) /* we check all structs in 'oldsdna' and compare them with * the structs in 'newsdna' */ + unsigned int newsdna_index_last = 0; for (a = 0; a < oldsdna->nr_structs; a++) { sp_old = oldsdna->structs[a]; /* search for type in cur */ - sp_new = findstruct_name(newsdna, oldsdna->types[sp_old[0]]); - - if (sp_new) { + int sp_new_index = DNA_struct_find_nr_ex(newsdna, oldsdna->types[sp_old[0]], &newsdna_index_last); + + /* The next indices will almost always match */ + newsdna_index_last++; + + if (sp_new_index != -1) { + sp_new = newsdna->structs[sp_new_index]; /* initial assumption */ compflags[a] = SDNA_CMP_NOT_EQUAL; @@ -1037,8 +1057,8 @@ static void reconstruct_elem( * \param cur Where to put converted struct contents */ static void reconstruct_struct( - SDNA *newsdna, - SDNA *oldsdna, + const SDNA *newsdna, + const SDNA *oldsdna, const char *compflags, int oldSDNAnr, @@ -1056,6 +1076,10 @@ static void reconstruct_struct( char *cpo, *cpc; const char *name, *nameo; + unsigned int oldsdna_index_last = UINT_MAX; + unsigned int cursdna_index_last = UINT_MAX; + + if (oldSDNAnr == -1) return; if (curSDNAnr == -1) return; @@ -1090,8 +1114,8 @@ static void reconstruct_struct( cpo = find_elem(oldsdna, type, name, spo, data, &sppo); if (cpo) { - oldSDNAnr = DNA_struct_find_nr(oldsdna, type); - curSDNAnr = DNA_struct_find_nr(newsdna, type); + oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last); + curSDNAnr = DNA_struct_find_nr_ex(newsdna, type, &cursdna_index_last); /* array! */ mul = DNA_elem_array_size(name); @@ -1132,7 +1156,7 @@ static void reconstruct_struct( * \param oldSDNAnr Index of struct info within oldsdna * \param data Struct data */ -void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data) +void DNA_struct_switch_endian(const SDNA *oldsdna, int oldSDNAnr, char *data) { /* Recursive! * If element is a struct, call recursive. @@ -1141,6 +1165,7 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data) const short *spo, *spc; char *cur; const char *type, *name; + unsigned int oldsdna_index_last = UINT_MAX; if (oldSDNAnr == -1) return; firststructtypenr = *(oldsdna->structs[0]); @@ -1165,7 +1190,7 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data) /* where does the old data start (is there one?) */ char *cpo = find_elem(oldsdna, type, name, spo, data, NULL); if (cpo) { - oldSDNAnr = DNA_struct_find_nr(oldsdna, type); + oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last); mul = DNA_elem_array_size(name); elena = elen / mul; @@ -1223,7 +1248,9 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data) * \param data Array of struct data * \return An allocated reconstructed struct */ -void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data) +void *DNA_struct_reconstruct( + const SDNA *newsdna, const SDNA *oldsdna, + char *compflags, int oldSDNAnr, int blocks, void *data) { int a, curSDNAnr, curlen = 0, oldlen; const short *spo, *spc; @@ -1263,7 +1290,6 @@ void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int */ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name) { - const int SDNAnr = DNA_struct_find_nr(sdna, stype); const short * const spo = sdna->structs[SDNAnr]; const char * const cp = find_elem(sdna, vartype, name, spo, NULL, NULL); @@ -1273,7 +1299,6 @@ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const ch bool DNA_struct_elem_find(SDNA *sdna, const char *stype, const char *vartype, const char *name) { - const int SDNAnr = DNA_struct_find_nr(sdna, stype); if (SDNAnr != -1) { diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index b1f3d1757bc..ef159cf5930 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -348,7 +348,10 @@ blender_include_dirs_sys( "${GLEW_INCLUDE_PATH}" ) +add_cc_flags_custom_test(makesrna) + add_executable(makesrna ${SRC} ${SRC_RNA_INC} ${SRC_DNA_INC}) + target_link_libraries(makesrna bf_dna) target_link_libraries(makesrna bf_dna_blenlib) diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 983d3f659ef..af8fe78c0af 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -686,7 +686,7 @@ static void rna_ImagePreview_icon_pixels_float_set(PointerRNA *ptr, const float static int rna_ImagePreview_icon_id_get(PointerRNA *ptr) { /* Using a callback here allows us to only generate icon matching that preview when icon_id is requested. */ - return BKE_icon_preview_ensure((PreviewImage *)(ptr->data)); + return BKE_icon_preview_ensure(ptr->id.data, (PreviewImage *)(ptr->data)); } static void rna_ImagePreview_icon_reload(PreviewImage *prv) { diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 00b7df122ee..5a93e18a7dd 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -3127,8 +3127,11 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA RNA_parameter_list_free(¶ms); } } - /*else - printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);*/ +#if 0 + else { + printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier); + } +#endif #endif if (r_ptr) { @@ -3187,8 +3190,11 @@ bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) return false; } - /*else - printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/ +#if 0 + else { + printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier); + } +#endif #endif return false; } diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index bf2b091576e..7ff4eaea169 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -531,12 +531,18 @@ BlenderRNA *RNA_create(void) BlenderRNA *brna; brna = MEM_callocN(sizeof(BlenderRNA), "BlenderRNA"); + const char *error_message = NULL; - DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false); BLI_listbase_clear(&DefRNA.structs); DefRNA.error = 0; DefRNA.preprocess = 1; + DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, &error_message); + if (DefRNA.sdna == NULL) { + fprintf(stderr, "Error decoding SDNA: %s\n", error_message); + DefRNA.error = 1; + } + return brna; } diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index ffc78a1db97..be783e5373a 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1875,6 +1875,12 @@ static void rna_def_modifier_boolean(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem prop_solver_items[] = { + {eBooleanModifierSolver_BMesh, "BMESH", 0, "BMesh", "Use the BMesh boolean solver"}, + {eBooleanModifierSolver_Carve, "CARVE", 0, "Carve", "Use the Carve boolean solver"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "BooleanModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Boolean Modifier", "Boolean operations modifier"); RNA_def_struct_sdna(srna, "BooleanModifierData"); @@ -1891,35 +1897,17 @@ static void rna_def_modifier_boolean(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Operation", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); -#if 0 /* WITH_MOD_BOOLEAN */ - /* BMesh intersection options */ - prop = RNA_def_property(srna, "use_bmesh", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_Enabled); - RNA_def_property_ui_text(prop, "Use BMesh", "Use BMesh boolean calculation"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - - prop = RNA_def_property(srna, "use_bmesh_separate", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_Separate); - RNA_def_property_ui_text(prop, "Separate", "Keep edges separate"); + prop = RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_solver_items); + RNA_def_property_ui_text(prop, "Solver", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop = RNA_def_property(srna, "use_bmesh_dissolve", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_NoDissolve); - RNA_def_property_ui_text(prop, "Dissolve", "Dissolve verts created from tessellated intersection"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - - prop = RNA_def_property(srna, "use_bmesh_connect_regions", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_NoConnectRegions); - RNA_def_property_ui_text(prop, "Calculate Holes", "Connect regions (needed for hole filling)"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - - prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_DISTANCE); - RNA_def_property_float_sdna(prop, NULL, "threshold"); + prop = RNA_def_property(srna, "double_threshold", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "double_threshold"); RNA_def_property_range(prop, 0, 1.0f); - RNA_def_property_ui_range(prop, 0, 1, 1, 7); - RNA_def_property_ui_text(prop, "Threshold", ""); + RNA_def_property_ui_range(prop, 0, 1, 0.0001, 7); + RNA_def_property_ui_text(prop, "Overlap Threshold", "Threshold for checking overlapping geometry"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); -#endif } static void rna_def_modifier_array(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index e8efb202531..127c6d4d95e 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1002,7 +1002,7 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value) ob->gameflag &= ~(OB_SENSOR | OB_OCCLUDER | OB_DYNAMIC | OB_RIGID_BODY | OB_SOFT_BODY | OB_ACTOR | OB_ANISOTROPIC_FRICTION | OB_DO_FH | OB_ROT_FH | OB_COLLISION_RESPONSE | OB_NAVMESH); /* When we switch to character physics and the collision bounds is set to triangle mesh - we have to change collision bounds because triangle mesh is not supported by Characters*/ + * we have to change collision bounds because triangle mesh is not supported by Characters */ if ((ob->gameflag & OB_BOUNDS) && ob->collision_boundtype == OB_BOUND_TRIANGLE_MESH) { ob->boundtype = ob->collision_boundtype = OB_BOUND_BOX; } diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 3f418fa16f3..da0f5aa3923 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -33,7 +33,7 @@ */ // #ifdef DEBUG_TIME -// #define USE_BMESH +#define USE_BMESH #ifdef WITH_MOD_BOOLEAN # define USE_CARVE WITH_MOD_BOOLEAN #endif @@ -71,6 +71,14 @@ #include "PIL_time_utildefines.h" #endif +static void initData(ModifierData *md) +{ + BooleanModifierData *bmd = (BooleanModifierData *)md; + + bmd->solver = eBooleanModifierSolver_BMesh; + bmd->double_threshold = 1e-6f; +} + static void copyData(ModifierData *md, ModifierData *target) { #if 0 @@ -222,7 +230,9 @@ static DerivedMesh *applyModifier_bmesh( #ifdef DEBUG_TIME TIMEIT_START(boolean_bmesh); #endif - bm = BM_mesh_create_ex(&allocsize, ); + bm = BM_mesh_create( + &allocsize, + &((struct BMeshCreateParams){.use_toolflags = false,})); DM_to_bmesh_ex(dm_other, bm, true); DM_to_bmesh_ex(dm, bm, true); @@ -296,16 +306,21 @@ static DerivedMesh *applyModifier_bmesh( * currently this is ok for 'BM_mesh_intersect' */ // BM_mesh_normals_update(bm); + /* change for testing */ + bool use_separate = false; + bool use_dissolve = true; + bool use_island_connect = true; + BM_mesh_intersect( bm, looptris, tottri, bm_face_isect_pair, NULL, false, - (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_Separate) != 0, - (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoDissolve) == 0, - (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoConnectRegions) == 0, + use_separate, + use_dissolve, + use_island_connect, bmd->operation, - bmd->threshold); + bmd->double_threshold); MEM_freeN(looptris); } @@ -409,15 +424,14 @@ static DerivedMesh *applyModifier( ModifierApplyFlag flag) { BooleanModifierData *bmd = (BooleanModifierData *)md; - const int method = (bmd->bm_flag & eBooleanModifierBMeshFlag_Enabled) ? 1 : 0; - switch (method) { + switch (bmd->solver) { #ifdef USE_CARVE - case 0: + case eBooleanModifierSolver_Carve: return applyModifier_carve(md, ob, derivedData, flag); #endif #ifdef USE_BMESH - case 1: + case eBooleanModifierSolver_BMesh: return applyModifier_bmesh(md, ob, derivedData, flag); #endif default: @@ -441,7 +455,7 @@ ModifierTypeInfo modifierType_Boolean = { /* deformMatricesEM */ NULL, /* applyModifier */ applyModifier, /* applyModifierEM */ NULL, - /* initData */ NULL, + /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ NULL, /* isDisabled */ isDisabled, diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index eb1594688c7..d5973baeadb 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -207,20 +207,21 @@ PyObject *BPyInit_bmesh(void) /* bmesh.types */ PyModule_AddObject(mod, "types", (submodule = BPyInit_bmesh_types())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); + /* bmesh.ops (not a real module, exposes module like access). */ PyModule_AddObject(mod, "ops", (submodule = BPyInit_bmesh_ops())); - /* PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); */ + /* PyDict_SetItemString(sys_modules, PyModule_GetNameObject(submodule), submodule); */ PyDict_SetItemString(sys_modules, "bmesh.ops", submodule); /* fake module */ Py_INCREF(submodule); PyModule_AddObject(mod, "utils", (submodule = BPyInit_bmesh_utils())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); PyModule_AddObject(mod, "geometry", (submodule = BPyInit_bmesh_geometry())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); return mod; diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index db8ed072722..11646f3f3df 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -1560,7 +1560,7 @@ PyObject *BPyInit_idprop(void) /* idprop.types */ PyModule_AddObject(mod, "types", (submodule = BPyInit_idprop_types())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); return mod; diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 7f13a7a4d94..72dec55e50b 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -177,7 +177,7 @@ PyObject *PyC_FromArray(const void *array, int length, const PyTypeObject *type, /** * Caller needs to ensure tuple is uninitialized. - * Handy for filling a typle with None for eg. + * Handy for filling a tuple with None for eg. */ void PyC_Tuple_Fill(PyObject *tuple, PyObject *value) { @@ -367,11 +367,12 @@ PyObject *PyC_FrozenSetFromStrings(const char **strings) } -/* similar to PyErr_Format(), +/** + * Similar to #PyErr_Format(), * - * implementation - we cant actually preprend the existing exception, + * Implementation - we cant actually prepend the existing exception, * because it could have _any_ arguments given to it, so instead we get its - * __str__ output and raise our own exception including it. + * ``__str__`` output and raise our own exception including it. */ PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...) { @@ -748,6 +749,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...) /* set the value so we can access it */ PyDict_SetItemString(py_dict, "values", values); + Py_DECREF(values); py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict); diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 17617a231b2..727d980b182 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -236,7 +236,7 @@ static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *clos PyDoc_STRVAR(bpy_app_binary_path_python_doc, "String, the path to the python executable (read-only)" ); -static PyObject *bpy_app_binary_path_python_get(PyObject *UNUSED(self), void *UNUSED(closure)) +static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(closure)) { /* refcount is held in BlenderAppType.tp_dict */ static PyObject *ret = NULL; @@ -248,7 +248,7 @@ static PyObject *bpy_app_binary_path_python_get(PyObject *UNUSED(self), void *UN fullpath, sizeof(fullpath), PY_MAJOR_VERSION, PY_MINOR_VERSION); ret = PyC_UnicodeFromByte(fullpath); - PyDict_SetItemString(BlenderAppType.tp_dict, "binary_path_python", ret); + PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(self), ret); } else { Py_INCREF(ret); @@ -356,10 +356,10 @@ static PyGetSetDef bpy_app_getsets[] = { static void py_struct_seq_getset_init(void) { /* tricky dynamic members, not to py-spec! */ - PyGetSetDef *getset; - - for (getset = bpy_app_getsets; getset->name; getset++) { - PyDict_SetItemString(BlenderAppType.tp_dict, getset->name, PyDescr_NewGetSet(&BlenderAppType, getset)); + for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) { + PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset); + PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item); + Py_DECREF(item); } } /* end dynamic bpy.app */ diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 9b477e384db..65b6bd501ce 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -110,9 +110,11 @@ static void bpy_pydriver_update_dict(const float evaltime) bpy_pydriver_InternStr__frame = PyUnicode_FromString("frame"); } + PyObject *item = PyFloat_FromDouble(evaltime); PyDict_SetItem(bpy_pydriver_Dict, bpy_pydriver_InternStr__frame, - PyFloat_FromDouble(evaltime)); + item); + Py_DECREF(item); bpy_pydriver_evaltime_prev = evaltime; } @@ -301,7 +303,10 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime) /* try to add to dictionary */ /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */ - if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) { + if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) { + Py_DECREF(driver_arg); + } + else { /* this target failed - bad name */ if (targets_ok) { /* first one - print some extra info for easier identification */ diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index a120e4886e0..37a7e0e23dd 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -39,7 +39,6 @@ #include "BLO_readfile.h" -#include "BKE_global.h" #include "BKE_main.h" #include "BKE_library.h" #include "BKE_idcode.h" @@ -186,6 +185,7 @@ PyDoc_STRVAR(bpy_lib_load_doc, static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"filepath", "link", "relative", NULL}; + Main *bmain = CTX_data_main(BPy_GetContext()); BPy_Library *ret; const char *filename = NULL; bool is_rel = false, is_link = false; @@ -204,7 +204,7 @@ static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject * BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath)); BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath)); - BLI_path_abs(ret->abspath, G.main->name); + BLI_path_abs(ret->abspath, bmain->name); ret->blo_handle = NULL; ret->flag = ((is_link ? FILE_LINK : 0) | @@ -222,19 +222,16 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype) int totnames; names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames); + list = PyList_New(totnames); if (names) { int counter = 0; - list = PyList_New(totnames); for (l = names; l; l = l->next) { PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); counter++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ } - else { - list = PyList_New(0); - } return list; } @@ -264,8 +261,13 @@ static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args)) if (BKE_idcode_is_linkable(code)) { const char *name_plural = BKE_idcode_to_name_plural(code); PyObject *str = PyUnicode_FromString(name_plural); - PyDict_SetItem(self->dict, str, PyList_New(0)); - PyDict_SetItem(from_dict, str, _bpy_names(self, code)); + PyObject *item; + + PyDict_SetItem(self->dict, str, item = PyList_New(0)); + Py_DECREF(item); + PyDict_SetItem(from_dict, str, item = _bpy_names(self, code)); + Py_DECREF(item); + Py_DECREF(str); } } @@ -346,48 +348,44 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) /* loop */ Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; - PyObject *item; - const char *item_str; for (i = 0; i < size; i++) { - item = PyList_GET_ITEM(ls, i); - item_str = _PyUnicode_AsString(item); + PyObject *item_src = PyList_GET_ITEM(ls, i); + PyObject *item_dst; /* must be set below */ + const char *item_idname = _PyUnicode_AsString(item_src); - // printf(" %s\n", item_str); + // printf(" %s\n", item_idname); - if (item_str) { - ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_str); + if (item_idname) { + ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_idname); if (id) { #ifdef USE_RNA_DATABLOCKS /* swap name for pointer to the id */ - Py_DECREF(item); - item = PyCapsule_New((void *)id, NULL, NULL); + item_dst = PyCapsule_New((void *)id, NULL, NULL); +#else + /* leave as is */ + continue; #endif } else { - bpy_lib_exit_warn_idname(self, name_plural, item_str); + bpy_lib_exit_warn_idname(self, name_plural, item_idname); /* just warn for now */ /* err = -1; */ -#ifdef USE_RNA_DATABLOCKS - item = Py_INCREF_RET(Py_None); -#endif + item_dst = Py_INCREF_RET(Py_None); } /* ID or None */ } else { /* XXX, could complain about this */ - bpy_lib_exit_warn_type(self, item); + bpy_lib_exit_warn_type(self, item_src); PyErr_Clear(); - -#ifdef USE_RNA_DATABLOCKS - item = Py_INCREF_RET(Py_None); -#endif + item_dst = Py_INCREF_RET(Py_None); } -#ifdef USE_RNA_DATABLOCKS - PyList_SET_ITEM(ls, i, item); -#endif + /* item_dst must be new or already incref'd */ + Py_DECREF(item_src); + PyList_SET_ITEM(ls, i, item_dst); } } } @@ -410,7 +408,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) /* copied from wm_operator.c */ { /* mark all library linked objects to be updated */ - BKE_main_lib_objects_recalc_all(G.main); + BKE_main_lib_objects_recalc_all(bmain); /* append, rather than linking */ if ((self->flag & FILE_LINK) == 0) { @@ -422,6 +420,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) /* finally swap the capsules for real bpy objects * important since BLO_library_append_end initializes NodeTree types used by srna->refine */ +#ifdef USE_RNA_DATABLOCKS { int idcode_step = 0, idcode; while ((idcode = BKE_idcode_iter_step(&idcode_step))) { @@ -451,6 +450,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) } } } +#endif /* USE_RNA_DATABLOCKS */ Py_RETURN_NONE; } diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index c3bb588f7eb..50dd4618166 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -330,10 +330,10 @@ PyObject *GPU_initPython(void) /* gpu.offscreen */ PyModule_AddObject(module, "offscreen", (submodule = BPyInit_gpu_offscreen())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); - PyDict_SetItemString(PyImport_GetModuleDict(), "gpu", module); + PyDict_SetItem(PyImport_GetModuleDict(), PyModule_GetNameObject(module), module); return module; } diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 635090869ea..5c505247a97 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -638,30 +638,30 @@ PyMODINIT_FUNC PyInit_mathutils(void) /* XXX, python doesnt do imports with this usefully yet * 'from mathutils.geometry import PolyFill' * ...fails without this. */ - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate())); /* XXX, python doesnt do imports with this usefully yet * 'from mathutils.geometry import PolyFill' * ...fails without this. */ - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); #ifndef MATH_STANDALONE /* Noise submodule */ PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); /* BVHTree submodule */ PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); /* KDTree submodule */ PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); #endif diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m index d42d0ee8ebb..ba7ee0a8936 100644 --- a/source/blender/quicktime/apple/qtkit_import.m +++ b/source/blender/quicktime/apple/qtkit_import.m @@ -200,7 +200,7 @@ static ImBuf *nsImageToiBuf(NSImage *sourceImage, int width, int height) /* Convert the image in a RGBA 32bit format */ /* As Core Graphics does not support contextes with non premutliplied alpha, - we need to get alpha key values in a separate batch */ + * we need to get alpha key values in a separate batch */ /* First get RGB values w/o Alpha to avoid pre-multiplication, 32bit but last byte is unused */ blBitmapFormatImageRGB = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 6de5da3795a..b3a5ccdae17 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -180,6 +180,7 @@ struct Render { float jit[32][2]; float mblur_jit[32][2]; ListBase *qmcsamplers; + int num_qmc_samplers; /* shadow counter, detect shadow-reuse for shaders */ int shadowsamplenr[BLENDER_MAX_THREADS]; diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 308903c6c6d..7254fd25ee6 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -90,7 +90,7 @@ extern void ray_shadow(ShadeInput *shi, LampRen *lar, float shadfac[4]); extern void ray_trace(ShadeInput *shi, ShadeResult *); extern void ray_ao(ShadeInput *shi, float ao[3], float env[3]); extern void init_jitter_plane(LampRen *lar); -extern void init_ao_sphere(struct World *wrld); +extern void init_ao_sphere(Render *re, struct World *wrld); extern void init_render_qmcsampler(Render *re); extern void free_render_qmcsampler(Render *re); diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index f511042749e..2104315dc00 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -145,8 +145,8 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *i if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v2, face->v3, &l, uv)) { /* check if intersection is within ray length */ if (l > -RE_RAYTRACE_EPSILON && l < *lambda) { - r_uv[0] = uv[0]; - r_uv[1] = uv[1]; + r_uv[0] = -uv[0]; + r_uv[1] = -uv[1]; *lambda = l; return 1; } @@ -157,8 +157,8 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *i if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v3, face->v4, &l, uv)) { /* check if intersection is within ray length */ if (l > -RE_RAYTRACE_EPSILON && l < *lambda) { - r_uv[0] = uv[0]; - r_uv[1] = uv[1]; + r_uv[0] = -uv[0]; + r_uv[1] = -uv[1]; *lambda = l; return 2; } diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 3dcde1f4bb1..468d66f6065 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -3961,7 +3961,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l if (re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) - init_ao_sphere(&re->wrld); + init_ao_sphere(re, &re->wrld); } /* still bad... doing all */ @@ -4687,7 +4687,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, if (re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) - init_ao_sphere(&re->wrld); + init_ao_sphere(re, &re->wrld); } /* still bad... doing all */ diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index c5c3b6bbf94..b3d31e3b93a 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -115,6 +115,8 @@ typedef struct OcclusionTree { int doindirect; OcclusionCache *cache; + + int num_threads; } OcclusionTree; typedef struct OcclusionThread { @@ -641,6 +643,7 @@ static void occ_build_sh_normalize(OccNode *node) static OcclusionTree *occ_tree_build(Render *re) { + const int num_threads = re->r.threads; OcclusionTree *tree; ObjectInstanceRen *obi; ObjectRen *obr; @@ -679,7 +682,7 @@ static OcclusionTree *occ_tree_build(Render *re) BLI_memarena_use_calloc(tree->arena); if (re->wrld.aomode & WO_AOCACHE) - tree->cache = MEM_callocN(sizeof(OcclusionCache) * BLENDER_MAX_THREADS, "OcclusionCache"); + tree->cache = MEM_callocN(sizeof(OcclusionCache) * num_threads, "OcclusionCache"); tree->face = MEM_callocN(sizeof(OccFace) * totface, "OcclusionFace"); tree->co = MEM_callocN(sizeof(float) * 3 * totface, "OcclusionCo"); @@ -730,9 +733,11 @@ static OcclusionTree *occ_tree_build(Render *re) if (!(re->test_break(re->tbh))) occ_build_sh_normalize(tree->root); - for (a = 0; a < BLENDER_MAX_THREADS; a++) + for (a = 0; a < num_threads; a++) tree->stack[a] = MEM_callocN(sizeof(OccNode) * TOTCHILD * (tree->maxdepth + 1), "OccStack"); + tree->num_threads = num_threads; + return tree; } @@ -742,7 +747,7 @@ static void occ_free_tree(OcclusionTree *tree) if (tree) { if (tree->arena) BLI_memarena_free(tree->arena); - for (a = 0; a < BLENDER_MAX_THREADS; a++) + for (a = 0; a < tree->num_threads; a++) if (tree->stack[a]) MEM_freeN(tree->stack[a]); if (tree->occlusion) MEM_freeN(tree->occlusion); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 100d87a037a..49d6e5a0d7f 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -354,7 +354,7 @@ Scene *RE_GetScene(Render *re) * Same as #RE_AcquireResultImage but creating the necessary views to store the result * fill provided result struct with a copy of thew views of what is done so far the * #RenderResult.views #ListBase needs to be freed after with #RE_ReleaseResultImageViews -*/ + */ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) { memset(rr, 0, sizeof(RenderResult)); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 9aac5ed1f1d..26a0b0c71b4 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -174,10 +174,11 @@ void freeraytree(Render *re) #ifdef RE_RAYCOUNTER { + const int num_threads = re->r.threads; RayCounter sum; memset(&sum, 0, sizeof(sum)); int i; - for (i=0; i<BLENDER_MAX_THREADS; i++) + for (i=0; i<num_threads; i++) RE_RC_MERGE(&sum, re_rc_counter+i); RE_RC_INFO(&sum); } @@ -1186,7 +1187,9 @@ static void QMC_sampleHemiCosine(float vec[3], QMCSampler *qsa, int thread, int /* called from convertBlenderScene.c */ void init_render_qmcsampler(Render *re) { - re->qmcsamplers= MEM_callocN(sizeof(ListBase)*BLENDER_MAX_THREADS, "QMCListBase"); + const int num_threads = re->r.threads; + re->qmcsamplers= MEM_callocN(sizeof(ListBase)*num_threads, "QMCListBase"); + re->num_qmc_samplers = num_threads; } static QMCSampler *get_thread_qmcsampler(Render *re, int thread, int type, int tot) @@ -1220,7 +1223,7 @@ void free_render_qmcsampler(Render *re) if (re->qmcsamplers) { QMCSampler *qsa, *next; int a; - for (a=0; a<BLENDER_MAX_THREADS; a++) { + for (a = 0; a < re->num_qmc_samplers; a++) { for (qsa=re->qmcsamplers[a].first; qsa; qsa=next) { next= qsa->next; QMC_freeSampler(qsa); @@ -1695,9 +1698,10 @@ static void DS_energy(float *sphere, int tot, float vec[3]) /* called from convertBlenderScene.c */ /* creates an equally distributed spherical sample pattern */ /* and allocates threadsafe memory */ -void init_ao_sphere(World *wrld) +void init_ao_sphere(Render *re, World *wrld) { /* fixed random */ + const int num_threads = re->r.threads; RNG *rng; float *fp; int a, tot, iter= 16; @@ -1721,7 +1725,7 @@ void init_ao_sphere(World *wrld) } /* tables */ - wrld->aotables= MEM_mallocN(BLENDER_MAX_THREADS*3*tot*sizeof(float), "AO tables"); + wrld->aotables= MEM_mallocN(num_threads*3*tot*sizeof(float), "AO tables"); BLI_rng_free(rng); } diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 513cfa6df7d..b4a14f5337d 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -3653,7 +3653,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) if (firsttime) { BLI_lock_thread(LOCK_IMAGE); if (firsttime) { - for (a=0; a<BLENDER_MAX_THREADS; a++) { + const int num_threads = BLI_system_thread_count(); + for (a = 0; a < num_threads; a++) { memset(&imatex[a], 0, sizeof(Tex)); BKE_texture_default(&imatex[a]); imatex[a].type= TEX_IMAGE; diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index 553710b4367..26ca3ad50e0 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -279,13 +279,19 @@ static void build_Rd_table(ScatterSettings *ss) for (i= 0; i < size; i++) { r= i*(RD_TABLE_RANGE/RD_TABLE_SIZE); - /*if (r < ss->invsigma_t_*ss->invsigma_t_) - r= ss->invsigma_t_*ss->invsigma_t_;*/ +#if 0 + if (r < ss->invsigma_t_*ss->invsigma_t_) { + r= ss->invsigma_t_*ss->invsigma_t_; + } +#endif ss->tableRd[i]= Rd(ss, sqrtf(r)); r= i*(RD_TABLE_RANGE_2/RD_TABLE_SIZE); - /*if (r < ss->invsigma_t_) - r= ss->invsigma_t_;*/ +#if 0 + if (r < ss->invsigma_t_) { + r= ss->invsigma_t_; + } +#endif ss->tableRd2[i]= Rd(ss, r); } } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 729af731dfe..fe257cc4c41 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -482,8 +482,6 @@ static void wm_file_read_post(bContext *C, bool is_startup_file) BPY_python_reset(C); addons_loaded = true; } -#else - UNUSED_VARS(is_startup_file); #endif /* WITH_PYTHON */ WM_operatortype_last_properties_clear_all(); @@ -492,8 +490,12 @@ static void wm_file_read_post(bContext *C, bool is_startup_file) BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); - /* would otherwise be handled by event loop */ - if (G.background) { + /* Would otherwise be handled by event loop. + * + * Disabled for startup file, since it causes problems when PyDrivers are used in the startup file. + * While its possible state of startup file may be wrong, + * in this case users nearly always load a file to replace the startup file. */ + if (G.background && (is_startup_file == false)) { Main *bmain = CTX_data_main(C); BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C)); } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 9d1083bbf63..3022d865460 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -40,6 +40,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_genfile.h" #include "DNA_scene_types.h" #include "DNA_userdef_types.h" #include "DNA_windowmanager_types.h" @@ -584,6 +585,8 @@ void WM_exit_ext(bContext *C, const bool do_python) GHOST_DisposeSystemPaths(); + DNA_sdna_current_free(); + BLI_threadapi_exit(); BKE_blender_atexit(); diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 206007b8d8b..ca841954b16 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -63,6 +63,8 @@ if(WIN32 AND NOT UNIX) COMPONENT Blenderplayer DESTINATION ".") +add_cc_flags_custom_test(blenderplayer) + elseif(APPLE) add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c) # setup Info.plist diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 4e8dd6f9fd3..d8435284096 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -222,6 +222,8 @@ if(WITH_BUILDINFO) add_dependencies(buildinfoobj buildinfo) endif() +add_cc_flags_custom_test(blender) + # message(STATUS "Configuring blender") if(WITH_PYTHON_MODULE) add_definitions(-DWITH_PYTHON_MODULE) diff --git a/source/creator/creator.c b/source/creator/creator.c index bd4db12888f..85c4e5b0681 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -42,6 +42,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_genfile.h" + #include "BLI_args.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -349,6 +351,8 @@ int main( BLI_threadapi_init(); + DNA_sdna_current_init(); + BKE_blender_globals_init(); /* blender.c */ IMB_init(); diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index c89cdea4e29..c3c76a0d1d3 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -739,8 +739,6 @@ static const char arg_handle_debug_mode_generic_set_doc_handlers[] = "\n\tEnable debug messages for event handling"; static const char arg_handle_debug_mode_generic_set_doc_wm[] = "\n\tEnable debug messages for the window manager, also prints every operator call"; -static const char arg_handle_debug_mode_generic_set_doc_all[] = -"\n\tEnable all debug messages (excludes libmv)"; static const char arg_handle_debug_mode_generic_set_doc_jobs[] = "\n\tEnable time profiling for background jobs."; static const char arg_handle_debug_mode_generic_set_doc_gpu[] = @@ -758,6 +756,20 @@ static int arg_handle_debug_mode_generic_set(int UNUSED(argc), const char **UNUS return 0; } +static const char arg_handle_debug_mode_all_doc[] = +"\n\tEnable all debug messages"; +static int arg_handle_debug_mode_all(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) +{ + G.debug |= G_DEBUG_ALL; +#ifdef WITH_LIBMV + libmv_startDebugLogging(); +#endif +#ifdef WITH_CYCLES_LOGGING + CCL_start_debug_logging(); +#endif + return 0; +} + #ifdef WITH_LIBMV static const char arg_handle_debug_mode_libmv_doc[] = "\n\tEnable debug messages from libmv library" @@ -1791,8 +1803,7 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) CB_EX(arg_handle_debug_mode_generic_set, handlers), (void *)G_DEBUG_HANDLERS); BLI_argsAdd(ba, 1, NULL, "--debug-wm", CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM); - BLI_argsAdd(ba, 1, NULL, "--debug-all", - CB_EX(arg_handle_debug_mode_generic_set, all), (void *)G_DEBUG_ALL); + BLI_argsAdd(ba, 1, NULL, "--debug-all", CB(arg_handle_debug_mode_all), NULL); BLI_argsAdd(ba, 1, NULL, "--debug-fpe", CB(arg_handle_debug_fpe_set), NULL); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 25936b34fde..fd2e723741c 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -163,7 +163,9 @@ void SCA_PythonController::SetNamespace(PyObject* pythondictionary) /* Without __file__ set the sys.argv[0] is used for the filename * which ends up with lines from the blender binary being printed in the console */ - PyDict_SetItemString(m_pythondictionary, "__file__", PyUnicode_From_STR_String(m_scriptName)); + PyObject *value = PyUnicode_From_STR_String(m_scriptName); + PyDict_SetItemString(m_pythondictionary, "__file__", value); + Py_DECREF(value); } #endif diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp index 19aae46f2a3..9a96a7b0334 100644 --- a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp +++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp @@ -113,11 +113,15 @@ PyObject *SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBU { SCA_PythonKeyboard* self = static_cast<SCA_PythonKeyboard*>(self_v); - for (int i=SCA_IInputDevice::KX_BEGINKEY; i<=SCA_IInputDevice::KX_ENDKEY; i++) - { + for (int i = SCA_IInputDevice::KX_BEGINKEY; i <= SCA_IInputDevice::KX_ENDKEY; i++) { const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); - - PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); + PyObject *key = PyLong_FromLong(i); + PyObject *value = PyLong_FromLong(inevent.m_status); + + PyDict_SetItem(self->m_event_dict, key, value); + + Py_DECREF(key); + Py_DECREF(value); } Py_INCREF(self->m_event_dict); return self->m_event_dict; @@ -129,12 +133,18 @@ PyObject *SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PY PyDict_Clear(self->m_event_dict); - for (int i=SCA_IInputDevice::KX_BEGINKEY; i<=SCA_IInputDevice::KX_ENDKEY; i++) - { + for (int i = SCA_IInputDevice::KX_BEGINKEY; i <= SCA_IInputDevice::KX_ENDKEY; i++) { const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); - if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) - PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); + if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) { + PyObject *key = PyLong_FromLong(i); + PyObject *value = PyLong_FromLong(inevent.m_status); + + PyDict_SetItem(self->m_event_dict, key, value); + + Py_DECREF(key); + Py_DECREF(value); + } } Py_INCREF(self->m_event_dict); return self->m_event_dict; diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.cpp b/source/gameengine/GameLogic/SCA_PythonMouse.cpp index 1617f714113..184b306a665 100644 --- a/source/gameengine/GameLogic/SCA_PythonMouse.cpp +++ b/source/gameengine/GameLogic/SCA_PythonMouse.cpp @@ -96,11 +96,15 @@ PyObject *SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_ { SCA_PythonMouse* self = static_cast<SCA_PythonMouse*>(self_v); - for (int i=SCA_IInputDevice::KX_BEGINMOUSE; i<=SCA_IInputDevice::KX_ENDMOUSE; i++) - { - const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); - - PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); + for (int i = SCA_IInputDevice::KX_BEGINMOUSE; i <= SCA_IInputDevice::KX_ENDMOUSE; i++) { + const SCA_InputEvent &inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); + PyObject *key = PyLong_FromLong(i); + PyObject *value = PyLong_FromLong(inevent.m_status); + + PyDict_SetItem(self->m_event_dict, key, value); + + Py_DECREF(key); + Py_DECREF(value); } Py_INCREF(self->m_event_dict); return self->m_event_dict; @@ -112,12 +116,19 @@ PyObject *SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATT PyDict_Clear(self->m_event_dict); - for (int i=SCA_IInputDevice::KX_BEGINMOUSE; i<=SCA_IInputDevice::KX_ENDMOUSE; i++) - { - const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); + for (int i = SCA_IInputDevice::KX_BEGINMOUSE; i <= SCA_IInputDevice::KX_ENDMOUSE; i++) { + const SCA_InputEvent &inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i); - if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) - PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status)); + if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) { + + PyObject *key = PyLong_FromLong(i); + PyObject *value = PyLong_FromLong(inevent.m_status); + + PyDict_SetItem(self->m_event_dict, key, value); + + Py_DECREF(key); + Py_DECREF(value); + } } Py_INCREF(self->m_event_dict); return self->m_event_dict; diff --git a/source/tools b/source/tools new file mode 160000 +Subproject 373945d0978b6601c55c9d5879e0f488b18515c |