diff --git a/.arcconfig b/.arcconfig deleted file mode 100644 index 548af935888c..000000000000 --- a/.arcconfig +++ /dev/null @@ -1,8 +0,0 @@ -{ - "project_id" : "Blender", - "conduit_uri" : "https://developer.blender.org/", - "phabricator.uri" : "https://developer.blender.org/", - "git.default-relative-commit" : "origin/master", - "arc.land.update.default" : "rebase", - "arc.land.onto.default" : "master" -} diff --git a/.clang-format b/.clang-format index 7e67aae1111d..967cb046a11c 100644 --- a/.clang-format +++ b/.clang-format @@ -236,6 +236,8 @@ ForEachMacros: - LOOP_UNSELECTED_POINTS - LOOP_VISIBLE_KEYS - LOOP_VISIBLE_POINTS + - LIGHT_FOREACH_BEGIN_DIRECTIONAL + - LIGHT_FOREACH_BEGIN_LOCAL - LISTBASE_CIRCULAR_BACKWARD_BEGIN - LISTBASE_CIRCULAR_FORWARD_BEGIN - LISTBASE_FOREACH diff --git a/CMakeLists.txt b/CMakeLists.txt index 1445b0a87e25..7b61275522a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -524,7 +524,7 @@ endif() if(NOT APPLE) option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON) option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF) - set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 gfx1100 gfx1101 gfx1102 CACHE STRING "AMD HIP architectures to build binaries for") + set(CYCLES_HIP_BINARIES_ARCH gfx900 gfx906 gfx90c gfx902 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 gfx1100 gfx1101 gfx1102 CACHE STRING "AMD HIP architectures to build binaries for") mark_as_advanced(WITH_CYCLES_DEVICE_HIP) mark_as_advanced(CYCLES_HIP_BINARIES_ARCH) endif() @@ -625,8 +625,10 @@ mark_as_advanced( # Vulkan option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (only for development)" OFF) +option(WITH_VULKAN_GUARDEDALLOC "Use guardedalloc for host allocations done inside Vulkan (development option)" OFF) mark_as_advanced( WITH_VULKAN_BACKEND + WITH_VULKAN_GUARDEDALLOC ) # Metal diff --git a/GNUmakefile b/GNUmakefile index a6b041597c39..f87e5fee972b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -299,7 +299,11 @@ else ifneq ("$(wildcard $(DEPS_BUILD_DIR)/build.ninja)","") DEPS_BUILD_COMMAND:=ninja else - DEPS_BUILD_COMMAND:=make -s + ifeq ($(OS), Darwin) + DEPS_BUILD_COMMAND:=make -s + else + DEPS_BUILD_COMMAND:="$(BLENDER_DIR)/build_files/build_environment/linux/make_deps_wrapper.sh" -s + endif endif endif @@ -398,7 +402,7 @@ endif deps: .FORCE @echo - @echo Configuring dependencies in \"$(DEPS_BUILD_DIR)\" + @echo Configuring dependencies in \"$(DEPS_BUILD_DIR)\", install to \"$(DEPS_INSTALL_DIR)\" @cmake -H"$(DEPS_SOURCE_DIR)" \ -B"$(DEPS_BUILD_DIR)" \ diff --git a/build_files/build_environment/cmake/gmp.cmake b/build_files/build_environment/cmake/gmp.cmake index ffab5ed00e56..f19d2ea3c636 100644 --- a/build_files/build_environment/cmake/gmp.cmake +++ b/build_files/build_environment/cmake/gmp.cmake @@ -22,7 +22,7 @@ elseif(UNIX AND NOT APPLE) ) endif() -# Boolean crashes with Arm assembly, see T103423. +# Boolean crashes with Arm assembly, see #103423. if(BLENDER_PLATFORM_ARM) set(GMP_OPTIONS ${GMP_OPTIONS} diff --git a/build_files/build_environment/linux/make_deps_wrapper.sh b/build_files/build_environment/linux/make_deps_wrapper.sh new file mode 100755 index 000000000000..2e2d00a9efc6 --- /dev/null +++ b/build_files/build_environment/linux/make_deps_wrapper.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later + +# This script ensures: +# - One dependency is built at a time. +# - That dependency uses all available cores. +# +# Without this, simply calling `make -j$(nproc)` from the `${CMAKE_BUILD_DIR}/deps/` +# directory will build many projects at once. +# +# This is undesirable for the following reasons: +# +# - The output from projects is mixed together, +# making it difficult to track down the cause of a build failure. +# +# - Larger dependencies such as LLVM can bottleneck the build process, +# making it necessary to cancel the build and manually run build commands in each directory. +# +# - Building many projects at once means canceling (Control-C) can lead to the build being in an undefined state. +# It's possible canceling happens as a patch is being applied or files are being copied. +# (steps that aren't part of the compilation process where it's typically safe to cancel). + +if [[ -z "$MY_MAKE_CALL_LEVEL" ]]; then + export MY_MAKE_CALL_LEVEL=0 + export MY_MAKEFLAGS=$MAKEFLAGS + + # Extract the jobs argument (`-jN`, `-j N`, `--jobs=N`). + add_next=0 + for i in "$@"; do + case $i in + -j*) + export MY_JOBS_ARG=$i + if [ "$MY_JOBS_ARG" = "-j" ]; then + add_next=1 + fi + ;; + --jobs=*) + shift # past argument=value + MY_JOBS_ARG=$i + ;; + *) + if (( add_next == 1 )); then + MY_JOBS_ARG="$MY_JOBS_ARG $i" + add_next=0 + fi + ;; + esac + done + unset i add_next + + if [[ -z "$MY_JOBS_ARG" ]]; then + MY_JOBS_ARG="-j$(nproc)" + fi + export MY_JOBS_ARG + # Support user defined `MAKEFLAGS`. + export MAKEFLAGS="$MY_MAKEFLAGS -j1" +else + export MY_MAKE_CALL_LEVEL=$(( MY_MAKE_CALL_LEVEL + 1 )) + if (( MY_MAKE_CALL_LEVEL == 1 )); then + # Important to set jobs to 1, otherwise user defined jobs argument is used. + export MAKEFLAGS="$MY_MAKEFLAGS -j1" + elif (( MY_MAKE_CALL_LEVEL == 2 )); then + # This is the level used by each sub-project. + export MAKEFLAGS="$MY_MAKEFLAGS $MY_JOBS_ARG" + fi + # Else leave `MY_MAKEFLAGS` flags as-is, avoids setting a high number of jobs on recursive + # calls (which may easily run out of memory). Let the job-server handle the rest. +fi + +# Useful for troubleshooting the wrapper. +# echo "Call level: $MY_MAKE_CALL_LEVEL, args=$@". + +# Call actual make but ensure recursive calls run via this script. +exec make MAKE="$0" "$@" diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index 08cb882ebfbb..108057285747 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -85,7 +85,7 @@ if(NOT APPLE) set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE) set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE) set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE) - set(WITH_CYCLES_HIP_BINARIES ON CACHE BOOL "" FORCE) + set(WITH_CYCLES_HIP_BINARIES OFF CACHE BOOL "" FORCE) set(WITH_CYCLES_DEVICE_ONEAPI ON CACHE BOOL "" FORCE) set(WITH_CYCLES_ONEAPI_BINARIES ON CACHE BOOL "" FORCE) endif() diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index dc7c101f91a2..fe3bb9d4737e 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -544,7 +544,7 @@ endfunction() function(setup_platform_linker_libs target ) - # jemalloc must be early in the list, to be before pthread (see T57998) + # jemalloc must be early in the list, to be before pthread (see #57998). if(WITH_MEM_JEMALLOC) target_link_libraries(${target} ${JEMALLOC_LIBRARIES}) endif() diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 0b7ae0532d88..ca0585ce9ad6 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -440,7 +440,7 @@ string(APPEND PLATFORM_LINKFLAGS " -stdlib=libc++") # Make stack size more similar to Embree, required for Embree. string(APPEND PLATFORM_LINKFLAGS_EXECUTABLE " -Wl,-stack_size,0x100000") -# Suppress ranlib "has no symbols" warnings (workaround for T48250) +# Suppress ranlib "has no symbols" warnings (workaround for #48250). set(CMAKE_C_ARCHIVE_CREATE " Scr ") set(CMAKE_CXX_ARCHIVE_CREATE " Scr ") # llvm-ranlib doesn't support this flag. Xcode's libtool does. diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 82bfa53b5a30..989d43f28fb0 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -121,7 +121,7 @@ if(WITH_WINDOWS_BUNDLE_CRT) include(InstallRequiredSystemLibraries) # ucrtbase(d).dll cannot be in the manifest, due to the way windows 10 handles - # redirects for this dll, for details see T88813. + # redirects for this dll, for details see #88813. foreach(lib ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}) string(FIND ${lib} "ucrtbase" pos) if(NOT pos EQUAL -1) @@ -295,7 +295,7 @@ unset(MATERIALX_LIB_FOLDER_EXISTS) if(NOT MSVC_CLANG AND # Available with MSVC 15.7+ but not for CLANG. NOT WITH_WINDOWS_SCCACHE AND # And not when sccache is enabled NOT VS_CLANG_TIDY) # Clang-tidy does not like these options - add_compile_options(/experimental:external /external:templates- /external:I "${LIBDIR}" /external:W0) + add_compile_options(/experimental:external /external:I "${LIBDIR}" /external:W0) endif() # Add each of our libraries to our cmake_prefix_path so find_package() could work diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index e1d8ac39bcf4..a9fa740805d0 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = V3.5 +PROJECT_NUMBER = V3.6 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 745acbdc5b58..7b604e855a34 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -476,7 +476,7 @@ MODULE_GROUPING = { # -------------------------------BLENDER---------------------------------------- -# converting bytes to strings, due to T30154 +# Converting bytes to strings, due to #30154. BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8') BLENDER_REVISION_TIMESTAMP = bpy.app.build_commit_timestamp @@ -487,7 +487,7 @@ BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1]) if BLENDER_REVISION != "Unknown": # SHA1 Git hash BLENDER_VERSION_HASH = BLENDER_REVISION - BLENDER_VERSION_HASH_HTML_LINK = "%s" % ( + BLENDER_VERSION_HASH_HTML_LINK = "%s" % ( BLENDER_VERSION_HASH, BLENDER_VERSION_HASH, ) BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP)) @@ -647,7 +647,7 @@ def undocumented_message(module_name, type_name, identifier): module_name, type_name, identifier, ) - return "Undocumented, consider `contributing `__." + return "Undocumented, consider `contributing `__." def range_str(val): @@ -2200,7 +2200,7 @@ def write_rst_enum_items(basepath, key, key_no_prefix, enum_items): Write a single page for a static enum in RST. This helps avoiding very large lists being in-lined in many places which is an issue - especially with icons in ``bpy.types.UILayout``. See T87008. + especially with icons in ``bpy.types.UILayout``. See #87008. """ filepath = os.path.join(basepath, "%s.rst" % key_no_prefix) with open(filepath, "w", encoding="utf-8") as fh: diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index f3d8426a23b2..785432583491 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1676,17 +1676,20 @@ class CyclesPreferences(bpy.types.AddonPreferences): col.label(text="and NVIDIA driver version %s or newer" % driver_version, icon='BLANK1', translate=False) elif device_type == 'HIP': - import sys - if sys.platform[:3] == "win": - driver_version = "21.Q4" - col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1') - col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version, - icon='BLANK1', translate=False) - elif sys.platform.startswith("linux"): - driver_version = "22.10" - col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1') - col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1', - translate=False) + if True: + col.label(text="HIP temporarily disabled due to compiler bugs", icon='BLANK1') + else: + import sys + if sys.platform[:3] == "win": + driver_version = "21.Q4" + col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1') + col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version, + icon='BLANK1', translate=False) + elif sys.platform.startswith("linux"): + driver_version = "22.10" + col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1') + col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1', + translate=False) elif device_type == 'ONEAPI': import sys if sys.platform.startswith("win"): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 81f940529d13..a162b3218532 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -20,7 +20,7 @@ class CyclesPresetPanel(PresetPanel, Panel): @staticmethod def post_cb(context): # Modify an arbitrary built-in scene property to force a depsgraph - # update, because add-on properties don't. (see T62325) + # update, because add-on properties don't. (see #62325) render = context.scene.render render.filter_size = render.filter_size diff --git a/intern/cycles/blender/display_driver.cpp b/intern/cycles/blender/display_driver.cpp index 8df0061d8cae..b000c8379b87 100644 --- a/intern/cycles/blender/display_driver.cpp +++ b/intern/cycles/blender/display_driver.cpp @@ -105,11 +105,12 @@ GPUShader *BlenderFallbackDisplayShader::bind(int width, int height) /* Bind shader now to enable uniform assignment. */ GPU_shader_bind(shader_program_); - GPU_shader_uniform_int(shader_program_, image_texture_location_, 0); + int slot = 0; + GPU_shader_uniform_int_ex(shader_program_, image_texture_location_, 1, 1, &slot); float size[2]; size[0] = width; size[1] = height; - GPU_shader_uniform_vector(shader_program_, fullscreen_location_, 2, 1, size); + GPU_shader_uniform_float_ex(shader_program_, fullscreen_location_, 2, 1, size); return shader_program_; } diff --git a/intern/cycles/blender/image.cpp b/intern/cycles/blender/image.cpp index ecea06fb1cdb..32633f47c0b0 100644 --- a/intern/cycles/blender/image.cpp +++ b/intern/cycles/blender/image.cpp @@ -20,7 +20,7 @@ BlenderImageLoader::BlenderImageLoader(BL::Image b_image, : b_image(b_image), frame(frame), tile_number(tile_number), - /* Don't free cache for preview render to avoid race condition from T93560, to be fixed + /* Don't free cache for preview render to avoid race condition from #93560, to be fixed * properly later as we are close to release. */ free_cache(!is_preview_render && !b_image.has_data()) { @@ -72,7 +72,7 @@ bool BlenderImageLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaDat metadata.colorspace = u_colorspace_raw; } else { - /* In some cases (e.g. T94135), the colorspace setting in Blender gets updated as part of the + /* In some cases (e.g. #94135), the colorspace setting in Blender gets updated as part of the * metadata queries in this function, so update the colorspace setting here. */ PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr; metadata.colorspace = get_enum_identifier(colorspace_ptr, "name"); diff --git a/intern/cycles/blender/light.cpp b/intern/cycles/blender/light.cpp index d5aba2041ad7..49545047d9e5 100644 --- a/intern/cycles/blender/light.cpp +++ b/intern/cycles/blender/light.cpp @@ -24,7 +24,7 @@ void BlenderSync::sync_light(BL::Object &b_parent, Light *light = light_map.find(key); /* Check if the transform was modified, in case a linked collection is moved we do not get a - * specific depsgraph update (T88515). This also mimics the behavior for Objects. */ + * specific depsgraph update (#88515). This also mimics the behavior for Objects. */ const bool tfm_updated = (light && light->get_tfm() != tfm); /* Update if either object or light data changed. */ diff --git a/intern/cycles/blender/python.cpp b/intern/cycles/blender/python.cpp index ebbdc8abf7f1..6ac680350331 100644 --- a/intern/cycles/blender/python.cpp +++ b/intern/cycles/blender/python.cpp @@ -94,7 +94,7 @@ void python_thread_state_restore(void **python_thread_state) *python_thread_state = NULL; } -static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) +static const char *PyC_UnicodeAsBytes(PyObject *py_str, PyObject **coerce) { const char *result = PyUnicode_AsUTF8(py_str); if (result) { @@ -131,8 +131,8 @@ static PyObject *init_func(PyObject * /*self*/, PyObject *args) } PyObject *path_coerce = nullptr, *user_path_coerce = nullptr; - path_init(PyC_UnicodeAsByte(path, &path_coerce), - PyC_UnicodeAsByte(user_path, &user_path_coerce)); + path_init(PyC_UnicodeAsBytes(path, &path_coerce), + PyC_UnicodeAsBytes(user_path, &user_path_coerce)); Py_XDECREF(path_coerce); Py_XDECREF(user_path_coerce); diff --git a/intern/cycles/blender/session.cpp b/intern/cycles/blender/session.cpp index 7dfacec8fc9c..ab0190ad235d 100644 --- a/intern/cycles/blender/session.cpp +++ b/intern/cycles/blender/session.cpp @@ -404,7 +404,7 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) * point we know that we've got everything to render current view layer. */ /* At the moment we only free if we are not doing multi-view - * (or if we are rendering the last view). See T58142/D4239 for discussion. + * (or if we are rendering the last view). See #58142/D4239 for discussion. */ if (view_index == num_views - 1) { free_blender_memory_if_possible(); diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index 7df2a8cf30f1..ee008bc6dcad 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -766,7 +766,7 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph) (BlenderSession::headless || is_interface_locked) && /* Baking re-uses the depsgraph multiple times, clearing crashes * reading un-evaluated mesh data which isn't aligned with the - * geometry we're baking, see T71012. */ + * geometry we're baking, see #71012. */ !scene->bake_manager->get_baking() && /* Persistent data must main caches for performance and correctness. */ !is_persistent_data; diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 4b165e1a5bec..b10aeec8bdf9 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -42,12 +42,15 @@ endif() ########################################################################### if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP) - find_package(HIP) - set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES) + set(WITH_CYCLES_HIP_BINARIES OFF) + message(STATUS "HIP temporarily disabled due to compiler bugs") - if(HIP_FOUND) - message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})") - endif() + # find_package(HIP) + # set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES) + + # if(HIP_FOUND) + # message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})") + # endif() endif() if(NOT WITH_HIP_DYNLOAD) diff --git a/intern/cycles/device/hip/device_impl.cpp b/intern/cycles/device/hip/device_impl.cpp index b9bcd7edcab4..010470c23aee 100644 --- a/intern/cycles/device/hip/device_impl.cpp +++ b/intern/cycles/device/hip/device_impl.cpp @@ -906,7 +906,7 @@ bool HIPDevice::should_use_graphics_interop() * possible, but from the empiric measurements it can be considerably slower than using naive * pixels copy. */ - /* Disable graphics interop for now, because of driver bug in 21.40. See T92972 */ + /* Disable graphics interop for now, because of driver bug in 21.40. See #92972 */ # if 0 HIPContextScope scope(this); diff --git a/intern/cycles/device/hip/util.h b/intern/cycles/device/hip/util.h index c8b4b67ded8b..4e4906171d1b 100644 --- a/intern/cycles/device/hip/util.h +++ b/intern/cycles/device/hip/util.h @@ -51,7 +51,7 @@ static inline bool hipSupportsDevice(const int hipDevId) hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId); hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId); - return (major >= 10); + return (major >= 9); } CCL_NAMESPACE_END diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm index ba673c461b2d..0d836e7c2d55 100644 --- a/intern/cycles/device/metal/device_impl.mm +++ b/intern/cycles/device/metal/device_impl.mm @@ -586,7 +586,7 @@ void MetalDevice::erase_allocation(device_memory &mem) if (it != metal_mem_map.end()) { MetalMem *mmem = it->second.get(); - /* blank out reference to MetalMem* in the launch params (fixes crash T94736) */ + /* blank out reference to MetalMem* in the launch params (fixes crash #94736) */ if (mmem->pointer_index >= 0) { device_ptr *pointers = (device_ptr *)&launch_params; pointers[mmem->pointer_index] = 0; diff --git a/intern/cycles/integrator/render_scheduler.cpp b/intern/cycles/integrator/render_scheduler.cpp index 2e05dbbaf6ee..066d6c3bf247 100644 --- a/intern/cycles/integrator/render_scheduler.cpp +++ b/intern/cycles/integrator/render_scheduler.cpp @@ -886,7 +886,7 @@ int RenderScheduler::get_num_samples_during_navigation(int resolution_divider) c { /* Special trick for fast navigation: schedule multiple samples during fast navigation * (which will prefer to use lower resolution to keep up with refresh rate). This gives more - * usable visual feedback for artists. There are a couple of tricks though. */ + * usable visual feedback for artists. */ if (is_denoise_active_during_update()) { /* When denoising is used during navigation prefer using a higher resolution with less samples @@ -896,25 +896,12 @@ int RenderScheduler::get_num_samples_during_navigation(int resolution_divider) c return 1; } - if (resolution_divider <= pixel_size_) { - /* When resolution divider is at or below pixel size, schedule one sample. This doesn't effect - * the sample count at this resolution division, but instead assists in the calculation of - * the resolution divider. */ - return 1; - } - - if (resolution_divider == pixel_size_ * 2) { - /* When resolution divider is the previous step to the final resolution, schedule two samples. - * This is so that rendering on lower resolution does not exceed time that it takes to render - * first sample at the full resolution. */ - return 2; - } - - /* Always render 4 samples, even if scene is configured for less. - * The idea here is to have enough information on the screen. Resolution divider of 2 allows us - * to have 4 time extra samples, so overall worst case timing is the same as the final resolution - * at one sample. */ - return 4; + /* Schedule samples equal to the resolution divider up to a maximum of 4. + * The idea is to have enough information on the screen by increasing the sample count as the + * resolution is decreased. */ + /* NOTE: Changing this formula will change the formula in + * `RenderScheduler::calculate_resolution_divider_for_time()`. */ + return min(max(1, resolution_divider / pixel_size_), 4); } bool RenderScheduler::work_need_adaptive_filter() const @@ -1100,9 +1087,10 @@ void RenderScheduler::update_start_resolution_divider() /* TODO(sergey): Need to add hysteresis to avoid resolution divider bouncing around when actual * render time is somewhere on a boundary between two resolutions. */ - /* Never increase resolution to higher than the pixel size (which is possible if the scene is - * simple and compute device is fast). */ - start_resolution_divider_ = max(resolution_divider_for_update, pixel_size_); + /* Don't let resolution drop below the desired one. It's better to be slow than provide an + * unreadable viewport render. */ + start_resolution_divider_ = min(resolution_divider_for_update, + default_start_resolution_divider_); VLOG_WORK << "Calculated resolution divider is " << start_resolution_divider_; } @@ -1187,24 +1175,24 @@ void RenderScheduler::check_time_limit_reached() int RenderScheduler::calculate_resolution_divider_for_time(double desired_time, double actual_time) { - /* TODO(sergey): There should a non-iterative analytical formula here. */ + const double ratio_between_times = actual_time / desired_time; - int resolution_divider = 1; + /* We can pass `ratio_between_times` to `get_num_samples_during_navigation()` to get our + * navigation samples because the equation for calculating the resolution divider is as follows: + * `actual_time / desired_time = sqr(resolution_divider) / sample_count`. + * While `resolution_divider` is less than or equal to 4, `resolution_divider = sample_count` + * (This relationship is determined in `get_num_samples_during_navigation()`). With some + * substitution we end up with `actual_time / desired_time = resolution_divider` while the + * resolution divider is less than or equal to 4. Once the resolution divider increases above 4, + * the relationship of `actual_time / desired_time = resolution_divider` is no longer true, + * however the sample count retrieved from `get_num_samples_during_navigation()` is still + * accurate if we continue using this assumption. It should be noted that the interaction between + * `pixel_size`, sample count, and resolution divider are automatically accounted for and that's + * why `pixel_size` isn't included in any of the equations. */ + const int navigation_samples = get_num_samples_during_navigation( + ceil_to_int(ratio_between_times)); - /* This algorithm iterates through resolution dividers until a divider is found that achieves - * the desired render time. A limit of default_start_resolution_divider_ is put in place as the - * maximum resolution divider to avoid an unreadable viewport due to a low resolution. - * pre_resolution_division_samples and post_resolution_division_samples are used in this - * calculation to better predict the performance impact of changing resolution divisions as - * the sample count can also change between resolution divisions. */ - while (actual_time > desired_time && resolution_divider < default_start_resolution_divider_) { - int pre_resolution_division_samples = get_num_samples_during_navigation(resolution_divider); - resolution_divider = resolution_divider * 2; - int post_resolution_division_samples = get_num_samples_during_navigation(resolution_divider); - actual_time /= 4.0 * pre_resolution_division_samples / post_resolution_division_samples; - } - - return resolution_divider; + return ceil_to_int(sqrt(navigation_samples * ratio_between_times)); } int calculate_resolution_divider_for_resolution(int width, int height, int resolution) diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 78bd71988c04..431b520b2823 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -412,11 +412,12 @@ if(WITH_CYCLES_CUDA_BINARIES) # warn for other versions if((CUDA_VERSION STREQUAL "101") OR (CUDA_VERSION STREQUAL "102") OR - (CUDA_VERSION_MAJOR STREQUAL "11")) + (CUDA_VERSION_MAJOR STREQUAL "11") OR + (CUDA_VERSION_MAJOR STREQUAL "12")) else() message(WARNING "CUDA version ${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR} detected, " - "build may succeed but only CUDA 11, 10.2 and 10.1 have been tested") + "build may succeed but only CUDA 12, 11, 10.2 and 10.1 have been tested") endif() # build for each arch @@ -514,6 +515,16 @@ if(WITH_CYCLES_CUDA_BINARIES) else() message(STATUS "CUDA binaries for ${arch} require CUDA 10 or earlier, skipped.") endif() + elseif(${arch} MATCHES ".*_3.") + if(DEFINED CUDA11_NVCC_EXECUTABLE) + set(cuda_nvcc_executable ${CUDA11_NVCC_EXECUTABLE}) + set(cuda_toolkit_root_dir ${CUDA11_TOOLKIT_ROOT_DIR}) + elseif("${CUDA_VERSION}" LESS 120) # Support for sm_35, sm_37 was removed in CUDA 12 + set(cuda_nvcc_executable ${CUDA_NVCC_EXECUTABLE}) + set(cuda_toolkit_root_dir ${CUDA_TOOLKIT_ROOT_DIR}) + else() + message(STATUS "CUDA binaries for ${arch} require CUDA 11 or earlier, skipped.") + endif() elseif(${arch} MATCHES ".*_7." AND "${CUDA_VERSION}" LESS 100) message(STATUS "CUDA binaries for ${arch} require CUDA 10.0+, skipped.") elseif(${arch} MATCHES ".*_8.") diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index e7754bde7c5a..343c7c919c01 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -686,7 +686,7 @@ ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd, albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value; break; case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: - albedo *= bsdf_principled_hair_albedo(sc); + albedo *= bsdf_principled_hair_albedo(sd, sc); break; default: break; diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h index f7cf3b716f64..ae3362c6cd10 100644 --- a/intern/cycles/kernel/closure/bsdf_hair_principled.h +++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h @@ -478,10 +478,18 @@ ccl_device_inline float bsdf_principled_hair_albedo_roughness_scale( return (((((0.245f * x) + 5.574f) * x - 10.73f) * x + 2.532f) * x - 0.215f) * x + 5.969f; } -ccl_device Spectrum bsdf_principled_hair_albedo(ccl_private const ShaderClosure *sc) +ccl_device Spectrum bsdf_principled_hair_albedo(ccl_private const ShaderData *sd, + ccl_private const ShaderClosure *sc) { ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)sc; - return exp(-sqrt(bsdf->sigma) * bsdf_principled_hair_albedo_roughness_scale(bsdf->v)); + + const float cos_theta_o = cos_from_sin(dot(sd->wi, safe_normalize(sd->dPdu))); + const float cos_gamma_o = cos_from_sin(bsdf->extra->geom.w); + const float f = fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta); + + const float roughness_scale = bsdf_principled_hair_albedo_roughness_scale(bsdf->v); + /* TODO(lukas): Adding the Fresnel term here as a workaround until the proper refactor. */ + return exp(-sqrt(bsdf->sigma) * roughness_scale) + make_spectrum(f); } ccl_device_inline Spectrum diff --git a/intern/cycles/kernel/device/cpu/kernel_avx2.cpp b/intern/cycles/kernel/device/cpu/kernel_avx2.cpp index a1644fb0dfe3..9d63be143f57 100644 --- a/intern/cycles/kernel/device/cpu/kernel_avx2.cpp +++ b/intern/cycles/kernel/device/cpu/kernel_avx2.cpp @@ -10,7 +10,7 @@ #ifndef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 # define KERNEL_STUB #else -/* SSE optimization disabled for now on 32 bit, see bug T36316. */ +/* SSE optimization disabled for now on 32 bit, see bug #36316. */ # if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86))) # define __KERNEL_SSE__ # define __KERNEL_SSE2__ diff --git a/intern/cycles/kernel/device/cpu/kernel_sse2.cpp b/intern/cycles/kernel/device/cpu/kernel_sse2.cpp index 6f420274e4a5..9a2e5cb7c3b3 100644 --- a/intern/cycles/kernel/device/cpu/kernel_sse2.cpp +++ b/intern/cycles/kernel/device/cpu/kernel_sse2.cpp @@ -10,7 +10,7 @@ #ifndef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 # define KERNEL_STUB #else -/* SSE optimization disabled for now on 32 bit, see bug T36316. */ +/* SSE optimization disabled for now on 32 bit, see bug #36316. */ # if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86))) # define __KERNEL_SSE2__ # endif diff --git a/intern/cycles/kernel/device/cpu/kernel_sse41.cpp b/intern/cycles/kernel/device/cpu/kernel_sse41.cpp index 1cfea5dc2301..2e511c226475 100644 --- a/intern/cycles/kernel/device/cpu/kernel_sse41.cpp +++ b/intern/cycles/kernel/device/cpu/kernel_sse41.cpp @@ -10,7 +10,7 @@ #ifndef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 # define KERNEL_STUB #else -/* SSE optimization disabled for now on 32 bit, see bug T36316. */ +/* SSE optimization disabled for now on 32 bit, see bug #36316. */ # if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86))) # define __KERNEL_SSE2__ # define __KERNEL_SSE3__ diff --git a/intern/cycles/kernel/device/gpu/kernel.h b/intern/cycles/kernel/device/gpu/kernel.h index 821fc1eaf15d..0c2fd76fcbde 100644 --- a/intern/cycles/kernel/device/gpu/kernel.h +++ b/intern/cycles/kernel/device/gpu/kernel.h @@ -645,7 +645,7 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb const int y, const half4 half_pixel) { - /* Work around HIP issue with half float display, see T92972. */ + /* Work around HIP issue with half float display, see #92972. */ #ifdef __KERNEL_HIP__ ccl_global half *out = ((ccl_global half *)rgba) + (rgba_offset + y * rgba_stride + x) * 4; out[0] = half_pixel.x; diff --git a/intern/cycles/scene/osl.cpp b/intern/cycles/scene/osl.cpp index 9260fbdcd8ef..9b65b780fe47 100644 --- a/intern/cycles/scene/osl.cpp +++ b/intern/cycles/scene/osl.cpp @@ -394,7 +394,7 @@ bool OSLShaderManager::osl_compile(const string &inputfile, const string &output /* Compile. * - * Mutex protected because the OSL compiler does not appear to be thread safe, see T92503. */ + * Mutex protected because the OSL compiler does not appear to be thread safe, see #92503. */ static thread_mutex osl_compiler_mutex; thread_scoped_lock lock(osl_compiler_mutex); diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp index f0faa91b4be1..dfd86f82bb69 100644 --- a/intern/cycles/scene/shader.cpp +++ b/intern/cycles/scene/shader.cpp @@ -573,7 +573,7 @@ void ShaderManager::device_update_common(Device * /*device*/, kfilm->is_rec709 = is_rec709; } -void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene) +void ShaderManager::device_free_common(Device * /*device*/, DeviceScene *dscene, Scene * /*scene*/) { dscene->shaders.free(); } diff --git a/intern/cycles/session/tile.cpp b/intern/cycles/session/tile.cpp index ab858e6f1921..371ca4728d45 100644 --- a/intern/cycles/session/tile.cpp +++ b/intern/cycles/session/tile.cpp @@ -520,7 +520,7 @@ bool TileManager::write_tile(const RenderBuffers &tile_buffers) /* If there is an overscan used for the tile copy pixels into single continuous block of memory * without any "gaps". * This is a workaround for bug in OIIO (https://github.com/OpenImageIO/oiio/pull/3176). - * Our task reference: T93008. */ + * Our task reference: #93008. */ if (tile_params.window_x || tile_params.window_y || tile_params.window_width != tile_params.width || tile_params.window_height != tile_params.height) { diff --git a/intern/cycles/util/math_fast.h b/intern/cycles/util/math_fast.h index c7d44739af99..4ebd50fdee37 100644 --- a/intern/cycles/util/math_fast.h +++ b/intern/cycles/util/math_fast.h @@ -421,7 +421,7 @@ ccl_device_inline float fast_expf(float x) #if !defined(__KERNEL_GPU__) && !defined(_MSC_VER) /* MSVC seems to have a code-gen bug here in at least SSE41/AVX, see - * T78047 and T78869 for details. Just disable for now, it only makes + * #78047 and #78869 for details. Just disable for now, it only makes * a small difference in denoising performance. */ ccl_device float4 fast_exp2f4(float4 x) { diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index 1aa0cb9def4e..4defd68b90ff 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -516,7 +516,7 @@ GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles() /* OpenGL on Metal * - * Use Metal layer to avoid Viewport lagging on macOS, see T60043. */ + * Use Metal layer to avoid Viewport lagging on macOS, see #60043. */ static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatBGRA8Unorm; static const OSType METAL_CORE_VIDEO_PIXEL_FORMAT = kCVPixelFormatType_32BGRA; diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp index d9f2df21ee03..71ec9d1c0095 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.cpp +++ b/intern/ghost/intern/GHOST_ContextGLX.cpp @@ -141,7 +141,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() /* -------------------------------------------------------------------- */ #else /* Important to initialize only GLXEW (_not_ GLEW), - * since this breaks w/ Mesa's `swrast`, see: T46431. */ + * since this breaks w/ Mesa's `swrast`, see: #46431. */ glxewInit(); #endif /* USE_GLXEW_INIT_WORKAROUND */ diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index e6e4ec25b294..d0309b4bba3c 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -302,7 +302,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id) switch (product_id) { case 0xC62E: /* Plugged in. */ case 0xC62F: /* Wireless. */ - case 0xC658: /* Wireless (3DConnexion Universal Wireless Receiver in WIN32), see T82412. */ + case 0xC658: /* Wireless (3DConnexion Universal Wireless Receiver in WIN32), see #82412. */ { device_type_ = NDOF_SpaceMouseWireless; hid_map_button_num_ = 2; diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index c3c64bab4cfc..6ef593e277cb 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -141,7 +141,7 @@ constexpr size_t events_pending_default_size = 4096 / sizeof(void *); * \{ */ /** - * GNOME (mutter 42.2 had a bug with confine not respecting scale - Hi-DPI), See: T98793. + * GNOME (mutter 42.2 had a bug with confine not respecting scale - Hi-DPI), See: #98793. * Even though this has been fixed, at time of writing it's not yet in a release. * Workaround the problem by implementing confine with a software cursor. * While this isn't ideal, it's not adding a lot of overhead as software @@ -176,7 +176,7 @@ static bool use_gnome_confine_hack = false; /** * KDE (plasma 5.26.1) has a bug where the cursor surface needs to be committed - * (via `wl_surface_commit`) when it was hidden and is being set to visible again, see: T102048. + * (via `wl_surface_commit`) when it was hidden and is being set to visible again, see: #102048. * See: https://bugs.kde.org/show_bug.cgi?id=461001 */ #define USE_KDE_TABLET_HIDDEN_CURSOR_HACK @@ -197,8 +197,8 @@ static bool use_gnome_confine_hack = false; * \{ */ /** - * Fix short-cut part of keyboard reading code not properly handling some keys, see: T102194. - * \note This is similar to X11 workaround by the same name, see: T47228. + * Fix short-cut part of keyboard reading code not properly handling some keys, see: #102194. + * \note This is similar to X11 workaround by the same name, see: #47228. */ #define USE_NON_LATIN_KB_WORKAROUND @@ -1328,7 +1328,7 @@ static void ghost_wl_display_report_error(struct wl_display *display) * So in practice re-connecting to the display server isn't an option. * * Exit since leaving the process open will simply flood the output and do nothing. - * Although as the process is in a valid state, auto-save for e.g. is possible, see: T100855. */ + * Although as the process is in a valid state, auto-save for e.g. is possible, see: #100855. */ ::exit(-1); } @@ -1442,7 +1442,7 @@ static GHOST_TKey xkb_map_gkey(const xkb_keysym_t sym) /* Additional keys for non US layouts. */ - /* Uses the same physical key as #XKB_KEY_KP_Decimal for QWERTZ layout, see: T102287. */ + /* Uses the same physical key as #XKB_KEY_KP_Decimal for QWERTZ layout, see: #102287. */ GXMAP(gkey, XKB_KEY_KP_Separator, GHOST_kKeyNumpadPeriod); default: @@ -3810,7 +3810,7 @@ static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers( /* NOTE(@ideasman42): Only perform the number-locked lookup as a fallback * when a number-pad key has been pressed. This is important as some key-maps use number lock - * for switching other layers (in particular `de(neo_qwertz)` turns on layer-4), see: T96170. + * for switching other layers (in particular `de(neo_qwertz)` turns on layer-4), see: #96170. * Alternative solutions could be to inspect the layout however this could get involved * and turning on the number-lock is only needed for a limited set of keys. */ @@ -4467,7 +4467,7 @@ static void xdg_output_handle_logical_size(void *data, #ifdef USE_GNOME_CONFINE_HACK /* Use a bug in GNOME to check GNOME is in use. If the bug is fixed this won't cause an issue - * as T98793 has been fixed up-stream too, but not in a release at time of writing. */ + * as #98793 has been fixed up-stream too, but not in a release at time of writing. */ use_gnome_confine_hack = true; #endif diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index 153931a0a39f..61c7f3a045ce 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -208,7 +208,7 @@ class GHOST_SystemWayland : public GHOST_System { * Clear all references to this output. * * \note The compositor should have already called the `wl_surface_listener.leave` callback, - * however some compositors may not (see T103586). + * however some compositors may not (see #103586). * So remove references to the output before it's destroyed to avoid crashing. * * \return true when any references were removed. diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 4a1fec6f8fdc..9fc69dabe002 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -565,8 +565,8 @@ GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw, bool *r_key_down) /** * \note this function can be extended to include other exotic cases as they arise. * - * This function was added in response to bug T25715. - * This is going to be a long list T42426. + * This function was added in response to bug #25715. + * This is going to be a long list #42426. */ GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short scanCode) const { @@ -1083,7 +1083,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind * so the box needs to small enough not to let the cursor escape the window but large * enough that the cursor isn't being warped every time. * If this was not the case it would be less trouble to simply warp the cursor to the - * center of the screen on every motion, see: D16558 (alternative fix for T102346). */ + * center of the screen on every motion, see: D16558 (alternative fix for #102346). */ const int32_t subregion_div = 4; /* One quarter of the region. */ const int32_t size[2] = {bounds.getWidth(), bounds.getHeight()}; const int32_t center[2] = {(bounds.m_l + bounds.m_r) / 2, (bounds.m_t + bounds.m_b) / 2}; @@ -1209,7 +1209,7 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA const bool ctrl_pressed = has_state && state[VK_CONTROL] & 0x80; const bool alt_pressed = has_state && state[VK_MENU] & 0x80; - /* We can be here with !key_down if processing dead keys (diacritics). See T103119. */ + /* We can be here with !key_down if processing dead keys (diacritics). See #103119. */ /* No text with control key pressed (Alt can be used to insert special characters though!). */ if (ctrl_pressed && !alt_pressed) { diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 88f21c063c08..2de81ce46d5d 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -46,7 +46,7 @@ #ifdef WITH_X11_XFIXES # include -/* Workaround for XWayland grab glitch: T53004. */ +/* Workaround for XWayland grab glitch: #53004. */ # define WITH_XWAYLAND_HACK #endif @@ -71,11 +71,11 @@ # define USE_XINPUT_HOTPLUG #endif -/* see T34039 Fix Alt key glitch on Unity desktop */ +/* see #34039 Fix Alt key glitch on Unity desktop */ #define USE_UNITY_WORKAROUND /* Fix 'shortcut' part of keyboard reading code only ever using first defined key-map - * instead of active one. See T47228 and D1746 */ + * instead of active one. See #47228 and D1746 */ #define USE_NON_LATIN_KB_WORKAROUND static uchar bit_is_on(const uchar *ptr, int bit) @@ -928,7 +928,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe) window->getClientBounds(bounds); /* TODO(@ideasman42): warp the cursor to `window->getCursorGrabInitPos`, - * on every motion event, see: D16557 (alternative fix for T102346). */ + * on every motion event, see: D16557 (alternative fix for #102346). */ const int32_t subregion_div = 4; /* One quarter of the region. */ const int32_t size[2] = {bounds.getWidth(), bounds.getHeight()}; const int32_t center[2] = { @@ -964,7 +964,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe) if (x_new != xme.x_root || y_new != xme.y_root) { /* Use time of last event to avoid wrapping several times on the 'same' actual wrap. * Note that we need to deal with X and Y separately as those might wrap at the same time - * but still in two different events (corner case, see T74918). + * but still in two different events (corner case, see #74918). * We also have to add a few extra milliseconds of 'padding', as sometimes we get two * close events that will generate extra wrap on the same axis within those few * milliseconds. */ @@ -1028,7 +1028,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe) /* XXX: Code below is kinda awfully convoluted... Issues are: * - In keyboards like Latin ones, numbers need a 'Shift' to be accessed but key_sym * is unmodified (or anyone swapping the keys with `xmodmap`). - * - #XLookupKeysym seems to always use first defined key-map (see T47228), which generates + * - #XLookupKeysym seems to always use first defined key-map (see #47228), which generates * key-codes unusable by ghost_key_from_keysym for non-Latin-compatible key-maps. * * To address this, we: @@ -1715,7 +1715,7 @@ GHOST_TSuccess GHOST_SystemX11::setCursorPosition(int32_t x, int32_t y) #if defined(WITH_X11_XINPUT) && defined(USE_X11_XINPUT_WARP) if ((m_xinput_version.present) && (m_xinput_version.major_version >= 2)) { - /* Needed to account for XInput "Coordinate Transformation Matrix", see T48901 */ + /* Needed to account for XInput "Coordinate Transformation Matrix", see #48901 */ int device_id; if (XIGetClientPointer(m_display, None, &device_id) != False) { XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, relx, rely); diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 1f071da6da7f..4eff2850afd9 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -20,8 +20,8 @@ /* Disable XINPUT warp, currently not implemented by Xorg for multi-head display. * (see comment in XSERVER `Xi/xiwarppointer.c` -> `FIXME: panoramix stuff is missing` ~ v1.13.4) - * If this is supported we can add back XINPUT for warping (fixing T48901). - * For now disable (see T50383). */ + * If this is supported we can add back XINPUT for warping (fixing #48901). + * For now disable (see #50383). */ // # define USE_X11_XINPUT_WARP #endif diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index 961c84f71e47..843f6f62c73f 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -306,14 +306,23 @@ static void gwl_window_frame_update_from_pending(GWL_Window *win); #ifdef USE_EVENT_BACKGROUND_THREAD enum eGWL_PendingWindowActions { - PENDING_FRAME_CONFIGURE = 0, - PENDING_EGL_RESIZE, + /** + * The state of the window frame has changed, apply the state from #GWL_Window::frame_pending. + */ + PENDING_WINDOW_FRAME_CONFIGURE = 0, + /** The EGL buffer must be resized to match #GWL_WindowFrame::size. */ + PENDING_EGL_WINDOW_RESIZE, # ifdef GHOST_OPENGL_ALPHA + /** Draw an opaque region behind the window. */ PENDING_OPAQUE_SET, # endif - PENDING_SCALE_UPDATE, + /** + * The DPI for a monitor has changed or the monitors (outputs) + * this window is visible on may have changed. Recalculate the windows scale. + */ + PENDING_OUTPUT_SCALE_UPDATE, }; -# define PENDING_NUM (PENDING_SCALE_UPDATE + 1) +# define PENDING_NUM (PENDING_OUTPUT_SCALE_UPDATE + 1) static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWindowActions type) { @@ -323,10 +332,10 @@ static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWin static void gwl_window_pending_actions_handle(GWL_Window *win) { - if (win->pending_actions[PENDING_FRAME_CONFIGURE].exchange(false)) { + if (win->pending_actions[PENDING_WINDOW_FRAME_CONFIGURE].exchange(false)) { gwl_window_frame_update_from_pending(win); } - if (win->pending_actions[PENDING_EGL_RESIZE].exchange(false)) { + if (win->pending_actions[PENDING_EGL_WINDOW_RESIZE].exchange(false)) { wl_egl_window_resize(win->egl_window, UNPACK2(win->frame.size), 0, 0); } # ifdef GHOST_OPENGL_ALPHA @@ -334,7 +343,7 @@ static void gwl_window_pending_actions_handle(GWL_Window *win) win->ghost_window->setOpaque(); } # endif - if (win->pending_actions[PENDING_SCALE_UPDATE].exchange(false)) { + if (win->pending_actions[PENDING_OUTPUT_SCALE_UPDATE].exchange(false)) { win->ghost_window->outputs_changed_update_scale(); } } @@ -342,9 +351,10 @@ static void gwl_window_pending_actions_handle(GWL_Window *win) #endif /* USE_EVENT_BACKGROUND_THREAD */ /** - * Update the window's #GWL_WindowFrame + * Update the window's #GWL_WindowFrame. + * The caller must handle locking & run from the main thread. */ -static void gwl_window_frame_update_from_pending_lockfree(GWL_Window *win) +static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win) { #ifdef USE_EVENT_BACKGROUND_THREAD GHOST_ASSERT(win->ghost_system->main_thread_id == std::this_thread::get_id(), @@ -381,7 +391,7 @@ static void gwl_window_frame_update_from_pending(GWL_Window *win) #ifdef USE_EVENT_BACKGROUND_THREAD std::lock_guard lock_frame_guard{win->frame_pending_mutex}; #endif - gwl_window_frame_update_from_pending_lockfree(win); + gwl_window_frame_update_from_pending_no_lock(win); } /** \} */ @@ -576,12 +586,12 @@ static void frame_handle_configure(struct libdecor_frame *frame, GHOST_SystemWayland *system = win->ghost_system; const bool is_main_thread = system->main_thread_id == std::this_thread::get_id(); if (!is_main_thread) { - gwl_window_pending_actions_tag(win, PENDING_FRAME_CONFIGURE); + gwl_window_pending_actions_tag(win, PENDING_WINDOW_FRAME_CONFIGURE); } else # endif { - gwl_window_frame_update_from_pending_lockfree(win); + gwl_window_frame_update_from_pending_no_lock(win); } } } @@ -671,7 +681,7 @@ static void xdg_surface_handle_configure(void *data, if (!is_main_thread) { /* NOTE(@ideasman42): this only gets one redraw, * I could not find a case where this causes problems. */ - gwl_window_pending_actions_tag(win, PENDING_FRAME_CONFIGURE); + gwl_window_pending_actions_tag(win, PENDING_WINDOW_FRAME_CONFIGURE); } else #endif @@ -812,12 +822,12 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, * when the `window_->scale` changed. */ const int32_t size_min[2] = {320, 240}; - /* This value is expected to match the base name of the `.desktop` file. see T101805. + /* This value is expected to match the base name of the `.desktop` file. see #101805. * * NOTE: the XDG desktop-entry-spec defines that this should follow the "reverse DNS" convention. * For e.g. `org.blender.Blender` - however the `.desktop` file distributed with Blender is * simply called `blender.desktop`, so the it's important to follow that name. - * Other distributions such as SNAP & FLATPAK may need to change this value T101779. + * Other distributions such as SNAP & FLATPAK may need to change this value #101779. * Currently there isn't a way to configure this, we may want to support that. */ const char *xdg_app_id = ( #ifdef WITH_GHOST_WAYLAND_APP_ID @@ -1080,7 +1090,7 @@ GHOST_WindowWayland::~GHOST_WindowWayland() /* NOTE(@ideasman42): Flushing will often run the appropriate handlers event * (#wl_surface_listener.leave in particular) to avoid attempted access to the freed surfaces. - * This is not fool-proof though, hence the call to #window_surface_unref, see: T99078. */ + * This is not fool-proof though, hence the call to #window_surface_unref, see: #99078. */ wl_display_flush(system_->wl_display()); delete window_; @@ -1373,7 +1383,7 @@ bool GHOST_WindowWayland::outputs_changed_update_scale() { #ifdef USE_EVENT_BACKGROUND_THREAD if (system_->main_thread_id != std::this_thread::get_id()) { - gwl_window_pending_actions_tag(window_, PENDING_SCALE_UPDATE); + gwl_window_pending_actions_tag(window_, PENDING_OUTPUT_SCALE_UPDATE); return false; } #endif diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index c5554f702004..04f247eef8d6 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -15,7 +15,7 @@ #include /* For #wl_fixed_t */ /** - * Define to workaround for a bug/limitation in WAYLAND, see: T100855 & upstream report: + * Define to workaround for a bug/limitation in WAYLAND, see: #100855 & upstream report: * https://gitlab.freedesktop.org/wayland/wayland/-/issues/159 * * Consume events from WAYLAND in a thread, this is needed because overflowing the event queue diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 5086920be432..b8e1b16ef4e1 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -93,7 +93,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, } RECT win_rect = {left, top, long(left + width), long(top + height)}; - adjustWindowRectForClosestMonitor(&win_rect, style, extended_style); + adjustWindowRectForDesktop(&win_rect, style, extended_style); wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); m_hWnd = ::CreateWindowExW(extended_style, /* window extended style */ @@ -154,7 +154,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, } if (parentwindow) { - /* Release any parent capture to allow immediate interaction (T90110). */ + /* Release any parent capture to allow immediate interaction (#90110). */ ::ReleaseCapture(); parentwindow->lostMouseCapture(); } @@ -298,24 +298,52 @@ GHOST_WindowWin32::~GHOST_WindowWin32() m_directManipulationHelper = NULL; } -void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect, - DWORD dwStyle, - DWORD dwExStyle) +void GHOST_WindowWin32::adjustWindowRectForDesktop(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle) { - /* Get Details of the closest monitor. */ - HMONITOR hmonitor = MonitorFromRect(win_rect, MONITOR_DEFAULTTONEAREST); + /* Windows can span multiple monitors, but must be usable. The desktop can have a larger + * surface than all monitors combined, for example when two monitors are aligned diagonally. + * Therefore we ensure that all the window's corners are within some monitor's Work area. */ + + POINT pt; + HMONITOR hmonitor; MONITORINFOEX monitor; monitor.cbSize = sizeof(MONITORINFOEX); monitor.dwFlags = 0; - GetMonitorInfo(hmonitor, &monitor); - /* Constrain requested size and position to fit within this monitor. */ - LONG width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect->right - win_rect->left); - LONG height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect->bottom - win_rect->top); - win_rect->left = min(max(monitor.rcWork.left, win_rect->left), monitor.rcWork.right - width); - win_rect->right = win_rect->left + width; - win_rect->top = min(max(monitor.rcWork.top, win_rect->top), monitor.rcWork.bottom - height); - win_rect->bottom = win_rect->top + height; + /* Note that with MonitorFromPoint using MONITOR_DEFAULTTONEAREST, it will return + * the exact monitor if there is one at the location or the nearest monitor if not. */ + + /* Top-left. */ + pt.x = win_rect->left; + pt.y = win_rect->top; + hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(hmonitor, &monitor); + win_rect->top = max(win_rect->top, monitor.rcWork.top); + win_rect->left = max(win_rect->left, monitor.rcWork.left); + + /* Top-right. */ + pt.x = win_rect->right; + pt.y = win_rect->top; + hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(hmonitor, &monitor); + win_rect->top = max(win_rect->top, monitor.rcWork.top); + win_rect->right = min(win_rect->right, monitor.rcWork.right); + + /* Bottom-left. */ + pt.x = win_rect->left; + pt.y = win_rect->bottom; + hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(hmonitor, &monitor); + win_rect->bottom = min(win_rect->bottom, monitor.rcWork.bottom); + win_rect->left = max(win_rect->left, monitor.rcWork.left); + + /* Bottom-right. */ + pt.x = win_rect->right; + pt.y = win_rect->bottom; + hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + GetMonitorInfo(hmonitor, &monitor); + win_rect->bottom = min(win_rect->bottom, monitor.rcWork.bottom); + win_rect->right = min(win_rect->right, monitor.rcWork.right); /* With Windows 10 and newer we can adjust for chrome that differs with DPI and scale. */ GHOST_WIN32_AdjustWindowRectExForDpi fpAdjustWindowRectExForDpi = nullptr; @@ -334,9 +362,6 @@ void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect, else { AdjustWindowRectEx(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle); } - - /* But never allow a top position that can hide part of the title bar. */ - win_rect->top = max(monitor.rcWork.top, win_rect->top); } bool GHOST_WindowWin32::getValid() const diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 44071f0915ec..b6c4aa25c793 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -87,12 +87,12 @@ class GHOST_WindowWin32 : public GHOST_Window { ~GHOST_WindowWin32(); /** - * Adjusts a requested window rect to fit and position correctly in monitor. + * Adjusts a requested window rect to fit and position within the desktop. * \param win_rect: pointer to rectangle that will be modified. * \param dwStyle: The Window Style of the window whose required size is to be calculated. * \param dwExStyle: The Extended Window Style of the window. */ - void adjustWindowRectForClosestMonitor(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle); + void adjustWindowRectForDesktop(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle); /** * Returns indication as to whether the window is valid. diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 00b0230888e9..393944eac973 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -418,7 +418,7 @@ void GHOST_WindowX11::refreshXInputDevices() for (GHOST_SystemX11::GHOST_TabletX11 &xtablet : m_system->GetXTablets()) { /* With modern XInput (XLIB 1.6.2 at least and/or EVDEV 2.9.0) and some 'no-name' tablets * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event, - * otherwise we do not get any tablet motion event once pen is pressed... See T43367. + * otherwise we do not get any tablet motion event once pen is pressed... See #43367. */ XEventClass ev; @@ -1467,7 +1467,7 @@ GHOST_TSuccess GHOST_WindowX11::setWindowCursorGrab(GHOST_TGrabCursorMode mode) } } - /* Perform this last so to workaround XWayland bug, see: T53004. */ + /* Perform this last so to workaround XWayland bug, see: #53004. */ if (m_cursorGrab == GHOST_kGrabHide) { setWindowCursorVisibility(true); } diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index 5ae333439492..69221877f153 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -281,6 +281,8 @@ inline T *MEM_new(const char *allocation_name, Args &&...args) */ template inline void MEM_delete(const T *ptr) { + static_assert(!std::is_void_v, + "MEM_delete on a void pointer not possible. Cast it to a non-void type?"); if (ptr == nullptr) { /* Support #ptr being null, because C++ `delete` supports that as well. */ return; diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp index 80e8d89799a8..dc69a3740748 100644 --- a/intern/locale/boost_locale_wrapper.cpp +++ b/intern/locale/boost_locale_wrapper.cpp @@ -108,7 +108,7 @@ void bl_locale_set(const char *locale) } /* Extra catch on `std::runtime_error` is needed for macOS/Clang as it seems that exceptions * like `boost::locale::conv::conversion_error` (which inherit from `std::runtime_error`) are - * not caught by their ancestor `std::exception`. See T88877#1177108 */ + * not caught by their ancestor `std::exception`. See #88877#1177108 */ catch (std::runtime_error const &e) { std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n"; } diff --git a/intern/locale/osx_user_locale.mm b/intern/locale/osx_user_locale.mm index 92c9eb216056..f38717f24d3d 100644 --- a/intern/locale/osx_user_locale.mm +++ b/intern/locale/osx_user_locale.mm @@ -23,7 +23,7 @@ const char *osx_user_locale() [myNSLocale autorelease]; // This produces gettext-invalid locale in recent macOS versions (11.4), - // like `ko-Kore_KR` instead of `ko_KR`. See T88877. + // like `ko-Kore_KR` instead of `ko_KR`. See #88877. // NSString *nsIdentifier = [myNSLocale localeIdentifier]; const NSString *nsIdentifier = [myNSLocale languageCode]; diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index 6a72cd2aacb1..28c66021d232 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -193,7 +193,7 @@ static bool createGPUShader(OCIO_GPUShader &shader, info.fragment_source("gpu_shader_display_transform_frag.glsl"); info.fragment_source_generated = source; - /* T96502: Work around for incorrect OCIO GLSL code generation when using + /* #96502: Work around for incorrect OCIO GLSL code generation when using * GradingPrimaryTransform. Should be reevaluated when changing to a next version of OCIO. * (currently v2.1.1). */ info.define("inf 1e32"); diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index 24e093833c4a..d75a0974f748 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -145,7 +145,7 @@ const UserDef U_default = { .ndof_flag = (NDOF_MODE_ORBIT | NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE | /* Software from the driver authors follows this convention - * so invert this by default, see: T67579. */ + * so invert this by default, see: #67579. */ NDOF_ROTX_INVERT_AXIS | NDOF_ROTY_INVERT_AXIS | NDOF_ROTZ_INVERT_AXIS | NDOF_PANX_INVERT_AXIS | NDOF_PANY_INVERT_AXIS | NDOF_PANZ_INVERT_AXIS | NDOF_ZOOM_INVERT | NDOF_CAMERA_PAN_ZOOM), diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c index 04ad04d48128..7d0cf9b031cf 100644 --- a/release/datafiles/userdef/userdef_default_theme.c +++ b/release/datafiles/userdef/userdef_default_theme.c @@ -370,6 +370,7 @@ const bTheme U_theme_default = { .clipping_border_3d = RGBA(0x3f3f3fff), .bundle_solid = RGBA(0xc8c8c8ff), .camera_path = RGBA(0x000000ff), + .camera_passepartout = RGBA(0x000000), .gp_vertex_size = 3, .gp_vertex = RGBA(0x000000ff), .gp_vertex_select = RGBA(0xff8500ff), diff --git a/release/scripts/freestyle/modules/freestyle/chainingiterators.py b/release/scripts/freestyle/modules/freestyle/chainingiterators.py index 656a5b09a373..fbe419293cac 100644 --- a/release/scripts/freestyle/modules/freestyle/chainingiterators.py +++ b/release/scripts/freestyle/modules/freestyle/chainingiterators.py @@ -286,7 +286,7 @@ class pySketchyChainingIterator(ChainingIterator): if not found: # This is a fatal error condition: self.current_edge must be found - # among the edges seen by the AdjacencyIterator [bug T35695]. + # among the edges seen by the AdjacencyIterator [bug #35695]. if bpy.app.debug_freestyle: print('pySketchyChainingIterator: current edge not found') return None diff --git a/release/scripts/modules/bl_console_utils/autocomplete/intellisense.py b/release/scripts/modules/bl_console_utils/autocomplete/intellisense.py index 7aff3596c42a..d2d00238ddf4 100644 --- a/release/scripts/modules/bl_console_utils/autocomplete/intellisense.py +++ b/release/scripts/modules/bl_console_utils/autocomplete/intellisense.py @@ -113,7 +113,7 @@ def expand(line, cursor, namespace, *, private=True): if len(matches) == 1: scrollback = '' else: - # causes blender bug T27495 since string keys may contain '.' + # causes blender bug #27495 since string keys may contain '.' # scrollback = ' '.join([m.split('.')[-1] for m in matches]) # add white space to align with the cursor diff --git a/release/scripts/modules/bl_ui_utils/bug_report_url.py b/release/scripts/modules/bl_ui_utils/bug_report_url.py index 37a52a5141c4..16bd6692d789 100644 --- a/release/scripts/modules/bl_ui_utils/bug_report_url.py +++ b/release/scripts/modules/bl_ui_utils/bug_report_url.py @@ -30,7 +30,7 @@ def url_prefill_from_blender(*, addon_info=None): "**Blender Version**\n" ) fh.write( - "Broken: version: %s, branch: %s, commit date: %s %s, hash: `rB%s`\n" % ( + "Broken: version: %s, branch: %s, commit date: %s %s, hash: `%s`\n" % ( bpy.app.version_string, bpy.app.build_branch.decode('utf-8', 'replace'), bpy.app.build_commit_date.decode('utf-8', 'replace'), diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py index cb6ea0318a41..4295aa5f237d 100644 --- a/release/scripts/modules/bpy/ops.py +++ b/release/scripts/modules/bpy/ops.py @@ -32,7 +32,7 @@ class _BPyOpsSubModOp: # XXX You never quite know what you get from bpy.types, # with operators... Operator and OperatorProperties # are shadowing each other, and not in the same way for - # native ops and py ones! See T39158. + # native ops and py ones! See #39158. # op_class = getattr(bpy.types, idname) op_class = _op_get_rna_type(idname) descr = op_class.description diff --git a/release/scripts/modules/bpy_extras/anim_utils.py b/release/scripts/modules/bpy_extras/anim_utils.py index 3b90b18359e0..9bd5d9a83fac 100644 --- a/release/scripts/modules/bpy_extras/anim_utils.py +++ b/release/scripts/modules/bpy_extras/anim_utils.py @@ -259,15 +259,15 @@ def bake_action_iter( if is_new_action: action = bpy.data.actions.new("Action") - # Only leave tweak mode if we actually need to modify the action (T57159) + # Only leave tweak mode if we actually need to modify the action (#57159) if action != atd.action: - # Leave tweak mode before trying to modify the action (T48397) + # Leave tweak mode before trying to modify the action (#48397) if atd.use_tweak_mode: atd.use_tweak_mode = False atd.action = action - # Baking the action only makes sense in Replace mode, so force it (T69105) + # Baking the action only makes sense in Replace mode, so force it (#69105) if not atd.use_tweak_mode: atd.action_blend_type = 'REPLACE' diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index 04b536fce40c..794c39e07dc6 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -111,7 +111,7 @@ def orientation_helper(axis_forward='Y', axis_up='Z'): """ def wrapper(cls): # Without that, we may end up adding those fields to some **parent** class' __annotations__ property - # (like the ImportHelper or ExportHelper ones)! See T58772. + # (like the ImportHelper or ExportHelper ones)! See #58772. if "__annotations__" not in cls.__dict__: setattr(cls, "__annotations__", {}) diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index d8d6a9123f2d..18dbab7c6249 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -564,7 +564,7 @@ class Mesh(bpy_types.ID): face_lengths = tuple(map(len, faces)) - # NOTE: check non-empty lists by length because of how `numpy` handles truth tests, see: T90268. + # NOTE: check non-empty lists by length because of how `numpy` handles truth tests, see: #90268. vertices_len = len(vertices) edges_len = len(edges) faces_len = len(faces) diff --git a/release/scripts/modules/rna_manual_reference.py b/release/scripts/modules/rna_manual_reference.py index a3654b12c207..bb5943b2adf7 100644 --- a/release/scripts/modules/rna_manual_reference.py +++ b/release/scripts/modules/rna_manual_reference.py @@ -991,6 +991,7 @@ url_manual_mapping = ( ("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/read/face_area.html#bpy-types-geometrynodeinputmeshfacearea"), ("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/read/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"), ("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"), + ("bpy.types.geometrynodematerialselection*", "modeling/geometry_nodes/material/material_selection.html#bpy-types-geometrynodematerialselection"), ("bpy.types.gpencillayer.viewlayer_render*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-viewlayer-render"), ("bpy.types.imagepaint.use_normal_falloff*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-use-normal-falloff"), ("bpy.types.layercollection.hide_viewport*", "editors/outliner/interface.html#bpy-types-layercollection-hide-viewport"), @@ -2027,6 +2028,7 @@ url_manual_mapping = ( ("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"), ("bpy.ops.mball.delete_metaelems*", "modeling/metas/editing.html#bpy-ops-mball-delete-metaelems"), ("bpy.ops.mball.reveal_metaelems*", "modeling/metas/properties.html#bpy-ops-mball-reveal-metaelems"), + ("bpy.ops.mesh.bridge_edge_loops*", "modeling/meshes/editing/edge/bridge_edge_loops.html#bpy-ops-mesh-bridge-edge-loops"), ("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"), ("bpy.ops.mesh.loop_multi_select*", "modeling/meshes/selecting/loops.html#bpy-ops-mesh-loop-multi-select"), ("bpy.ops.mesh.vert_connect_path*", "modeling/meshes/editing/vertex/connect_vertex_path.html#bpy-ops-mesh-vert-connect-path"), @@ -3021,6 +3023,7 @@ url_manual_mapping = ( ("bpy.types.bakesettings*", "render/cycles/baking.html#bpy-types-bakesettings"), ("bpy.types.blendtexture*", "render/materials/legacy_textures/types/blend.html#bpy-types-blendtexture"), ("bpy.types.brush.height*", "sculpt_paint/sculpting/tools/layer.html#bpy-types-brush-height"), + ("bpy.types.brush.jitter*", "sculpt_paint/brush/stroke.html#bpy-types-brush-jitter"), ("bpy.types.castmodifier*", "modeling/modifiers/deform/cast.html#bpy-types-castmodifier"), ("bpy.types.curve.offset*", "modeling/curves/properties/geometry.html#bpy-types-curve-offset"), ("bpy.types.geometrynode*", "modeling/geometry_nodes/index.html#bpy-types-geometrynode"), diff --git a/release/scripts/presets/interface_theme/Blender_Light.xml b/release/scripts/presets/interface_theme/Blender_Light.xml index 49955bc3ff95..68245c53525c 100644 --- a/release/scripts/presets/interface_theme/Blender_Light.xml +++ b/release/scripts/presets/interface_theme/Blender_Light.xml @@ -29,11 +29,11 @@ icon_modifier="#84b8ffff" icon_shading="#ea7581ff" icon_folder="#e3c16eff" - icon_border_intensity="0.85" + icon_border_intensity="1" > + + + + @@ -519,9 +535,9 @@ > @@ -552,7 +568,7 @@ header="#adadadff" header_text="#000000" header_text_hi="#ffffff" - button="#999999e6" + button="#b3b3b3ff" button_title="#1a1a1a" button_text="#000000" button_text_hi="#000000" @@ -565,9 +581,9 @@ > @@ -623,9 +639,9 @@ > @@ -698,9 +714,9 @@ > @@ -783,9 +799,9 @@ > @@ -843,14 +859,23 @@ > + + + + @@ -871,7 +896,7 @@ button_title="#000000" button_text="#000000" button_text_hi="#000000" - navigation_bar="#656565ff" + navigation_bar="#1d1d1dff" execution_buts="#00000000" tab_active="#6697e6" tab_inactive="#535353" @@ -880,9 +905,9 @@ > @@ -927,9 +952,9 @@ > @@ -939,44 +964,44 @@ @@ -1013,8 +1038,8 @@ @@ -1091,9 +1116,9 @@ > @@ -1125,9 +1150,9 @@ > @@ -1137,26 +1162,26 @@ @@ -1231,9 +1256,9 @@ > @@ -1274,9 +1299,9 @@ > @@ -1292,7 +1317,7 @@ title="#ffffff" text="#ffffff" text_hi="#ffffff" - header="#adadadff" + header="#999999ff" header_text="#1a1a1a" header_text_hi="#ffffff" button="#2f303500" @@ -1308,9 +1333,9 @@ > @@ -1331,7 +1356,7 @@ header="#adadadff" header_text="#000000" header_text_hi="#ffffff" - button="#999999e6" + button="#b3b3b3ff" button_title="#1a1a1a" button_text="#000000" button_text_hi="#000000" @@ -1344,9 +1369,9 @@ > @@ -1585,8 +1610,8 @@ shadow="3" shadow_offset_x="0" shadow_offset_y="-1" - shadow_alpha="0.3" - shadow_value="0.7" + shadow_alpha="1" + shadow_value="0.8" > @@ -1596,8 +1621,8 @@ shadow="3" shadow_offset_x="0" shadow_offset_y="-1" - shadow_alpha="0.3" - shadow_value="0.7" + shadow_alpha="0" + shadow_value="0.8" > @@ -1607,8 +1632,8 @@ shadow="1" shadow_offset_x="0" shadow_offset_y="-1" - shadow_alpha="0.3" - shadow_value="0.7" + shadow_alpha="0" + shadow_value="0.8" > diff --git a/release/scripts/presets/keyconfig/Blender.py b/release/scripts/presets/keyconfig/Blender.py index e77fde4c39c7..52e4c2d42290 100644 --- a/release/scripts/presets/keyconfig/Blender.py +++ b/release/scripts/presets/keyconfig/Blender.py @@ -86,7 +86,7 @@ class Prefs(bpy.types.KeyConfigPreferences): update=update_fn, ) - # Experimental: only show with developer extras, see: T96544. + # Experimental: only show with developer extras, see: #96544. use_tweak_select_passthrough: BoolProperty( name="Tweak Select: Mouse Select & Move", description=( @@ -96,7 +96,7 @@ class Prefs(bpy.types.KeyConfigPreferences): default=False, update=update_fn, ) - # Experimental: only show with developer extras, see: T96544. + # Experimental: only show with developer extras, see: #96544. use_tweak_tool_lmb_interaction: BoolProperty( name="Tweak Tool: Left Mouse Select & Move", description=( diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index b960c56ffe72..252bcaeab433 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -37,7 +37,7 @@ class Params: # instead be bound to a binding that doesn't de-select all, this way: # - Click-drag moves the current selection. # - Click selects only the item at the cursor position. - # See: T97032. + # See: #97032. "use_tweak_select_passthrough", "use_tweak_tool_lmb_interaction", "use_mouse_emulate_3_button", @@ -465,7 +465,7 @@ def _template_items_tool_select( fallback=False, ): if not params.legacy and not fallback: - # Experimental support for LMB interaction for the tweak tool. see: T96544. + # Experimental support for LMB interaction for the tweak tool. see: #96544. # NOTE: For RMB-select this is a much bigger change as it disables 3D cursor placement on LMB. # For LMB-select this means an LMB -drag will not first de-select all (similar to node/graph editor). select_passthrough = False @@ -498,7 +498,7 @@ def _template_items_tool_select( {"properties": [("toggle", True), *operator_props]}), # Fallback key-map must transform as the primary tool is expected - # to be accessed via gizmos in this case. See: T96885. + # to be accessed via gizmos in this case. See: #96885. *(() if not fallback else ( ("transform.translate", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'}, {"properties": [("release_confirm", True)]}), @@ -4730,7 +4730,7 @@ def _template_paint_radial_control(paint, rotation=False, secondary_rotation=Fal def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_mod=None): # NOTE: `exclude_mod` is needed since we don't want this tool to exclude Control-RMB actions when this is used - # as a tool key-map with RMB-select and `use_fallback_tool` is enabled with RMB select. See T92467. + # as a tool key-map with RMB-select and `use_fallback_tool` is enabled with RMB select. See #92467. props_vert_without_handles = () if select_passthrough: @@ -5629,6 +5629,10 @@ def km_curves(params): ("curves.disable_selection", {"type": 'TWO', "value": 'PRESS', "alt": True}, None), *_template_items_select_actions(params, "curves.select_all"), ("curves.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None), + ("curves.delete", {"type": 'X', "value": 'PRESS'}, None), + ("curves.delete", {"type": 'DEL', "value": 'PRESS'}, None), + ("curves.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), + ("curves.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ]) return keymap @@ -5683,7 +5687,7 @@ def km_object_non_modal(params): ]) else: items.extend([ - # NOTE: this shortcut (while not temporary) is not ideal, see: T89757. + # NOTE: this shortcut (while not temporary) is not ideal, see: #89757. ("object.transfer_mode", {"type": 'Q', "value": 'PRESS', "alt": True}, None), ]) @@ -6345,9 +6349,8 @@ def km_node_link_modal_map(_params): return keymap + # Fallback for gizmos that don't have custom a custom key-map. - - def km_generic_gizmo(_params): keymap = ( "Generic Gizmo", diff --git a/release/scripts/startup/bl_operators/geometry_nodes.py b/release/scripts/startup/bl_operators/geometry_nodes.py index 2b92b87a97fd..9696063ac1ed 100644 --- a/release/scripts/startup/bl_operators/geometry_nodes.py +++ b/release/scripts/startup/bl_operators/geometry_nodes.py @@ -6,8 +6,8 @@ from bpy.types import Operator from bpy.app.translations import pgettext_data as data_ -def geometry_node_group_empty_new(): - group = bpy.data.node_groups.new(data_("Geometry Nodes"), 'GeometryNodeTree') +def build_default_empty_geometry_node_group(name): + group = bpy.data.node_groups.new(name, 'GeometryNodeTree') group.inputs.new('NodeSocketGeometry', data_("Geometry")) group.outputs.new('NodeSocketGeometry', data_("Geometry")) input_node = group.nodes.new('NodeGroupInput') @@ -20,8 +20,12 @@ def geometry_node_group_empty_new(): input_node.location.x = -200 - input_node.width output_node.location.x = 200 - group.links.new(output_node.inputs[0], input_node.outputs[0]) + return group + +def geometry_node_group_empty_new(): + group = build_default_empty_geometry_node_group(data_("Geometry Nodes")) + group.links.new(group.nodes["Group Input"].outputs[0], group.nodes["Group Output"].inputs[0]) return group @@ -35,6 +39,158 @@ def geometry_modifier_poll(context): return True +def get_context_modifier(context): + if context.area.type == 'PROPERTIES': + modifier = context.modifier + else: + modifier = context.object.modifiers.active + if modifier is None or modifier.type != 'NODES': + return None + return modifier + + +def edit_geometry_nodes_modifier_poll(context): + return get_context_modifier(context) is not None + + +def socket_idname_to_attribute_type(idname): + if idname.startswith("NodeSocketInt"): + return "INT" + elif idname.startswith("NodeSocketColor"): + return "FLOAT_COLOR" + elif idname.startswith("NodeSocketVector"): + return "FLOAT_VECTOR" + elif idname.startswith("NodeSocketBool"): + return "BOOLEAN" + elif idname.startswith("NodeSocketFloat"): + return "FLOAT" + raise ValueError("Unsupported socket type") + return "" + + +def modifier_attribute_name_get(modifier, identifier): + try: + return modifier[identifier + "_attribute_name"] + except KeyError: + return None + + +def modifier_input_use_attribute(modifier, identifier): + try: + return modifier[identifier + "_use_attribute"] != 0 + except KeyError: + return False + + +def get_socket_with_identifier(sockets, identifier): + for socket in sockets: + if socket.identifier == identifier: + return socket + return None + + +def get_enabled_socket_with_name(sockets, name): + for socket in sockets: + if socket.name == name and socket.enabled: + return socket + return None + + +class MoveModifierToNodes(Operator): + """Move inputs and outputs from in the modifier to a new node group""" + + bl_idname = "object.geometry_nodes_move_to_nodes" + bl_label = "Move to Nodes" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + return edit_geometry_nodes_modifier_poll(context) + + def execute(self, context): + modifier = get_context_modifier(context) + if not modifier: + return {'CANCELLED'} + old_group = modifier.node_group + if not old_group: + return {'CANCELLED'} + + wrapper_name = old_group.name + ".wrapper" + group = build_default_empty_geometry_node_group(wrapper_name) + group_node = group.nodes.new("GeometryNodeGroup") + group_node.node_tree = old_group + group_node.update() + + group_input_node = group.nodes["Group Input"] + group_output_node = group.nodes["Group Output"] + + # Copy default values for inputs and create named attribute input nodes. + input_nodes = [] + first_geometry_input = None + for input_socket in old_group.inputs: + identifier = input_socket.identifier + group_node_input = get_socket_with_identifier(group_node.inputs, identifier) + if modifier_input_use_attribute(modifier, identifier): + input_node = group.nodes.new("GeometryNodeInputNamedAttribute") + input_nodes.append(input_node) + input_node.data_type = socket_idname_to_attribute_type(input_socket.bl_socket_idname) + attribute_name = modifier_attribute_name_get(modifier, identifier) + input_node.inputs["Name"].default_value = attribute_name + output_socket = get_enabled_socket_with_name(input_node.outputs, "Attribute") + group.links.new(output_socket, group_node_input) + elif hasattr(input_socket, "default_value"): + group_node_input.default_value = modifier[identifier] + elif input_socket.bl_socket_idname == 'NodeSocketGeometry': + if not first_geometry_input: + first_geometry_input = group_node_input + + group.links.new(group_input_node.outputs[0], first_geometry_input) + + # Adjust locations of named attribute input nodes and group input node to make some space. + if input_nodes: + for i, node in enumerate(input_nodes): + node.location.x = -175 + node.location.y = i * -50 + group_input_node.location.x = -350 + + # Connect outputs to store named attribute nodes to replace modifier attribute outputs. + store_nodes = [] + first_geometry_output = None + for output_socket in old_group.outputs: + identifier = output_socket.identifier + group_node_output = get_socket_with_identifier(group_node.outputs, identifier) + attribute_name = modifier_attribute_name_get(modifier, identifier) + if attribute_name: + store_node = group.nodes.new("GeometryNodeStoreNamedAttribute") + store_nodes.append(store_node) + store_node.data_type = socket_idname_to_attribute_type(output_socket.bl_socket_idname) + store_node.domain = output_socket.attribute_domain + store_node.inputs["Name"].default_value = attribute_name + input_socket = get_enabled_socket_with_name(store_node.inputs, "Value") + group.links.new(group_node_output, input_socket) + elif output_socket.bl_socket_idname == 'NodeSocketGeometry': + if not first_geometry_output: + first_geometry_output = group_node_output + + # Adjust locations of store named attribute nodes and move group output. + if store_nodes: + for i, node in enumerate(store_nodes): + node.location.x = (i + 1) * 175 + node.location.y = 0 + group_output_node.location.x = (len(store_nodes) + 1) * 175 + + group.links.new(first_geometry_output, store_nodes[0].inputs["Geometry"]) + for i in range(len(store_nodes) - 1): + group.links.new(store_nodes[i].outputs["Geometry"], store_nodes[i + 1].inputs["Geometry"]) + group.links.new(store_nodes[-1].outputs["Geometry"], group_output_node.inputs["Geometry"]) + else: + group.links.new(first_geometry_output, group_output_node.inputs["Geometry"]) + + modifier.node_group = group + + return {'FINISHED'} + + class NewGeometryNodesModifier(Operator): """Create a new modifier with a new geometry node group""" @@ -48,7 +204,6 @@ class NewGeometryNodesModifier(Operator): def execute(self, context): modifier = context.object.modifiers.new(data_("GeometryNodes"), "NODES") - if not modifier: return {'CANCELLED'} @@ -70,11 +225,7 @@ class NewGeometryNodeTreeAssign(Operator): return geometry_modifier_poll(context) def execute(self, context): - if context.area.type == 'PROPERTIES': - modifier = context.modifier - else: - modifier = context.object.modifiers.active - + modifier = get_context_modifier(context) if not modifier: return {'CANCELLED'} @@ -87,4 +238,5 @@ class NewGeometryNodeTreeAssign(Operator): classes = ( NewGeometryNodesModifier, NewGeometryNodeTreeAssign, + MoveModifierToNodes, ) diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 6a130edbb380..810c40cb6875 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -790,7 +790,7 @@ class TransformsToDeltasAnim(Operator): continue # first pass over F-Curves: ensure that we don't have conflicting - # transforms already (e.g. if this was applied already) T29110. + # transforms already (e.g. if this was applied already) #29110. existingFCurves = {} for fcu in adt.action.fcurves: # get "delta" path - i.e. the final paths which may clash diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index d8b0e85be0e0..dc3edcd9b752 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -36,67 +36,136 @@ class ObjectModeOperator: class QuickFur(ObjectModeOperator, Operator): - """Add fur setup to the selected objects""" + """Add a fur setup to the selected objects""" bl_idname = "object.quick_fur" bl_label = "Quick Fur" bl_options = {'REGISTER', 'UNDO'} density: EnumProperty( - name="Fur Density", + name="Density", items=( - ('LIGHT', "Light", ""), + ('LOW', "Low", ""), ('MEDIUM', "Medium", ""), - ('HEAVY', "Heavy", ""), + ('HIGH', "High", ""), ), default='MEDIUM', ) - view_percentage: IntProperty( - name="View %", - min=1, max=100, - soft_min=1, soft_max=100, - default=10, - ) length: FloatProperty( name="Length", min=0.001, max=100, soft_min=0.01, soft_max=10, default=0.1, + subtype='DISTANCE' + ) + radius: FloatProperty( + name="Hair Radius", + min=0.0, max=10, + soft_min=0.0001, soft_max=0.1, + default=0.001, + subtype='DISTANCE' + ) + view_percentage: FloatProperty( + name="View Percentage", + min=0.0, max=1.0, + default=1.0, + subtype='FACTOR' + ) + apply_hair_guides: BoolProperty( + name="Apply Hair Guides", + default=True, + ) + use_noise: BoolProperty( + name="Noise", + default=True, + ) + use_frizz: BoolProperty( + name="Frizz", + default=True, ) def execute(self, context): - fake_context = context.copy() - mesh_objects = [obj for obj in context.selected_objects - if obj.type == 'MESH'] - + import os + mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH'] if not mesh_objects: self.report({'ERROR'}, "Select at least one mesh object") return {'CANCELLED'} - mat = bpy.data.materials.new("Fur Material") + if self.density == 'LOW': + count = 1000 + elif self.density == 'MEDIUM': + count = 10000 + elif self.density == 'HIGH': + count = 100000 - for obj in mesh_objects: - fake_context["object"] = obj - bpy.ops.object.particle_system_add(fake_context) + node_groups_to_append = {"Generate Hair Curves", "Set Hair Curve Profile", "Interpolate Hair Curves"} + if self.use_noise: + node_groups_to_append.add("Hair Curves Noise") + if self.use_frizz: + node_groups_to_append.add("Frizz Hair Curves") + assets_directory = os.path.join(bpy.utils.system_resource('DATAFILES'), + "assets", + "geometry_nodes", + "procedural_hair_node_assets.blend", + "NodeTree") + for name in node_groups_to_append: + bpy.ops.wm.append(directory=assets_directory, + filename=name, + use_recursive=True, + clear_asset_data=True, + do_reuse_local_id=True) + generate_group = bpy.data.node_groups["Generate Hair Curves"] + interpolate_group = bpy.data.node_groups["Interpolate Hair Curves"] + radius_group = bpy.data.node_groups["Set Hair Curve Profile"] + noise_group = bpy.data.node_groups["Hair Curves Noise"] if self.use_noise else None + frizz_group = bpy.data.node_groups["Frizz Hair Curves"] if self.use_frizz else None - psys = obj.particle_systems[-1] - psys.settings.type = 'HAIR' + material = bpy.data.materials.new("Fur Material") - if self.density == 'LIGHT': - psys.settings.count = 100 - elif self.density == 'MEDIUM': - psys.settings.count = 1000 - elif self.density == 'HEAVY': - psys.settings.count = 10000 + for mesh_object in mesh_objects: + mesh = mesh_object.data + with context.temp_override(active_object=mesh_object): + bpy.ops.object.curves_empty_hair_add() + curves_object = context.active_object + curves = curves_object.data + curves.materials.append(material) - psys.settings.child_nbr = self.view_percentage - psys.settings.hair_length = self.length - psys.settings.use_strand_primitive = True - psys.settings.use_hair_bspline = True - psys.settings.child_type = 'INTERPOLATED' - psys.settings.tip_radius = 0.25 + area = 0.0 + for poly in mesh.polygons: + area += poly.area + density = count / area - obj.data.materials.append(mat) - psys.settings.material = len(obj.data.materials) + generate_modifier = curves_object.modifiers.new(name="Generate", type='NODES') + generate_modifier.node_group = generate_group + generate_modifier["Input_2"] = mesh_object + generate_modifier["Input_18_attribute_name"] = curves.surface_uv_map + generate_modifier["Input_20"] = self.length + generate_modifier["Input_22"] = material + generate_modifier["Input_15"] = density * 0.01 + curves_object.modifiers.move(1, 0) + + radius_modifier = curves_object.modifiers.new(name="Set Hair Curve Profile", type='NODES') + radius_modifier.node_group = radius_group + radius_modifier["Input_3"] = self.radius + + interpolate_modifier = curves_object.modifiers.new(name="Interpolate Hair Curves", type='NODES') + interpolate_modifier.node_group = interpolate_group + interpolate_modifier["Input_2"] = mesh_object + interpolate_modifier["Input_18_attribute_name"] = curves.surface_uv_map + interpolate_modifier["Input_15"] = density + interpolate_modifier["Input_17"] = self.view_percentage + interpolate_modifier["Input_24"] = True + + if noise_group: + noise_modifier = curves_object.modifiers.new(name="Hair Curves Noise", type='NODES') + noise_modifier.node_group = noise_group + + if frizz_group: + frizz_modifier = curves_object.modifiers.new(name="Frizz Hair Curves", type='NODES') + frizz_modifier.node_group = frizz_group + + if self.apply_hair_guides: + with context.temp_override(object=curves_object): + bpy.ops.object.modifier_apply(modifier=generate_modifier.name) return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/userpref.py b/release/scripts/startup/bl_operators/userpref.py index dc8504c057e4..d0134bd076f1 100644 --- a/release/scripts/startup/bl_operators/userpref.py +++ b/release/scripts/startup/bl_operators/userpref.py @@ -700,7 +700,7 @@ class PREFERENCES_OT_addon_install(Operator): addons_new.discard("modules") # disable any addons we may have enabled previously and removed. - # this is unlikely but do just in case. bug T23978. + # this is unlikely but do just in case. bug #23978. for new_addon in addons_new: addon_utils.disable(new_addon, default_set=True) diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py index ca309bff9e4f..6d1d0f1be991 100644 --- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py +++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py @@ -581,7 +581,7 @@ class LightMapPack(Operator): # Proper solution would be to make undo stack aware of such things, # but for now just disable redo. Keep undo here so unwanted changes to uv # coords might be undone. - # This fixes infinite image creation reported there T30968 (sergey) + # This fixes infinite image creation reported there #30968 (sergey) bl_options = {'UNDO'} PREF_CONTEXT: bpy.props.EnumProperty( diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py index 616e37d37e7a..0b948fa27636 100644 --- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py +++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py @@ -90,7 +90,7 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, tone_range = max_tone - min_tone if tone_range < 0.0001: - # weak, don't cancel, see T43345 + # weak, don't cancel, see #43345 tone_range = 0.0 else: tone_range = 1.0 / tone_range diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py index bb0d163fdd67..6eee0ef84f03 100644 --- a/release/scripts/startup/bl_operators/view3d.py +++ b/release/scripts/startup/bl_operators/view3d.py @@ -42,7 +42,7 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator): bpy.ops.mesh.extrude_vertices_move('INVOKE_REGION_WIN') # ignore return from operators above because they are 'RUNNING_MODAL', - # and cause this one not to be freed. T24671. + # and cause this one not to be freed. #24671. return {'FINISHED'} def invoke(self, context, _event): @@ -104,7 +104,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator): 'INVOKE_REGION_WIN', TRANSFORM_OT_translate={ # Don't set the constraint axis since users will expect MMB - # to use the user setting, see: T61637 + # to use the user setting, see: #61637 # "orient_type": 'NORMAL', # Not a popular choice, too restrictive for retopo. # "constraint_axis": (True, True, False)}) @@ -114,7 +114,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator): bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN') # ignore return from operators above because they are 'RUNNING_MODAL', - # and cause this one not to be freed. T24671. + # and cause this one not to be freed. #24671. return {'FINISHED'} def execute(self, context): diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 6d47fef371c6..25b26bdbf408 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1249,7 +1249,31 @@ class WM_OT_doc_view_manual(Operator): # XXX, for some reason all RNA ID's are stored lowercase # Adding case into all ID's isn't worth the hassle so force lowercase. rna_id = rna_id.lower() + + # NOTE: `fnmatch` in Python is slow as it translate the string to a regular-expression + # which needs to be compiled (as of Python 3.11), this is slow enough to cause a noticeable + # delay when opening manual links (approaching half a second). + # + # Resolve by matching characters that have a special meaning to `fnmatch`. + # The characters that can occur as the first special character are `*?[`. + # If any of these are used we must let `fnmatch` run its own matching logic. + # However, in most cases a literal prefix is used making it considerably faster + # to do a simple `startswith` check before performing a full match. + # An alternative solution could be to use `fnmatch` from C which is significantly + # faster than Python's, see !104581 for details. + import re + re_match_non_special = re.compile(r"^[^?\*\[]+").match + for pattern, url_suffix in url_mapping: + + # Simple optimization, makes a big difference (over 50x speedup). + # Even when `non_special.end()` is zero (resulting in an empty-string), + # the `startswith` check succeeds so there is no need to check for an empty match. + non_special = re_match_non_special(pattern) + if non_special is None or not rna_id.startswith(pattern[:non_special.end()]): + continue + # End simple optimization. + if fnmatchcase(rna_id, pattern): if verbose: print(" match found: '%s' --> '%s'" % (pattern, url_suffix)) @@ -1725,7 +1749,7 @@ class WM_OT_properties_edit(Operator): for nt in adt.nla_tracks: _update_strips(nt.strips) - # Otherwise existing buttons which reference freed memory may crash Blender (T26510). + # Otherwise existing buttons which reference freed memory may crash Blender (#26510). for win in context.window_manager.windows: for area in win.screen.areas: area.tag_redraw() diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 8e09a64b9154..c837a038c9f4 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -604,7 +604,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel): colliding_names = [] for collection in ( # Built-in names. - {"shade_smooth": None, "normal": None, "crease": None}, + {"shade_smooth": None, "crease": None}, mesh.attributes, None if ob is None else ob.vertex_groups, ): diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index c912de8f3e41..63dd18cb7033 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -1141,6 +1141,11 @@ def brush_texture_settings(layout, brush, sculpt): # texture_sample_bias layout.prop(brush, "texture_sample_bias", slider=True, text="Sample Bias") + if brush.sculpt_tool == 'DRAW': + col = layout.column() + col.active = tex_slot.map_mode == 'AREA_PLANE' + col.prop(brush, "use_color_as_displacement", text="Vector Displacement") + def brush_mask_texture_settings(layout, brush): mask_tex_slot = brush.mask_texture_slot diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index 8abd8b618392..4d97fe9cf62c 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -91,7 +91,7 @@ class TEXTURE_PT_preview(TextureButtonsPanel, Panel): else: layout.template_preview(tex, slot=slot) - # Show Alpha Button for Brush Textures, see T29502. + # Show Alpha Button for Brush Textures, see #29502. idblock = context_tex_datablock(context) if isinstance(idblock, Brush): layout.prop(tex, "use_preview_alpha") diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index 85313b143411..88fdc087584c 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -22,7 +22,7 @@ class FILEBROWSER_HT_header(Header): layout.separator_spacer() - if params.asset_library_ref != 'LOCAL': + if params.asset_library_ref not in {'LOCAL', 'ESSENTIALS'}: layout.prop(params, "import_type", text="") layout.separator_spacer() diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 7e221d63d4a0..c54dea94318c 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -62,7 +62,7 @@ class NODE_HT_header(Header): types_that_support_material = {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'GPENCIL', 'VOLUME', 'CURVES', 'POINTCLOUD'} - # disable material slot buttons when pinned, cannot find correct slot within id_from (T36589) + # disable material slot buttons when pinned, cannot find correct slot within id_from (#36589) # disable also when the selected object does not support materials has_material_slots = not snode.pin and ob_type in types_that_support_material diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 66a3ca8d95a0..3976f503aa24 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -407,7 +407,7 @@ class SEQUENCER_MT_view(Menu): if st.view_type == 'PREVIEW': # Specifying the REGION_PREVIEW context is needed in preview-only # mode, else the lookup for the shortcut will fail in - # wm_keymap_item_find_props() (see T32595). + # wm_keymap_item_find_props() (see #32595). layout.operator_context = 'INVOKE_REGION_PREVIEW' layout.prop(st, "show_region_ui") layout.prop(st, "show_region_tool_header") @@ -429,7 +429,7 @@ class SEQUENCER_MT_view(Menu): layout.operator_context = 'INVOKE_REGION_WIN' if st.view_type == 'PREVIEW': - # See above (T32595) + # See above (#32595) layout.operator_context = 'INVOKE_REGION_PREVIEW' layout.operator("sequencer.view_selected", text="Frame Selected") @@ -931,8 +931,14 @@ class SEQUENCER_MT_strip(Menu): if has_sequencer: - layout.operator("sequencer.split", text="Split").type = 'SOFT' - layout.operator("sequencer.split", text="Hold Split").type = 'HARD' + props = layout.operator("sequencer.split", text="Split") + props.type = 'SOFT' + props.side = 'RIGHT' + + props = layout.operator("sequencer.split", text="Hold Split") + props.type = 'HARD' + props.side = 'RIGHT' + layout.separator() if has_sequencer: diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 533d0976af0f..bc6407993526 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -25,15 +25,14 @@ def kmi_to_string_or_none(kmi): def generate_from_enum_ex( - _context, - *, - idname_prefix, - icon_prefix, - type, - attr, - cursor="DEFAULT", - tooldef_keywords={}, - exclude_filter={}, + _context, *, + idname_prefix, + icon_prefix, + type, + attr, + cursor='DEFAULT', + tooldef_keywords={}, + exclude_filter={}, ): tool_defs = [] for enum in type.bl_rna.properties[attr].enum_items_static: @@ -79,11 +78,12 @@ class _defs_view3d_generic: props = tool.operator_properties("view3d.cursor3d") layout.prop(props, "use_depth") layout.prop(props, "orientation") - return dict( idname="builtin.cursor", label="Cursor", - description=("Set the cursor location, drag to transform"), + description=( + "Set the cursor location, drag to transform" + ), icon="ops.generic.cursor", keymap="3D View Tool: Cursor", draw_settings=draw_settings, @@ -118,7 +118,6 @@ class _defs_view3d_generic: kmi_to_string_or_none(kmi_add), kmi_to_string_or_none(kmi_remove), ) - return dict( idname="builtin.measure", label="Measure", @@ -130,6 +129,7 @@ class _defs_view3d_generic: class _defs_annotate: + def draw_settings_common(context, layout, tool): gpd = context.annotation_data region_type = context.region.type @@ -139,15 +139,15 @@ class _defs_annotate: text = gpd.layers.active_note maxw = 25 if len(text) > maxw: - text = text[: maxw - 5] + ".." + text[-3:] + text = text[:maxw - 5] + '..' + text[-3:] else: text = "" gpl = context.active_annotation_layer if gpl is not None: layout.label(text="Annotation:") - if context.space_data.type in {"VIEW_3D", "SEQUENCE_EDITOR"}: - if region_type == "TOOL_HEADER": + if context.space_data.type in {'VIEW_3D', 'SEQUENCE_EDITOR'}: + if region_type == 'TOOL_HEADER': sub = layout.split(align=True, factor=0.5) sub.ui_units_x = 6.5 sub.prop(gpl, "color", text="") @@ -164,30 +164,21 @@ class _defs_annotate: space_type = tool.space_type tool_settings = context.tool_settings - if space_type == "VIEW_3D": + if space_type == 'VIEW_3D': row = layout.row(align=True) - row.prop( - tool_settings, "annotation_stroke_placement_view3d", text="Placement" - ) - if tool_settings.gpencil_stroke_placement_view3d == "CURSOR": + row.prop(tool_settings, "annotation_stroke_placement_view3d", text="Placement") + if tool_settings.gpencil_stroke_placement_view3d == 'CURSOR': row.prop(tool_settings.gpencil_sculpt, "lockaxis") - elif tool_settings.gpencil_stroke_placement_view3d in {"SURFACE", "STROKE"}: + elif tool_settings.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}: row.prop(tool_settings, "use_gpencil_stroke_endpoints") - elif space_type in { - "IMAGE_EDITOR", - "NODE_EDITOR", - "SEQUENCE_EDITOR", - "CLIP_EDITOR", - }: + elif space_type in {'IMAGE_EDITOR', 'NODE_EDITOR', 'SEQUENCE_EDITOR', 'CLIP_EDITOR'}: row = layout.row(align=True) - row.prop( - tool_settings, "annotation_stroke_placement_view2d", text="Placement" - ) + row.prop(tool_settings, "annotation_stroke_placement_view2d", text="Placement") if tool.idname == "builtin.annotate_line": props = tool.operator_properties("gpencil.annotate") - if region_type == "TOOL_HEADER": + if region_type == 'TOOL_HEADER': row = layout.row() row.ui_units_x = 15 row.prop(props, "arrowstyle_start", text="Start") @@ -199,7 +190,7 @@ class _defs_annotate: col.prop(props, "arrowstyle_end", text="End") elif tool.idname == "builtin.annotate": props = tool.operator_properties("gpencil.annotate") - if region_type == "TOOL_HEADER": + if region_type == 'TOOL_HEADER': row = layout.row() row.prop(props, "use_stabilizer", text="Stabilize Stroke") subrow = layout.row(align=False) @@ -219,10 +210,10 @@ class _defs_annotate: idname="builtin.annotate", label="Annotate", icon="ops.gpencil.draw", - cursor="PAINT_BRUSH", + cursor='PAINT_BRUSH', keymap="Generic Tool: Annotate", draw_settings=draw_settings, - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn.with_args(draw_settings=draw_settings_common) @@ -231,10 +222,10 @@ class _defs_annotate: idname="builtin.annotate_line", label="Annotate Line", icon="ops.gpencil.draw.line", - cursor="PAINT_BRUSH", + cursor='PAINT_BRUSH', keymap="Generic Tool: Annotate Line", draw_settings=draw_settings, - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn.with_args(draw_settings=draw_settings_common) @@ -243,10 +234,10 @@ class _defs_annotate: idname="builtin.annotate_polygon", label="Annotate Polygon", icon="ops.gpencil.draw.poly", - cursor="PAINT_BRUSH", + cursor='PAINT_BRUSH', keymap="Generic Tool: Annotate Polygon", draw_settings=draw_settings, - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -255,21 +246,21 @@ class _defs_annotate: # TODO: Move this setting to tool_settings prefs = context.preferences layout.prop(prefs.edit, "grease_pencil_eraser_radius", text="Radius") - return dict( idname="builtin.annotate_eraser", label="Annotate Eraser", icon="ops.gpencil.draw.eraser", - cursor="ERASER", + cursor='ERASER', keymap="Generic Tool: Annotate Eraser", draw_settings=draw_settings, - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ) class _defs_transform: + def draw_transform_sculpt_tool_settings(context, layout): - if context.mode != "SCULPT": + if context.mode != 'SCULPT': return layout.prop(context.tool_settings.sculpt, "transform_mode") @@ -277,10 +268,7 @@ class _defs_transform: def translate(): def draw_settings(context, layout, _tool): _defs_transform.draw_transform_sculpt_tool_settings(context, layout) - _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index( - context, layout, 1 - ) - + _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1) return dict( idname="builtin.move", label="Move", @@ -296,10 +284,7 @@ class _defs_transform: def rotate(): def draw_settings(context, layout, _tool): _defs_transform.draw_transform_sculpt_tool_settings(context, layout) - _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index( - context, layout, 2 - ) - + _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 2) return dict( idname="builtin.rotate", label="Rotate", @@ -315,10 +300,7 @@ class _defs_transform: def scale(): def draw_settings(context, layout, _tool): _defs_transform.draw_transform_sculpt_tool_settings(context, layout) - _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index( - context, layout, 3 - ) - + _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 3) return dict( idname="builtin.scale", label="Scale", @@ -333,10 +315,7 @@ class _defs_transform: @ToolDef.from_fn def scale_cage(): def draw_settings(context, layout, _tool): - _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index( - context, layout, 3 - ) - + _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 3) return dict( idname="builtin.scale_cage", label="Scale Cage", @@ -351,10 +330,7 @@ class _defs_transform: def shear(): def draw_settings(context, layout, _tool): # props = tool.operator_properties("transform.shear") - _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index( - context, layout, 2 - ) - + _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 2) return dict( idname="builtin.shear", label="Shear", @@ -372,7 +348,7 @@ class _defs_transform: show_drag = True tool_settings = context.tool_settings - if tool_settings.workspace_tool_type == "FALLBACK": + if tool_settings.workspace_tool_type == 'FALLBACK': show_drag = False if show_drag: @@ -380,14 +356,14 @@ class _defs_transform: layout.prop(props, "drag_action") _defs_transform.draw_transform_sculpt_tool_settings(context, layout) - _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index( - context, layout, 1 - ) + _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 1) return dict( idname="builtin.transform", label="Transform", - description=("Supports any combination of grab, rotate, and scale at once"), + description=( + "Supports any combination of grab, rotate, and scale at once" + ), icon="ops.transform.transform", widget="VIEW3D_GGT_xform_gizmo", keymap="3D View Tool: Transform", @@ -396,6 +372,7 @@ class _defs_transform: class _defs_view3d_select: + @ToolDef.from_fn def select(): return dict( @@ -413,7 +390,6 @@ class _defs_view3d_select: row = layout.row() row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) - return dict( idname="builtin.select_box", label="Select Box", @@ -430,7 +406,6 @@ class _defs_view3d_select: row = layout.row() row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) - return dict( idname="builtin.select_lasso", label="Select Lasso", @@ -451,7 +426,6 @@ class _defs_view3d_select: def draw_cursor(_context, tool, xy): from gpu_extras.presets import draw_circle_2d - props = tool.operator_properties("view3d.select_circle") radius = props.radius draw_circle_2d(xy, (1.0,) * 4, radius, segments=32) @@ -468,6 +442,7 @@ class _defs_view3d_select: class _defs_view3d_add: + @staticmethod def description_interactive_add(context, _item, _km, *, prefix): km = context.window_manager.keyconfigs.user.keymaps["View3D Placement Modal"] @@ -478,9 +453,9 @@ class _defs_view3d_add: return item if km is not None: - kmi_snap = keymap_item_from_propvalue("SNAP_ON") - kmi_center = keymap_item_from_propvalue("PIVOT_CENTER_ON") - kmi_fixed_aspect = keymap_item_from_propvalue("FIXED_ASPECT_ON") + kmi_snap = keymap_item_from_propvalue('SNAP_ON') + kmi_center = keymap_item_from_propvalue('PIVOT_CENTER_ON') + kmi_fixed_aspect = keymap_item_from_propvalue('FIXED_ASPECT_ON') else: kmi_snap = None kmi_center = None @@ -515,7 +490,7 @@ class _defs_view3d_add: row = layout.row() row.prop(props, "snap_target") - region_is_header = bpy.context.region.type == "TOOL_HEADER" + region_is_header = bpy.context.region.type == 'TOOL_HEADER' if region_is_header: # Don't draw the "extra" popover here as we might have other settings & this should be last. @@ -539,9 +514,7 @@ class _defs_view3d_add: @ToolDef.from_fn def cube_add(): def draw_settings(_context, layout, tool, *, extra=False): - show_extra = _defs_view3d_add.draw_settings_interactive_add( - layout, tool, extra - ) + show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra) if show_extra: layout.popover("TOPBAR_PT_tool_settings_extra", text="...") @@ -550,8 +523,7 @@ class _defs_view3d_add: label="Add Cube", icon="ops.mesh.primitive_cube_add_gizmo", description=lambda *args: _defs_view3d_add.description_interactive_add( - *args, - prefix=tip_("Add cube to mesh interactively"), + *args, prefix=tip_("Add cube to mesh interactively"), ), widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", @@ -561,9 +533,7 @@ class _defs_view3d_add: @ToolDef.from_fn def cone_add(): def draw_settings(_context, layout, tool, *, extra=False): - show_extra = _defs_view3d_add.draw_settings_interactive_add( - layout, tool, extra - ) + show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra) if extra: return @@ -579,8 +549,7 @@ class _defs_view3d_add: label="Add Cone", icon="ops.mesh.primitive_cone_add_gizmo", description=lambda *args: _defs_view3d_add.description_interactive_add( - *args, - prefix=tip_("Add cone to mesh interactively"), + *args, prefix=tip_("Add cone to mesh interactively"), ), widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", @@ -590,9 +559,7 @@ class _defs_view3d_add: @ToolDef.from_fn def cylinder_add(): def draw_settings(_context, layout, tool, *, extra=False): - show_extra = _defs_view3d_add.draw_settings_interactive_add( - layout, tool, extra - ) + show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra) if extra: return @@ -602,14 +569,12 @@ class _defs_view3d_add: if show_extra: layout.popover("TOPBAR_PT_tool_settings_extra", text="...") - return dict( idname="builtin.primitive_cylinder_add", label="Add Cylinder", icon="ops.mesh.primitive_cylinder_add_gizmo", description=lambda *args: _defs_view3d_add.description_interactive_add( - *args, - prefix=tip_("Add cylinder to mesh interactively"), + *args, prefix=tip_("Add cylinder to mesh interactively"), ), widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", @@ -619,9 +584,7 @@ class _defs_view3d_add: @ToolDef.from_fn def uv_sphere_add(): def draw_settings(_context, layout, tool, *, extra=False): - show_extra = _defs_view3d_add.draw_settings_interactive_add( - layout, tool, extra - ) + show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra) if extra: return @@ -631,14 +594,12 @@ class _defs_view3d_add: if show_extra: layout.popover("TOPBAR_PT_tool_settings_extra", text="...") - return dict( idname="builtin.primitive_uv_sphere_add", label="Add UV Sphere", icon="ops.mesh.primitive_sphere_add_gizmo", description=lambda *args: _defs_view3d_add.description_interactive_add( - *args, - prefix=tip_("Add sphere to mesh interactively"), + *args, prefix=tip_("Add sphere to mesh interactively"), ), widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", @@ -648,9 +609,7 @@ class _defs_view3d_add: @ToolDef.from_fn def ico_sphere_add(): def draw_settings(_context, layout, tool, *, extra=False): - show_extra = _defs_view3d_add.draw_settings_interactive_add( - layout, tool, extra - ) + show_extra = _defs_view3d_add.draw_settings_interactive_add(layout, tool, extra) if extra: return @@ -659,14 +618,12 @@ class _defs_view3d_add: if show_extra: layout.popover("TOPBAR_PT_tool_settings_extra", text="...") - return dict( idname="builtin.primitive_ico_sphere_add", label="Add Ico Sphere", icon="ops.mesh.primitive_sphere_add_gizmo", description=lambda *args: _defs_view3d_add.description_interactive_add( - *args, - prefix=tip_("Add sphere to mesh interactively"), + *args, prefix=tip_("Add sphere to mesh interactively"), ), widget="VIEW3D_GGT_placement", keymap="3D View Tool: Object, Add Primitive", @@ -677,8 +634,8 @@ class _defs_view3d_add: # ----------------------------------------------------------------------------- # Object Modes (named based on context.mode) - class _defs_edit_armature: + @ToolDef.from_fn def roll(): return dict( @@ -725,7 +682,7 @@ class _defs_edit_armature: return dict( idname="builtin.extrude_to_cursor", label="Extrude to Cursor", - cursor="CROSSHAIR", + cursor='CROSSHAIR', icon="ops.armature.extrude_cursor", widget=None, keymap=(), @@ -733,6 +690,7 @@ class _defs_edit_armature: class _defs_edit_mesh: + @ToolDef.from_fn def rip_region(): def draw_settings(_context, layout, tool): @@ -765,7 +723,6 @@ class _defs_edit_mesh: props = tool.operator_properties("mesh.polybuild_face_at_cursor_move") props_macro = props.MESH_OT_polybuild_face_at_cursor layout.prop(props_macro, "create_quads") - return dict( idname="builtin.poly_build", label="Poly Build", @@ -866,9 +823,9 @@ class _defs_edit_mesh: def draw_settings(context, layout, tool, *, extra=False): props = tool.operator_properties("mesh.bevel") - region_is_header = context.region.type == "TOOL_HEADER" + region_is_header = context.region.type == 'TOOL_HEADER' - edge_bevel = props.affect == "EDGES" + edge_bevel = props.affect == 'EDGES' if not extra: if region_is_header: @@ -910,7 +867,7 @@ class _defs_edit_mesh: col.active = edge_bevel col.prop(props, "miter_outer", text="Miter Outer") col.prop(props, "miter_inner", text="Inner") - if props.miter_inner == "ARC": + if props.miter_inner == 'ARC': col.prop(props, "spread") layout.separator() @@ -923,11 +880,9 @@ class _defs_edit_mesh: layout.prop(props, "profile_type") - if props.profile_type == "CUSTOM": + if props.profile_type == 'CUSTOM': tool_settings = context.tool_settings - layout.template_curveprofile( - tool_settings, "custom_bevel_profile_preset" - ) + layout.template_curveprofile(tool_settings, "custom_bevel_profile_preset") return dict( idname="builtin.bevel", @@ -944,7 +899,9 @@ class _defs_edit_mesh: idname="builtin.extrude_region", label="Extrude Region", # The operator description isn't useful in this case, give our own. - description=("Extrude freely or along an axis"), + description=( + "Extrude freely or along an axis" + ), icon="ops.mesh.extrude_region_move", widget="VIEW3D_GGT_xform_extrude", # Important to use same operator as 'E' key. @@ -972,7 +929,6 @@ class _defs_edit_mesh: props = tool.operator_properties("mesh.extrude_region_shrink_fatten") props_macro = props.TRANSFORM_OT_shrink_fatten layout.prop(props_macro, "use_even_offset") - return dict( idname="builtin.extrude_along_normals", label="Extrude Along Normals", @@ -1002,7 +958,7 @@ class _defs_edit_mesh: return dict( idname="builtin.extrude_to_cursor", label="Extrude to Cursor", - cursor="CROSSHAIR", + cursor='CROSSHAIR', icon="ops.mesh.dupli_extrude_cursor", widget=None, keymap=(), @@ -1011,6 +967,7 @@ class _defs_edit_mesh: @ToolDef.from_fn def loopcut_slide(): + def draw_settings(_context, layout, tool): props = tool.operator_properties("mesh.loopcut_slide") props_macro = props.MESH_OT_loopcut @@ -1042,7 +999,6 @@ class _defs_edit_mesh: def draw_settings(_context, layout, tool): props = tool.operator_properties("mesh.vertices_smooth") layout.prop(props, "repeat") - return dict( idname="builtin.smooth", label="Smooth", @@ -1059,7 +1015,6 @@ class _defs_edit_mesh: layout.prop(props, "uniform") layout.prop(props, "normal") layout.prop(props, "seed") - return dict( idname="builtin.randomize", label="Randomize", @@ -1113,7 +1068,7 @@ class _defs_edit_mesh: layout.prop(props, "use_occlude_geometry") layout.prop(props, "only_selected") layout.prop(props, "xray") - region_is_header = bpy.context.region.type == "TOOL_HEADER" + region_is_header = bpy.context.region.type == 'TOOL_HEADER' if region_is_header: show_extra = True else: @@ -1128,16 +1083,15 @@ class _defs_edit_mesh: layout.prop(props, "angle_snapping_increment", text="") if show_extra: layout.popover("TOPBAR_PT_tool_settings_extra", text="...") - return dict( idname="builtin.knife", label="Knife", - cursor="KNIFE", + cursor='KNIFE', icon="ops.mesh.knife_tool", widget=None, keymap=(), draw_settings=draw_settings, - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -1148,7 +1102,6 @@ class _defs_edit_mesh: layout.prop(props, "clear_inner") layout.prop(props, "clear_outer") layout.prop(props, "threshold") - return dict( idname="builtin.bisect", label="Bisect", @@ -1160,6 +1113,7 @@ class _defs_edit_mesh: class _defs_edit_curve: + @ToolDef.from_fn def draw(): def draw_settings(context, layout, _tool, *, extra=False): @@ -1168,7 +1122,7 @@ class _defs_edit_curve: cps = tool_settings.curve_paint_settings region_type = context.region.type - if region_type == "TOOL_HEADER": + if region_type == 'TOOL_HEADER': if not extra: layout.prop(cps, "curve_type", text="") layout.prop(cps, "depth_mode", expand=True) @@ -1178,13 +1132,13 @@ class _defs_edit_curve: layout.use_property_split = True layout.use_property_decorate = False - if region_type != "TOOL_HEADER": + if region_type != 'TOOL_HEADER': layout.prop(cps, "curve_type") layout.separator() - if cps.curve_type == "BEZIER": + if cps.curve_type == 'BEZIER': layout.prop(cps, "fit_method") layout.prop(cps, "error_threshold") - if region_type != "TOOL_HEADER": + if region_type != 'TOOL_HEADER': row = layout.row(heading="Detect Corners", align=True) else: row = layout.row(heading="Corners", align=True) @@ -1202,13 +1156,13 @@ class _defs_edit_curve: col.prop(cps, "radius_max", text="Max") col.prop(cps, "use_pressure_radius") - if region_type != "TOOL_HEADER" or cps.depth_mode == "SURFACE": + if region_type != 'TOOL_HEADER' or cps.depth_mode == 'SURFACE': layout.separator() - if region_type != "TOOL_HEADER": + if region_type != 'TOOL_HEADER': row = layout.row() row.prop(cps, "depth_mode", expand=True) - if cps.depth_mode == "SURFACE": + if cps.depth_mode == 'SURFACE': col = layout.column() col.prop(cps, "surface_offset") col.prop(cps, "use_offset_absolute") @@ -1220,7 +1174,7 @@ class _defs_edit_curve: return dict( idname="builtin.draw", label="Draw", - cursor="PAINT_BRUSH", + cursor='PAINT_BRUSH', icon="ops.curve.draw", widget=None, keymap=(), @@ -1243,7 +1197,7 @@ class _defs_edit_curve: return dict( idname="builtin.extrude_cursor", label="Extrude to Cursor", - cursor="CROSSHAIR", + cursor='CROSSHAIR', icon="ops.curve.extrude_cursor", widget=None, keymap=(), @@ -1255,11 +1209,10 @@ class _defs_edit_curve: props = tool.operator_properties("curve.pen") layout.prop(props, "close_spline") layout.prop(props, "extrude_handle") - return dict( idname="builtin.pen", label="Curve Pen", - cursor="CROSSHAIR", + cursor='CROSSHAIR', icon="ops.curve.pen", widget=None, keymap=(), @@ -1281,7 +1234,9 @@ class _defs_edit_curve: return dict( idname="builtin.radius", label="Radius", - description=("Expand or contract the radius of the selected curve points"), + description=( + "Expand or contract the radius of the selected curve points" + ), icon="ops.curve.radius", widget="VIEW3D_GGT_tool_generic_handle_free", keymap=(), @@ -1294,7 +1249,6 @@ class _defs_edit_curve: layout.prop(props, "uniform") layout.prop(props, "normal") layout.prop(props, "seed") - return dict( idname="builtin.randomize", label="Randomize", @@ -1306,6 +1260,7 @@ class _defs_edit_curve: class _defs_pose: + @ToolDef.from_fn def breakdown(): return dict( @@ -1338,6 +1293,7 @@ class _defs_pose: class _defs_particle: + @staticmethod def generate_from_brushes(context): return generate_from_enum_ex( @@ -1350,6 +1306,7 @@ class _defs_particle: class _defs_sculpt: + @staticmethod def generate_from_brushes(context): return generate_from_enum_ex( @@ -1453,7 +1410,6 @@ class _defs_sculpt: layout.prop(props, "trim_mode", expand=False) layout.prop(props, "trim_extrude_mode", expand=False) layout.prop(props, "use_cursor_depth", expand=False) - return dict( idname="builtin.box_trim", label="Box Trim", @@ -1471,7 +1427,6 @@ class _defs_sculpt: layout.prop(props, "trim_orientation", expand=False) layout.prop(props, "trim_extrude_mode", expand=False) layout.prop(props, "use_cursor_depth", expand=False) - return dict( idname="builtin.lasso_trim", label="Lasso Trim", @@ -1505,10 +1460,10 @@ class _defs_sculpt: row = layout.row(align=True) row.prop(props, "deform_axis") layout.prop(props, "orientation", expand=False) - if props.type == "SURFACE_SMOOTH": + if props.type == 'SURFACE_SMOOTH': layout.prop(props, "surface_smooth_shape_preservation", expand=False) layout.prop(props, "surface_smooth_current_vertex", expand=False) - elif props.type == "SHARPEN": + elif props.type == 'SHARPEN': layout.prop(props, "sharpen_smooth_ratio", expand=False) layout.prop(props, "sharpen_intensify_detail_strength", expand=False) layout.prop(props, "sharpen_curvature_smooth_iterations", expand=False) @@ -1550,7 +1505,7 @@ class _defs_sculpt: def draw_settings(_context, layout, tool): props = tool.operator_properties("sculpt.color_filter") layout.prop(props, "type", expand=False) - if props.type == "FILL": + if props.type == 'FILL': layout.prop(props, "fill_color", expand=False) layout.prop(props, "strength") @@ -1599,16 +1554,15 @@ class _defs_sculpt: class _defs_vertex_paint: + @staticmethod def poll_select_mask(context): if context is None: return True ob = context.active_object - return ( - ob - and ob.type == "MESH" - and (ob.data.use_paint_mask or ob.data.use_paint_mask_vertex) - ) + return (ob and ob.type == 'MESH' and + (ob.data.use_paint_mask or + ob.data.use_paint_mask_vertex)) @staticmethod def generate_from_brushes(context): @@ -1622,12 +1576,14 @@ class _defs_vertex_paint: class _defs_texture_paint: + @staticmethod def poll_select_mask(context): if context is None: return True ob = context.active_object - return ob and ob.type == "MESH" and (ob.data.use_paint_mask) + return (ob and ob.type == 'MESH' and + (ob.data.use_paint_mask)) @staticmethod def generate_from_brushes(context): @@ -1637,21 +1593,20 @@ class _defs_texture_paint: icon_prefix="brush.paint_texture.", type=bpy.types.Brush, attr="image_tool", - cursor="PAINT_CROSS", + cursor='PAINT_CROSS', ) class _defs_weight_paint: + @staticmethod def poll_select_mask(context): if context is None: return True ob = context.active_object - return ( - ob - and ob.type == "MESH" - and (ob.data.use_paint_mask or ob.data.use_paint_mask_vertex) - ) + return (ob and ob.type == 'MESH' and + (ob.data.use_paint_mask or + ob.data.use_paint_mask_vertex)) @staticmethod def generate_from_brushes(context): @@ -1673,12 +1628,11 @@ class _defs_weight_paint: else: return layout.label(text="Weight: %.3f" % weight) - return dict( idname="builtin.sample_weight", label="Sample Weight", icon="ops.paint.weight_sample", - cursor="EYEDROPPER", + cursor='EYEDROPPER', widget=None, keymap=(), draw_settings=draw_settings, @@ -1690,7 +1644,7 @@ class _defs_weight_paint: idname="builtin.sample_vertex_group", label="Sample Vertex Group", icon="ops.paint.weight_sample_group", - cursor="EYEDROPPER", + cursor='EYEDROPPER', widget=None, keymap=(), ) @@ -1701,7 +1655,6 @@ class _defs_weight_paint: brush = context.tool_settings.weight_paint.brush if brush is not None: from bl_ui.properties_paint_common import UnifiedPaintPanel - UnifiedPaintPanel.prop_unified( layout, context, @@ -1735,6 +1688,7 @@ class _defs_weight_paint: class _defs_image_generic: + @staticmethod def poll_uvedit(context): if context is None: @@ -1751,7 +1705,9 @@ class _defs_image_generic: return dict( idname="builtin.cursor", label="Cursor", - description=("Set the cursor location, drag to transform"), + description=( + "Set the cursor location, drag to transform" + ), icon="ops.generic.cursor", keymap=(), ) @@ -1763,11 +1719,12 @@ class _defs_image_generic: def draw_settings(_context, layout, tool): props = tool.operator_properties("image.sample") layout.prop(props, "size") - return dict( idname="builtin.sample", label="Sample", - description=("Sample pixel values under the cursor"), + description=( + "Sample pixel values under the cursor" + ), icon="ops.paint.weight_sample", # XXX, needs own icon. keymap="Image Editor Tool: Sample", draw_settings=draw_settings, @@ -1775,6 +1732,7 @@ class _defs_image_generic: class _defs_image_uv_transform: + @ToolDef.from_fn def translate(): return dict( @@ -1813,7 +1771,9 @@ class _defs_image_uv_transform: return dict( idname="builtin.transform", label="Transform", - description=("Supports any combination of grab, rotate, and scale at once"), + description=( + "Supports any combination of grab, rotate, and scale at once" + ), icon="ops.transform.transform", widget="IMAGE_GGT_gizmo2d", # No keymap default action, only for gizmo! @@ -1821,6 +1781,7 @@ class _defs_image_uv_transform: class _defs_image_uv_select: + @ToolDef.from_fn def select(): return dict( @@ -1838,7 +1799,6 @@ class _defs_image_uv_select: row = layout.row() row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) - return dict( idname="builtin.select_box", label="Select Box", @@ -1855,7 +1815,6 @@ class _defs_image_uv_select: row = layout.row() row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) - return dict( idname="builtin.select_lasso", label="Select Lasso", @@ -1876,7 +1835,6 @@ class _defs_image_uv_select: def draw_cursor(_context, tool, xy): from gpu_extras.presets import draw_circle_2d - props = tool.operator_properties("uv.select_circle") radius = props.radius draw_circle_2d(xy, (1.0,) * 4, radius, segments=32) @@ -1893,6 +1851,7 @@ class _defs_image_uv_select: class _defs_image_uv_edit: + @ToolDef.from_fn def rip_region(): return dict( @@ -1902,16 +1861,16 @@ class _defs_image_uv_edit: # TODO: generic operator (UV version of `VIEW3D_GGT_tool_generic_handle_free`). widget=None, keymap=(), - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ) class _defs_image_uv_sculpt: + @staticmethod def generate_from_brushes(context): def draw_cursor(context, _tool, xy): from gpu_extras.presets import draw_circle_2d - tool_settings = context.tool_settings uv_sculpt = tool_settings.uv_sculpt if not uv_sculpt.show_brush: @@ -1936,12 +1895,13 @@ class _defs_image_uv_sculpt: operator="sculpt.uv_sculpt_stroke", keymap="Image Editor Tool: Uv, Sculpt Stroke", draw_cursor=draw_cursor, - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ), ) class _defs_gpencil_paint: + @staticmethod def gpencil_primitive_toolbar(context, layout, _tool, props): paint = context.tool_settings.gpencil_paint @@ -1974,7 +1934,7 @@ class _defs_gpencil_paint: icon_prefix="brush.gpencil_draw.", type=bpy.types.Brush, attr="gpencil_tool", - cursor="DOT", + cursor='DOT', tooldef_keywords=dict( operator="gpencil.draw", ), @@ -1987,12 +1947,11 @@ class _defs_gpencil_paint: row = layout.row() row.use_property_split = False row.prop(props, "flat_caps") - return dict( idname="builtin.cutter", label="Cutter", icon="ops.gpencil.stroke_cutter", - cursor="KNIFE", + cursor='KNIFE', widget=None, keymap=(), draw_settings=draw_settings, @@ -2008,7 +1967,7 @@ class _defs_gpencil_paint: idname="builtin.line", label="Line", icon="ops.gpencil.primitive_line", - cursor="CROSSHAIR", + cursor='CROSSHAIR', widget=None, keymap=(), draw_settings=draw_settings, @@ -2024,7 +1983,7 @@ class _defs_gpencil_paint: idname="builtin.polyline", label="Polyline", icon="ops.gpencil.primitive_polyline", - cursor="CROSSHAIR", + cursor='CROSSHAIR', widget=None, keymap=(), draw_settings=draw_settings, @@ -2040,7 +1999,7 @@ class _defs_gpencil_paint: idname="builtin.box", label="Box", icon="ops.gpencil.primitive_box", - cursor="CROSSHAIR", + cursor='CROSSHAIR', widget=None, keymap=(), draw_settings=draw_settings, @@ -2056,7 +2015,7 @@ class _defs_gpencil_paint: idname="builtin.circle", label="Circle", icon="ops.gpencil.primitive_circle", - cursor="CROSSHAIR", + cursor='CROSSHAIR', widget=None, keymap=(), draw_settings=draw_settings, @@ -2072,7 +2031,7 @@ class _defs_gpencil_paint: idname="builtin.arc", label="Arc", icon="ops.gpencil.primitive_arc", - cursor="CROSSHAIR", + cursor='CROSSHAIR', widget=None, keymap=(), draw_settings=draw_settings, @@ -2088,7 +2047,7 @@ class _defs_gpencil_paint: idname="builtin.curve", label="Curve", icon="ops.gpencil.primitive_curve", - cursor="CROSSHAIR", + cursor='CROSSHAIR', widget=None, keymap=(), draw_settings=draw_settings, @@ -2101,12 +2060,11 @@ class _defs_gpencil_paint: row = layout.row() row.use_property_split = False row.prop(props, "mode", expand=True) - return dict( idname="builtin.eyedropper", label="Eyedropper", icon="ops.paint.eyedropper_add", - cursor="EYEDROPPER", + cursor='EYEDROPPER', widget=None, keymap=(), draw_settings=draw_settings, @@ -2126,7 +2084,7 @@ class _defs_gpencil_paint: idname="builtin.interpolate", label="Interpolate", icon="ops.pose.breakdowner", - cursor="DEFAULT", + cursor='DEFAULT', widget=None, keymap=(), draw_settings=draw_settings, @@ -2136,11 +2094,11 @@ class _defs_gpencil_paint: class _defs_gpencil_edit: def is_segment(context): ts = context.scene.tool_settings - if context.mode == "EDIT_GPENCIL": - return ts.gpencil_selectmode_edit == "SEGMENT" - elif context.mode == "SCULPT_GPENCIL": + if context.mode == 'EDIT_GPENCIL': + return ts.gpencil_selectmode_edit == 'SEGMENT' + elif context.mode == 'SCULPT_GPENCIL': return ts.use_gpencil_select_mask_segment - elif context.mode == "VERTEX_GPENCIL": + elif context.mode == 'VERTEX_GPENCIL': return ts.use_gpencil_vertex_select_mask_segment else: return False @@ -2159,10 +2117,7 @@ class _defs_gpencil_edit: def select(): def draw_settings(context, layout, _tool): if _defs_gpencil_edit.is_segment(context): - layout.prop( - context.tool_settings.gpencil_sculpt, "intersection_threshold" - ) - + layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold") return dict( idname="builtin.select", label="Tweak", @@ -2180,10 +2135,7 @@ class _defs_gpencil_edit: row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) if _defs_gpencil_edit.is_segment(context): - layout.prop( - context.tool_settings.gpencil_sculpt, "intersection_threshold" - ) - + layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold") return dict( idname="builtin.select_box", label="Select Box", @@ -2201,10 +2153,7 @@ class _defs_gpencil_edit: row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) if _defs_gpencil_edit.is_segment(context): - layout.prop( - context.tool_settings.gpencil_sculpt, "intersection_threshold" - ) - + layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold") return dict( idname="builtin.select_lasso", label="Select Lasso", @@ -2223,13 +2172,10 @@ class _defs_gpencil_edit: row.prop(props, "mode", text="", expand=True, icon_only=True) layout.prop(props, "radius") if _defs_gpencil_edit.is_segment(context): - layout.prop( - context.tool_settings.gpencil_sculpt, "intersection_threshold" - ) + layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold") def draw_cursor(_context, tool, xy): from gpu_extras.presets import draw_circle_2d - props = tool.operator_properties("gpencil.select_circle") radius = props.radius draw_circle_2d(xy, (1.0,) * 4, radius, segments=32) @@ -2249,8 +2195,11 @@ class _defs_gpencil_edit: return dict( idname="builtin.radius", label="Radius", - description=("Expand or contract the radius of the selected points"), + description=( + "Expand or contract the radius of the selected points" + ), icon="ops.gpencil.radius", + widget=None, keymap=(), ) @@ -2298,7 +2247,7 @@ class _defs_gpencil_edit: idname="builtin.transform_fill", label="Transform Fill", icon="ops.gpencil.transform_fill", - cursor="DEFAULT", + cursor='DEFAULT', widget=None, keymap=(), draw_settings=draw_settings, @@ -2319,7 +2268,7 @@ class _defs_gpencil_edit: idname="builtin.interpolate", label="Interpolate", icon="ops.pose.breakdowner", - cursor="DEFAULT", + cursor='DEFAULT', widget=None, keymap=(), draw_settings=draw_settings, @@ -2327,21 +2276,16 @@ class _defs_gpencil_edit: class _defs_gpencil_sculpt: + @staticmethod def poll_select_mask(context): if context is None: return True ob = context.active_object ts = context.scene.tool_settings - return ( - ob - and ob.type == "GPENCIL" - and ( - ts.use_gpencil_select_mask_point - or ts.use_gpencil_select_mask_stroke - or ts.use_gpencil_select_mask_segment - ) - ) + return ob and ob.type == 'GPENCIL' and (ts.use_gpencil_select_mask_point or + ts.use_gpencil_select_mask_stroke or + ts.use_gpencil_select_mask_segment) @staticmethod def generate_from_brushes(context): @@ -2358,6 +2302,7 @@ class _defs_gpencil_sculpt: class _defs_gpencil_weight: + @staticmethod def generate_from_brushes(context): return generate_from_enum_ex( @@ -2373,6 +2318,7 @@ class _defs_gpencil_weight: class _defs_curves_sculpt: + @ToolDef.from_fn def selection_paint(): return dict( @@ -2388,7 +2334,7 @@ class _defs_curves_sculpt: idname="builtin_brush.comb", label="Comb", icon="ops.curves.sculpt_comb", - data_block="COMB", + data_block='COMB', ) @ToolDef.from_fn @@ -2397,7 +2343,7 @@ class _defs_curves_sculpt: idname="builtin_brush.add", label="Add", icon="ops.curves.sculpt_add", - data_block="ADD", + data_block='ADD', ) @ToolDef.from_fn @@ -2406,7 +2352,7 @@ class _defs_curves_sculpt: idname="builtin_brush.delete", label="Delete", icon="ops.curves.sculpt_delete", - data_block="DELETE", + data_block='DELETE', ) @ToolDef.from_fn @@ -2415,7 +2361,7 @@ class _defs_curves_sculpt: idname="builtin_brush.snake_hook", label="Snake Hook", icon="ops.curves.sculpt_snake_hook", - data_block="SNAKE_HOOK", + data_block='SNAKE_HOOK', ) @ToolDef.from_fn @@ -2424,7 +2370,7 @@ class _defs_curves_sculpt: idname="builtin_brush.grow_shrink", label="Grow/Shrink", icon="ops.curves.sculpt_grow_shrink", - data_block="GROW_SHRINK", + data_block='GROW_SHRINK', ) @ToolDef.from_fn @@ -2433,7 +2379,7 @@ class _defs_curves_sculpt: idname="builtin_brush.pinch", label="Pinch", icon="ops.curves.sculpt_pinch", - data_block="PINCH", + data_block='PINCH', ) @ToolDef.from_fn @@ -2442,7 +2388,7 @@ class _defs_curves_sculpt: idname="builtin_brush.smooth", label="Smooth", icon="ops.curves.sculpt_smooth", - data_block="SMOOTH", + data_block='SMOOTH', ) @ToolDef.from_fn @@ -2451,7 +2397,7 @@ class _defs_curves_sculpt: idname="builtin_brush.puff", label="Puff", icon="ops.curves.sculpt_puff", - data_block="PUFF", + data_block='PUFF', ) @ToolDef.from_fn @@ -2474,21 +2420,16 @@ class _defs_curves_sculpt: class _defs_gpencil_vertex: + @staticmethod def poll_select_mask(context): if context is None: return True ob = context.active_object ts = context.scene.tool_settings - return ( - ob - and ob.type == "GPENCIL" - and ( - ts.use_gpencil_vertex_select_mask_point - or ts.use_gpencil_vertex_select_mask_stroke - or ts.use_gpencil_vertex_select_mask_segment - ) - ) + return ob and ob.type == 'GPENCIL' and (ts.use_gpencil_vertex_select_mask_point or + ts.use_gpencil_vertex_select_mask_stroke or + ts.use_gpencil_vertex_select_mask_segment) @staticmethod def generate_from_brushes(context): @@ -2498,7 +2439,7 @@ class _defs_gpencil_vertex: icon_prefix="brush.paint_vertex.", type=bpy.types.Brush, attr="gpencil_vertex_tool", - cursor="DOT", + cursor='DOT', tooldef_keywords=dict( operator="gpencil.vertex_paint", ), @@ -2506,6 +2447,7 @@ class _defs_gpencil_vertex: class _defs_node_select: + @ToolDef.from_fn def select(): return dict( @@ -2523,7 +2465,6 @@ class _defs_node_select: row = layout.row() row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) - return dict( idname="builtin.select_box", label="Select Box", @@ -2540,7 +2481,6 @@ class _defs_node_select: row = layout.row() row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) - return dict( idname="builtin.select_lasso", label="Select Lasso", @@ -2561,7 +2501,6 @@ class _defs_node_select: def draw_cursor(_context, tool, xy): from gpu_extras.presets import draw_circle_2d - props = tool.operator_properties("node.select_circle") radius = props.radius draw_circle_2d(xy, (1.0,) * 4, radius, segments=32) @@ -2578,6 +2517,7 @@ class _defs_node_select: class _defs_node_edit: + @ToolDef.from_fn def links_cut(): return dict( @@ -2586,17 +2526,20 @@ class _defs_node_edit: icon="ops.node.links_cut", widget=None, keymap="Node Tool: Links Cut", - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ) class _defs_sequencer_generic: + @ToolDef.from_fn def cursor(): return dict( idname="builtin.cursor", label="Cursor", - description=("Set the cursor location, drag to transform"), + description=( + "Set the cursor location, drag to transform" + ), icon="ops.generic.cursor", keymap="Sequencer Tool: Cursor", ) @@ -2608,16 +2551,15 @@ class _defs_sequencer_generic: row = layout.row() row.use_property_split = False row.prop(props, "type", expand=True) - return dict( idname="builtin.blade", label="Blade", icon="ops.sequencer.blade", - cursor="CROSSHAIR", + cursor='CROSSHAIR', widget=None, keymap="Sequencer Tool: Blade", draw_settings=draw_settings, - options={"KEYMAP_FALLBACK"}, + options={'KEYMAP_FALLBACK'}, ) @ToolDef.from_fn @@ -2625,7 +2567,9 @@ class _defs_sequencer_generic: return dict( idname="builtin.sample", label="Sample", - description=("Sample pixel values under the cursor"), + description=( + "Sample pixel values under the cursor" + ), icon="ops.paint.weight_sample", # XXX, needs own icon. keymap="Sequencer Tool: Sample", ) @@ -2668,7 +2612,9 @@ class _defs_sequencer_generic: return dict( idname="builtin.transform", label="Transform", - description=("Supports any combination of grab, rotate, and scale at once"), + description=( + "Supports any combination of grab, rotate, and scale at once" + ), icon="ops.transform.transform", widget="SEQUENCER_GGT_gizmo2d", # No keymap default action, only for gizmo! @@ -2694,7 +2640,6 @@ class _defs_sequencer_select: row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) pass - return dict( idname="builtin.select_box", label="Select Box", @@ -2706,10 +2651,10 @@ class _defs_sequencer_select: class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel): - bl_space_type = "IMAGE_EDITOR" - bl_region_type = "TOOLS" + bl_space_type = 'IMAGE_EDITOR' + bl_region_type = 'TOOLS' bl_label = "Tools" # not visible - bl_options = {"HIDE_HEADER"} + bl_options = {'HIDE_HEADER'} # Satisfy the 'ToolSelectPanelHelper' API. keymap_prefix = "Image Editor Tool:" @@ -2721,7 +2666,7 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel): def tools_from_context(cls, context, mode=None): if mode is None: if context.space_data is None: - mode = "VIEW" + mode = 'VIEW' else: mode = context.space_data.mode for tools in (cls._tools[None], cls._tools.get(mode, ())): @@ -2769,11 +2714,11 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel): None: [ # for all modes ], - "VIEW": [ + 'VIEW': [ _defs_image_generic.sample, *_tools_annotate, ], - "UV": [ + 'UV': [ *_tools_select, _defs_image_generic.cursor, None, @@ -2789,10 +2734,10 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel): else () ), ], - "MASK": [ + 'MASK': [ None, ], - "PAINT": [ + 'PAINT': [ _defs_texture_paint.generate_from_brushes, None, *_tools_annotate, @@ -2801,10 +2746,10 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel): class NODE_PT_tools_active(ToolSelectPanelHelper, Panel): - bl_space_type = "NODE_EDITOR" - bl_region_type = "TOOLS" + bl_space_type = 'NODE_EDITOR' + bl_region_type = 'TOOLS' bl_label = "Tools" # not visible - bl_options = {"HIDE_HEADER"} + bl_options = {'HIDE_HEADER'} # Satisfy the 'ToolSelectPanelHelper' API. keymap_prefix = "Node Editor Tool:" @@ -2865,10 +2810,10 @@ class NODE_PT_tools_active(ToolSelectPanelHelper, Panel): class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): - bl_space_type = "VIEW_3D" - bl_region_type = "TOOLS" + bl_space_type = 'VIEW_3D' + bl_region_type = 'TOOLS' bl_label = "Tools" # not visible - bl_options = {"HIDE_HEADER"} + bl_options = {'HIDE_HEADER'} # Satisfy the 'ToolSelectPanelHelper' API. keymap_prefix = "3D View Tool:" @@ -2957,12 +2902,12 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): # _defs_view3d_generic.cursor, # End group. ], - "OBJECT": [ + 'OBJECT': [ *_tools_default, None, _tools_view3d_add, ], - "POSE": [ + 'POSE': [ *_tools_default, None, ( @@ -2971,7 +2916,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_pose.relax, ), ], - "EDIT_ARMATURE": [ + 'EDIT_ARMATURE': [ *_tools_default, None, _defs_edit_armature.roll, @@ -2986,8 +2931,9 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): ), _defs_transform.shear, ], - "EDIT_MESH": [ + 'EDIT_MESH': [ *_tools_default, + None, _tools_view3d_add, None, @@ -3034,7 +2980,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_edit_mesh.rip_edge, ), ], - "EDIT_CURVE": [ + 'EDIT_CURVE': [ *_tools_default, None, _defs_edit_curve.draw, @@ -3050,37 +2996,37 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_transform.shear, _defs_edit_curve.curve_vertex_randomize, ], - "EDIT_CURVES": [ - *_tools_select, + 'EDIT_CURVES': [ + *_tools_default, ], - "EDIT_SURFACE": [ + 'EDIT_SURFACE': [ *_tools_default, None, _defs_transform.shear, ], - "EDIT_METABALL": [ + 'EDIT_METABALL': [ *_tools_default, None, _defs_transform.shear, ], - "EDIT_LATTICE": [ + 'EDIT_LATTICE': [ *_tools_default, None, _defs_transform.shear, ], - "EDIT_TEXT": [ + 'EDIT_TEXT': [ _defs_view3d_generic.cursor, None, *_tools_annotate, _defs_view3d_generic.ruler, ], - "PARTICLE": [ + 'PARTICLE': [ *_tools_select, _defs_view3d_generic.cursor, None, _defs_particle.generate_from_brushes, ], - "SCULPT": [ + 'SCULPT': [ _defs_sculpt.generate_from_brushes, None, ( @@ -3113,7 +3059,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): None, *_tools_annotate, ], - "PAINT_TEXTURE": [ + 'PAINT_TEXTURE': [ _defs_texture_paint.generate_from_brushes, None, lambda context: ( @@ -3123,7 +3069,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): ), *_tools_annotate, ], - "PAINT_VERTEX": [ + 'PAINT_VERTEX': [ _defs_vertex_paint.generate_from_brushes, None, lambda context: ( @@ -3133,7 +3079,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): ), *_tools_annotate, ], - "PAINT_WEIGHT": [ + 'PAINT_WEIGHT': [ _defs_weight_paint.generate_from_brushes, _defs_weight_paint.gradient, None, @@ -3159,7 +3105,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): ), *_tools_annotate, ], - "PAINT_GPENCIL": [ + 'PAINT_GPENCIL': [ _defs_view3d_generic.cursor, None, _defs_gpencil_paint.generate_from_brushes, @@ -3178,7 +3124,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): None, *_tools_annotate, ], - "EDIT_GPENCIL": [ + 'EDIT_GPENCIL': [ *_tools_gpencil_select, _defs_view3d_generic.cursor, None, @@ -3197,7 +3143,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): None, *_tools_annotate, ], - "SCULPT_GPENCIL": [ + 'SCULPT_GPENCIL': [ _defs_gpencil_sculpt.generate_from_brushes, None, *_tools_annotate, @@ -3207,12 +3153,12 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): else () ), ], - "WEIGHT_GPENCIL": [ + 'WEIGHT_GPENCIL': [ _defs_gpencil_weight.generate_from_brushes, None, *_tools_annotate, ], - "VERTEX_GPENCIL": [ + 'VERTEX_GPENCIL': [ _defs_gpencil_vertex.generate_from_brushes, None, *_tools_annotate, @@ -3223,7 +3169,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): else () ), ], - "SCULPT_CURVES": [ + 'SCULPT_CURVES': [ _defs_curves_sculpt.selection_paint, None, _defs_curves_sculpt.add, @@ -3244,10 +3190,10 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel): - bl_space_type = "SEQUENCE_EDITOR" - bl_region_type = "TOOLS" + bl_space_type = 'SEQUENCE_EDITOR' + bl_region_type = 'TOOLS' bl_label = "Tools" # not visible - bl_options = {"HIDE_HEADER"} + bl_options = {'HIDE_HEADER'} # Satisfy the 'ToolSelectPanelHelper' API. keymap_prefix = "Sequence Editor Tool:" @@ -3292,8 +3238,9 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel): # The keys match sequence editors view type: `context.space_data.view_type`. # The values represent the tools, see `ToolSelectPanelHelper` for details. _tools = { - None: [], - "PREVIEW": [ + None: [ + ], + 'PREVIEW': [ *_tools_select, _defs_sequencer_generic.cursor, None, @@ -3305,11 +3252,11 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_sequencer_generic.sample, *_tools_annotate, ], - "SEQUENCER": [ + 'SEQUENCER': [ *_tools_select, _defs_sequencer_generic.blade, ], - "SEQUENCER_PREVIEW": [ + 'SEQUENCER_PREVIEW': [ *_tools_select, None, *_tools_annotate, @@ -3328,6 +3275,5 @@ classes = ( if __name__ == "__main__": # only for live edit. from bpy.utils import register_class - for cls in classes: register_class(cls) diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 50bb1e42602c..1872b3cbd518 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -326,7 +326,7 @@ class TOPBAR_MT_file_new(Menu): # Expand template paths. # Use a set to avoid duplicate user/system templates. - # This is a corner case, but users managed to do it! T76849. + # This is a corner case, but users managed to do it! #76849. app_templates = set() for path in template_paths: for d in os.listdir(path): diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 96b83be6ad81..f0dedc42c54e 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1424,34 +1424,40 @@ class USERPREF_PT_file_paths_asset_libraries(FilePathsPanel, Panel): layout.use_property_decorate = False paths = context.preferences.filepaths + active_library_index = paths.active_asset_library - box = layout.box() - split = box.split(factor=0.35) - name_col = split.column() - path_col = split.column() + row = layout.row() - row = name_col.row(align=True) # Padding - row.separator() - row.label(text="Name") + row.template_list( + "USERPREF_UL_asset_libraries", "user_asset_libraries", + paths, "asset_libraries", + paths, "active_asset_library" + ) - row = path_col.row(align=True) # Padding - row.separator() - row.label(text="Path") + col = row.column(align=True) + col.operator("preferences.asset_library_add", text="", icon='ADD') + props = col.operator("preferences.asset_library_remove", text="", icon='REMOVE') + props.index = active_library_index - for i, library in enumerate(paths.asset_libraries): - row = name_col.row() - row.alert = not library.name - row.prop(library, "name", text="") + if active_library_index < 0: + return - row = path_col.row() - subrow = row.row() - subrow.alert = not library.path - subrow.prop(library, "path", text="") - row.operator("preferences.asset_library_remove", text="", icon='X', emboss=False).index = i + layout.separator() - row = box.row() - row.alignment = 'RIGHT' - row.operator("preferences.asset_library_add", text="", icon='ADD', emboss=False) + active_library = paths.asset_libraries[active_library_index] + layout.prop(active_library, "path") + layout.prop(active_library, "import_method", text="Import Method") + + +class USERPREF_UL_asset_libraries(bpy.types.UIList): + def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index): + asset_library = item + + if self.layout_type in {'DEFAULT', 'COMPACT'}: + layout.prop(asset_library, "name", text="", emboss=False) + elif self.layout_type == 'GRID': + layout.alignment = 'CENTER' + layout.prop(asset_library, "name", text="", emboss=False) # ----------------------------------------------------------------------------- @@ -2319,21 +2325,15 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel): bl_label = "New Features" def draw(self, context): - self._draw_items(context, - (({"property": "use_sculpt_tools_tilt"}, - ("blender/blender/issues/82877", - "#82877")), - ({"property": "use_extended_asset_browser"}, - ("blender/blender/projects/10", - "Pipeline, Assets & IO Project Page")), - ({"property": "use_override_templates"}, - ("blender/blender/issues/73318", - "Milestone 4")), - ({"property": "use_new_volume_nodes"}, - ("blender/blender/issues/103248", - "#103248")), - ), - ) + self._draw_items( + context, ( + ({"property": "use_sculpt_tools_tilt"}, ("blender/blender/issues/82877", "#82877")), + ({"property": "use_extended_asset_browser"}, + ("blender/blender/projects/10", "Pipeline, Assets & IO Project Page")), + ({"property": "use_override_templates"}, ("blender/blender/issues/73318", "Milestone 4")), + ({"property": "use_new_volume_nodes"}, ("blender/blender/issues/103248", "#103248")), + ), + ) class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel): @@ -2493,6 +2493,9 @@ classes = ( # USERPREF_PT_experimental_tweaks, USERPREF_PT_experimental_debugging, + # UI lists + USERPREF_UL_asset_libraries, + # Add dynamically generated editor theme panels last, # so they show up last in the theme section. *ThemeGenericClassGenerator.generate_panel_classes_from_theme_areas(), diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index d74dc27843e7..e2335af687dc 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -161,6 +161,8 @@ class VIEW3D_HT_tool_header(Header): sub.prop(context.object.data, "use_mirror_y", text="Y", toggle=True) sub.prop(context.object.data, "use_mirror_z", text="Z", toggle=True) + layout.prop(context.object.data, "use_sculpt_collision", icon='MOD_PHYSICS', icon_only=True, toggle=True) + # Expand panels from the side-bar as popovers. popover_kw = {"space_type": 'VIEW_3D', "region_type": 'UI', "category": "Tool"} @@ -520,7 +522,8 @@ class _draw_tool_settings_context_mode: if curves_tool == 'COMB': layout.prop(brush, "falloff_shape", expand=True) - layout.popover("VIEW3D_PT_tools_brush_falloff") + layout.popover("VIEW3D_PT_tools_brush_falloff", text="Brush Falloff") + layout.popover("VIEW3D_PT_curves_sculpt_parameter_falloff", text="Curve Falloff") elif curves_tool == 'ADD': layout.prop(brush, "falloff_shape", expand=True) layout.prop(brush.curves_sculpt_settings, "add_amount") @@ -890,7 +893,7 @@ class VIEW3D_HT_header(Header): row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'}) # While exposing `shading.show_xray(_wireframe)` is correct. - # this hides the key shortcut from users: T70433. + # this hides the key shortcut from users: #70433. if has_pose_mode: draw_depressed = overlay.show_xray_bone elif shading.type == 'WIREFRAME': @@ -2041,6 +2044,16 @@ class VIEW3D_MT_select_paint_mask_vertex(Menu): layout.operator("paint.vert_select_linked", text="Select Linked") +class VIEW3D_MT_edit_curves_select_more_less(Menu): + bl_label = "Select More/Less" + + def draw(self, _context): + layout = self.layout + + layout.operator("curves.select_more", text="More") + layout.operator("curves.select_less", text="Less") + + class VIEW3D_MT_select_edit_curves(Menu): bl_label = "Select" @@ -2050,10 +2063,17 @@ class VIEW3D_MT_select_edit_curves(Menu): layout.operator("curves.select_all", text="All").action = 'SELECT' layout.operator("curves.select_all", text="None").action = 'DESELECT' layout.operator("curves.select_all", text="Invert").action = 'INVERT' + + layout.separator() + layout.operator("curves.select_random", text="Random") layout.operator("curves.select_end", text="Endpoints") layout.operator("curves.select_linked", text="Linked") + layout.separator() + + layout.menu("VIEW3D_MT_edit_curves_select_more_less") + class VIEW3D_MT_select_sculpt_curves(Menu): bl_label = "Select" @@ -2114,6 +2134,7 @@ class VIEW3D_MT_curve_add(Menu): layout.separator() layout.operator("object.curves_empty_hair_add", text="Empty Hair", icon='CURVES_DATA') + layout.operator("object.quick_fur", text="Fur", icon='CURVES_DATA') experimental = context.preferences.experimental if experimental.use_new_curves_tools: @@ -2268,7 +2289,7 @@ class VIEW3D_MT_add(Menu): # NOTE: don't use 'EXEC_SCREEN' or operators won't get the `v3d` context. # NOTE: was `EXEC_AREA`, but this context does not have the `rv3d`, which prevents - # "align_view" to work on first call (see T32719). + # "align_view" to work on first call (see #32719). layout.operator_context = 'EXEC_REGION_WIN' # layout.operator_menu_enum("object.mesh_add", "type", text="Mesh", icon='OUTLINER_OB_MESH') @@ -3867,6 +3888,7 @@ class VIEW3D_MT_edit_mesh(Menu): layout.menu("VIEW3D_MT_edit_mesh_normals") layout.menu("VIEW3D_MT_edit_mesh_shading") layout.menu("VIEW3D_MT_edit_mesh_weights") + layout.operator("mesh.attribute_set") layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...") layout.separator() @@ -5308,6 +5330,7 @@ class VIEW3D_MT_edit_curves(Menu): layout.menu("VIEW3D_MT_transform") layout.separator() + layout.operator("curves.delete") class VIEW3D_MT_object_mode_pie(Menu): @@ -5376,7 +5399,7 @@ class VIEW3D_MT_shading_ex_pie(Menu): pie.prop_enum(view.shading, "type", value='WIREFRAME') pie.prop_enum(view.shading, "type", value='SOLID') - # Note this duplicates "view3d.toggle_xray" logic, so we can see the active item: T58661. + # Note this duplicates "view3d.toggle_xray" logic, so we can see the active item: #58661. if context.pose_object: pie.prop(view.overlay, "show_xray_bone", icon='XRAY') else: @@ -6718,15 +6741,15 @@ class VIEW3D_PT_overlay_sculpt(Panel): overlay = view.overlay row = layout.row(align=True) - row.prop(overlay, "sculpt_show_mask", text="") + row.prop(overlay, "show_sculpt_mask", text="") sub = row.row() - sub.active = overlay.sculpt_show_mask + sub.active = overlay.show_sculpt_mask sub.prop(overlay, "sculpt_mode_mask_opacity", text="Mask") row = layout.row(align=True) - row.prop(overlay, "sculpt_show_face_sets", text="") + row.prop(overlay, "show_sculpt_face_sets", text="") sub = row.row() - sub.active = overlay.sculpt_show_face_sets + sub.active = overlay.show_sculpt_face_sets row.prop(overlay, "sculpt_mode_face_sets_opacity", text="Face Sets") @@ -6753,6 +6776,13 @@ class VIEW3D_PT_overlay_sculpt_curves(Panel): row.active = overlay.show_overlays row.prop(overlay, "sculpt_mode_mask_opacity", text="Selection Opacity") + row = layout.row(align=True) + row.active = overlay.show_overlays + row.prop(overlay, "show_sculpt_curves_cage", text="") + subrow = row.row(align=True) + subrow.active = overlay.show_sculpt_curves_cage + subrow.prop(overlay, "sculpt_curves_cage_opacity", text="Cage Opacity") + class VIEW3D_PT_overlay_bones(Panel): bl_space_type = 'VIEW_3D' @@ -7934,6 +7964,28 @@ class VIEW3D_PT_curves_sculpt_add_shape(Panel): col.prop(brush.curves_sculpt_settings, "points_per_curve", text="Points") +class VIEW3D_PT_curves_sculpt_parameter_falloff(Panel): + # Only for popover, these are dummy values. + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_label = "Curves Sculpt Parameter Falloff" + + def draw(self, context): + layout = self.layout + + settings = UnifiedPaintPanel.paint_settings(context) + brush = settings.brush + + layout.template_curve_mapping(brush.curves_sculpt_settings, "curve_parameter_falloff") + row = layout.row(align=True) + row.operator("brush.sculpt_curves_falloff_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH' + row.operator("brush.sculpt_curves_falloff_preset", icon='SPHERECURVE', text="").shape = 'ROUND' + row.operator("brush.sculpt_curves_falloff_preset", icon='ROOTCURVE', text="").shape = 'ROOT' + row.operator("brush.sculpt_curves_falloff_preset", icon='SHARPCURVE', text="").shape = 'SHARP' + row.operator("brush.sculpt_curves_falloff_preset", icon='LINCURVE', text="").shape = 'LINE' + row.operator("brush.sculpt_curves_falloff_preset", icon='NOCURVE', text="").shape = 'MAX' + + class VIEW3D_PT_curves_sculpt_grow_shrink_scaling(Panel): # Only for popover, these are dummy values. bl_space_type = 'VIEW_3D' @@ -8011,6 +8063,7 @@ classes = ( VIEW3D_MT_select_gpencil, VIEW3D_MT_select_paint_mask, VIEW3D_MT_select_paint_mask_vertex, + VIEW3D_MT_edit_curves_select_more_less, VIEW3D_MT_select_edit_curves, VIEW3D_MT_select_sculpt_curves, VIEW3D_MT_mesh_add, @@ -8211,6 +8264,7 @@ classes = ( TOPBAR_PT_gpencil_vertexcolor, TOPBAR_PT_annotation_layers, VIEW3D_PT_curves_sculpt_add_shape, + VIEW3D_PT_curves_sculpt_parameter_falloff, VIEW3D_PT_curves_sculpt_grow_shrink_scaling, VIEW3D_PT_viewport_debug, ) diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py index 37032657d7ae..6fc0b643552a 100644 --- a/release/scripts/startup/keyingsets_builtins.py +++ b/release/scripts/startup/keyingsets_builtins.py @@ -639,7 +639,7 @@ class BUILTIN_KSI_DeltaScale(KeyingSetInfo): # Note that this controls order of options in `insert keyframe` menu. # Better try to keep some logical order here beyond mere alphabetical one, also because of menu entries shortcut. -# See also T51867. +# See also #51867. classes = ( BUILTIN_KSI_Available, BUILTIN_KSI_Location, diff --git a/source/blender/asset_system/AS_asset_library.hh b/source/blender/asset_system/AS_asset_library.hh index b3b7d4217242..d92375082d92 100644 --- a/source/blender/asset_system/AS_asset_library.hh +++ b/source/blender/asset_system/AS_asset_library.hh @@ -58,6 +58,11 @@ class AssetLibrary { std::function on_refresh_; + std::optional import_method_; + /** Assets owned by this library may be imported with a different method than set in + * #import_method_ above, it's just a default. */ + bool may_override_import_method_ = false; + bCallbackFuncStore on_save_callback_store_{}; public: @@ -68,6 +73,7 @@ class AssetLibrary { std::unique_ptr catalog_service; friend class AssetLibraryService; + friend class AssetRepresentation; public: /** diff --git a/source/blender/asset_system/AS_asset_representation.h b/source/blender/asset_system/AS_asset_representation.h index 6a5425979aa2..359567cbf0b1 100644 --- a/source/blender/asset_system/AS_asset_representation.h +++ b/source/blender/asset_system/AS_asset_representation.h @@ -22,6 +22,8 @@ const char *AS_asset_representation_name_get(const AssetRepresentation *asset) AssetMetaData *AS_asset_representation_metadata_get(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT; bool AS_asset_representation_is_local_id(const AssetRepresentation *asset) ATTR_WARN_UNUSED_RESULT; +bool AS_asset_representation_is_never_link(const AssetRepresentation *asset) + ATTR_WARN_UNUSED_RESULT; #ifdef __cplusplus } diff --git a/source/blender/asset_system/AS_asset_representation.hh b/source/blender/asset_system/AS_asset_representation.hh index 65f7e08f3951..99fde7d3dc25 100644 --- a/source/blender/asset_system/AS_asset_representation.hh +++ b/source/blender/asset_system/AS_asset_representation.hh @@ -12,10 +12,13 @@ #pragma once #include +#include #include #include "BLI_string_ref.hh" +#include "DNA_asset_types.h" + #include "AS_asset_identifier.hh" struct AssetMetaData; @@ -23,11 +26,15 @@ struct ID; namespace blender::asset_system { +class AssetLibrary; + class AssetRepresentation { AssetIdentifier identifier_; /** Indicate if this is a local or external asset, and as such, which of the union members below * should be used. */ const bool is_local_id_ = false; + /** Asset library that owns this asset representation. */ + const AssetLibrary *owner_asset_library_; struct ExternalAsset { std::string name; @@ -44,10 +51,13 @@ class AssetRepresentation { /** Constructs an asset representation for an external ID. The asset will not be editable. */ AssetRepresentation(AssetIdentifier &&identifier, StringRef name, - std::unique_ptr metadata); + std::unique_ptr metadata, + const AssetLibrary &owner_asset_library); /** Constructs an asset representation for an ID stored in the current file. This makes the asset * local and fully editable. */ - AssetRepresentation(AssetIdentifier &&identifier, ID &id); + AssetRepresentation(AssetIdentifier &&identifier, + ID &id, + const AssetLibrary &owner_asset_library); AssetRepresentation(AssetRepresentation &&other); /* Non-copyable type. */ AssetRepresentation(const AssetRepresentation &other) = delete; @@ -63,8 +73,18 @@ class AssetRepresentation { StringRefNull get_name() const; AssetMetaData &get_metadata() const; + /** Get the import method to use for this asset. A different one may be used if + * #may_override_import_method() returns true, otherwise, the returned value must be used. If + * there is no import method predefined for this asset no value is returned. + */ + std::optional get_import_method() const; + /** Returns if this asset may be imported with an import method other than the one returned by + * #get_import_method(). Also returns true if there is no predefined import method + * (when #get_import_method() returns no value). */ + bool may_override_import_method() const; /** Returns if this asset is stored inside this current file, and as such fully editable. */ bool is_local_id() const; + const AssetLibrary &owner_asset_library() const; }; } // namespace blender::asset_system @@ -73,3 +93,6 @@ class AssetRepresentation { struct AssetRepresentation; const std::string AS_asset_representation_full_path_get(const ::AssetRepresentation *asset); +std::optional AS_asset_representation_import_method_get( + const ::AssetRepresentation *asset_handle); +bool AS_asset_representation_may_override_import_method(const ::AssetRepresentation *asset_handle); diff --git a/source/blender/asset_system/AS_essentials_library.hh b/source/blender/asset_system/AS_essentials_library.hh new file mode 100644 index 000000000000..fafaab6e6a09 --- /dev/null +++ b/source/blender/asset_system/AS_essentials_library.hh @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + */ + +#pragma once + +#include "BLI_string_ref.hh" + +namespace blender::asset_system { + +StringRefNull essentials_directory_path(); + +} diff --git a/source/blender/asset_system/CMakeLists.txt b/source/blender/asset_system/CMakeLists.txt index f8e1df40d808..25b00e54e71f 100644 --- a/source/blender/asset_system/CMakeLists.txt +++ b/source/blender/asset_system/CMakeLists.txt @@ -17,6 +17,7 @@ set(SRC intern/asset_catalog.cc intern/asset_catalog_path.cc intern/asset_catalog_tree.cc + intern/asset_essentials_library.cc intern/asset_identifier.cc intern/asset_library.cc intern/asset_library_service.cc @@ -30,6 +31,7 @@ set(SRC AS_asset_identifier.hh AS_asset_library.hh AS_asset_representation.hh + AS_essentials_library.hh intern/asset_library_service.hh intern/asset_storage.hh intern/utils.hh diff --git a/source/blender/asset_system/intern/asset_essentials_library.cc b/source/blender/asset_system/intern/asset_essentials_library.cc new file mode 100644 index 000000000000..8a4e51af27a1 --- /dev/null +++ b/source/blender/asset_system/intern/asset_essentials_library.cc @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup asset_system + */ + +#include "BLI_path_util.h" + +#include "BKE_appdir.h" + +#include "AS_essentials_library.hh" + +namespace blender::asset_system { + +StringRefNull essentials_directory_path() +{ + static std::string path = []() { + const char *datafiles_path = BKE_appdir_folder_id(BLENDER_DATAFILES, "assets"); + return datafiles_path; + }(); + return path; +} + +} // namespace blender::asset_system diff --git a/source/blender/asset_system/intern/asset_library.cc b/source/blender/asset_system/intern/asset_library.cc index 2379e738e37e..15abc7c776e5 100644 --- a/source/blender/asset_system/intern/asset_library.cc +++ b/source/blender/asset_system/intern/asset_library.cc @@ -169,13 +169,14 @@ AssetRepresentation &AssetLibrary::add_external_asset(StringRef relative_asset_p std::unique_ptr metadata) { AssetIdentifier identifier = asset_identifier_from_library(relative_asset_path); - return asset_storage_->add_external_asset(std::move(identifier), name, std::move(metadata)); + return asset_storage_->add_external_asset( + std::move(identifier), name, std::move(metadata), *this); } AssetRepresentation &AssetLibrary::add_local_id_asset(StringRef relative_asset_path, ID &id) { AssetIdentifier identifier = asset_identifier_from_library(relative_asset_path); - return asset_storage_->add_local_id_asset(std::move(identifier), id); + return asset_storage_->add_local_id_asset(std::move(identifier), id, *this); } bool AssetLibrary::remove_asset(AssetRepresentation &asset) @@ -259,6 +260,12 @@ StringRefNull AssetLibrary::root_path() const Vector all_valid_asset_library_refs() { Vector result; + { + AssetLibraryReference library_ref{}; + library_ref.custom_library_index = -1; + library_ref.type = ASSET_LIBRARY_ESSENTIALS; + result.append(library_ref); + } int i; LISTBASE_FOREACH_INDEX (const bUserAssetLibrary *, asset_library, &U.asset_libraries, i) { if (!BLI_is_dir(asset_library->path)) { diff --git a/source/blender/asset_system/intern/asset_library_service.cc b/source/blender/asset_system/intern/asset_library_service.cc index af48a173bc05..cf52f9d1d76e 100644 --- a/source/blender/asset_system/intern/asset_library_service.cc +++ b/source/blender/asset_system/intern/asset_library_service.cc @@ -16,6 +16,7 @@ #include "AS_asset_catalog_tree.hh" #include "AS_asset_library.hh" +#include "AS_essentials_library.hh" #include "asset_library_service.hh" #include "utils.hh" @@ -60,6 +61,14 @@ AssetLibrary *AssetLibraryService::get_asset_library( const eAssetLibraryType type = eAssetLibraryType(library_reference.type); switch (type) { + case ASSET_LIBRARY_ESSENTIALS: { + const StringRefNull root_path = essentials_directory_path(); + + AssetLibrary *library = get_asset_library_on_disk(root_path); + library->import_method_ = ASSET_IMPORT_APPEND_REUSE; + + return library; + } case ASSET_LIBRARY_LOCAL: { /* For the "Current File" library we get the asset library root path based on main. */ std::string root_path = bmain ? AS_asset_library_find_suitable_root_path_from_main(bmain) : @@ -74,12 +83,22 @@ AssetLibrary *AssetLibraryService::get_asset_library( case ASSET_LIBRARY_ALL: return get_asset_library_all(bmain); case ASSET_LIBRARY_CUSTOM: { - std::string root_path = root_path_from_library_ref(library_reference); - - if (!root_path.empty()) { - return get_asset_library_on_disk(root_path); + bUserAssetLibrary *custom_library = find_custom_asset_library_from_library_ref( + library_reference); + if (!custom_library) { + return nullptr; } - break; + + std::string root_path = custom_library->path; + if (root_path.empty()) { + return nullptr; + } + + AssetLibrary *library = get_asset_library_on_disk(root_path); + library->import_method_ = eAssetImportMethod(custom_library->import_method); + library->may_override_import_method_ = true; + + return library; } } @@ -180,6 +199,15 @@ AssetLibrary *AssetLibraryService::get_asset_library_all(const Main *bmain) return all_library_.get(); } +bUserAssetLibrary *AssetLibraryService::find_custom_asset_library_from_library_ref( + const AssetLibraryReference &library_reference) +{ + BLI_assert(library_reference.type == ASSET_LIBRARY_CUSTOM); + BLI_assert(library_reference.custom_library_index >= 0); + + return BKE_preferences_asset_library_find_from_index(&U, library_reference.custom_library_index); +} + std::string AssetLibraryService::root_path_from_library_ref( const AssetLibraryReference &library_reference) { @@ -187,16 +215,13 @@ std::string AssetLibraryService::root_path_from_library_ref( return ""; } - BLI_assert(library_reference.type == ASSET_LIBRARY_CUSTOM); - BLI_assert(library_reference.custom_library_index >= 0); - - bUserAssetLibrary *user_library = BKE_preferences_asset_library_find_from_index( - &U, library_reference.custom_library_index); - if (!user_library || !user_library->path[0]) { + bUserAssetLibrary *custom_library = find_custom_asset_library_from_library_ref( + library_reference); + if (!custom_library || !custom_library->path[0]) { return ""; } - return user_library->path; + return custom_library->path; } void AssetLibraryService::allocate_service_instance() diff --git a/source/blender/asset_system/intern/asset_library_service.hh b/source/blender/asset_system/intern/asset_library_service.hh index 1dd9bda7acad..1c0a2e9dc368 100644 --- a/source/blender/asset_system/intern/asset_library_service.hh +++ b/source/blender/asset_system/intern/asset_library_service.hh @@ -14,6 +14,7 @@ #include struct AssetLibraryReference; +struct bUserAssetLibrary; namespace blender::asset_system { @@ -58,6 +59,8 @@ class AssetLibraryService { static void destroy(); static std::string root_path_from_library_ref(const AssetLibraryReference &library_reference); + static bUserAssetLibrary *find_custom_asset_library_from_library_ref( + const AssetLibraryReference &library_reference); AssetLibrary *get_asset_library(const Main *bmain, const AssetLibraryReference &library_reference); diff --git a/source/blender/asset_system/intern/asset_representation.cc b/source/blender/asset_system/intern/asset_representation.cc index 573358b7df72..daaa7bdff0f5 100644 --- a/source/blender/asset_system/intern/asset_representation.cc +++ b/source/blender/asset_system/intern/asset_representation.cc @@ -8,8 +8,10 @@ #include "DNA_ID.h" #include "DNA_asset_types.h" +#include "DNA_userdef_types.h" #include "AS_asset_identifier.hh" +#include "AS_asset_library.hh" #include "AS_asset_representation.h" #include "AS_asset_representation.hh" @@ -17,15 +19,24 @@ namespace blender::asset_system { AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier, StringRef name, - std::unique_ptr metadata) - : identifier_(identifier), is_local_id_(false), external_asset_() + std::unique_ptr metadata, + const AssetLibrary &owner_asset_library) + : identifier_(identifier), + is_local_id_(false), + owner_asset_library_(&owner_asset_library), + external_asset_() { external_asset_.name = name; external_asset_.metadata_ = std::move(metadata); } -AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier, ID &id) - : identifier_(identifier), is_local_id_(true), local_asset_id_(&id) +AssetRepresentation::AssetRepresentation(AssetIdentifier &&identifier, + ID &id, + const AssetLibrary &owner_asset_library) + : identifier_(identifier), + is_local_id_(true), + owner_asset_library_(&owner_asset_library), + local_asset_id_(&id) { if (!id.asset_data) { throw std::invalid_argument("Passed ID is not an asset"); @@ -70,11 +81,32 @@ AssetMetaData &AssetRepresentation::get_metadata() const return is_local_id_ ? *local_asset_id_->asset_data : *external_asset_.metadata_; } +std::optional AssetRepresentation::get_import_method() const +{ + if (!owner_asset_library_) { + return {}; + } + return owner_asset_library_->import_method_; +} + +bool AssetRepresentation::may_override_import_method() const +{ + if (!owner_asset_library_ || !owner_asset_library_->import_method_) { + return true; + } + return owner_asset_library_->may_override_import_method_; +} + bool AssetRepresentation::is_local_id() const { return is_local_id_; } +const AssetLibrary &AssetRepresentation::owner_asset_library() const +{ + return *owner_asset_library_; +} + } // namespace blender::asset_system using namespace blender; @@ -87,6 +119,21 @@ const std::string AS_asset_representation_full_path_get(const AssetRepresentatio return identifier.full_path(); } +std::optional AS_asset_representation_import_method_get( + const AssetRepresentation *asset_handle) +{ + const asset_system::AssetRepresentation *asset = + reinterpret_cast(asset_handle); + return asset->get_import_method(); +} + +bool AS_asset_representation_may_override_import_method(const AssetRepresentation *asset_handle) +{ + const asset_system::AssetRepresentation *asset = + reinterpret_cast(asset_handle); + return asset->may_override_import_method(); +} + /* ---------------------------------------------------------------------- */ /** \name C-API * \{ */ diff --git a/source/blender/asset_system/intern/asset_storage.cc b/source/blender/asset_system/intern/asset_storage.cc index 73b9d5826161..f14b0cd0f79f 100644 --- a/source/blender/asset_system/intern/asset_storage.cc +++ b/source/blender/asset_system/intern/asset_storage.cc @@ -15,18 +15,21 @@ namespace blender::asset_system { -AssetRepresentation &AssetStorage::add_local_id_asset(AssetIdentifier &&identifier, ID &id) +AssetRepresentation &AssetStorage::add_local_id_asset(AssetIdentifier &&identifier, + ID &id, + const AssetLibrary &owner_asset_library) { return *local_id_assets_.lookup_key_or_add( - std::make_unique(std::move(identifier), id)); + std::make_unique(std::move(identifier), id, owner_asset_library)); } AssetRepresentation &AssetStorage::add_external_asset(AssetIdentifier &&identifier, StringRef name, - std::unique_ptr metadata) + std::unique_ptr metadata, + const AssetLibrary &owner_asset_library) { - return *external_assets_.lookup_key_or_add( - std::make_unique(std::move(identifier), name, std::move(metadata))); + return *external_assets_.lookup_key_or_add(std::make_unique( + std::move(identifier), name, std::move(metadata), owner_asset_library)); } bool AssetStorage::remove_asset(AssetRepresentation &asset) diff --git a/source/blender/asset_system/intern/asset_storage.hh b/source/blender/asset_system/intern/asset_storage.hh index 2b4614abca52..c4a9ec143191 100644 --- a/source/blender/asset_system/intern/asset_storage.hh +++ b/source/blender/asset_system/intern/asset_storage.hh @@ -35,9 +35,12 @@ class AssetStorage { /** See #AssetLibrary::add_external_asset(). */ AssetRepresentation &add_external_asset(AssetIdentifier &&identifier, StringRef name, - std::unique_ptr metadata); + std::unique_ptr metadata, + const AssetLibrary &owner_asset_library); /** See #AssetLibrary::add_external_asset(). */ - AssetRepresentation &add_local_id_asset(AssetIdentifier &&identifier, ID &id); + AssetRepresentation &add_local_id_asset(AssetIdentifier &&identifier, + ID &id, + const AssetLibrary &owner_asset_library); /** See #AssetLibrary::remove_asset(). */ bool remove_asset(AssetRepresentation &asset); diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index d4f5be617fd4..a8cbb89c7ada 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -165,7 +165,7 @@ int BLF_load_unique(const char *name) /* XXX: Temporarily disable kerning in our main font. Kerning had been accidentally removed from * our font in 3.1. In 3.4 we disable kerning here in the new version to keep spacing the same - * (T101506). Enable again later with change of font, placement, or rendering - Harley. */ + * (#101506). Enable again later with change of font, placement, or rendering - Harley. */ if (font && BLI_str_endswith(filepath, BLF_DEFAULT_PROPORTIONAL_FONT)) { font->face_flags &= ~FT_FACE_FLAG_KERNING; } diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 79d0fe6e20ad..8c875ec456d1 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -271,7 +271,7 @@ struct bPoseChannel *BKE_pose_channel_active_if_layer_visible(struct Object *ob) * In this case the active-selected is an obvious choice when finding the target for a * constraint for eg. however from the users perspective the active pose bone of the * active object is the _real_ active bone, so any other non-active selected bone - * is a candidate for being the other selected bone, see: T58447. + * is a candidate for being the other selected bone, see: #58447. */ struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob); /** diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 46aacf1e7fda..e0ffea9aadf9 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -37,7 +37,7 @@ struct bActionGroup; /* Container for data required to do FCurve and Driver evaluation. */ typedef struct AnimationEvalContext { /* For drivers, so that they have access to the dependency graph and the current view layer. See - * T77086. */ + * #77086. */ struct Depsgraph *depsgraph; /* FCurves and Drivers can be evaluated at a different time than the current scene time, for diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 7c01a9205fc0..76558b9ba286 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -41,6 +41,7 @@ typedef enum eAttrDomainMask { ATTR_DOMAIN_MASK_CURVE = (1 << 4), ATTR_DOMAIN_MASK_ALL = (1 << 5) - 1 } eAttrDomainMask; +ENUM_OPERATORS(eAttrDomainMask, ATTR_DOMAIN_MASK_ALL); #define ATTR_DOMAIN_AS_MASK(domain) ((eAttrDomainMask)((1 << (int)(domain)))) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index f5514fcc6320..672054b7c529 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -17,15 +17,17 @@ extern "C" { */ /* Blender major and minor version. */ -#define BLENDER_VERSION 305 +#define BLENDER_VERSION 306 /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ #define BLENDER_VERSION_CYCLE alpha +/* TODO proper version bump. */ + /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 8 +#define BLENDER_FILE_SUBVERSION 0 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_crazyspace.hh b/source/blender/blenkernel/BKE_crazyspace.hh index 5f206bcefb23..36b15dcb5901 100644 --- a/source/blender/blenkernel/BKE_crazyspace.hh +++ b/source/blender/blenkernel/BKE_crazyspace.hh @@ -46,6 +46,7 @@ struct GeometryDeformation { * function either retrieves the deformation data from the evaluated object, or falls back to * returning the original data. */ +GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig); GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, const Object &ob_orig); diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh index 0a3915755980..c3ad7c027a1b 100644 --- a/source/blender/blenkernel/BKE_curves.hh +++ b/source/blender/blenkernel/BKE_curves.hh @@ -71,16 +71,11 @@ class CurvesGeometryRuntime { mutable SharedCache> nurbs_basis_cache; - /** Cache of evaluated positions. */ - struct EvaluatedPositions { - Vector vector; - /** - * The evaluated positions result, using a separate span in case all curves are poly curves, - * in which case a separate array of evaluated positions is unnecessary. - */ - Span span; - }; - mutable SharedCache evaluated_position_cache; + /** + * Cache of evaluated positions for all curves. The positions span will + * be used directly rather than the cache when all curves are poly type. + */ + mutable SharedCache> evaluated_position_cache; /** * A cache of bounds shared between data-blocks with unchanged positions and radii. diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 905eb43179a5..297cd3c2433f 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -137,6 +137,7 @@ bool CustomData_has_referenced(const struct CustomData *data); * implemented for mloopuv/mloopcol, for now. */ void CustomData_data_copy_value(int type, const void *source, void *dest); +void CustomData_data_set_default_value(int type, void *elem); /** * Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into @@ -281,6 +282,7 @@ bool CustomData_has_layer(const struct CustomData *data, int type); * Returns the number of layers with this type. */ int CustomData_number_of_layers(const struct CustomData *data, int type); +int CustomData_number_of_anonymous_layers(const struct CustomData *data, int type); int CustomData_number_of_layers_typemask(const struct CustomData *data, eCustomDataMask mask); /** @@ -304,8 +306,8 @@ void CustomData_copy_data(const struct CustomData *source, int source_index, int dest_index, int count); -void CustomData_copy_data_layer(const CustomData *source, - CustomData *dest, +void CustomData_copy_data_layer(const struct CustomData *source, + struct CustomData *dest, int src_layer_index, int dst_layer_index, int src_index, @@ -444,7 +446,7 @@ void *CustomData_get_layer_named_for_write(CustomData *data, int totelem); int CustomData_get_offset(const struct CustomData *data, int type); -int CustomData_get_offset_named(const CustomData *data, int type, const char *name); +int CustomData_get_offset_named(const struct CustomData *data, int type, const char *name); int CustomData_get_n_offset(const struct CustomData *data, int type, int n); int CustomData_get_layer_index(const struct CustomData *data, int type); @@ -506,6 +508,8 @@ void CustomData_clear_layer_flag(struct CustomData *data, int type, int flag); void CustomData_bmesh_set_default(struct CustomData *data, void **block); void CustomData_bmesh_free_block(struct CustomData *data, void **block); +void CustomData_bmesh_alloc_block(struct CustomData *data, void **block); + /** * Same as #CustomData_bmesh_free_block but zero the memory rather than freeing. */ @@ -517,24 +521,6 @@ void CustomData_bmesh_free_block_data_exclude_by_type(struct CustomData *data, void *block, eCustomDataMask mask_exclude); -/** - * Copy custom data to/from layers as in mesh/derived-mesh, to edit-mesh - * blocks of data. the CustomData's must not be compatible. - * - * \param use_default_init: initializes data which can't be copied, - * typically you'll want to use this if the BM_xxx create function - * is called with BM_CREATE_SKIP_CD flag - */ -void CustomData_to_bmesh_block(const struct CustomData *source, - struct CustomData *dest, - int src_index, - void **dest_block, - bool use_default_init); -void CustomData_from_bmesh_block(const struct CustomData *source, - struct CustomData *dest, - void *src_block, - int dest_index); - /** * Query info over types. */ @@ -743,7 +729,7 @@ void CustomData_blend_write(BlendWriter *writer, void CustomData_blend_read(struct BlendDataReader *reader, struct CustomData *data, int count); -size_t CustomData_get_elem_size(struct CustomDataLayer *layer); +size_t CustomData_get_elem_size(const struct CustomDataLayer *layer); #ifndef NDEBUG struct DynStr; diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 4030803dc1fa..daf394b811a0 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -134,7 +134,7 @@ typedef struct Main { /** * When linking, disallow creation of new data-blocks. - * Make sure we don't do this by accident, see T76738. + * Make sure we don't do this by accident, see #76738. */ bool is_locked_for_linking; diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 6b4553f7246d..be447ab0ecce 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -812,7 +812,7 @@ struct Mesh *BKE_mesh_merge_verts(struct Mesh *mesh, * Account for custom-data such as UVs becoming detached because of imprecision * in custom-data interpolation. * Without running this operation subdivision surface can cause UVs to be disconnected, - * see: T81065. + * see: #81065. */ void BKE_mesh_merge_customdata_for_apply_modifier(struct Mesh *me); diff --git a/source/blender/blenkernel/BKE_mesh_types.h b/source/blender/blenkernel/BKE_mesh_types.h index 2fe8bd21b7ad..b9c62f39c570 100644 --- a/source/blender/blenkernel/BKE_mesh_types.h +++ b/source/blender/blenkernel/BKE_mesh_types.h @@ -132,7 +132,7 @@ struct MeshRuntime { * * Modifiers that edit the mesh data in-place must set this to false * (most #eModifierTypeType_NonGeometrical modifiers). Otherwise the edit-mesh - * data will be used for drawing, missing changes from modifiers. See T79517. + * data will be used for drawing, missing changes from modifiers. See #79517. */ bool is_original_bmesh = false; diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index 086f21aa897f..a58b4166ba57 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -36,15 +36,15 @@ struct PropertyRNA; /* Data Management */ /** - * Remove the given NLA strip from the NLA track it occupies, free the strip's data, - * and the strip itself. + * Frees the given NLA strip, and calls #BKE_nlastrip_remove_and_free to + * remove and free all children strips. */ -void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip, bool do_id_user); +void BKE_nlastrip_free(struct NlaStrip *strip, bool do_id_user); /** - * Remove the given NLA track from the set of NLA tracks, free the track's data, - * and the track itself. + * Remove & Frees all NLA strips from the given NLA track, + * then frees (doesn't remove) the track itself. */ -void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user); +void BKE_nlatrack_free(struct NlaTrack *nlt, bool do_id_user); /** * Free the elements of type NLA Tracks provided in the given list, but do not free * the list itself since that is not free-standing @@ -94,10 +94,33 @@ void BKE_nla_tracks_copy_from_adt(struct Main *bmain, struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt, struct NlaTrack *prev, bool is_liboverride); + +/** + * Removes the given NLA track from the list of tracks provided. + */ +void BKE_nlatrack_remove(ListBase *tracks, struct NlaTrack *nlt); + +/** + * Remove the given NLA track from the list of NLA tracks, free the track's data, + * and the track itself. + */ +void BKE_nlatrack_remove_and_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user); + /** * Create a NLA Strip referencing the given Action. */ struct NlaStrip *BKE_nlastrip_new(struct bAction *act); + +/* + * Removes the given NLA strip from the list of strips provided. + */ +void BKE_nlastrip_remove(ListBase *strips, struct NlaStrip *strip); + +/* + * Removes the given NLA strip from the list of strips provided, and frees it's memory. + */ +void BKE_nlastrip_remove_and_free(ListBase *strips, struct NlaStrip *strip, const bool do_id_user); + /** * Add new NLA-strip to the top of the NLA stack - i.e. * into the last track if space, or a new one otherwise. @@ -139,13 +162,9 @@ void BKE_nlastrips_sort_strips(ListBase *strips); void BKE_nlastrips_add_strip_unsafe(ListBase *strips, struct NlaStrip *strip); /** - * \brief NULL checks incoming strip and verifies no overlap / invalid - * configuration against other strips in NLA Track. - * - * \param strips: - * \param strip: - * \return true - * \return false + * NULL checks incoming strip and verifies no overlap / invalid + * configuration against other strips in NLA Track before calling + * #BKE_nlastrips_add_strip_unsafe. */ bool BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip); @@ -215,11 +234,16 @@ bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); void BKE_nlatrack_sort_strips(struct NlaTrack *nlt); /** - * Add the given NLA-Strip to the given NLA-Track, assuming that it - * isn't currently attached to another one. + * Add the given NLA-Strip to the given NLA-Track. + * Calls #BKE_nlastrips_add_strip to check if strip can be added. */ bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip, bool is_liboverride); +/** + * Remove the NLA-Strip from the given NLA-Track. + */ +void BKE_nlatrack_remove_strip(struct NlaTrack *track, struct NlaStrip *strip); + /** * Get the extents of the given NLA-Track including gaps between strips, * returning whether this succeeded or not diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index f387122079b8..a0f6405a6ac4 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -995,7 +995,7 @@ void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwid void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size); /** * \warning Nodes defining a storage type _must_ allocate this for new nodes. - * Otherwise nodes will reload as undefined (T46619). + * Otherwise nodes will reload as undefined (#46619). */ void node_type_storage(struct bNodeType *ntype, const char *storagename, diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index c77faf98b25e..92ea5bd49867 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -370,7 +370,7 @@ void BKE_object_dimensions_get(struct Object *ob, float r_vec[3]); * typically this caused by parenting, constraints or delta-scale. * * Re-using these values from the object causes a feedback loop - * when multiple values are modified at once in some situations. see: T69536. + * when multiple values are modified at once in some situations. see: #69536. */ void BKE_object_dimensions_set_ex(struct Object *ob, const float value[3], diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 367dc9a3035b..12a55151c9bb 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -775,7 +775,7 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node, /** * \note doing a full search on all vertices here seems expensive, * however this is important to avoid having to recalculate bound-box & sync the buffers to the - * GPU (which is far more expensive!) See: T47232. + * GPU (which is far more expensive!) See: #47232. */ bool BKE_pbvh_node_has_vert_with_normal_update_tag(PBVH *pbvh, PBVHNode *node); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 850c55de7e92..2291827e3744 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -249,8 +249,8 @@ set(SRC intern/particle_distribute.c intern/particle_system.c intern/pbvh.cc - intern/pbvh_colors.cc intern/pbvh_bmesh.cc + intern/pbvh_colors.cc intern/pbvh_pixels.cc intern/pbvh_uv_islands.cc intern/pointcache.c diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index b17f58e68724..459db322b013 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -911,7 +911,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* set the Mesh to only copy needed data */ CustomData_MeshMasks mask = md_datamask->mask; - /* needMapping check here fixes bug T28112, otherwise it's + /* needMapping check here fixes bug #28112, otherwise it's * possible that it won't be copied */ CustomData_MeshMasks_update(&mask, &append_mask); if (need_mapping) { @@ -1678,7 +1678,7 @@ void makeDerivedMesh(struct Depsgraph *depsgraph, BLI_assert(ob->type == OB_MESH); /* Evaluated meshes aren't supposed to be created on original instances. If you do, - * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ + * they aren't cleaned up properly on mode switch, causing crashes, e.g #58150. */ BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); BKE_object_free_derived_caches(ob); @@ -1715,7 +1715,7 @@ Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, BLI_assert(DEG_is_evaluating(depsgraph) == false); /* Evaluated meshes aren't supposed to be created on original instances. If you do, - * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ + * they aren't cleaned up properly on mode switch, causing crashes, e.g #58150. */ BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); /* if there's no evaluated mesh or the last data mask used doesn't include @@ -1757,7 +1757,7 @@ Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, BLI_assert(DEG_is_evaluating(depsgraph) == false); /* Evaluated meshes aren't supposed to be created on original instances. If you do, - * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ + * they aren't cleaned up properly on mode switch, causing crashes, e.g #58150. */ BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); /* if there's no derived mesh or the last data mask used doesn't include diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index d4a7a7cbb1e1..8549f2df1dcb 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1406,7 +1406,7 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_ * - no "selected only", since this is often used in the backend * - no "minimum length" (we will apply this later), otherwise * single-keyframe curves will increase the overall length by - * a phantom frame (T50354) + * a phantom frame (#50354) */ BKE_fcurve_calc_range(fcu, &nmin, &nmax, false, false); diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 9b68c19c6e26..e84e08744843 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -1461,7 +1461,7 @@ void BKE_animdata_blend_read_data(BlendDataReader *reader, AnimData *adt) /* relink active track/strip - even though strictly speaking this should only be used * if we're in 'tweaking mode', we need to be able to have this loaded back for - * undo, but also since users may not exit tweak-mode before saving (T24535). + * undo, but also since users may not exit tweak-mode before saving (#24535). */ /* TODO: it's not really nice that anyone should be able to save the file in this * state, but it's going to be too hard to enforce this single case. */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 928626ecc7bf..09120a34d807 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -2880,7 +2880,7 @@ static void nlastrip_evaluate_meta(const int evaluation_mode, STRIP_EVAL_NOBLEND)); /* directly evaluate child strip into accumulation buffer... - * - there's no need to use a temporary buffer (as it causes issues [T40082]) + * - there's no need to use a temporary buffer (as it causes issues [#40082]) */ if (tmp_nes) { nlastrip_evaluate(evaluation_mode, @@ -4163,7 +4163,7 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCu const float curval = calculate_fcurve(&anim_rna, fcu, &anim_eval_context); ok = BKE_animsys_write_to_rna_path(&anim_rna, curval); - /* Flush results & status codes to original data for UI (T59984) */ + /* Flush results & status codes to original data for UI (#59984) */ if (ok && DEG_is_active(depsgraph)) { animsys_write_orig_anim_rna(&id_ptr, fcu->rna_path, fcu->array_index, curval); diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 5f749472b2d6..6c809a8269d6 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -925,7 +925,7 @@ static void pose_channel_flush_to_orig_if_needed(struct Depsgraph *depsgraph, return; } bPoseChannel *pchan_orig = pchan->orig_pchan; - /* TODO(sergey): Using BKE_pose_copy_pchan_result() introduces T70901, but why? */ + /* TODO(sergey): Using BKE_pose_copy_pchan_result() introduces #70901, but why? */ copy_m4_m4(pchan_orig->pose_mat, pchan->pose_mat); copy_m4_m4(pchan_orig->chan_mat, pchan->chan_mat); copy_v3_v3(pchan_orig->pose_head, pchan->pose_mat[3]); diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 8a6e14867013..2ba03b6d1cf6 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -316,9 +316,6 @@ GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const void *owner) cons GAttributeWriter BuiltinCustomDataLayerProvider::try_get_for_write(void *owner) const { - if (writable_ != Writable) { - return {}; - } CustomData *custom_data = custom_data_access_.get_custom_data(owner); if (custom_data == nullptr) { return {}; diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh index b429756e7549..a1a74e3b81c0 100644 --- a/source/blender/blenkernel/intern/attribute_access_intern.hh +++ b/source/blender/blenkernel/intern/attribute_access_intern.hh @@ -37,10 +37,6 @@ class BuiltinAttributeProvider { Creatable, NonCreatable, }; - enum WritableEnum { - Writable, - Readonly, - }; enum DeletableEnum { Deletable, NonDeletable, @@ -51,7 +47,6 @@ class BuiltinAttributeProvider { const eAttrDomain domain_; const eCustomDataType data_type_; const CreatableEnum createable_; - const WritableEnum writable_; const DeletableEnum deletable_; const AttributeValidator validator_; @@ -60,14 +55,12 @@ class BuiltinAttributeProvider { const eAttrDomain domain, const eCustomDataType data_type, const CreatableEnum createable, - const WritableEnum writable, const DeletableEnum deletable, AttributeValidator validator = {}) : name_(std::move(name)), domain_(domain), data_type_(data_type), createable_(createable), - writable_(writable), deletable_(deletable), validator_(validator) { @@ -205,20 +198,14 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { const eCustomDataType attribute_type, const eCustomDataType stored_type, const CreatableEnum creatable, - const WritableEnum writable, const DeletableEnum deletable, const CustomDataAccessInfo custom_data_access, const AsReadAttribute as_read_attribute, const AsWriteAttribute as_write_attribute, const UpdateOnChange update_on_write, const AttributeValidator validator = {}) - : BuiltinAttributeProvider(std::move(attribute_name), - domain, - attribute_type, - creatable, - writable, - deletable, - validator), + : BuiltinAttributeProvider( + std::move(attribute_name), domain, attribute_type, creatable, deletable, validator), stored_type_(stored_type), custom_data_access_(custom_data_access), as_read_attribute_(as_read_attribute), diff --git a/source/blender/blenkernel/intern/blendfile.cc b/source/blender/blenkernel/intern/blendfile.cc index 4deaa6d21091..8f0e462cd27a 100644 --- a/source/blender/blenkernel/intern/blendfile.cc +++ b/source/blender/blenkernel/intern/blendfile.cc @@ -203,7 +203,7 @@ static void setup_app_data(bContext *C, * But if they close one of the screens, * undo will ensure that the scene being operated on will be activated * (otherwise we'd be undoing on an off-screen scene which isn't acceptable). - * see: T43424 + * see: #43424 */ wmWindow *win; bScreen *curscreen = nullptr; diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c index 49b480fcb648..8b97ab4b061d 100644 --- a/source/blender/blenkernel/intern/blendfile_link_append.c +++ b/source/blender/blenkernel/intern/blendfile_link_append.c @@ -613,10 +613,10 @@ static void loose_data_instantiate_collection_process( } /* Forced instantiation of indirectly appended collections is not wanted. Users can now - * easily instantiate collections (and their objects) as needed by themselves. See T67032. */ + * easily instantiate collections (and their objects) as needed by themselves. See #67032. */ /* We need to check that objects in that collections are already instantiated in a scene. * Otherwise, it's better to add the collection to the scene's active collection, than to - * instantiate its objects in active scene's collection directly. See T61141. + * instantiate its objects in active scene's collection directly. See #61141. * * NOTE: We only check object directly into that collection, not recursively into its * children. @@ -625,7 +625,7 @@ static void loose_data_instantiate_collection_process( /* The collection could be linked/appended together with an Empty object instantiating it, * better not instantiate the collection in the view-layer in that case. * - * Can easily happen when copy/pasting such instantiating empty, see T93839. */ + * Can easily happen when copy/pasting such instantiating empty, see #93839. */ const bool collection_is_instantiated = collection_instantiated_by_any_object(bmain, collection); /* Always consider adding collections directly selected by the user. */ @@ -751,7 +751,7 @@ static void loose_data_instantiate_object_process(LooseDataInstantiateContext *i * While this is not ideal (in theory no object should remain un-owned), in case of indirectly * linked objects, the other solution would be to add them to a local collection, which would * make them directly linked. Think for now keeping them indirectly linked is more important. - * Ref. T93757. + * Ref. #93757. */ if (is_linking && (item->tag & LINK_APPEND_TAG_INDIRECT) != 0) { continue; @@ -935,7 +935,7 @@ static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_d * the dependency here. Indeed, either they are both linked in another way (through their own * meshes for shape keys e.g.), or this is an unsupported case (two shape-keys depending on * each-other need to be also 'linked' in by their respective meshes, independent shape-keys - * are not allowed). ref T96048. */ + * are not allowed). ref #96048. */ if (id != cb_data->id_self && BKE_idtype_idcode_is_linkable(GS(cb_data->id_self->name))) { BKE_library_foreach_ID_link( cb_data->bmain, id, foreach_libblock_link_append_callback, data, IDWALK_NOP); @@ -1244,7 +1244,7 @@ void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *re mainl = BLO_library_link_begin(&blo_handle, libname, lapp_context->params); lib = mainl->curlib; BLI_assert(lib != NULL); - /* In case lib was already existing but not found originally, see T99820. */ + /* In case lib was already existing but not found originally, see #99820. */ lib->id.tag &= ~LIB_TAG_MISSING; if (mainl->versionfile < 250) { @@ -1424,7 +1424,7 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context, /* All override rules need to be up to date, since there will be no do_version here, otherwise * older, now-invalid rules might be applied and likely fail, or some changes might be missing, - * etc. See T93353. */ + * etc. See #93353. */ BKE_lib_override_library_main_operations_create(bmain, true, NULL); /* Remove all IDs to be reloaded from Main. */ diff --git a/source/blender/blenkernel/intern/brush.cc b/source/blender/blenkernel/intern/brush.cc index 8d5737e940d0..9a66b6b7d96a 100644 --- a/source/blender/blenkernel/intern/brush.cc +++ b/source/blender/blenkernel/intern/brush.cc @@ -100,6 +100,8 @@ static void brush_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, cons if (brush_src->curves_sculpt_settings != nullptr) { brush_dst->curves_sculpt_settings = MEM_cnew( __func__, *(brush_src->curves_sculpt_settings)); + brush_dst->curves_sculpt_settings->curve_parameter_falloff = BKE_curvemapping_copy( + brush_src->curves_sculpt_settings->curve_parameter_falloff); } /* enable fake user by default */ @@ -130,6 +132,7 @@ static void brush_free_data(ID *id) MEM_SAFE_FREE(brush->gpencil_settings); } if (brush->curves_sculpt_settings != nullptr) { + BKE_curvemapping_free(brush->curves_sculpt_settings->curve_parameter_falloff); MEM_freeN(brush->curves_sculpt_settings); } @@ -255,6 +258,7 @@ static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_addres } if (brush->curves_sculpt_settings) { BLO_write_struct(writer, BrushCurvesSculptSettings, brush->curves_sculpt_settings); + BKE_curvemapping_blend_write(writer, brush->curves_sculpt_settings->curve_parameter_falloff); } if (brush->gradient) { BLO_write_struct(writer, ColorBand, brush->gradient); @@ -337,6 +341,12 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id) } BLO_read_data_address(reader, &brush->curves_sculpt_settings); + if (brush->curves_sculpt_settings) { + BLO_read_data_address(reader, &brush->curves_sculpt_settings->curve_parameter_falloff); + if (brush->curves_sculpt_settings->curve_parameter_falloff) { + BKE_curvemapping_blend_read(reader, brush->curves_sculpt_settings->curve_parameter_falloff); + } + } brush->preview = nullptr; brush->icon_imbuf = nullptr; @@ -1583,6 +1593,7 @@ void BKE_brush_init_curves_sculpt_settings(Brush *brush) settings->minimum_length = 0.01f; settings->curve_length = 0.3f; settings->density_add_attempts = 100; + settings->curve_parameter_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); } struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode) diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 2d5dc9010bf4..47f031e8dca1 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -537,7 +537,7 @@ void BKE_camera_view_frame_ex(const Scene *scene, r_vec[3][2] = depth; if (do_clip) { - /* Ensure the frame isn't behind the near clipping plane, T62814. */ + /* Ensure the frame isn't behind the near clipping plane, #62814. */ float fac = ((camera->clip_start + 0.1f) / -r_vec[0][2]) * scale[2]; for (uint i = 0; i < 4; i++) { if (camera->type == CAM_ORTHO) { diff --git a/source/blender/blenkernel/intern/colorband.c b/source/blender/blenkernel/intern/colorband.c index d36b148f2d66..99236ed81ead 100644 --- a/source/blender/blenkernel/intern/colorband.c +++ b/source/blender/blenkernel/intern/colorband.c @@ -469,7 +469,7 @@ bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4]) } else { /* was setting to 0.0 in 2.56 & previous, but this - * is incorrect for the last element, see T26732. */ + * is incorrect for the last element, see #26732. */ fac = (a != coba->tot) ? 0.0f : 1.0f; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 81fae6f4b110..1ffae922408d 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -141,7 +141,7 @@ bConstraintOb *BKE_constraints_make_evalob( /* NOTE: Versions <= 2.76 assumed that "default" order * would always get used, so we may seem some rig * breakage as a result. However, this change here - * is needed to fix T46599 + * is needed to fix #46599 */ cob->rotOrder = ob->rotmode; } @@ -1222,7 +1222,7 @@ static void vectomat(const float vec[3], } /* NOTE: even though 'n' is normalized, don't use 'project_v3_v3v3_normalized' below - * because precision issues cause a problem in near degenerate states, see: T53455. */ + * because precision issues cause a problem in near degenerate states, see: #53455. */ /* project the up vector onto the plane specified by n */ project_v3_v3v3(proj, u, n); /* first u onto n... */ @@ -1953,7 +1953,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar /* To allow compatible rotations, must get both rotations in the order of the owner... */ mat4_to_eulO(obeul, rot_order, cob->matrix); /* We must get compatible eulers from the beginning because - * some of them can be modified below (see bug T21875). + * some of them can be modified below (see bug #21875). * Additionally, since this constraint is based on euler rotation math, it doesn't work well * with shear. The Y axis is chosen as the main axis when we orthogonalize the matrix because * constraints are used most commonly on bones. */ @@ -4024,7 +4024,7 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t mat4_to_size(dvec, ct->matrix); if (is_negative_m4(ct->matrix)) { - /* Bugfix T27886: (this is a limitation that riggers will have to live with for now). + /* Bugfix #27886: (this is a limitation that riggers will have to live with for now). * We can't be sure which axis/axes are negative, * though we know that something is negative. * Assume we don't care about negativity of separate axes. */ @@ -4307,7 +4307,7 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *UNUSED(depsgraph), /* Transform normal into requested space */ /* Note that in this specific case, we need to keep scaling in non-parented 'local2world' * object case, because SpaceTransform also takes it into account when handling normals. - * See T42447. */ + * See #42447. */ unit_m4(mat); BKE_constraint_mat_convertspace( cob->ob, cob->pchan, cob, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace, true); @@ -5605,7 +5605,7 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool { const short type = con->type; if (BKE_constraint_remove(list, con)) { - /* ITASC needs to be rebuilt once a constraint is removed T26920. */ + /* ITASC needs to be rebuilt once a constraint is removed #26920. */ if (clear_dep && ELEM(type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) { BIK_clear_data(ob->pose); } @@ -5831,7 +5831,7 @@ static bConstraint *add_new_constraint(Object *ob, } case CONSTRAINT_TYPE_ACTION: { /* The Before or Split modes require computing in local space, but - * for objects the Local space doesn't make sense (T78462, D6095 etc). + * for objects the Local space doesn't make sense (#78462, D6095 etc). * So only default to Before (Split) if the constraint is on a bone. */ if (pchan) { bActionConstraint *data = con->data; @@ -6422,7 +6422,7 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, /* Interpolate the enforcement, to blend result of constraint into final owner transform * - all this happens in world-space to prevent any weirdness creeping in - * (T26014 and T25725), since some constraints may not convert the solution back to the input + * (#26014 and #25725), since some constraints may not convert the solution back to the input * space before blending but all are guaranteed to end up in good "world-space" result. */ /* NOTE: all kind of stuff here before (caused trouble), much easier to just interpolate, diff --git a/source/blender/blenkernel/intern/crazyspace.cc b/source/blender/blenkernel/intern/crazyspace.cc index 906d4c826237..d63ba6d08b30 100644 --- a/source/blender/blenkernel/intern/crazyspace.cc +++ b/source/blender/blenkernel/intern/crazyspace.cc @@ -398,7 +398,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, } else { /* More complex handling will continue in BKE_crazyspace_build_sculpt. - * Exiting the loop on a non-deform modifier causes issues - T71213. */ + * Exiting the loop on a non-deform modifier causes issues - #71213. */ BLI_assert(crazyspace_modifier_supports_deform(md)); break; } @@ -596,8 +596,7 @@ void BKE_crazyspace_api_eval_clear(Object *object) namespace blender::bke::crazyspace { -GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, - const Object &ob_orig) +GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig) { BLI_assert(ob_orig.type == OB_CURVES); const Curves &curves_id_orig = *static_cast(ob_orig.data); @@ -608,7 +607,6 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, /* Use the undeformed positions by default. */ deformation.positions = curves_orig.positions(); - const Object *ob_eval = DEG_get_evaluated_object(&depsgraph, const_cast(&ob_orig)); if (ob_eval == nullptr) { return deformation; } @@ -653,4 +651,11 @@ GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, return deformation; } +GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, + const Object &ob_orig) +{ + const Object *ob_eval = DEG_get_evaluated_object(&depsgraph, const_cast(&ob_orig)); + return get_evaluated_curves_deformation(ob_eval, ob_orig); +} + } // namespace blender::bke::crazyspace diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc index 443e96a1ee0d..6a85e268bca6 100644 --- a/source/blender/blenkernel/intern/curve.cc +++ b/source/blender/blenkernel/intern/curve.cc @@ -2097,10 +2097,10 @@ static void bevel_list_calc_bisect(BevList *bl) } /* In the unlikely situation that handles define a zeroed direction, - * calculate it from the adjacent points, see T80742. + * calculate it from the adjacent points, see #80742. * * Only do this as a fallback since we typically want the end-point directions - * to be exactly aligned with the handles at the end-point, see T83117. */ + * to be exactly aligned with the handles at the end-point, see #83117. */ if (is_cyclic == false) { bevp0 = &bl->bevpoints[0]; bevp1 = &bl->bevpoints[1]; @@ -2252,7 +2252,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl) float q[4]; const bool is_cyclic = bl->poly != -1; /* NOTE(@ideasman42): For non-cyclic curves only initialize the first direction - * (via `vec_to_quat`), necessary for symmetry, see T71137. + * (via `vec_to_quat`), necessary for symmetry, see #71137. * Otherwise initialize the first and second points before propagating rotation forward. * This is historical as changing this can cause significantly different output. * Specifically: `deform_modifiers` test: (`CurveMeshDeform`). @@ -2906,7 +2906,7 @@ void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, const bool for_ continue; } - /* Scale the threshold so high resolution shapes don't get over reduced, see: T49850. */ + /* Scale the threshold so high resolution shapes don't get over reduced, see: #49850. */ const float threshold_resolu = 0.00001f / resolu; const bool is_cyclic = bl->poly != -1; nr = bl->nr; @@ -3284,7 +3284,7 @@ static void calchandleNurb_intern(BezTriple *bezt, } if (skip_align || - /* When one handle is free, aligning makes no sense, see: T35952 */ + /* When one handle is free, aligning makes no sense, see: #35952 */ ELEM(HD_FREE, bezt->h1, bezt->h2) || /* Also when no handles are aligned, skip this step. */ (!ELEM(HD_ALIGN, bezt->h1, bezt->h2) && !ELEM(HD_ALIGN_DOUBLESIDE, bezt->h1, bezt->h2))) { diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index d49bc0435685..ccecfadb474d 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -120,7 +120,7 @@ static void fill_mesh_topology(const int vert_offset, } } - const bool has_caps = fill_caps && !main_cyclic && profile_cyclic; + const bool has_caps = fill_caps && !main_cyclic && profile_cyclic && profile_point_num > 2; if (has_caps) { const int poly_num = main_segment_num * profile_segment_num; const int cap_loop_offset = loop_offset + poly_num * 4; @@ -271,7 +271,7 @@ static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool const int profile_point_num = profile_offsets.size(i_profile); const int profile_segment_num = curves::segments_num(profile_point_num, profile_cyclic); - const bool has_caps = fill_caps && !main_cyclic && profile_cyclic; + const bool has_caps = fill_caps && !main_cyclic && profile_cyclic && profile_point_num > 2; const int tube_face_num = main_segment_num * profile_segment_num; vert_offset += main_point_num * profile_point_num; diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index f6fb6cf4d870..704bbb34f49b 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -605,17 +605,15 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const Span CurvesGeometry::evaluated_positions() const { const bke::CurvesGeometryRuntime &runtime = *this->runtime; + if (this->is_single_type(CURVE_TYPE_POLY)) { + runtime.evaluated_position_cache.ensure( + [&](Vector &r_data) { r_data.clear_and_shrink(); }); + return this->positions(); + } this->ensure_nurbs_basis_cache(); - runtime.evaluated_position_cache.ensure([&](CurvesGeometryRuntime::EvaluatedPositions &r_data) { - if (this->is_single_type(CURVE_TYPE_POLY)) { - r_data.span = this->positions(); - r_data.vector.clear_and_shrink(); - return; - } - - r_data.vector.resize(this->evaluated_points_num()); - r_data.span = r_data.vector; - MutableSpan evaluated_positions = r_data.vector; + runtime.evaluated_position_cache.ensure([&](Vector &r_data) { + r_data.resize(this->evaluated_points_num()); + MutableSpan evaluated_positions = r_data; const OffsetIndices points_by_curve = this->points_by_curve(); const OffsetIndices evaluated_points_by_curve = this->evaluated_points_by_curve(); @@ -672,7 +670,7 @@ Span CurvesGeometry::evaluated_positions() const } }); }); - return runtime.evaluated_position_cache.data().span; + return runtime.evaluated_position_cache.data(); } Span CurvesGeometry::evaluated_tangents() const @@ -781,6 +779,7 @@ static void evaluate_generic_data_for_curve( Span CurvesGeometry::evaluated_normals() const { const bke::CurvesGeometryRuntime &runtime = *this->runtime; + this->ensure_nurbs_basis_cache(); runtime.evaluated_normal_cache.ensure([&](Vector &r_data) { const OffsetIndices points_by_curve = this->points_by_curve(); const OffsetIndices evaluated_points_by_curve = this->evaluated_points_by_curve(); diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 0e7e81a23836..eac61c6c5c3f 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -147,7 +147,7 @@ struct LayerTypeInfo { * \note in some cases \a dest pointer is in \a sources * so all functions have to take this into account and delay * applying changes while reading from sources. - * See bug T32395 - Campbell. + * See bug #32395 - Campbell. */ cd_interp interp; @@ -2991,6 +2991,19 @@ int CustomData_number_of_layers(const CustomData *data, const int type) return number; } +int CustomData_number_of_anonymous_layers(const CustomData *data, const int type) +{ + int number = 0; + + for (int i = 0; i < data->totlayer; i++) { + if (data->layers[i].type == type && data->layers[i].anonymous_id != nullptr) { + number++; + } + } + + return number; +} + int CustomData_number_of_layers_typemask(const CustomData *data, const eCustomDataMask mask) { int number = 0; @@ -3654,7 +3667,7 @@ void CustomData_bmesh_free_block_data(CustomData *data, void *block) } } -static void CustomData_bmesh_alloc_block(CustomData *data, void **block) +void CustomData_bmesh_alloc_block(CustomData *data, void **block) { if (*block) { CustomData_bmesh_free_block(data, block); @@ -3689,19 +3702,23 @@ void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data, } } -static void CustomData_bmesh_set_default_n(CustomData *data, void **block, const int n) +void CustomData_data_set_default_value(const int type, void *elem) { - int offset = data->layers[n].offset; - const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type); - + const LayerTypeInfo *typeInfo = layerType_getInfo(type); if (typeInfo->set_default_value) { - typeInfo->set_default_value(POINTER_OFFSET(*block, offset), 1); + typeInfo->set_default_value(elem, 1); } else { - memset(POINTER_OFFSET(*block, offset), 0, typeInfo->size); + memset(elem, 0, typeInfo->size); } } +static void CustomData_bmesh_set_default_n(CustomData *data, void **block, const int n) +{ + const int offset = data->layers[n].offset; + CustomData_data_set_default_value(data->layers[n].type, POINTER_OFFSET(*block, offset)); +} + void CustomData_bmesh_set_default(CustomData *data, void **block) { if (*block == nullptr) { @@ -3891,8 +3908,8 @@ void CustomData_data_copy_value(int type, const void *source, void *dest) return; } - if (typeInfo->copyvalue) { - typeInfo->copyvalue(source, dest, CDT_MIX_NOMIX, 0.0f); + if (typeInfo->copy) { + typeInfo->copy(source, dest, 1); } else { memcpy(dest, source, typeInfo->size); @@ -4067,115 +4084,6 @@ void CustomData_bmesh_interp(CustomData *data, } } -void CustomData_to_bmesh_block(const CustomData *source, - CustomData *dest, - int src_index, - void **dest_block, - bool use_default_init) -{ - if (*dest_block == nullptr) { - CustomData_bmesh_alloc_block(dest, dest_block); - } - - /* copies a layer at a time */ - int dest_i = 0; - for (int src_i = 0; src_i < source->totlayer; src_i++) { - - /* find the first dest layer with type >= the source type - * (this should work because layers are ordered by type) - */ - while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) { - if (use_default_init) { - CustomData_bmesh_set_default_n(dest, dest_block, dest_i); - } - dest_i++; - } - - /* if there are no more dest layers, we're done */ - if (dest_i >= dest->totlayer) { - break; - } - - /* if we found a matching layer, copy the data */ - if (dest->layers[dest_i].type == source->layers[src_i].type) { - int offset = dest->layers[dest_i].offset; - const void *src_data = source->layers[src_i].data; - void *dest_data = POINTER_OFFSET(*dest_block, offset); - - const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type); - const size_t src_offset = size_t(src_index) * typeInfo->size; - - if (typeInfo->copy) { - typeInfo->copy(POINTER_OFFSET(src_data, src_offset), dest_data, 1); - } - else { - memcpy(dest_data, POINTER_OFFSET(src_data, src_offset), typeInfo->size); - } - - /* if there are multiple source & dest layers of the same type, - * we don't want to copy all source layers to the same dest, so - * increment dest_i - */ - dest_i++; - } - } - - if (use_default_init) { - while (dest_i < dest->totlayer) { - CustomData_bmesh_set_default_n(dest, dest_block, dest_i); - dest_i++; - } - } -} - -void CustomData_from_bmesh_block(const CustomData *source, - CustomData *dest, - void *src_block, - int dest_index) -{ - /* copies a layer at a time */ - int dest_i = 0; - for (int src_i = 0; src_i < source->totlayer; src_i++) { - if (source->layers[src_i].flag & CD_FLAG_NOCOPY) { - continue; - } - - /* find the first dest layer with type >= the source type - * (this should work because layers are ordered by type) - */ - while (dest_i < dest->totlayer && dest->layers[dest_i].type < source->layers[src_i].type) { - dest_i++; - } - - /* if there are no more dest layers, we're done */ - if (dest_i >= dest->totlayer) { - return; - } - - /* if we found a matching layer, copy the data */ - if (dest->layers[dest_i].type == source->layers[src_i].type) { - const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type); - int offset = source->layers[src_i].offset; - const void *src_data = POINTER_OFFSET(src_block, offset); - void *dst_data = POINTER_OFFSET(dest->layers[dest_i].data, - size_t(dest_index) * typeInfo->size); - - if (typeInfo->copy) { - typeInfo->copy(src_data, dst_data, 1); - } - else { - memcpy(dst_data, src_data, typeInfo->size); - } - - /* if there are multiple source & dest layers of the same type, - * we don't want to copy all source layers to the same dest, so - * increment dest_i - */ - dest_i++; - } - } -} - void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num) { const LayerTypeInfo *typeInfo = layerType_getInfo(type); @@ -4356,7 +4264,7 @@ bool CustomData_verify_versions(CustomData *data, const int index) } /* This is a preemptive fix for cases that should not happen * (layers that should not be written in .blend files), - * but can happen due to bugs (see e.g. T62318). + * but can happen due to bugs (see e.g. #62318). * Also for forward compatibility, in future, * we may put into `.blend` file some currently un-written data types, * this should cover that case as well. @@ -4397,9 +4305,9 @@ static bool CustomData_layer_ensure_data_exists(CustomDataLayer *layer, size_t c switch (layer->type) { /* When more instances of corrupt files are found, add them here. */ - case CD_PROP_BOOL: /* See T84935. */ - case CD_MLOOPUV: /* See T90620. */ - case CD_PROP_FLOAT2: /* See T90620. */ + case CD_PROP_BOOL: /* See #84935. */ + case CD_MLOOPUV: /* See #90620. */ + case CD_PROP_FLOAT2: /* See #90620. */ layer->data = MEM_calloc_arrayN(count, typeInfo->size, layerType_getName(layer->type)); BLI_assert(layer->data); if (typeInfo->set_default_value) { @@ -5150,7 +5058,7 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int { BLO_read_data_address(reader, &data->layers); - /* Annoying workaround for bug T31079 loading legacy files with + /* Annoying workaround for bug #31079 loading legacy files with * no polygons _but_ have stale custom-data. */ if (UNLIKELY(count == 0 && data->layers == nullptr && data->totlayer != 0)) { CustomData_reset(data); @@ -5173,8 +5081,8 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int BLO_read_data_address(reader, &layer->data); if (CustomData_layer_ensure_data_exists(layer, count)) { /* Under normal operations, this shouldn't happen, but... - * For a CD_PROP_BOOL example, see T84935. - * For a CD_MLOOPUV example, see T90620. */ + * For a CD_PROP_BOOL example, see #84935. + * For a CD_MLOOPUV example, see #90620. */ CLOG_WARN(&LOG, "Allocated custom data layer that was not saved correctly for layer->type = %d.", layer->type); @@ -5308,7 +5216,7 @@ eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type) } // namespace blender::bke -size_t CustomData_get_elem_size(CustomDataLayer *layer) +size_t CustomData_get_elem_size(const CustomDataLayer *layer) { return LAYERTYPEINFO[layer->type].size; } diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc index 745db5e7fe58..49a2861afae1 100644 --- a/source/blender/blenkernel/intern/displist.cc +++ b/source/blender/blenkernel/intern/displist.cc @@ -1353,7 +1353,7 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph, * but it doesn't seem to work in this case. * * Since the plan is to replace this legacy curve object with the curves data-block - * (see T95355), this somewhat hacky inefficient solution is relatively temporary. + * (see #95355), this somewhat hacky inefficient solution is relatively temporary. */ Curve &cow_curve = *reinterpret_cast( BKE_id_copy_ex(nullptr, &original_curve.id, nullptr, LIB_ID_COPY_LOCALIZE)); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 3434f9bad4d6..6f03efe8137b 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -683,7 +683,7 @@ bool get_effector_data(EffectorCache *eff, bool ret = false; /* In case surface object is in Edit mode when loading the .blend, - * surface modifier is never executed and bvhtree never built, see T48415. */ + * surface modifier is never executed and bvhtree never built, see #48415. */ if (eff->pd && eff->pd->shape == PFIELD_SHAPE_SURFACE && eff->surmd && eff->surmd->runtime.bvhtree) { /* closest point in the object surface is an effector */ diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index d2550f9db0dd..304ac5c63a0e 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1903,10 +1903,10 @@ static float fcurve_eval_keyframes_interpolate(const FCurve *fcu, * * The threshold here has the following constraints: * - 0.001 is too coarse: - * We get artifacts with 2cm driver movements at 1BU = 1m (see T40332). + * We get artifacts with 2cm driver movements at 1BU = 1m (see #40332). * * - 0.00001 is too fine: - * Weird errors, like selecting the wrong keyframe range (see T39207), occur. + * Weird errors, like selecting the wrong keyframe range (see #39207), occur. * This lower bound was established in b888a32eee8147b028464336ad2404d8155c64dd. */ a = BKE_fcurve_bezt_binarysearch_index_ex(bezts, evaltime, fcu->totvert, 0.0001, &exact); @@ -1914,7 +1914,7 @@ static float fcurve_eval_keyframes_interpolate(const FCurve *fcu, if (exact) { /* Index returned must be interpreted differently when it sits on top of an existing keyframe - * - That keyframe is the start of the segment we need (see action_bug_2.blend in T39207). + * - That keyframe is the start of the segment we need (see action_bug_2.blend in #39207). */ return bezt->vec[1][1]; } @@ -1925,7 +1925,7 @@ static float fcurve_eval_keyframes_interpolate(const FCurve *fcu, const BezTriple *prevbezt = (a > 0) ? (bezt - 1) : bezt; /* Use if the key is directly on the frame, in rare cases this is needed else we get 0.0 instead. - * XXX: consult T39207 for examples of files where failure of these checks can cause issues. */ + * XXX: consult #39207 for examples of files where failure of these checks can cause issues. */ if (fabsf(bezt->vec[1][0] - evaltime) < eps) { return bezt->vec[1][1]; } @@ -1976,7 +1976,7 @@ static float fcurve_eval_keyframes_interpolate(const FCurve *fcu, if (fabsf(v1[1] - v4[1]) < FLT_EPSILON && fabsf(v2[1] - v3[1]) < FLT_EPSILON && fabsf(v3[1] - v4[1]) < FLT_EPSILON) { /* Optimization: If all the handles are flat/at the same values, - * the value is simply the shared value (see T40372 -> F91346). + * the value is simply the shared value (see #40372 -> F91346). */ return v1[1]; } @@ -2285,7 +2285,7 @@ float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, * XXX: additive is a bit more dicey; it really depends then if things are in range or not... */ LISTBASE_FOREACH (FModifier *, fcm, &fcu->modifiers) { - /* If there are range-restrictions, we must definitely block T36950. */ + /* If there are range-restrictions, we must definitely block #36950. */ if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 || (fcm->sfra <= evaltime && fcm->efra >= evaltime)) { /* Within range: here it probably doesn't matter, @@ -2507,7 +2507,7 @@ void BKE_fcurve_blend_read_data(BlendDataReader *reader, ListBase *fcurves) /* group */ BLO_read_data_address(reader, &fcu->grp); - /* clear disabled flag - allows disabled drivers to be tried again (T32155), + /* clear disabled flag - allows disabled drivers to be tried again (#32155), * but also means that another method for "reviving disabled F-Curves" exists */ fcu->flag &= ~FCURVE_DISABLED; @@ -2523,7 +2523,7 @@ void BKE_fcurve_blend_read_data(BlendDataReader *reader, ListBase *fcurves) driver->expr_simple = NULL; /* Give the driver a fresh chance - the operating environment may be different now - * (addons, etc. may be different) so the driver namespace may be sane now T32155. */ + * (addons, etc. may be different) so the driver namespace may be sane now #32155. */ driver->flag &= ~DRIVER_FLAG_INVALID; /* relink variables, targets and their paths */ diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c index 3d1439b5530e..5b4a67360047 100644 --- a/source/blender/blenkernel/intern/fcurve_driver.c +++ b/source/blender/blenkernel/intern/fcurve_driver.c @@ -472,8 +472,8 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) /* Check if object or bone, and get transform matrix accordingly: * - "use_eulers" code is used to prevent the problems associated with non-uniqueness - * of euler decomposition from matrices T20870. - * - "local-space" is for T21384, where parent results are not wanted + * of euler decomposition from matrices #20870. + * - "local-space" is for #21384, where parent results are not wanted * but #DTAR_FLAG_LOCAL_CONSTS is for all the common "corrective-shapes-for-limbs" situations. */ if (pchan) { diff --git a/source/blender/blenkernel/intern/fcurve_test.cc b/source/blender/blenkernel/intern/fcurve_test.cc index 285c6a0af4dc..66c4477ebc20 100644 --- a/source/blender/blenkernel/intern/fcurve_test.cc +++ b/source/blender/blenkernel/intern/fcurve_test.cc @@ -34,7 +34,7 @@ TEST(evaluate_fcurve, OnKeys) EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f), 13.0f, EPSILON); /* hits 'between' function */ EXPECT_NEAR(evaluate_fcurve(fcu, 3.0f), 19.0f, EPSILON); /* hits 'on or after last' function */ - /* Also test within a specific time epsilon of the keys, as this was an issue in T39207. + /* Also test within a specific time epsilon of the keys, as this was an issue in #39207. * This epsilon is just slightly smaller than the epsilon given to * BKE_fcurve_bezt_binarysearch_index_ex() in fcurve_eval_between_keyframes(), so it should hit * the "exact" code path. */ diff --git a/source/blender/blenkernel/intern/fluid.cc b/source/blender/blenkernel/intern/fluid.cc index 70a5c90269b3..769fc63f2bb2 100644 --- a/source/blender/blenkernel/intern/fluid.cc +++ b/source/blender/blenkernel/intern/fluid.cc @@ -215,7 +215,7 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds, # if 0 /* Note (sebbas): * Disabling this "skip section" as not copying borders results in weird cut-off effects. - * It is possible that this cutting off is the reason for line effects as seen in T74559. + * It is possible that this cutting off is the reason for line effects as seen in #74559. * Since domain borders will be handled on the simulation side anyways, * copying border values should not be an issue. */ @@ -3812,7 +3812,7 @@ static void fluid_modifier_processDomain(FluidModifierData *fmd, /* When reading data from cache (has_config == true) ensure that active fields are allocated. * update_flowsflags() and update_obstacleflags() will not find flow sources hidden from renders. - * See also: T72192. */ + * See also: #72192. */ if (has_config) { ensure_flowsfields(fds); ensure_obstaclefields(fds); @@ -4169,7 +4169,7 @@ Mesh *BKE_fluid_modifier_do( * This does not seem particularly useful, but it's backwards compatible. * * Smoke simulation needs a texture space relative to the adaptive domain bounds, not the - * original mesh. So recompute it at this point in the modifier stack. See T58492. */ + * original mesh. So recompute it at this point in the modifier stack. See #58492. */ BKE_mesh_texspace_calc(result); return result; diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc index e775a2a00a97..7401546c19d4 100644 --- a/source/blender/blenkernel/intern/geometry_component_curves.cc +++ b/source/blender/blenkernel/intern/geometry_component_curves.cc @@ -375,7 +375,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_FLOAT3, CD_PROP_FLOAT3, BuiltinAttributeProvider::NonCreatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::NonDeletable, point_access, make_array_read_attribute, @@ -387,7 +386,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_FLOAT, CD_PROP_FLOAT, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -399,7 +397,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_INT32, CD_PROP_INT32, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -411,7 +408,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_FLOAT, CD_PROP_FLOAT, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -423,7 +419,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_FLOAT3, CD_PROP_FLOAT3, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -435,7 +430,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_FLOAT3, CD_PROP_FLOAT3, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -453,7 +447,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_INT8, CD_PROP_INT8, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -466,7 +459,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_INT8, CD_PROP_INT8, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -479,7 +471,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_FLOAT, CD_PROP_FLOAT, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -495,7 +486,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_INT8, CD_PROP_INT8, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, curve_access, make_array_read_attribute, @@ -514,7 +504,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_INT8, CD_PROP_INT8, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, curve_access, make_array_read_attribute, @@ -533,7 +522,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_INT8, CD_PROP_INT8, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, curve_access, make_array_read_attribute, @@ -552,7 +540,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_INT8, CD_PROP_INT8, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, curve_access, make_array_read_attribute, @@ -569,7 +556,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_INT32, CD_PROP_INT32, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, curve_access, make_array_read_attribute, @@ -582,7 +568,6 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() CD_PROP_BOOL, CD_PROP_BOOL, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, curve_access, make_array_read_attribute, diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc index 25143bf20a0d..0c8c66206683 100644 --- a/source/blender/blenkernel/intern/geometry_component_instances.cc +++ b/source/blender/blenkernel/intern/geometry_component_instances.cc @@ -129,7 +129,7 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider public: InstancePositionAttributeProvider() : BuiltinAttributeProvider( - "position", ATTR_DOMAIN_INSTANCE, CD_PROP_FLOAT3, NonCreatable, Writable, NonDeletable) + "position", ATTR_DOMAIN_INSTANCE, CD_PROP_FLOAT3, NonCreatable, NonDeletable) { } @@ -200,7 +200,6 @@ static ComponentAttributeProviders create_attribute_providers_for_instances() CD_PROP_INT32, CD_PROP_INT32, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, instance_custom_data_access, make_array_read_attribute, diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index bdb1b0edf8bf..44697ca2a307 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -1137,48 +1137,6 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { } }; -/** - * This provider makes face normals available as a read-only float3 attribute. - */ -class NormalAttributeProvider final : public BuiltinAttributeProvider { - public: - NormalAttributeProvider() - : BuiltinAttributeProvider( - "normal", ATTR_DOMAIN_FACE, CD_PROP_FLOAT3, NonCreatable, Readonly, NonDeletable) - { - } - - GVArray try_get_for_read(const void *owner) const final - { - const Mesh *mesh = static_cast(owner); - if (mesh == nullptr || mesh->totpoly == 0) { - return {}; - } - return VArray::ForSpan({(float3 *)BKE_mesh_poly_normals_ensure(mesh), mesh->totpoly}); - } - - GAttributeWriter try_get_for_write(void * /*owner*/) const final - { - return {}; - } - - bool try_delete(void * /*owner*/) const final - { - return false; - } - - bool try_create(void * /*owner*/, const AttributeInit & /*initializer*/) const final - { - return false; - } - - bool exists(const void *owner) const final - { - const Mesh *mesh = static_cast(owner); - return mesh->totpoly != 0; - } -}; - /** * In this function all the attribute providers for a mesh component are created. Most data in this * function is statically allocated, because it does not change over time. @@ -1222,21 +1180,17 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() CD_PROP_FLOAT3, CD_PROP_FLOAT3, BuiltinAttributeProvider::NonCreatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::NonDeletable, point_access, make_array_read_attribute, make_array_write_attribute, tag_component_positions_changed); - static NormalAttributeProvider normal; - static BuiltinCustomDataLayerProvider id("id", ATTR_DOMAIN_POINT, CD_PROP_INT32, CD_PROP_INT32, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -1255,7 +1209,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() CD_PROP_INT32, CD_PROP_INT32, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, face_access, make_array_read_attribute, @@ -1269,7 +1222,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() CD_PROP_BOOL, CD_MPOLY, BuiltinAttributeProvider::NonCreatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::NonDeletable, face_access, make_derived_read_attribute, @@ -1281,7 +1233,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() CD_PROP_BOOL, CD_PROP_BOOL, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, edge_access, make_array_read_attribute, @@ -1294,7 +1245,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() CD_PROP_FLOAT, CD_CREASE, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, edge_access, make_array_read_attribute, @@ -1308,7 +1258,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() static CustomDataAttributeProvider face_custom_data(ATTR_DOMAIN_FACE, face_access); return ComponentAttributeProviders( - {&position, &id, &material_index, &shade_smooth, &sharp_edge, &normal, &crease}, + {&position, &id, &material_index, &shade_smooth, &sharp_edge, &crease}, {&corner_custom_data, &vertex_groups, &point_custom_data, diff --git a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc index 71484bbd5f04..41966fe868a6 100644 --- a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc +++ b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc @@ -142,7 +142,6 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud() CD_PROP_FLOAT3, CD_PROP_FLOAT3, BuiltinAttributeProvider::NonCreatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::NonDeletable, point_access, make_array_read_attribute, @@ -153,7 +152,6 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud() CD_PROP_FLOAT, CD_PROP_FLOAT, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, @@ -164,7 +162,6 @@ static ComponentAttributeProviders create_attribute_providers_for_point_cloud() CD_PROP_INT32, CD_PROP_INT32, BuiltinAttributeProvider::Creatable, - BuiltinAttributeProvider::Writable, BuiltinAttributeProvider::Deletable, point_access, make_array_read_attribute, diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index 5e8a2cad99e8..7d25e5249282 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -313,7 +313,7 @@ static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data) if (result) { if (flag & BKE_BPATH_FOREACH_PATH_RELOAD_EDITED) { if (!BKE_image_has_packedfile(ima) && - /* Image may have been painted onto (and not saved, T44543). */ + /* Image may have been painted onto (and not saved, #44543). */ !BKE_image_is_dirty(ima)) { BKE_image_signal(bpath_data->bmain, ima, nullptr, IMA_SIGNAL_RELOAD); } diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index 7d835c2464d9..7a9ef93734bc 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -1875,7 +1875,7 @@ KeyBlock *BKE_keyblock_add_ctime(Key *key, const char *name, const bool do_force /* In case of absolute keys, there is no point in adding more than one key with the same pos. * Hence only set new key-block pos to current time if none previous one already use it. * Now at least people just adding absolute keys without touching to ctime - * won't have to systematically use retiming func (and have ordering issues, too). See T39897. + * won't have to systematically use retiming func (and have ordering issues, too). See #39897. */ if (!do_force && (key->type != KEY_RELATIVE)) { KeyBlock *it_kb; diff --git a/source/blender/blenkernel/intern/layer.cc b/source/blender/blenkernel/intern/layer.cc index 9e452662055c..ee6290027adc 100644 --- a/source/blender/blenkernel/intern/layer.cc +++ b/source/blender/blenkernel/intern/layer.cc @@ -765,7 +765,7 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection * regarding this resync process. * Proper fix would be to make resync itself lazy, i.e. only happen * when actually needed. - * See also T73411. + * See also #73411. * \{ */ static bool no_resync = false; diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index fcf585dfcfc5..d09511ec4b3a 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -1810,7 +1810,7 @@ void BKE_library_make_local(Main *bmain, /* Step 4: We have to remap local usages of old (linked) ID to new (local) * ID in a separated loop, * as lbarray ordering is not enough to ensure us we did catch all dependencies - * (e.g. if making local a parent object before its child...). See T48907. */ + * (e.g. if making local a parent object before its child...). See #48907. */ /* TODO: This is now the biggest step by far (in term of processing time). * We may be able to gain here by using again main->relations mapping, but... * this implies BKE_libblock_remap & co to be able to update main->relations on the fly. @@ -1828,7 +1828,7 @@ void BKE_library_make_local(Main *bmain, /* Special hack for groups... Thing is, since we can't instantiate them here, we need to * ensure they remain 'alive' (only instantiation is a real group 'user'... *sigh* See - * T49722. */ + * #49722. */ if (GS(id->name) == ID_GR && (id->tag & LIB_TAG_INDIRECT) != 0) { id_us_ensure_real(id->newid); } diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc index 8a9440a8e321..065ee010e727 100644 --- a/source/blender/blenkernel/intern/lib_override.cc +++ b/source/blender/blenkernel/intern/lib_override.cc @@ -396,7 +396,7 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain, ID *local_id = lib_override_library_create_from(bmain, nullptr, reference_id, 0); /* We cannot allow automatic hierarchy resync on this ID, it is highly likely to generate a giant * mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies. - * Ref T94650. */ + * Ref #94650. */ local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY; local_id->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED; local_id->override_library->hierarchy_root = local_id; @@ -2105,7 +2105,7 @@ static bool lib_override_library_resync(Main *bmain, if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && id->override_library->reference->lib->id.tag & LIB_TAG_MISSING) { /* Do not delete overrides which reference is missing because the library itself is missing - * (ref. T100586). */ + * (ref. #100586). */ } else if (!BKE_lib_override_library_is_user_edited(id)) { /* If user never edited them, we can delete them. */ @@ -2720,7 +2720,7 @@ void BKE_lib_override_library_main_resync(Main *bmain, /* Necessary to improve performances, and prevent layers matching override sub-collections to be * lost when re-syncing the parent override collection. - * Ref. T73411. */ + * Ref. #73411. */ BKE_layer_collection_resync_forbid(); int library_indirect_level = lib_override_libraries_index_define(bmain); diff --git a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c index 88f6fbb0ead5..deb75441b542 100644 --- a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c +++ b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c @@ -45,7 +45,7 @@ bool BKE_lib_override_library_proxy_convert(Main *bmain, &ob_proxy->proxy->id; ID *id_instance_hint = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id; - /* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not + /* In some cases the instance collection of a proxy object may be local (see e.g. #83875). Not * sure this is a valid state, but for now just abort the overriding process. */ if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(id_root)) { if (ob_proxy->proxy != NULL) { @@ -73,7 +73,7 @@ bool BKE_lib_override_library_proxy_convert(Main *bmain, /* In case of proxy conversion, remap all local ID usages to linked IDs to their newly created * overrides. Also do that for the IDs from the same lib as the proxy in case it is linked. * While this might not be 100% the desired behavior, it is likely to be the case most of the - * time. Ref: T91711. */ + * time. Ref: #91711. */ ID *id_iter; FOREACH_MAIN_ID_BEGIN (bmain, id_iter) { if (!ID_IS_LINKED(id_iter) || id_iter->lib == ob_proxy->id.lib) { diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index 124ba21d4065..4d6b78e67c4a 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -165,7 +165,7 @@ void BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp) } else if (flag & IDWALK_RECURSE) { /* Defer handling into main loop, recursively calling BKE_library_foreach_ID_link in - * IDWALK_RECURSE case is troublesome, see T49553. */ + * IDWALK_RECURSE case is troublesome, see #49553. */ /* XXX note that this breaks the 'owner id' thing now, we likely want to handle that * differently at some point, but for now it should not be a problem in practice. */ if (BLI_gset_add(data->ids_handled, id)) { diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index 127459508c20..4ef3bdabfaa4 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -608,7 +608,7 @@ static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_ /* Node trees may virtually use any kind of data-block... */ /* XXX Yuck!!!! nodetree update can do pretty much any thing when talking about py nodes, - * including creating new data-blocks (see T50385), so we need to unlock main here. :( + * including creating new data-blocks (see #50385), so we need to unlock main here. :( * Why can't we have re-entrent locks? */ BKE_main_unlock(bmain); libblock_remap_data_postprocess_nodetree_update(bmain, new_id); diff --git a/source/blender/blenkernel/intern/material.cc b/source/blender/blenkernel/intern/material.cc index 941485f9cbc3..b34e92837a9e 100644 --- a/source/blender/blenkernel/intern/material.cc +++ b/source/blender/blenkernel/intern/material.cc @@ -877,7 +877,7 @@ void BKE_object_materials_test(Main *bmain, Object *ob, ID *id) /* Exception: In case the object is a valid data, but its obdata is an empty place-holder, * use object's material slots amount as reference. * This avoids losing materials in a local object when its linked obdata goes missing. - * See T92780. */ + * See #92780. */ BKE_id_material_resize(bmain, id, short(ob->totcol), false); } else { @@ -1311,7 +1311,7 @@ bool BKE_object_material_slot_remove(Main *bmain, Object *ob) for (Object *obt = static_cast(bmain->objects.first); obt; obt = static_cast(obt->id.next)) { if (obt->data == ob->data) { - /* Can happen when object material lists are used, see: T52953 */ + /* Can happen when object material lists are used, see: #52953 */ if (actcol > obt->totcol) { continue; } diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index ee1129f6b4ba..5b4c4edd0a28 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -907,7 +907,7 @@ void BKE_mesh_free_data_for_undo(Mesh *me) * * - Edit-Mesh (#Mesh.edit_mesh) * Since edit-mesh is tied to the objects mode, - * which crashes when called in edit-mode, see: T90972. + * which crashes when called in edit-mode, see: #90972. */ static void mesh_clear_geometry(Mesh *mesh) { diff --git a/source/blender/blenkernel/intern/mesh_calc_edges.cc b/source/blender/blenkernel/intern/mesh_calc_edges.cc index 033a52081baf..f186d89a4e58 100644 --- a/source/blender/blenkernel/intern/mesh_calc_edges.cc +++ b/source/blender/blenkernel/intern/mesh_calc_edges.cc @@ -176,7 +176,7 @@ static void update_edge_indices_in_poly_loops(Mesh *mesh, else { /* This is an invalid edge; normally this does not happen in Blender, * but it can be part of an imported mesh with invalid geometry. See - * T76514. */ + * #76514. */ edge_index = 0; } prev_loop->e = edge_index; diff --git a/source/blender/blenkernel/intern/mesh_evaluate.cc b/source/blender/blenkernel/intern/mesh_evaluate.cc index 3c25cd2e07e4..d6f40a472de5 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.cc +++ b/source/blender/blenkernel/intern/mesh_evaluate.cc @@ -154,7 +154,7 @@ static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MPoly *mpoly, /** * A version of mesh_calc_poly_volume_centroid that takes an initial reference center, * use this to increase numeric stability as the quality of the result becomes - * very low quality as the value moves away from 0.0, see: T65986. + * very low quality as the value moves away from 0.0, see: #65986. */ static float mesh_calc_poly_volume_centroid_with_reference_center(const MPoly *mpoly, const MLoop *loopstart, diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index dee96b42e57a..92197800aeaf 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -651,7 +651,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) { if (UNLIKELY((me->totface != 0) && (me->totpoly == 0))) { /* Pass, otherwise this function clears 'mface' before - * versioning 'mface -> mpoly' code kicks in T30583. + * versioning 'mface -> mpoly' code kicks in #30583. * * Callers could also check but safer to do here - campbell */ } diff --git a/source/blender/blenkernel/intern/mesh_mirror.cc b/source/blender/blenkernel/intern/mesh_mirror.cc index 95f8008a4f91..3c603a5a1f3b 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.cc +++ b/source/blender/blenkernel/intern/mesh_mirror.cc @@ -161,7 +161,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, copy_v3_v3(plane_co, itmp[3]); copy_v3_v3(plane_no, itmp[axis]); - /* Account for non-uniform scale in `ob`, see: T87592. */ + /* Account for non-uniform scale in `ob`, see: #87592. */ float ob_scale[3] = { len_squared_v3(ob->object_to_world[0]), len_squared_v3(ob->object_to_world[1]), @@ -248,7 +248,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, * generate a 1:1 mapping by scanning vertices from the beginning of the array * as is done in #BKE_editmesh_vert_coords_when_deformed. Without this, * the coordinates returned will sometimes point to the copied vertex locations, see: - * T91444. + * #91444. * * However, such a change also affects non-versionable things like some modifiers binding, so * we cannot enforce that behavior on existing modifiers, in which case we keep using the diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 22b6ce5222cb..c83de7a843ae 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -1749,7 +1749,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3], /* We also have to check between last and first loops, * otherwise we may miss some sharp edges here! * This is just a simplified version of above while loop. - * See T45984. */ + * See #45984. */ loops = lnors_spacearr.lspacearr[i]->loops; if (loops && org_nor) { const int lidx = POINTER_AS_INT(loops->link); diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index 5f3961398fbe..8c25315ab19b 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -1666,7 +1666,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, if (dot > best_nor_dot - 1e-6f) { /* We need something as fallback decision in case dest normal matches several - * source normals (see T44522), using distance between polys' centers here. */ + * source normals (see #44522), using distance between polys' centers here. */ float *pcent_src; float sqdist; diff --git a/source/blender/blenkernel/intern/modifier.cc b/source/blender/blenkernel/intern/modifier.cc index 580c08a51ba6..e82e9c0f559a 100644 --- a/source/blender/blenkernel/intern/modifier.cc +++ b/source/blender/blenkernel/intern/modifier.cc @@ -1045,7 +1045,7 @@ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval) if ((ob_eval->type == OB_MESH) && (ob_eval->mode & OB_MODE_EDIT)) { /* In EditMode, evaluated mesh is stored in BMEditMesh, not the object... */ BMEditMesh *em = BKE_editmesh_from_object(ob_eval); - /* 'em' might not exist yet in some cases, just after loading a .blend file, see T57878. */ + /* 'em' might not exist yet in some cases, just after loading a .blend file, see #57878. */ if (em != nullptr) { me = BKE_object_get_editmesh_eval_final(ob_eval); } diff --git a/source/blender/blenkernel/intern/multires_reshape_ccg.cc b/source/blender/blenkernel/intern/multires_reshape_ccg.cc index 97be97ae3c1f..94751a37fc5d 100644 --- a/source/blender/blenkernel/intern/multires_reshape_ccg.cc +++ b/source/blender/blenkernel/intern/multires_reshape_ccg.cc @@ -64,7 +64,7 @@ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext * used by sculpt changes. In other use cases the code might not catch inconsistency and * silently do wrong decision. */ /* NOTE: There is a known bug in Undo code that results in first Sculpt step - * after a Memfile one to never be undone (see T83806). This might be the root cause of + * after a Memfile one to never be undone (see #83806). This might be the root cause of * this inconsistency. */ if (reshape_level_key.has_mask && grid_element.mask != nullptr) { *grid_element.mask = *CCG_grid_elem_mask(&reshape_level_key, ccg_grid, x, y); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 6b631462ebdb..2dbab08ef20b 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -61,7 +61,7 @@ static void nla_tweakmode_find_active(const ListBase /* NlaTrack */ *nla_tracks, /* Freeing ------------------------------------------- */ -void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user) +void BKE_nlastrip_free(NlaStrip *strip, const bool do_id_user) { NlaStrip *cs, *csn; @@ -73,7 +73,7 @@ void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user) /* free child-strips */ for (cs = strip->strips.first; cs; cs = csn) { csn = cs->next; - BKE_nlastrip_free(&strip->strips, cs, do_id_user); + BKE_nlastrip_remove_and_free(&strip->strips, cs, do_id_user); } /* remove reference to action */ @@ -81,10 +81,6 @@ void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user) id_us_min(&strip->act->id); } - /* free remapping info */ - // if (strip->remap) - // BKE_animremap_free(); - /* free own F-Curves */ BKE_fcurves_free(&strip->fcurves); @@ -92,15 +88,10 @@ void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user) free_fmodifiers(&strip->modifiers); /* free the strip itself */ - if (strips) { - BLI_freelinkN(strips, strip); - } - else { - MEM_freeN(strip); - } + MEM_freeN(strip); } -void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user) +void BKE_nlatrack_free(NlaTrack *nlt, const bool do_id_user) { NlaStrip *strip, *stripn; @@ -112,16 +103,11 @@ void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user) /* free strips */ for (strip = nlt->strips.first; strip; strip = stripn) { stripn = strip->next; - BKE_nlastrip_free(&nlt->strips, strip, do_id_user); + BKE_nlastrip_remove_and_free(&nlt->strips, strip, do_id_user); } /* free NLA track itself now */ - if (tracks) { - BLI_freelinkN(tracks, nlt); - } - else { - MEM_freeN(nlt); - } + MEM_freeN(nlt); } void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user) @@ -136,7 +122,7 @@ void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user) /* free tracks one by one */ for (nlt = tracks->first; nlt; nlt = nltn) { nltn = nlt->next; - BKE_nlatrack_free(tracks, nlt, do_id_user); + BKE_nlatrack_remove_and_free(tracks, nlt, do_id_user); } /* clear the list's pointers to be safe */ @@ -523,6 +509,20 @@ void BKE_nla_strip_foreach_id(NlaStrip *strip, LibraryForeachIDData *data) } } +/* Removing ------------------------------------------ */ + +void BKE_nlatrack_remove(ListBase *tracks, struct NlaTrack *nlt) +{ + BLI_assert(tracks); + BLI_remlink(tracks, nlt); +} + +void BKE_nlatrack_remove_and_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user) +{ + BKE_nlatrack_remove(tracks, nlt); + BKE_nlatrack_free(nlt, do_id_user); +} + /* *************************************************** */ /* NLA Evaluation <-> Editing Stuff */ @@ -875,7 +875,7 @@ void BKE_nlastrips_clear_metastrip(ListBase *strips, NlaStrip *strip) } /* free the meta-strip now */ - BKE_nlastrip_free(strips, strip, true); + BKE_nlastrip_remove_and_free(strips, strip, true); } void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp) @@ -1190,6 +1190,12 @@ bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, const bool is_libove return BKE_nlastrips_add_strip(&nlt->strips, strip); } +void BKE_nlatrack_remove_strip(NlaTrack *track, NlaStrip *strip) +{ + BLI_assert(track); + BKE_nlastrip_remove(&track->strips, strip); +} + bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2]) { NlaStrip *strip; @@ -1318,6 +1324,18 @@ NlaStrip *BKE_nlastrip_find_active(NlaTrack *nlt) return nlastrip_find_active(&nlt->strips); } +void BKE_nlastrip_remove(ListBase *strips, NlaStrip *strip) +{ + BLI_assert(strips); + BLI_remlink(strips, strip); +} + +void BKE_nlastrip_remove_and_free(ListBase *strips, NlaStrip *strip, const bool do_id_user) +{ + BKE_nlastrip_remove(strips, strip); + BKE_nlastrip_free(strip, do_id_user); +} + void BKE_nlastrip_set_active(AnimData *adt, NlaStrip *strip) { NlaTrack *nlt; @@ -2009,8 +2027,7 @@ void BKE_nla_action_pushdown(AnimData *adt, const bool is_liboverride) /* copy current "action blending" settings from adt to the strip, * as it was keyframed with these settings, so omitting them will - * change the effect [T54233] - */ + * change the effect [#54233]. */ strip->blendmode = adt->act_blendmode; strip->influence = adt->act_influence; strip->extendmode = adt->act_extendmode; @@ -2058,7 +2075,7 @@ static void nla_tweakmode_find_active(const ListBase /* NlaTrack */ *nla_tracks, /* There are situations where we may have multiple strips selected and we want to enter * tweak-mode on all of those at once. Usually in those cases, * it will usually just be a single strip per AnimData. - * In such cases, compromise and take the last selected track and/or last selected strip, T28468. + * In such cases, compromise and take the last selected track and/or last selected strip, #28468. */ if (activeTrack == NULL) { /* try last selected track for active strip */ @@ -2178,7 +2195,7 @@ void BKE_nla_tweakmode_exit(AnimData *adt) /* sync the length of the user-strip with the new state of the action * but only if the user has explicitly asked for this to happen - * (see T34645 for things to be careful about) + * (see #34645 for things to be careful about) */ if ((adt->actstrip) && (adt->actstrip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) { strip = adt->actstrip; diff --git a/source/blender/blenkernel/intern/nla_test.cc b/source/blender/blenkernel/intern/nla_test.cc index ef9ca83e25f2..401d846eb11e 100644 --- a/source/blender/blenkernel/intern/nla_test.cc +++ b/source/blender/blenkernel/intern/nla_test.cc @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-or-later * Copyright 2023 Blender Foundation. All rights reserved. */ +#include "BLI_listbase.h" + #include "BKE_nla.h" #include "DNA_anim_types.h" @@ -20,19 +22,19 @@ TEST(nla_strip, BKE_nlastrip_recalculate_blend) strip.start = 1; strip.end = 10; - /* Scaling a strip up doesn't affect the blend in/out value */ + /* Scaling a strip up doesn't affect the blend in/out value. */ strip.end = 20; BKE_nlastrip_recalculate_blend(&strip); EXPECT_FLOAT_EQ(strip.blendin, 4.0); EXPECT_FLOAT_EQ(strip.blendout, 5.0); - /* Scaling a strip down affects the blend-in value before the blend-out value */ + /* Scaling a strip down affects the blend-in value before the blend-out value. */ strip.end = 7; BKE_nlastrip_recalculate_blend(&strip); EXPECT_FLOAT_EQ(strip.blendin, 1.0); EXPECT_FLOAT_EQ(strip.blendout, 5.0); - /* Scaling a strip down to nothing updates the blend in/out values accordingly */ + /* Scaling a strip down to nothing updates the blend in/out values accordingly. */ strip.end = 1.1; BKE_nlastrip_recalculate_blend(&strip); EXPECT_FLOAT_EQ(strip.blendin, 0.0); @@ -63,4 +65,55 @@ TEST(nla_strip, BKE_nlastrips_add_strip) EXPECT_TRUE(BKE_nlastrips_add_strip(&strips, &strip2)); } +TEST(nla_track, BKE_nlatrack_remove_strip) +{ + NlaTrack track{}; + ListBase strips{}; + NlaStrip strip1{}; + strip1.start = 0; + strip1.end = 10; + + NlaStrip strip2{}; + strip2.start = 11; + strip2.end = 20; + + // Add NLA strips to the NLATrack. + BKE_nlastrips_add_strip(&strips, &strip1); + BKE_nlastrips_add_strip(&strips, &strip2); + track.strips = strips; + + // ensure we have 2 strips in the track. + EXPECT_EQ(2, BLI_listbase_count(&track.strips)); + + BKE_nlatrack_remove_strip(&track, &strip2); + EXPECT_EQ(1, BLI_listbase_count(&track.strips)); + // ensure the correct strip was removed. + EXPECT_EQ(-1, BLI_findindex(&track.strips, &strip2)); +} + +TEST(nla_track, BKE_nlatrack_remove_and_free) +{ + AnimData adt{}; + NlaTrack *track1; + NlaTrack *track2; + + // Add NLA tracks to the Animation Data. + track1 = BKE_nlatrack_add(&adt, NULL, false); + track2 = BKE_nlatrack_add(&adt, track1, false); + + // ensure we have 2 tracks in the track. + EXPECT_EQ(2, BLI_listbase_count(&adt.nla_tracks)); + + BKE_nlatrack_remove_and_free(&adt.nla_tracks, track2, false); + EXPECT_EQ(1, BLI_listbase_count(&adt.nla_tracks)); + + // ensure the correct track was removed. + EXPECT_EQ(-1, BLI_findindex(&adt.nla_tracks, track2)); + + // free the rest of the tracks, and ensure they are removed. + BKE_nlatrack_remove_and_free(&adt.nla_tracks, track1, false); + EXPECT_EQ(0, BLI_listbase_count(&adt.nla_tracks)); + EXPECT_EQ(-1, BLI_findindex(&adt.nla_tracks, track1)); +} + } // namespace blender::bke::tests diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 0d18709a6d67..7c3055c41e56 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -406,7 +406,7 @@ static ID **node_owner_pointer_get(ID *id) if ((id->flag & LIB_EMBEDDED_DATA) == 0) { return nullptr; } - /* TODO: Sort this NO_MAIN or not for embedded node trees. See T86119. */ + /* TODO: Sort this NO_MAIN or not for embedded node trees. See #86119. */ // BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0); bNodeTree *ntree = reinterpret_cast(id); @@ -542,7 +542,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) /* pass */ } else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_GLARE)) { - /* Simple forward compatibility for fix for T50736. + /* Simple forward compatibility for fix for #50736. * Not ideal (there is no ideal solution here), but should do for now. */ NodeGlare *ndg = (NodeGlare *)node->storage; /* Not in undo case. */ @@ -838,7 +838,7 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock IDP_BlendReadLib(reader, lib, sock->prop); /* This can happen for all socket types when a file is saved in an older version of Blender than - * it was originally created in (T86298). Some socket types still require a default value. The + * it was originally created in (#86298). Some socket types still require a default value. The * default value of those sockets will be created in `ntreeSetTypes`. */ if (sock->default_value == nullptr) { return; @@ -3109,7 +3109,7 @@ static void free_localized_node_groups(bNodeTree *ntree) /* Only localized node trees store a copy for each node group tree. * Each node group tree in a localized node tree can be freed, * since it is a localized copy itself (no risk of accessing free'd - * data in main, see T37939). */ + * data in main, see #37939). */ if (!(ntree->id.tag & LIB_TAG_LOCALIZED)) { return; } diff --git a/source/blender/blenkernel/intern/node_tree_field_inferencing.cc b/source/blender/blenkernel/intern/node_tree_field_inferencing.cc index af2824856713..abe5f736ebad 100644 --- a/source/blender/blenkernel/intern/node_tree_field_inferencing.cc +++ b/source/blender/blenkernel/intern/node_tree_field_inferencing.cc @@ -119,7 +119,7 @@ static const FieldInferencingInterface &get_node_field_inferencing_interface(con return empty_interface; } if (!ntreeIsRegistered(group)) { - /* This can happen when there is a linked node group that was not found (see T92799). */ + /* This can happen when there is a linked node group that was not found (see #92799). */ return get_dummy_field_inferencing_interface(node, scope); } if (!group->runtime->field_inferencing_interface) { diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index 984de28394f3..97114c6c6241 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -622,7 +622,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id) const bool is_undo = BLO_read_data_is_undo(reader); if (ob->id.tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT)) { /* Do not allow any non-object mode for linked data. - * See T34776, T42780, T81027 for more information. */ + * See #34776, #42780, #81027 for more information. */ ob->mode &= ~OB_MODE_ALL_MODE_DATA; } else if (is_undo) { @@ -939,7 +939,7 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id) } /* When the object is local and the data is library its possible - * the material list size gets out of sync. T22663. */ + * the material list size gets out of sync. #22663. */ if (ob->data && ob->id.lib != ((ID *)ob->data)->lib) { BKE_object_materials_test(bmain, ob, (ID *)ob->data); } @@ -3151,7 +3151,7 @@ static bool ob_parcurve(Object *ob, Object *par, float r_mat[4][4]) * dependency cycles. We can't correct anything from here, since that would * cause threading conflicts. * - * TODO(sergey): Some of the legit looking cases like T56619 need to be + * TODO(sergey): Some of the legit looking cases like #56619 need to be * looked into, and maybe curve cache (and other dependencies) are to be * evaluated prior to conversion. */ if (par->runtime.curve_cache == nullptr) { @@ -3556,7 +3556,7 @@ void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *o * are supposed to be applied after the object's local loc/rot/scale. If the (inverted) effect of * constraints would be included in the parent inverse matrix, these would be applied before the * object's local loc/rot/scale instead of after. For example, a "Copy Rotation" constraint would - * rotate the object's local translation as well. See T82156. */ + * rotate the object's local translation as well. See #82156. */ BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr)); diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 76120e66e826..fbd3e31140d6 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -265,7 +265,7 @@ static DupliObject *make_dupli(const DupliContext *ctx, /* Store geometry set data for attribute lookup in innermost to outermost * order, copying only non-null entries to save space. */ - const int max_instance = sizeof(dob->instance_data) / sizeof(void *); + const int max_instance = ARRAY_SIZE(dob->instance_data); int next_instance = 0; if (geometry != nullptr) { dob->instance_idx[next_instance] = int(instance_index); @@ -1535,7 +1535,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } if (part->ren_as == PART_DRAW_GR) { - /* Prevent divide by zero below T28336. */ + /* Prevent divide by zero below #28336. */ if (totcollection == 0) { continue; } @@ -1821,7 +1821,7 @@ static bool find_geonode_attribute_rgba(const DupliObject *dupli, using namespace blender; /* Loop over layers from innermost to outermost. */ - for (const int i : IndexRange(sizeof(dupli->instance_data) / sizeof(void *))) { + for (const int i : IndexRange(ARRAY_SIZE(dupli->instance_data))) { /* Skip non-geonode layers. */ if (dupli->instance_data[i] == nullptr) { continue; diff --git a/source/blender/blenkernel/intern/object_update.cc b/source/blender/blenkernel/intern/object_update.cc index 5abd5188d1ef..e5bb1b529df8 100644 --- a/source/blender/blenkernel/intern/object_update.cc +++ b/source/blender/blenkernel/intern/object_update.cc @@ -149,7 +149,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o cddata_masks.pmask |= CD_MASK_PROP_ALL; cddata_masks.lmask |= CD_MASK_PROP_ALL; - /* Make sure Freestyle edge/face marks appear in DM for render (see T40315). + /* Make sure Freestyle edge/face marks appear in DM for render (see #40315). * Due to Line Art implementation, edge marks should also be shown in viewport. */ #ifdef WITH_FREESTYLE cddata_masks.emask |= CD_MASK_FREESTYLE_EDGE; diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 0c9d9f5b048f..4399a65276a0 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -878,7 +878,7 @@ void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p) BLO_read_packed_address(reader, &pf->data); if (pf->data == NULL) { /* We cannot allow a PackedFile with a NULL data field, - * the whole code assumes this is not possible. See T70315. */ + * the whole code assumes this is not possible. See #70315. */ printf("%s: NULL packedfile data, cleaning up...\n", __func__); MEM_SAFE_FREE(pf); } diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 0ee517311d2c..3ec6525ac6b3 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1424,7 +1424,7 @@ void BKE_sculptsession_bm_to_me(Object *ob, bool reorder) sculptsession_bm_to_me_update_data_only(ob, reorder); /* Ensure the objects evaluated mesh doesn't hold onto arrays - * now realloc'd in the mesh T34473. */ + * now realloc'd in the mesh #34473. */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } } diff --git a/source/blender/blenkernel/intern/particle.cc b/source/blender/blenkernel/intern/particle.cc index fc350c1838a4..28be787a1914 100644 --- a/source/blender/blenkernel/intern/particle.cc +++ b/source/blender/blenkernel/intern/particle.cc @@ -847,7 +847,7 @@ void psys_find_group_weights(ParticleSettings *part) { /* Find object pointers based on index. If the collection is linked from * another library linking may not have the object pointers available on - * file load, so we have to retrieve them later. See T49273. */ + * file load, so we have to retrieve them later. See #49273. */ ListBase instance_collection_objects = {nullptr, nullptr}; if (part->instance_collection) { @@ -3035,7 +3035,7 @@ static void psys_thread_create_path(ParticleTask *task, */ cpa_num = ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND) ? pa->num : pa->num_dmcache; - /* XXX hack to avoid messed up particle num and subsequent crash (T40733) */ + /* XXX hack to avoid messed up particle num and subsequent crash (#40733) */ if (cpa_num > ctx->sim.psmd->mesh_final->totface) { cpa_num = 0; } @@ -5099,7 +5099,7 @@ void psys_get_dupli_texture(ParticleSystem *psys, * the entire scenes dupli's are scanned, which also looks into uncalculated data. * * For now just include this workaround as an alternative to crashing, - * but longer term meta-balls should behave in a more manageable way, see: T46622. */ + * but longer term meta-balls should behave in a more manageable way, see: #46622. */ uv[0] = uv[1] = 0.0f; diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 085f2cc8ddb8..671a3e17cdf7 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -1206,12 +1206,12 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, step = (totpart < 2) ? 0.5 : 1.0 / (double)totpart; /* This is to address tricky issues with vertex-emitting when user tries - * (and expects) exact 1-1 vert/part distribution (see T47983 and its two example files). + * (and expects) exact 1-1 vert/part distribution (see #47983 and its two example files). * It allows us to consider pos as 'midpoint between v and v+1' * (or 'p and p+1', depending whether we have more vertices than particles or not), * and avoid stumbling over float impression in element_sum. * NOTE: moved face and volume distribution to this as well (instead of starting at zero), - * for the same reasons, see T52682. */ + * for the same reasons, see #52682. */ pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index f131739287ed..1053bfaf875a 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3536,12 +3536,12 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re } } - /* dynamics with cloth simulation, psys->particles can be NULL with 0 particles T25519. */ + /* dynamics with cloth simulation, psys->particles can be NULL with 0 particles #25519. */ if (psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS && psys->particles) { do_hair_dynamics(sim); } - /* following lines were removed r29079 but cause bug T22811, see report for details */ + /* following lines were removed r29079 but cause bug #22811, see report for details */ psys_update_effectors(sim); psys_update_path_cache(sim, cfra, use_render_params); diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index 7c829d32a825..7d4769c6e25a 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -932,7 +932,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh, /* Ensure leaf limit is at least 4 so there's room * to split at original face boundaries. - * Fixes T102209. + * Fixes #102209. */ pbvh->leaf_limit = max_ii(LEAF_LIMIT / (gridsize * gridsize), max_grids); diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.cc b/source/blender/blenkernel/intern/pbvh_bmesh.cc index 35aa523c69c8..b5f5a3b7ce14 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.cc +++ b/source/blender/blenkernel/intern/pbvh_bmesh.cc @@ -1417,7 +1417,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh, normalize_v3(v_conn->no); /* Update bounding boxes attached to the connected vertex. - * Note that we can often get-away without this but causes T48779. */ + * Note that we can often get-away without this but causes #48779. */ BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) { PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, l->f); f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateBB; diff --git a/source/blender/blenkernel/intern/preferences.c b/source/blender/blenkernel/intern/preferences.c index dd76f9eddc17..02169cd45350 100644 --- a/source/blender/blenkernel/intern/preferences.c +++ b/source/blender/blenkernel/intern/preferences.c @@ -8,6 +8,8 @@ #include +#include "DNA_asset_types.h" + #include "MEM_guardedalloc.h" #include "BLI_fileops.h" @@ -44,6 +46,7 @@ bUserAssetLibrary *BKE_preferences_asset_library_add(UserDef *userdef, if (path) { BLI_strncpy(library->path, path, sizeof(library->path)); } + library->import_method = ASSET_IMPORT_APPEND_REUSE; return library; } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 6f9abd4c48de..f89a44ee0245 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1704,7 +1704,7 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Object *ob, RigidBodyO } } - /* Make transformed objects temporarily kinmatic + /* Make transformed objects temporarily kinematic * so that they can be moved by the user during simulation. */ if (is_selected && (G.moving & G_TRANSFORM_OBJ)) { RB_body_set_kinematic_state(rbo->shared->physics_object, true); @@ -1728,7 +1728,7 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, { /* update world */ /* Note physics_world can get NULL when undoing the deletion of the last object in it (see - * T70667). */ + * #70667). */ if (rebuild || rbw->shared->physics_world == NULL) { BKE_rigidbody_validate_sim_world(scene, rbw, rebuild); /* We have rebuilt the world so we need to make sure the rest is rebuilt as well. */ diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc index 6a020343f55f..ccf62a6f899b 100644 --- a/source/blender/blenkernel/intern/scene.cc +++ b/source/blender/blenkernel/intern/scene.cc @@ -3083,7 +3083,7 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl return value * pow(unit->scale_length, 3); case B_UNIT_MASS: return value * pow(unit->scale_length, 3); - case B_UNIT_CAMERA: /* *Do not* use scene's unit scale for camera focal lens! See T42026. */ + case B_UNIT_CAMERA: /* *Do not* use scene's unit scale for camera focal lens! See #42026. */ default: return value; } diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 95ef6b7b9253..fabcd6278b48 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -956,7 +956,9 @@ ScrArea *BKE_screen_area_map_find_area_xy(const ScrAreaMap *areamap, const int xy[2]) { LISTBASE_FOREACH (ScrArea *, area, &areamap->areabase) { - if (BLI_rcti_isect_pt_v(&area->totrct, xy)) { + /* Test area's outer screen verts, not inner totrct. */ + if (xy[0] >= area->v1->vec.x && xy[0] <= area->v4->vec.x && xy[1] >= area->v1->vec.y && + xy[1] <= area->v2->vec.y) { if (ELEM(spacetype, SPACE_TYPE_ANY, area->spacetype)) { return area; } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index f6fab9164268..96e4fb941af1 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -854,7 +854,7 @@ static double get_cur_time(Scene *scene) { /* We divide by the current framelen to take into account time remapping. * Otherwise we will get the wrong starting time which will break A/V sync. - * See T74111 for further details. */ + * See #74111 for further details. */ return FRA2TIME((scene->r.cfra + scene->r.subframe) / (double)scene->r.framelen); } @@ -1230,7 +1230,7 @@ bool BKE_sound_info_get(struct Main *main, struct bSound *sound, SoundInfo *soun } /* TODO(sergey): Make it fully independent audio handle. */ /* Don't free waveforms during non-destructive queries. - * This causes unnecessary recalculation - see T69921 */ + * This causes unnecessary recalculation - see #69921 */ sound_load_audio(main, sound, false); const bool result = sound_info_from_playback_handle(sound->playback_handle, sound_info); sound_free_audio(sound); diff --git a/source/blender/blenkernel/intern/subdiv_ccg.cc b/source/blender/blenkernel/intern/subdiv_ccg.cc index bf09be444b1d..ba1627935823 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.cc +++ b/source/blender/blenkernel/intern/subdiv_ccg.cc @@ -352,7 +352,7 @@ struct StaticOrHeapIntStorage { static void static_or_heap_storage_init(StaticOrHeapIntStorage *storage) { - storage->static_storage_len = sizeof(storage->static_storage) / sizeof(*storage->static_storage); + storage->static_storage_len = ARRAY_SIZE(storage->static_storage); storage->heap_storage = nullptr; storage->heap_storage_len = 0; } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.cc b/source/blender/blenkernel/intern/subsurf_ccg.cc index 311c474cd0ab..47e2ecf98e8f 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.cc +++ b/source/blender/blenkernel/intern/subsurf_ccg.cc @@ -269,7 +269,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, limit[0] = limit[1] = STD_UV_CONNECT_LIMIT; /* previous behavior here is without accounting for winding, however this causes stretching in - * UV map in really simple cases with mirror + subsurf, see second part of T44530. + * UV map in really simple cases with mirror + subsurf, see second part of #44530. * Also, initially intention is to treat merged vertices from mirror modifier as seams. * This fixes a very old regression (2.49 was correct here) */ vmap = BKE_mesh_uv_vert_map_create( @@ -1885,7 +1885,7 @@ DerivedMesh *subsurf_make_derived_from_derived(DerivedMesh *dm, CCGDerivedMesh *result; /* NOTE: editmode calculation can only run once per - * modifier stack evaluation (uses freed cache) T36299. */ + * modifier stack evaluation (uses freed cache) #36299. */ if (flags & SUBSURF_FOR_EDIT_MODE) { int levels = (scene != nullptr && !ignore_simplify) ? get_render_subsurf_level(&scene->r, smd->levels, false) : diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 1a0c0716fcda..9b2f9c72c902 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -392,7 +392,7 @@ static void text_from_buf(Text *text, const uchar *buffer, const int len) * in this case content of such line would be used to fill text line buffer * - file is empty. in this case new line is needed to start editing from. * - last character in buffer is \n. in this case new line is needed to - * deal with newline at end of file. (see T28087) (sergey) */ + * deal with newline at end of file. (see #28087) (sergey) */ if (llen != 0 || lines_count == 0 || buffer[len - 1] == '\n') { TextLine *tmp; @@ -2225,7 +2225,7 @@ int txt_setcurr_tab_spaces(Text *text, int space) /* if we find a ':' on this line, then add a tab but not if it is: * 1) in a comment * 2) within an identifier - * 3) after the cursor (text->curc), i.e. when creating space before a function def T25414. + * 3) after the cursor (text->curc), i.e. when creating space before a function def #25414. */ int a; bool is_indent = false; diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index dd4bc3fd0212..375177f4cb5e 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -538,13 +538,14 @@ void tracking_cameraIntrinscisOptionsFromTracking( void tracking_trackingCameraFromIntrinscisOptions( MovieTracking *tracking, const libmv_CameraIntrinsicsOptions *camera_intrinsics_options) { - float aspy = 1.0f / tracking->camera.pixel_aspect; MovieTrackingCamera *camera = &tracking->camera; camera->focal = camera_intrinsics_options->focal_length; + /* NOTE: The image size stored in the `camera_intrinsics_options` is aspect-ratio corrected, + * so there is no need to "un-apply" it from the principal point. */ const float principal_px[2] = {camera_intrinsics_options->principal_point_x, - camera_intrinsics_options->principal_point_y / (double)aspy}; + camera_intrinsics_options->principal_point_y}; tracking_principal_point_pixel_to_normalized(principal_px, camera_intrinsics_options->image_width, diff --git a/source/blender/blenkernel/intern/undo_system.cc b/source/blender/blenkernel/intern/undo_system.cc index 946d94f15031..01235e718f3b 100644 --- a/source/blender/blenkernel/intern/undo_system.cc +++ b/source/blender/blenkernel/intern/undo_system.cc @@ -40,7 +40,7 @@ #define WITH_GLOBAL_UNDO_ENSURE_UPDATED /** - * Make sure we don't apply edits on top of a newer memfile state, see: T56163. + * Make sure we don't apply edits on top of a newer memfile state, see: #56163. * \note Keep an eye on this, could solve differently. */ #define WITH_GLOBAL_UNDO_CORRECT_ORDER @@ -183,7 +183,7 @@ static void undosys_step_decode(bContext *C, } else { /* Load the previous memfile state so any ID's referenced in this - * undo step will be correctly resolved, see: T56163. */ + * undo step will be correctly resolved, see: #56163. */ undosys_step_decode(C, bmain, ustack, us_iter, dir, false); /* May have been freed on memfile read. */ bmain = G_MAIN; @@ -564,7 +564,7 @@ eUndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack, if (use_memfile_step) { /* Make this the user visible undo state, so redo always applies - * on top of the mem-file undo instead of skipping it. see: T67256. */ + * on top of the mem-file undo instead of skipping it. see: #67256. */ UndoStep *us_prev = ustack->step_active; const char *name_internal = us_prev->name; const bool ok = undosys_stack_push_main(ustack, name_internal, G_MAIN); diff --git a/source/blender/blenkernel/intern/vfont.c b/source/blender/blenkernel/intern/vfont.c index 9f48b9b9c4a9..5c468689e948 100644 --- a/source/blender/blenkernel/intern/vfont.c +++ b/source/blender/blenkernel/intern/vfont.c @@ -720,10 +720,10 @@ typedef struct VFontToCurveIter { * Wrap words that extends beyond the text-box width (enabled by default). * * Currently only disabled when scale-to-fit is enabled, - * so floating-point error doesn't cause unexpected wrapping, see T89241. + * so floating-point error doesn't cause unexpected wrapping, see #89241. * * \note This should only be set once, in the #VFONT_TO_CURVE_INIT pass - * otherwise iterations wont behave predictably, see T91401. + * otherwise iterations wont behave predictably, see #91401. */ bool word_wrap; int status; @@ -974,7 +974,7 @@ static bool vfont_to_curve(Object *ob, * * Floating precision error can cause the text to be slightly larger. * Assert this is a small value as large values indicate incorrect - * calculations with scale-to-fit which shouldn't be ignored. See T89241. */ + * calculations with scale-to-fit which shouldn't be ignored. See #89241. */ if (x_used > x_available) { BLI_assert_msg(compare_ff_relative(x_used, x_available, FLT_EPSILON, 64), "VFontToCurveIter.scale_to_fit not set correctly!"); @@ -993,7 +993,7 @@ static bool vfont_to_curve(Object *ob, * Typically when a text-box has any height and overflow is set to scale * the text will wrap to fit the width as necessary. When wrapping isn't * possible it's important to use the same code-path as zero-height lines. - * Without this exception a single word will not scale-to-fit (see: T95116). */ + * Without this exception a single word will not scale-to-fit (see: #95116). */ tb_scale.h = 0.0f; } break; @@ -1229,7 +1229,7 @@ static bool vfont_to_curve(Object *ob, if (cu->overflow == CU_OVERFLOW_TRUNCATE) { /* Ensure overflow doesn't truncate text, before centering vertically - * giving odd/buggy results, see: T66614. */ + * giving odd/buggy results, see: #66614. */ if ((tb_index == cu->totbox - 1) && (last_line != -1)) { lines = last_line - ct_first->linenr; } diff --git a/source/blender/blenkernel/intern/volume_to_mesh.cc b/source/blender/blenkernel/intern/volume_to_mesh.cc index 8fb8f40cbcc0..8cb59a310b61 100644 --- a/source/blender/blenkernel/intern/volume_to_mesh.cc +++ b/source/blender/blenkernel/intern/volume_to_mesh.cc @@ -99,7 +99,7 @@ struct VolumeToMeshOp { openvdb::tools::volumeToMesh( grid, this->verts, this->tris, this->quads, this->threshold, this->adaptivity); - /* Better align generated mesh with volume (see T85312). */ + /* Better align generated mesh with volume (see #85312). */ openvdb::Vec3s offset = grid.voxelSize() / 2.0f; for (openvdb::Vec3s &position : this->verts) { position += offset; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index baf14bab2671..6d5bacdb2d28 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -477,7 +477,7 @@ static const AVCodec *get_av1_encoder( switch (context->ffmpeg_preset) { case FFM_PRESET_BEST: /* `libaom-av1` may produce better VMAF-scoring videos in several cases, but there are cases - * where using a different encoder is desirable, such as in T103849. */ + * where using a different encoder is desirable, such as in #103849. */ codec = avcodec_find_encoder_by_name("librav1e"); if (!codec) { /* Fallback to `libaom-av1` if librav1e is not found. */ @@ -1666,7 +1666,7 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset) rd->ffcodecdata.type = FFMPEG_MPEG2; rd->ffcodecdata.video_bitrate = 6000; -# if 0 /* Don't set resolution, see T21351. */ +# if 0 /* Don't set resolution, see #21351. */ rd->xsch = 720; rd->ysch = isntsc ? 480 : 576; # endif diff --git a/source/blender/blenlib/BLI_bit_vector.hh b/source/blender/blenlib/BLI_bit_vector.hh index bad371fc88a0..237bdce14526 100644 --- a/source/blender/blenlib/BLI_bit_vector.hh +++ b/source/blender/blenlib/BLI_bit_vector.hh @@ -16,13 +16,13 @@ * * The compact nature of storing bools in individual bits has some downsides that have to be kept * in mind: - * - Writing to separate bits in the same byte is not thread-safe. Therefore, an existing vector of + * - Writing to separate bits in the same int is not thread-safe. Therefore, an existing vector of * bool can't easily be replaced with a bit vector, if it is written to from multiple threads. * Read-only access from multiple threads is fine though. * - Writing individual elements is more expensive when the array is in cache already. That is - * because changing a bit is always a read-modify-write operation on the byte the bit resides in. + * because changing a bit is always a read-modify-write operation on the int the bit resides in. * - Reading individual elements is more expensive when the array is in cache already. That is - * because additional bit-wise operations have to be applied after the corresponding byte is + * because additional bit-wise operations have to be applied after the corresponding int is * read. * * Comparison to `std::vector`: @@ -42,18 +42,27 @@ #include "BLI_memory_utils.hh" #include "BLI_span.hh" -namespace blender { +namespace blender::bits { /** - * This is a read-only pointer to a specific bit. The value of the bit can be retrieved, but not - * changed. + * Using a large integer type is better because then it's easier to process many bits at once. + */ +using IntType = uint64_t; +static constexpr int64_t BitsPerInt = int64_t(sizeof(IntType) * 8); +static constexpr int64_t BitToIntIndexShift = 3 + (sizeof(IntType) >= 2) + (sizeof(IntType) >= 4) + + (sizeof(IntType) >= 8); +static constexpr IntType BitIndexMask = (IntType(1) << BitToIntIndexShift) - 1; + +/** + * This is a read-only pointer to a specific bit. The value of the bit can be retrieved, but + * not changed. */ class BitRef { private: - /** Points to the exact byte that the bit is in. */ - const uint8_t *byte_ptr_; + /** Points to the integer that the bit is in. */ + const IntType *ptr_; /** All zeros except for a single one at the bit that is referenced. */ - uint8_t mask_; + IntType mask_; friend class MutableBitRef; @@ -61,13 +70,13 @@ class BitRef { BitRef() = default; /** - * Reference a specific bit in a byte array. Note that #byte_ptr does *not* have to point to the - * exact byte the bit is in. + * Reference a specific bit in an array. Note that #ptr does *not* have to point to the + * exact integer the bit is in. */ - BitRef(const uint8_t *byte_ptr, const int64_t bit_index) + BitRef(const IntType *ptr, const int64_t bit_index) { - byte_ptr_ = byte_ptr + (bit_index >> 3); - mask_ = 1 << (bit_index & 7); + ptr_ = ptr + (bit_index >> BitToIntIndexShift); + mask_ = IntType(1) << (bit_index & BitIndexMask); } /** @@ -75,9 +84,9 @@ class BitRef { */ bool test() const { - const uint8_t byte = *byte_ptr_; - const uint8_t masked_byte = byte & mask_; - return masked_byte != 0; + const IntType value = *ptr_; + const IntType masked_value = value & mask_; + return masked_value != 0; } operator bool() const @@ -91,22 +100,22 @@ class BitRef { */ class MutableBitRef { private: - /** Points to the exact byte that the bit is in. */ - uint8_t *byte_ptr_; + /** Points to the integer that the bit is in. */ + IntType *ptr_; /** All zeros except for a single one at the bit that is referenced. */ - uint8_t mask_; + IntType mask_; public: MutableBitRef() = default; /** - * Reference a specific bit in a byte array. Note that #byte_ptr does *not* have to point to the - * exact byte the bit is in. + * Reference a specific bit in an array. Note that #ptr does *not* have to point to the + * exact int the bit is in. */ - MutableBitRef(uint8_t *byte_ptr, const int64_t bit_index) + MutableBitRef(IntType *ptr, const int64_t bit_index) { - byte_ptr_ = byte_ptr + (bit_index >> 3); - mask_ = 1 << uint8_t(bit_index & 7); + ptr_ = ptr + (bit_index >> BitToIntIndexShift); + mask_ = IntType(1) << IntType(bit_index & BitIndexMask); } /** @@ -115,7 +124,7 @@ class MutableBitRef { operator BitRef() const { BitRef bit_ref; - bit_ref.byte_ptr_ = byte_ptr_; + bit_ref.ptr_ = ptr_; bit_ref.mask_ = mask_; return bit_ref; } @@ -125,9 +134,9 @@ class MutableBitRef { */ bool test() const { - const uint8_t byte = *byte_ptr_; - const uint8_t masked_byte = byte & mask_; - return masked_byte != 0; + const IntType value = *ptr_; + const IntType masked_value = value & mask_; + return masked_value != 0; } operator bool() const @@ -140,7 +149,7 @@ class MutableBitRef { */ void set() { - *byte_ptr_ |= mask_; + *ptr_ |= mask_; } /** @@ -148,7 +157,7 @@ class MutableBitRef { */ void reset() { - *byte_ptr_ &= ~mask_; + *ptr_ &= ~mask_; } /** @@ -177,21 +186,20 @@ template< typename Allocator = GuardedAllocator> class BitVector { private: - static constexpr int64_t required_bytes_for_bits(const int64_t number_of_bits) + static constexpr int64_t required_ints_for_bits(const int64_t number_of_bits) { - return (number_of_bits + BitsPerByte - 1) / BitsPerByte; + return (number_of_bits + BitsPerInt - 1) / BitsPerInt; } - static constexpr int64_t BitsPerByte = 8; - static constexpr int64_t BytesInInlineBuffer = required_bytes_for_bits(InlineBufferCapacity); - static constexpr int64_t BitsInInlineBuffer = BytesInInlineBuffer * BitsPerByte; - static constexpr int64_t AllocationAlignment = 8; + static constexpr int64_t IntsInInlineBuffer = required_ints_for_bits(InlineBufferCapacity); + static constexpr int64_t BitsInInlineBuffer = IntsInInlineBuffer * BitsPerInt; + static constexpr int64_t AllocationAlignment = alignof(IntType); /** - * Points to the first byte used by the vector. It might point to the memory in the inline + * Points to the first integer used by the vector. It might point to the memory in the inline * buffer. */ - uint8_t *data_; + IntType *data_; /** Current size of the vector in bits. */ int64_t size_in_bits_; @@ -203,7 +211,7 @@ class BitVector { BLI_NO_UNIQUE_ADDRESS Allocator allocator_; /** Contains the bits as long as the vector is small enough. */ - BLI_NO_UNIQUE_ADDRESS TypedBuffer inline_buffer_; + BLI_NO_UNIQUE_ADDRESS TypedBuffer inline_buffer_; public: BitVector(Allocator allocator = {}) noexcept : allocator_(allocator) @@ -211,7 +219,7 @@ class BitVector { data_ = inline_buffer_; size_in_bits_ = 0; capacity_in_bits_ = BitsInInlineBuffer; - uninitialized_fill_n(data_, BytesInInlineBuffer, uint8_t(0)); + uninitialized_fill_n(data_, IntsInInlineBuffer, IntType(0)); } BitVector(NoExceptConstructor, Allocator allocator = {}) noexcept : BitVector(allocator) @@ -220,29 +228,29 @@ class BitVector { BitVector(const BitVector &other) : BitVector(NoExceptConstructor(), other.allocator_) { - const int64_t bytes_to_copy = other.used_bytes_amount(); + const int64_t ints_to_copy = other.used_ints_amount(); if (other.size_in_bits_ <= BitsInInlineBuffer) { /* The data is copied into the owned inline buffer. */ data_ = inline_buffer_; capacity_in_bits_ = BitsInInlineBuffer; } else { - /* Allocate a new byte array because the inline buffer is too small. */ - data_ = static_cast( - allocator_.allocate(bytes_to_copy, AllocationAlignment, __func__)); - capacity_in_bits_ = bytes_to_copy * BitsPerByte; + /* Allocate a new array because the inline buffer is too small. */ + data_ = static_cast( + allocator_.allocate(ints_to_copy * sizeof(IntType), AllocationAlignment, __func__)); + capacity_in_bits_ = ints_to_copy * BitsPerInt; } size_in_bits_ = other.size_in_bits_; - uninitialized_copy_n(other.data_, bytes_to_copy, data_); + uninitialized_copy_n(other.data_, ints_to_copy, data_); } BitVector(BitVector &&other) noexcept : BitVector(NoExceptConstructor(), other.allocator_) { if (other.is_inline()) { /* Copy the data into the inline buffer. */ - const int64_t bytes_to_copy = other.used_bytes_amount(); + const int64_t ints_to_copy = other.used_ints_amount(); data_ = inline_buffer_; - uninitialized_copy_n(other.data_, bytes_to_copy, data_); + uninitialized_copy_n(other.data_, ints_to_copy, data_); } else { /* Steal the pointer. */ @@ -305,7 +313,7 @@ class BitVector { bool is_empty() const { - return this->size() == 0; + return size_in_bits_ == 0; } /** @@ -442,20 +450,20 @@ class BitVector { */ void fill_range(const IndexRange range, const bool value) { - const AlignedIndexRanges aligned_ranges = split_index_range_by_alignment(range, BitsPerByte); + const AlignedIndexRanges aligned_ranges = split_index_range_by_alignment(range, BitsPerInt); /* Fill first few bits. */ for (const int64_t i : aligned_ranges.prefix) { (*this)[i].set(value); } - /* Fill entire bytes at once. */ - const int64_t start_fill_byte_index = aligned_ranges.aligned.start() / BitsPerByte; - const int64_t bytes_to_fill = aligned_ranges.aligned.size() / BitsPerByte; - const uint8_t fill_value = value ? uint8_t(0xff) : uint8_t(0x00); - initialized_fill_n(data_ + start_fill_byte_index, bytes_to_fill, fill_value); + /* Fill entire ints at once. */ + const int64_t start_fill_int_index = aligned_ranges.aligned.start() / BitsPerInt; + const int64_t ints_to_fill = aligned_ranges.aligned.size() / BitsPerInt; + const IntType fill_value = value ? IntType(-1) : IntType(0); + initialized_fill_n(data_ + start_fill_int_index, ints_to_fill, fill_value); - /* Fill bits in the end that don't cover a full byte. */ + /* Fill bits in the end that don't cover a full int. */ for (const int64_t i : aligned_ranges.suffix) { (*this)[i].set(value); } @@ -509,37 +517,35 @@ class BitVector { } BLI_NOINLINE void realloc_to_at_least(const int64_t min_capacity_in_bits, - const uint8_t initial_value_for_new_bytes = 0x00) + const IntType initial_value_for_new_ints = 0x00) { if (capacity_in_bits_ >= min_capacity_in_bits) { return; } - const int64_t min_capacity_in_bytes = this->required_bytes_for_bits(min_capacity_in_bits); + const int64_t min_capacity_in_ints = this->required_ints_for_bits(min_capacity_in_bits); /* At least double the size of the previous allocation. */ - const int64_t min_new_capacity_in_bytes = capacity_in_bits_ * 2; + const int64_t min_new_capacity_in_ints = 2 * this->required_ints_for_bits(capacity_in_bits_); - const int64_t new_capacity_in_bytes = std::max(min_capacity_in_bytes, - min_new_capacity_in_bytes); - const int64_t bytes_to_copy = this->used_bytes_amount(); + const int64_t new_capacity_in_ints = std::max(min_capacity_in_ints, min_new_capacity_in_ints); + const int64_t ints_to_copy = this->used_ints_amount(); - uint8_t *new_data = static_cast( - allocator_.allocate(new_capacity_in_bytes, AllocationAlignment, __func__)); - uninitialized_copy_n(data_, bytes_to_copy, new_data); + IntType *new_data = static_cast(allocator_.allocate( + new_capacity_in_ints * sizeof(IntType), AllocationAlignment, __func__)); + uninitialized_copy_n(data_, ints_to_copy, new_data); /* Always initialize new capacity even if it isn't used yet. That's necessary to avoid warnings * caused by using uninitialized memory. This happens when e.g. setting a clearing a bit in an - * uninitialized byte. */ - uninitialized_fill_n(new_data + bytes_to_copy, - new_capacity_in_bytes - bytes_to_copy, - uint8_t(initial_value_for_new_bytes)); + * uninitialized int. */ + uninitialized_fill_n( + new_data + ints_to_copy, new_capacity_in_ints - ints_to_copy, initial_value_for_new_ints); if (!this->is_inline()) { allocator_.deallocate(data_); } data_ = new_data; - capacity_in_bits_ = new_capacity_in_bytes * BitsPerByte; + capacity_in_bits_ = new_capacity_in_ints * BitsPerInt; } bool is_inline() const @@ -547,10 +553,16 @@ class BitVector { return data_ == inline_buffer_; } - int64_t used_bytes_amount() const + int64_t used_ints_amount() const { - return this->required_bytes_for_bits(size_in_bits_); + return this->required_ints_for_bits(size_in_bits_); } }; +} // namespace blender::bits + +namespace blender { +using bits::BitRef; +using bits::BitVector; +using bits::MutableBitRef; } // namespace blender diff --git a/source/blender/blenlib/BLI_index_mask_ops.hh b/source/blender/blenlib/BLI_index_mask_ops.hh index e4eece11e83a..51c80bafe3ed 100644 --- a/source/blender/blenlib/BLI_index_mask_ops.hh +++ b/source/blender/blenlib/BLI_index_mask_ops.hh @@ -71,4 +71,9 @@ IndexMask find_indices_from_virtual_array(IndexMask indices_to_check, int64_t parallel_grain_size, Vector &r_indices); +/** + * Find the true indices in a boolean span. + */ +IndexMask find_indices_from_array(Span array, Vector &r_indices); + } // namespace blender::index_mask_ops diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index c0c4594ddc03..eed379d02ad4 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -97,8 +97,9 @@ MINLINE float saacos(float fac); MINLINE float saasin(float fac); MINLINE float sasqrt(float fac); -MINLINE float interpf(float a, float b, float t); -MINLINE double interpd(double a, double b, double t); +/* Compute linear interpolation (lerp) between origin and target. */ +MINLINE float interpf(float target, float origin, float t); +MINLINE double interpd(double target, double origin, double t); MINLINE float ratiof(float min, float max, float pos); MINLINE double ratiod(double min, double max, double pos); @@ -308,7 +309,7 @@ float ceil_power_of_10(float f); * check the vector is unit length, or zero length (which can't be helped in some cases). */ #ifndef NDEBUG -/** \note 0.0001 is too small because normals may be converted from short's: see T34322. */ +/** \note 0.0001 is too small because normals may be converted from short's: see #34322. */ # define BLI_ASSERT_UNIT_EPSILON 0.0002f # define BLI_ASSERT_UNIT_EPSILON_DB 0.0002 /** diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 1278bc90e446..5724f590aa36 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -246,7 +246,7 @@ bool invert_m4_m4(float inverse[4][4], const float mat[4][4]); * * \note this has worse performance than #EIG_invert_m4_m4 (Eigen), but e.g. * for non-invertible scale matrices, finding a partial solution can - * be useful to have a valid local transform center, see T57767. + * be useful to have a valid local transform center, see #57767. */ bool invert_m4_m4_fallback(float inverse[4][4], const float mat[4][4]); @@ -519,7 +519,7 @@ void blend_m4_m4m4(float out[4][4], const float dst[4][4], const float src[4][4] * (it typically remains below 2 usec on an average i74700, * while #blend_m3_m3m3 remains below 0.4 usec). * However, it gives expected results even with non-uniformly scaled matrices, - * see T46418 for an example. + * see #46418 for an example. * * Based on "Matrix Animation and Polar Decomposition", by Ken Shoemake & Tom Duff * diff --git a/source/blender/blenlib/BLI_math_matrix.hh b/source/blender/blenlib/BLI_math_matrix.hh index 757f23113bc8..5b15920b136c 100644 --- a/source/blender/blenlib/BLI_math_matrix.hh +++ b/source/blender/blenlib/BLI_math_matrix.hh @@ -94,7 +94,7 @@ template * (it typically remains below 2 usec on an average i74700, * while naive implementation remains below 0.4 usec). * However, it gives expected results even with non-uniformly scaled matrices, - * see T46418 for an example. + * see #46418 for an example. * * Based on "Matrix Animation and Polar Decomposition", by Ken Shoemake & Tom Duff * @@ -125,7 +125,7 @@ template * * \note This code is about five times faster than the polar decomposition. * However, it gives un-expected results even with non-uniformly scaled matrices, - * see T46418 for an example. + * see #46418 for an example. * * \param A: Input matrix which is totally effective with `t = 0.0`. * \param B: Input matrix which is totally effective with `t = 1.0`. @@ -142,7 +142,7 @@ template * * \note This code is about five times faster than the polar decomposition. * However, it gives un-expected results even with non-uniformly scaled matrices, - * see T46418 for an example. + * see #46418 for an example. * * \param A: Input matrix which is totally effective with `t = 0.0`. * \param B: Input matrix which is totally effective with `t = 1.0`. @@ -693,7 +693,7 @@ extern template void normalized_to_eul2(const double3x3 &mat, template detail::Quaternion normalized_to_quat_fast(const MatBase &mat) { BLI_assert(math::is_unit_scale(mat)); - /* Caller must ensure matrices aren't negative for valid results, see: T24291, T94231. */ + /* Caller must ensure matrices aren't negative for valid results, see: #24291, #94231. */ BLI_assert(!math::is_negative(mat)); detail::Quaternion q; @@ -758,7 +758,7 @@ template detail::Quaternion normalized_to_quat_fast(const MatBase } else { /* NOTE(@ideasman42): A zero matrix will fall through to this block, - * needed so a zero scaled matrices to return a quaternion without rotation, see: T101848. + * needed so a zero scaled matrices to return a quaternion without rotation, see: #101848. */ const T trace = 1.0f + mat[0][0] + mat[1][1] + mat[2][2]; T s = 2.0f * math::sqrt(trace); diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 78f8e5297406..3df5a85ca852 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -342,7 +342,7 @@ void BLI_path_normalize_dir(const char *relabase, char *dir, size_t dir_maxlen) * \note Space case ' ' is a bit of an edge case here - in theory it is allowed, * but again can be an issue in some cases, so we simply replace it by an underscore too * (good practice anyway). - * REMOVED based on popular demand (see T45900). + * REMOVED based on popular demand (see #45900). * Percent '%' char is a bit same case - not recommended to use it, * but supported by all decent file-systems/operating-systems around. * diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index 3be492009b01..b07e1f0a5bdf 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -426,7 +426,7 @@ void BLI_task_graph_edge_create(struct TaskNode *from_node, struct TaskNode *to_ * cannot run the tasks itself. On a single thread, that causes a deadlock already. When there are * multiple threads, another thread will typically run the task and avoid the deadlock. However, if * this situation happens on all threads at the same time, all threads will deadlock. This happened - * in T88598. + * in #88598. * \{ */ void BLI_task_isolate(void (*func)(void *userdata), void *userdata); diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 5cc91a229446..e03bc7ba78af 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -806,6 +806,10 @@ extern bool BLI_memory_is_zero(const void *arr, size_t arr_size); { \ return a = (_enum_type)(uint64_t(a) & uint64_t(b)); \ } \ + inline _enum_type &operator^=(_enum_type &a, _enum_type b) \ + { \ + return a = (_enum_type)(uint64_t(a) ^ uint64_t(b)); \ + } \ } /* extern "C++" */ #else diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 7c24fb8b5e71..16635df908b0 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -281,10 +281,10 @@ set(SRC BLI_math_solvers.h BLI_math_statistics.h BLI_math_time.h - BLI_math_vector_mpq_types.hh - BLI_math_vector_types.hh BLI_math_vector.h BLI_math_vector.hh + BLI_math_vector_mpq_types.hh + BLI_math_vector_types.hh BLI_memarena.h BLI_memblock.h BLI_memiter.h @@ -490,13 +490,13 @@ if(WITH_GTESTS) tests/BLI_math_bits_test.cc tests/BLI_math_color_test.cc tests/BLI_math_geom_test.cc - tests/BLI_math_matrix_types_test.cc tests/BLI_math_matrix_test.cc + tests/BLI_math_matrix_types_test.cc tests/BLI_math_rotation_test.cc tests/BLI_math_solvers_test.cc tests/BLI_math_time_test.cc - tests/BLI_math_vector_types_test.cc tests/BLI_math_vector_test.cc + tests/BLI_math_vector_types_test.cc tests/BLI_memiter_test.cc tests/BLI_memory_utils_test.cc tests/BLI_mesh_boolean_test.cc diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 005de1f85b43..d7ab08d8bc88 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -526,7 +526,7 @@ int BLI_copy(const char *file, const char *to) # if 0 int BLI_create_symlink(const char *file, const char *to) { - /* See patch from T30870, should this ever become needed. */ + /* See patch from #30870, should this ever become needed. */ callLocalErrorCallBack("Linking files is unsupported on Windows"); (void)file; (void)to; diff --git a/source/blender/blenlib/intern/filereader_zstd.c b/source/blender/blenlib/intern/filereader_zstd.c index aeb000e9754f..960be159c9d1 100644 --- a/source/blender/blenlib/intern/filereader_zstd.c +++ b/source/blender/blenlib/intern/filereader_zstd.c @@ -281,7 +281,7 @@ static void zstd_close(FileReader *reader) if (zstd->reader.seek) { MEM_freeN(zstd->seek.uncompressed_ofs); MEM_freeN(zstd->seek.compressed_ofs); - /* When an error has occurred this may be NULL, see: T99744. */ + /* When an error has occurred this may be NULL, see: #99744. */ if (zstd->seek.cached_content) { MEM_freeN(zstd->seek.cached_content); } diff --git a/source/blender/blenlib/intern/index_mask.cc b/source/blender/blenlib/intern/index_mask.cc index adcc2de8bdb1..bc58707b4793 100644 --- a/source/blender/blenlib/intern/index_mask.cc +++ b/source/blender/blenlib/intern/index_mask.cc @@ -208,8 +208,7 @@ IndexMask find_indices_from_virtual_array(const IndexMask indices_to_check, } if (virtual_array.is_span()) { const Span span = virtual_array.get_internal_span(); - return find_indices_based_on_predicate( - indices_to_check, 4096, r_indices, [&](const int64_t i) { return span[i]; }); + return find_indices_from_array(span, r_indices); } threading::EnumerableThreadSpecific> materialize_buffers; @@ -241,4 +240,10 @@ IndexMask find_indices_from_virtual_array(const IndexMask indices_to_check, return detail::find_indices_based_on_predicate__merge(indices_to_check, sub_masks, r_indices); } +IndexMask find_indices_from_array(const Span array, Vector &r_indices) +{ + return find_indices_based_on_predicate( + array.index_range(), 4096, r_indices, [array](const int64_t i) { return array[i]; }); +} + } // namespace blender::index_mask_ops diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h index f7993eb5adc9..53a3ea90285c 100644 --- a/source/blender/blenlib/intern/kdtree_impl.h +++ b/source/blender/blenlib/intern/kdtree_impl.h @@ -46,7 +46,7 @@ struct KDTree { /** * When set we know all values are unbalanced, - * otherwise clear them when re-balancing: see T62210. + * otherwise clear them when re-balancing: see #62210. */ #define KD_NODE_ROOT_IS_INIT ((uint)-2) diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 5b0f744ea162..e55eb46235ae 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1225,7 +1225,7 @@ int isect_seg_seg_v2_point_ex(const float v0[2], /* When 'd' approaches zero, float precision lets non-overlapping co-linear segments * detect as an intersection. So re-calculate 'v' to ensure the point overlaps both. - * see T45123 */ + * see #45123 */ /* inline since we have most vars already */ #if 0 @@ -2887,7 +2887,7 @@ int isect_line_line_epsilon_v3(const float v1[3], d = dot_v3v3(c, ab); div = dot_v3v3(ab, ab); - /* important not to use an epsilon here, see: T45919 */ + /* important not to use an epsilon here, see: #45919 */ /* test zero length line */ if (UNLIKELY(div == 0.0f)) { return 0; @@ -2962,7 +2962,7 @@ bool isect_line_line_strict_v3(const float v1[3], d = dot_v3v3(c, ab); div = dot_v3v3(ab, ab); - /* important not to use an epsilon here, see: T45919 */ + /* important not to use an epsilon here, see: #45919 */ /* test zero length line */ if (UNLIKELY(div == 0.0f)) { return false; @@ -4034,7 +4034,7 @@ static float mean_value_half_tan_v3(const struct Float3_Len *d_curr, float cross[3]; cross_v3_v3v3(cross, d_curr->dir, d_next->dir); const float area = len_v3(cross); - /* Compare against zero since 'FLT_EPSILON' can be too large, see: T73348. */ + /* Compare against zero since 'FLT_EPSILON' can be too large, see: #73348. */ if (LIKELY(area != 0.0f)) { const float dot = dot_v3v3(d_curr->dir, d_next->dir); const float len = d_curr->len * d_next->len; @@ -4060,7 +4060,7 @@ static double mean_value_half_tan_v2_db(const struct Double2_Len *d_curr, { /* Different from the 3d version but still correct. */ const double area = cross_v2v2_db(d_curr->dir, d_next->dir); - /* Compare against zero since 'FLT_EPSILON' can be too large, see: T73348. */ + /* Compare against zero since 'FLT_EPSILON' can be too large, see: #73348. */ if (LIKELY(area != 0.0)) { const double dot = dot_v2v2_db(d_curr->dir, d_next->dir); const double len = d_curr->len * d_next->len; diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index e07675d683a2..c74a0322ac52 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1663,7 +1663,7 @@ void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize) * * \note If an object has a zero scaled axis, this function can be used to "clean" the matrix * to behave as if the scale on that axis was `unit_length`. So it can be inverted - * or used in matrix multiply without creating degenerate matrices, see: T50103 + * or used in matrix multiply without creating degenerate matrices, see: #50103 * \{ */ /** @@ -2412,7 +2412,7 @@ void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], con /* Quaternions cannot represent an axis flip. If such a singularity is detected, choose a * different decomposition of the matrix that still satisfies A = U_A * P_A but which has a - * positive determinant and thus no axis flips. This resolves T77154. + * positive determinant and thus no axis flips. This resolves #77154. * * Note that a flip of two axes is just a rotation of 180 degrees around the third axis, and * three flipped axes are just an 180 degree rotation + a single axis flip. It is thus sufficient diff --git a/source/blender/blenlib/intern/math_matrix.cc b/source/blender/blenlib/intern/math_matrix.cc index 122920923b24..f215b4600013 100644 --- a/source/blender/blenlib/intern/math_matrix.cc +++ b/source/blender/blenlib/intern/math_matrix.cc @@ -325,7 +325,7 @@ MatBase interpolate(const MatBase &A, const MatBase & /* Quaternions cannot represent an axis flip. If such a singularity is detected, choose a * different decomposition of the matrix that still satisfies A = U_A * P_A but which has a - * positive determinant and thus no axis flips. This resolves T77154. + * positive determinant and thus no axis flips. This resolves #77154. * * Note that a flip of two axes is just a rotation of 180 degrees around the third axis, and * three flipped axes are just an 180 degree rotation + a single axis flip. It is thus sufficient diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 33f9fa1cde6f..f47bc2d8ed73 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -272,7 +272,7 @@ void quat_to_mat4(float m[4][4], const float q[4]) void mat3_normalized_to_quat_fast(float q[4], const float mat[3][3]) { BLI_ASSERT_UNIT_M3(mat); - /* Caller must ensure matrices aren't negative for valid results, see: T24291, T94231. */ + /* Caller must ensure matrices aren't negative for valid results, see: #24291, #94231. */ BLI_assert(!is_negative_m3(mat)); /* Method outlined by Mike Day, ref: https://math.stackexchange.com/a/3183435/220949 @@ -335,7 +335,7 @@ void mat3_normalized_to_quat_fast(float q[4], const float mat[3][3]) } else { /* NOTE(@ideasman42): A zero matrix will fall through to this block, - * needed so a zero scaled matrices to return a quaternion without rotation, see: T101848. */ + * needed so a zero scaled matrices to return a quaternion without rotation, see: #101848. */ const float trace = 1.0f + mat[0][0] + mat[1][1] + mat[2][2]; float s = 2.0f * sqrtf(trace); q[0] = 0.25f * s; @@ -964,7 +964,7 @@ void sin_cos_from_fraction(int numerator, int denominator, float *r_sin, float * /* By default, creating a circle from an integer: calling #sinf & #cosf on the fraction doesn't * create symmetrical values (because floats can't represent Pi exactly). * Resolve this when the rotation is calculated from a fraction by mapping the `numerator` - * to lower values so X/Y values for points around a circle are exactly symmetrical, see T87779. + * to lower values so X/Y values for points around a circle are exactly symmetrical, see #87779. * * Multiply both the `numerator` and `denominator` by eight to ensure we can divide the circle * into 8 octants. For each octant, we then use symmetry and negation to bring the `numerator` diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 9de75de5ffa8..5c15975f393c 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -2761,7 +2761,7 @@ static IMesh raycast_tris_boolean(const IMesh &tm, * For most operations, even a hint of being inside * gives good results, but when shape is a cutter in a Difference * operation, we want to be pretty sure that the point is inside other_shape. - * E.g., T75827. + * E.g., #75827. * Also, when the operation is intersection, we also want high confidence. */ bool need_high_confidence = (op == BoolOpType::Difference && shape != 0) || diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c index 4f4166d8de87..c5a877a9539b 100644 --- a/source/blender/blenlib/intern/polyfill_2d.c +++ b/source/blender/blenlib/intern/polyfill_2d.c @@ -58,7 +58,7 @@ # include "PIL_time_utildefines.h" #endif -typedef signed char eSign; +typedef int8_t eSign; #ifdef USE_KDTREE /** @@ -84,24 +84,24 @@ typedef bool axis_t; /* use for sorting */ typedef struct KDTreeNode2D_head { - uint neg, pos; - uint index; + uint32_t neg, pos; + uint32_t index; } KDTreeNode2D_head; typedef struct KDTreeNode2D { - uint neg, pos; - uint index; + uint32_t neg, pos; + uint32_t index; axis_t axis; /* range is only (0-1) */ - ushort flag; - uint parent; + uint16_t flag; + uint32_t parent; } KDTreeNode2D; struct KDTree2D { KDTreeNode2D *nodes; const float (*coords)[2]; - uint root; - uint node_num; - uint *nodes_map; /* index -> node lookup */ + uint32_t root; + uint32_t node_num; + uint32_t *nodes_map; /* index -> node lookup */ }; struct KDRange2D { @@ -119,14 +119,14 @@ typedef struct PolyFill { struct PolyIndex *indices; /* vertex aligned */ const float (*coords)[2]; - uint coords_num; + uint32_t coords_num; #ifdef USE_CONVEX_SKIP - uint coords_num_concave; + uint32_t coords_num_concave; #endif /* A polygon with n vertices has a triangulation of n-2 triangles. */ - uint (*tris)[3]; - uint tris_num; + uint32_t (*tris)[3]; + uint32_t tris_num; #ifdef USE_KDTREE struct KDTree2D kdtree; @@ -136,7 +136,7 @@ typedef struct PolyFill { /** Circular double linked-list. */ typedef struct PolyIndex { struct PolyIndex *next, *prev; - uint index; + uint32_t index; eSign sign; } PolyIndex; @@ -189,13 +189,13 @@ static eSign span_tri_v2_sign(const float v1[2], const float v2[2], const float } #ifdef USE_KDTREE -# define KDNODE_UNSET ((uint)-1) +# define KDNODE_UNSET ((uint32_t)-1) enum { KDNODE_FLAG_REMOVED = (1 << 0), }; -static void kdtree2d_new(struct KDTree2D *tree, uint tot, const float (*coords)[2]) +static void kdtree2d_new(struct KDTree2D *tree, uint32_t tot, const float (*coords)[2]) { /* set by caller */ // tree->nodes = nodes; @@ -207,10 +207,12 @@ static void kdtree2d_new(struct KDTree2D *tree, uint tot, const float (*coords)[ /** * no need for kdtree2d_insert, since we know the coords array. */ -static void kdtree2d_init(struct KDTree2D *tree, const uint coords_num, const PolyIndex *indices) +static void kdtree2d_init(struct KDTree2D *tree, + const uint32_t coords_num, + const PolyIndex *indices) { KDTreeNode2D *node; - uint i; + uint32_t i; for (i = 0, node = tree->nodes; i < coords_num; i++) { if (indices[i].sign != CONVEX) { @@ -222,14 +224,17 @@ static void kdtree2d_init(struct KDTree2D *tree, const uint coords_num, const Po } } - BLI_assert(tree->node_num == (uint)(node - tree->nodes)); + BLI_assert(tree->node_num == (uint32_t)(node - tree->nodes)); } -static uint kdtree2d_balance_recursive( - KDTreeNode2D *nodes, uint node_num, axis_t axis, const float (*coords)[2], const uint ofs) +static uint32_t kdtree2d_balance_recursive(KDTreeNode2D *nodes, + uint32_t node_num, + axis_t axis, + const float (*coords)[2], + const uint32_t ofs) { KDTreeNode2D *node; - uint neg, pos, median, i, j; + uint32_t neg, pos, median, i, j; if (node_num <= 0) { return KDNODE_UNSET; @@ -287,7 +292,7 @@ static void kdtree2d_balance(struct KDTree2D *tree) static void kdtree2d_init_mapping(struct KDTree2D *tree) { - uint i; + uint32_t i; KDTreeNode2D *node; for (i = 0, node = tree->nodes; i < tree->node_num; i++, node++) { @@ -306,9 +311,9 @@ static void kdtree2d_init_mapping(struct KDTree2D *tree) tree->nodes[tree->root].parent = KDNODE_UNSET; } -static void kdtree2d_node_remove(struct KDTree2D *tree, uint index) +static void kdtree2d_node_remove(struct KDTree2D *tree, uint32_t index) { - uint node_index = tree->nodes_map[index]; + uint32_t node_index = tree->nodes_map[index]; KDTreeNode2D *node; if (node_index == KDNODE_UNSET) { @@ -327,7 +332,7 @@ static void kdtree2d_node_remove(struct KDTree2D *tree, uint index) (node->parent != KDNODE_UNSET)) { KDTreeNode2D *node_parent = &tree->nodes[node->parent]; - BLI_assert((uint)(node - tree->nodes) == node_index); + BLI_assert((uint32_t)(node - tree->nodes) == node_index); if (node_parent->neg == node_index) { node_parent->neg = KDNODE_UNSET; } @@ -347,7 +352,7 @@ static void kdtree2d_node_remove(struct KDTree2D *tree, uint index) } static bool kdtree2d_isect_tri_recursive(const struct KDTree2D *tree, - const uint tri_index[3], + const uint32_t tri_index[3], const float *tri_coords[3], const float tri_center[2], const struct KDRange2D bounds[2], @@ -404,10 +409,10 @@ static bool kdtree2d_isect_tri_recursive(const struct KDTree2D *tree, return false; } -static bool kdtree2d_isect_tri(struct KDTree2D *tree, const uint ind[3]) +static bool kdtree2d_isect_tri(struct KDTree2D *tree, const uint32_t ind[3]) { const float *vs[3]; - uint i; + uint32_t i; struct KDRange2D bounds[2] = { {FLT_MAX, -FLT_MAX}, {FLT_MAX, -FLT_MAX}, @@ -432,7 +437,7 @@ static bool kdtree2d_isect_tri(struct KDTree2D *tree, const uint ind[3]) #endif /* USE_KDTREE */ -static uint *pf_tri_add(PolyFill *pf) +static uint32_t *pf_tri_add(PolyFill *pf) { return pf->tris[pf->tris_num++]; } @@ -453,7 +458,7 @@ static void pf_coord_remove(PolyFill *pf, PolyIndex *pi) pf->indices = pi->next; } #ifdef DEBUG - pi->index = (uint)-1; + pi->index = (uint32_t)-1; pi->next = pi->prev = NULL; #endif @@ -544,14 +549,16 @@ static void pf_triangulate(PolyFill *pf) } # endif #else +# ifdef USE_CLIP_SWEEP if ((reverse ? pi_prev->prev : pi_next->next)->sign != CONVEX) { reverse = !reverse; } +# endif #endif } if (pf->coords_num == 3) { - uint *tri = pf_tri_add(pf); + uint32_t *tri = pf_tri_add(pf); pi_ear = pf->indices; tri[0] = pi_ear->index; pi_ear = pi_ear->next; @@ -584,10 +591,10 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf ) { /* localize */ - const uint coords_num = pf->coords_num; + const uint32_t coords_num = pf->coords_num; PolyIndex *pi_ear; - uint i; + uint32_t i; /* Use two passes when looking for an ear. * @@ -670,7 +677,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign si #endif #if defined(USE_CONVEX_SKIP) && !defined(USE_KDTREE) - uint coords_num_concave_checked = 0; + uint32_t coords_num_concave_checked = 0; #endif #ifdef USE_CONVEX_SKIP @@ -678,7 +685,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign si # ifdef USE_CONVEX_SKIP_TEST /* check if counting is wrong */ { - uint coords_num_concave_test = 0; + uint32_t coords_num_concave_test = 0; PolyIndex *pi_iter = pi_ear_tip; do { if (pi_iter->sign != CONVEX) { @@ -701,7 +708,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign si #ifdef USE_KDTREE { - const uint ind[3] = {pi_ear_tip->index, pi_ear_tip->next->index, pi_ear_tip->prev->index}; + const uint32_t ind[3] = {pi_ear_tip->index, pi_ear_tip->next->index, pi_ear_tip->prev->index}; if (kdtree2d_isect_tri(&pf->kdtree, ind)) { return false; @@ -750,7 +757,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign si static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip) { - uint *tri = pf_tri_add(pf); + uint32_t *tri = pf_tri_add(pf); tri[0] = pi_ear_tip->prev->index; tri[1] = pi_ear_tip->index; @@ -764,15 +771,15 @@ static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip) */ static void polyfill_prepare(PolyFill *pf, const float (*coords)[2], - const uint coords_num, + const uint32_t coords_num, int coords_sign, - uint (*r_tris)[3], + uint32_t (*r_tris)[3], PolyIndex *r_indices) { /* localize */ PolyIndex *indices = r_indices; - uint i; + uint32_t i; /* assign all polyfill members here */ pf->indices = r_indices; @@ -810,7 +817,7 @@ static void polyfill_prepare(PolyFill *pf, } else { /* reversed */ - uint n = coords_num - 1; + uint32_t n = coords_num - 1; for (i = 0; i < coords_num; i++) { indices[i].next = &indices[i + 1]; indices[i].prev = &indices[i - 1]; @@ -849,9 +856,9 @@ static void polyfill_calc(PolyFill *pf) } void BLI_polyfill_calc_arena(const float (*coords)[2], - const uint coords_num, + const uint32_t coords_num, const int coords_sign, - uint (*r_tris)[3], + uint32_t (*r_tris)[3], struct MemArena *arena) { @@ -894,9 +901,9 @@ void BLI_polyfill_calc_arena(const float (*coords)[2], } void BLI_polyfill_calc(const float (*coords)[2], - const uint coords_num, + const uint32_t coords_num, const int coords_sign, - uint (*r_tris)[3]) + uint32_t (*r_tris)[3]) { /* Fallback to heap memory for large allocations. * Avoid running out of stack memory on systems with 512kb stack (macOS). diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c index 38cf97d6a8f3..b6750a46c012 100644 --- a/source/blender/blenlib/intern/polyfill_2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c @@ -205,11 +205,11 @@ static void polyedge_beauty_cost_update_single(const float (*coords)[2], * which leads to infinite loop. Anyway, costs above that are not worth recomputing, * maybe we could even optimize it to a smaller limit? * Actually, FLT_EPSILON is too small in some cases, 1e-6f seems to work OK hopefully? - * See T43578, T49478. + * See #43578, #49478. * * In fact a larger epsilon can still fail when the area of the face is very large, * now the epsilon is scaled by the face area. - * See T56532. */ + * See #56532. */ if (cost < -1e-6f * max_ff(area, 1.0f)) { BLI_heap_insert_or_update(eheap, &eheap_table[i], cost, e); } diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c index 4f057fb348d0..4492d8b46cfd 100644 --- a/source/blender/blenlib/intern/quadric.c +++ b/source/blender/blenlib/intern/quadric.c @@ -13,7 +13,7 @@ * even though input/output are floats in some cases. * * This is done because the cases quadrics are useful - * often need high precision, see T44780. + * often need high precision, see #44780. */ #include "BLI_math.h" diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 4145125c1d75..04e6ed4a7bbf 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -524,11 +524,11 @@ static uint scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) BLI_remlink(&sf_ctx->filledgebase, eed); /* This code is for handling zero-length edges that get * collapsed in step 0. It was removed for some time to - * fix trunk bug T4544, so if that comes back, this code + * fix trunk bug #4544, so if that comes back, this code * may need some work, or there will have to be a better - * fix to T4544. + * fix to #4544. * - * warning, this can hang on un-ordered edges, see: T33281. + * warning, this can hang on un-ordered edges, see: #33281. * for now disable 'BLI_SCANFILL_CALC_REMOVE_DOUBLES' for ngons. */ if (eed->v1->f == SF_VERT_ZERO_LEN) { @@ -660,7 +660,7 @@ static uint scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) * (concave holes) we continue searching and pick the * one with sharpest corner. */ if (best_sc == NULL) { - /* even without holes we need to keep checking T35861. */ + /* even without holes we need to keep checking #35861. */ best_sc = sc1; } else { @@ -867,7 +867,7 @@ uint BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float n * which historically this function supports so better not change */ /* WARNING: this only gives stable direction with single polygons, - * ideally we'd calculate connectivity and each polys normal, see T41047 */ + * ideally we'd calculate connectivity and each polys normal, see #41047 */ const float *v_prev; zero_v3(n); diff --git a/source/blender/blenlib/tests/BLI_math_rotation_test.cc b/source/blender/blenlib/tests/BLI_math_rotation_test.cc index 140f499ca8e7..2d74b40a90da 100644 --- a/source/blender/blenlib/tests/BLI_math_rotation_test.cc +++ b/source/blender/blenlib/tests/BLI_math_rotation_test.cc @@ -140,7 +140,7 @@ TEST(math_rotation, quat_to_mat_to_quat_near_0001) test_quat_to_mat_to_quat(0.30f, -0.030f, -0.30f, 0.95f); } -/* A zeroed matrix converted to a quaternion and back should not add rotation, see: T101848 */ +/* A zeroed matrix converted to a quaternion and back should not add rotation, see: #101848 */ TEST(math_rotation, quat_to_mat_to_quat_zeroed_matrix) { float matrix_zeroed[3][3] = {{0.0f}}; diff --git a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc index f3b66bedf88a..547300a098e3 100644 --- a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc @@ -33,6 +33,12 @@ static void polyfill_to_obj(const char *id, const uint tris[][3], const uint tris_num); +using ePolyFill2DTestFlag = enum ePolyFill2DTestFlag { + POLYFILL2D_TEST_IS_DEGENERATE = (1 << 0), + POLYFILL2D_TEST_NO_ZERO_AREA_TRIS = (1 << 1), + POLYFILL2D_TEST_NOP = 0, +}; + /* -------------------------------------------------------------------- */ /* test utility functions */ @@ -159,13 +165,31 @@ static void test_polyfill_area(const float poly[][2], EXPECT_NEAR(area_total, area_total_tris, eps); } +/** + * Check that none of the tessellated triangles are zero area. + */ +static void test_polyfill_area_tri_nonzero(const float poly[][2], + const uint /*poly_num*/, + const uint tris[][3], + const uint tris_num) +{ + uint i; + uint total = 0; + for (i = 0; i < tris_num; i++) { + if (area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]) < 1e-6f) { + total += 1; + } + } + EXPECT_EQ(total, 0); +} + /* -------------------------------------------------------------------- */ /* Macro and helpers to manage checking */ /** * Main template for polyfill testing. */ static void test_polyfill_template_check(const char *id, - bool is_degenerate, + const ePolyFill2DTestFlag test_flag, const float poly[][2], const uint poly_num, const uint tris[][3], @@ -173,16 +197,22 @@ static void test_polyfill_template_check(const char *id, { test_polyfill_simple(poly, poly_num, tris, tris_num); test_polyfill_topology(poly, poly_num, tris, tris_num); - if (!is_degenerate) { + if (!(test_flag & POLYFILL2D_TEST_IS_DEGENERATE)) { test_polyfill_winding(poly, poly_num, tris, tris_num); test_polyfill_area(poly, poly_num, tris, tris_num); + + /* Only check when non-degenerate, because the number of zero area triangles + * are undefined for degenerate polygons as there is no correct solution. */ + if (test_flag & POLYFILL2D_TEST_NO_ZERO_AREA_TRIS) { + test_polyfill_area_tri_nonzero(poly, poly_num, tris, tris_num); + } } polyfill_to_obj(id, poly, poly_num, tris, tris_num); } static void test_polyfill_template(const char *id, - bool is_degenerate, + const ePolyFill2DTestFlag test_flag, const float poly[][2], const uint poly_num, uint tris[][3], @@ -192,7 +222,7 @@ static void test_polyfill_template(const char *id, BLI_polyfill_calc(poly, poly_num, 0, tris); /* check all went well */ - test_polyfill_template_check(id, is_degenerate, poly, poly_num, tris, tris_num); + test_polyfill_template_check(id, test_flag, poly, poly_num, tris, tris_num); #ifdef USE_BEAUTIFY /* check beautify gives good results too */ @@ -202,7 +232,7 @@ static void test_polyfill_template(const char *id, BLI_polyfill_beautify(poly, poly_num, tris, pf_arena, pf_heap); - test_polyfill_template_check(id, is_degenerate, poly, poly_num, tris, tris_num); + test_polyfill_template_check(id, test_flag, poly, poly_num, tris, tris_num); BLI_memarena_free(pf_arena); BLI_heap_free(pf_heap, nullptr); @@ -211,7 +241,7 @@ static void test_polyfill_template(const char *id, } static void test_polyfill_template_flip_sign(const char *id, - bool is_degenerate, + const ePolyFill2DTestFlag test_flag, const float poly[][2], const uint poly_num, uint tris[][3], @@ -226,7 +256,7 @@ static void test_polyfill_template_flip_sign(const char *id, poly_copy[i][0] = poly[i][0] * sign_x; poly_copy[i][1] = poly[i][1] * sign_y; } - test_polyfill_template(id, is_degenerate, poly_copy, poly_num, tris, tris_num); + test_polyfill_template(id, test_flag, poly_copy, poly_num, tris, tris_num); } } MEM_freeN(poly_copy); @@ -234,7 +264,7 @@ static void test_polyfill_template_flip_sign(const char *id, #ifdef USE_COMBINATIONS_ALL static void test_polyfill_template_main(const char *id, - bool is_degenerate, + const ePolyFill2DTestFlag test_flag, const float poly[][2], const uint poly_num, uint tris[][3], @@ -256,7 +286,7 @@ static void test_polyfill_template_main(const char *id, for (poly_cycle = 0; poly_cycle < poly_num; poly_cycle++) { // printf("polytest %s ofs=%d, reverse=%d\n", id, poly_cycle, poly_reverse); - test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_num, tris, tris_num); + test_polyfill_template_flip_sign(id, test_flag, poly, poly_num, tris, tris_num); /* cycle */ copy_v2_v2(tmp, poly_copy[0]); @@ -269,24 +299,24 @@ static void test_polyfill_template_main(const char *id, } #else /* USE_COMBINATIONS_ALL */ static void test_polyfill_template_main(const char *id, - bool is_degenerate, + const ePolyFill2DTestFlag test_flag, const float poly[][2], const uint poly_num, uint tris[][3], const uint tris_num) { - test_polyfill_template_flip_sign(id, is_degenerate, poly, poly_num, tris, tris_num); + test_polyfill_template_flip_sign(id, test_flag, poly, poly_num, tris, tris_num); } #endif /* USE_COMBINATIONS_ALL */ -#define TEST_POLYFILL_TEMPLATE_STATIC(poly, is_degenerate) \ +#define TEST_POLYFILL_TEMPLATE_STATIC(poly, test_flag) \ { \ uint tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \ const uint poly_num = ARRAY_SIZE(poly); \ const uint tris_num = ARRAY_SIZE(tris); \ const char *id = typeid(*this).name(); \ \ - test_polyfill_template_main(id, is_degenerate, poly, poly_num, tris, tris_num); \ + test_polyfill_template_main(id, test_flag, poly, poly_num, tris, tris_num); \ } \ (void)0 @@ -380,56 +410,56 @@ static void polyfill_to_obj(const char *id, TEST(polyfill2d, TriangleCCW) { const float poly[][2] = {{0, 0}, {0, 1}, {1, 0}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* A counterclockwise square */ TEST(polyfill2d, SquareCCW) { const float poly[][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* A clockwise square */ TEST(polyfill2d, SquareCW) { const float poly[][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Starfleet insigna */ TEST(polyfill2d, Starfleet) { const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Starfleet insigna with repeated point */ TEST(polyfill2d, StarfleetDegenerate) { const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Three collinear points */ TEST(polyfill2d, 3Colinear) { const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Four collinear points */ TEST(polyfill2d, 4Colinear) { const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Non-consecutive collinear points */ TEST(polyfill2d, UnorderedColinear) { const float poly[][2] = {{0, 0}, {1, 1}, {2, 0}, {3, 1}, {4, 0}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Plus shape */ @@ -449,14 +479,14 @@ TEST(polyfill2d, PlusShape) {0, 1}, {1, 1}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Star shape */ TEST(polyfill2d, StarShape) { const float poly[][2] = {{4, 0}, {5, 3}, {8, 4}, {5, 5}, {4, 8}, {3, 5}, {0, 4}, {3, 3}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* U shape */ @@ -464,7 +494,7 @@ TEST(polyfill2d, UShape) { const float poly[][2] = { {1, 0}, {2, 0}, {3, 1}, {3, 3}, {2, 3}, {2, 1}, {1, 1}, {1, 3}, {0, 3}, {0, 1}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Spiral */ @@ -488,7 +518,7 @@ TEST(polyfill2d, Spiral) {4, 1}, {0, 1}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Test case from http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml */ @@ -511,14 +541,14 @@ TEST(polyfill2d, TestFlipCode) {4, 3}, {2, 6}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Self-intersection */ TEST(polyfill2d, SelfIntersect) { const float poly[][2] = {{0, 0}, {1, 1}, {2, -1}, {3, 1}, {4, 0}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, true); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_IS_DEGENERATE); } /* Self-touching */ @@ -538,7 +568,7 @@ TEST(polyfill2d, SelfTouch) {2, 4}, {0, 4}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Self-overlapping */ @@ -558,7 +588,7 @@ TEST(polyfill2d, SelfOverlap) {3, 4}, {0, 4}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, true); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_IS_DEGENERATE); } /* Test case from http://www.davdata.nl/math/polygons.html */ @@ -570,7 +600,7 @@ TEST(polyfill2d, TestDavData) {410, 30}, {470, 440}, {640, 410}, {630, 140}, {590, 140}, {580, 360}, {510, 370}, {510, 60}, {650, 70}, {660, 450}, {190, 480}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Issue 815, http://code.google.com/p/libgdx/issues/detail?id=815 */ @@ -586,7 +616,7 @@ TEST(polyfill2d, Issue815) {2.0f, 1.0f}, {2.0f, 0.0f}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Issue 207, comment #1, http://code.google.com/p/libgdx/issues/detail?id=207#c1 */ @@ -605,7 +635,7 @@ TEST(polyfill2d, Issue207_1) {126.70667f, 170.07617f}, {73.22717f, 199.51062f}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, true); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_IS_DEGENERATE); } /* Issue 207, comment #11, http://code.google.com/p/libgdx/issues/detail?id=207#c11 */ @@ -625,7 +655,7 @@ TEST(polyfill2d, Issue207_11) {1934.0381f, 485.3833f}, {1934.5234f, 484.11328f}, {1934.9502f, 482.9663f}, {1935.3125f, 481.96875f}, {1935.6045f, 481.14697f}, {1935.8203f, 480.52734f}, {1935.9541f, 480.13623f}, {1936.0f, 480.0f}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Issue 1407, http://code.google.com/p/libgdx/issues/detail?id=1407 */ @@ -637,7 +667,7 @@ TEST(polyfill2d, Issue1407) {4.8973203f, 1.9063174f}, {5.4979978f, 1.9096732f}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } /* Issue 1407, http://code.google.com/p/libgdx/issues/detail?id=1407, */ @@ -651,10 +681,10 @@ TEST(polyfill2d, Issue1407_pt) {5.4979978f, 1.9096732f}, {4, 4}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } -/* Simplified from Blender bug T40777 */ +/* Simplified from Blender bug #40777 */ TEST(polyfill2d, IssueT40777_colinear) { const float poly[][2] = { @@ -662,10 +692,10 @@ TEST(polyfill2d, IssueT40777_colinear) {0.88, 0.4}, {0.94, 0.4}, {0.94, 0}, {1, 0}, {1, 0.4}, {0.03, 0.62}, {0.03, 0.89}, {0.59, 0.89}, {0.03, 1}, {0, 1}, {0, 0}, {0.03, 0}, {0.03, 0.37}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } -/* Blender bug T41986 */ +/* Blender bug #41986 */ TEST(polyfill2d, IssueT41986_axis_align) { const float poly[][2] = { @@ -677,10 +707,10 @@ TEST(polyfill2d, IssueT41986_axis_align) {0.68, 0.06}, {0.57, -0.36}, {-0.25, -0.37}, {0.49, -0.74}, {-0.59, -1.21}, {-0.25, -0.15}, {-0.46, -0.52}, {-1.08, -0.83}, {-1.45, -0.33}, {-1.25, -0.04}}; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } -/* Blender bug T52834 */ +/* Blender bug #52834 */ TEST(polyfill2d, IssueT52834_axis_align_co_linear) { const float poly[][2] = { @@ -692,10 +722,10 @@ TEST(polyfill2d, IssueT52834_axis_align_co_linear) {18, -2}, {23, -2}, {24, -2}, {29, -2}, {30, -2}, {35, -2}, {36, -2}, {40, -2}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } -/* Blender bug T67109 (version a). */ +/* Blender bug #67109 (version a). */ /* Multiple versions are offset & rotated, this fails in cases where others works. */ TEST(polyfill2d, IssueT67109_axis_align_co_linear_a) { @@ -711,10 +741,10 @@ TEST(polyfill2d, IssueT67109_axis_align_co_linear_a) {2.8720665, -2.6659985}, {2.8720665, -0.15499878}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } -/* Blender bug T67109, (version b). */ +/* Blender bug #67109, (version b). */ TEST(polyfill2d, IssueT67109_axis_align_co_linear_b) { const float poly[][2] = { @@ -729,10 +759,10 @@ TEST(polyfill2d, IssueT67109_axis_align_co_linear_b) {25.825695, -6.320076}, {24.00582, -4.5899982}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); } -/* Blender bug T67109 (version c). */ +/* Blender bug #67109 (version c). */ TEST(polyfill2d, IssueT67109_axis_align_co_linear_c) { const float poly[][2] = { @@ -747,5 +777,19 @@ TEST(polyfill2d, IssueT67109_axis_align_co_linear_c) {-60.546703, 71.07365}, {-58.37554, 78.83239}, }; - TEST_POLYFILL_TEMPLATE_STATIC(poly, false); + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NOP); +} + +/* Blender bug #103913 where co-linear edges create zero area tessellation + * when a valid solution exists without zero area triangles. */ +TEST(polyfill2d, Issue103913_axis_align_co_linear_no_zero_area_tri) +{ + const float poly[][2] = { + {-10, 0}, {-10, 2}, {-8, 2}, {-6, 2}, {-4, 2}, {-2, 2}, {-2, 4}, {-2, 6}, + {-2, 8}, {-2, 10}, {0, 10}, {2, 10}, {2, 8}, {2, 6}, {2, 4}, {2, 2}, + {4, 2}, {6, 2}, {8, 2}, {10, 2}, {10, 0}, {10, -2}, {8, -2}, {6, -2}, + {4, -2}, {2, -2}, {2, -4}, {2, -6}, {2, -8}, {2, -10}, {0, -10}, {-2, -10}, + {-2, -8}, {-2, -6}, {-2, -4}, {-2, -2}, {-4, -2}, {-6, -2}, {-8, -2}, {-10, -2}, + }; + TEST_POLYFILL_TEMPLATE_STATIC(poly, POLYFILL2D_TEST_NO_ZERO_AREA_TRIS); } diff --git a/source/blender/blenlib/tests/BLI_string_test.cc b/source/blender/blenlib/tests/BLI_string_test.cc index d726fbccf209..9ea46f22890d 100644 --- a/source/blender/blenlib/tests/BLI_string_test.cc +++ b/source/blender/blenlib/tests/BLI_string_test.cc @@ -612,6 +612,25 @@ TEST(string, StrFormatIntegerUnits) EXPECT_STREQ("-2B", size_str); } +TEST(string, StringNLen) +{ + EXPECT_EQ(0, BLI_strnlen("", 0)); + EXPECT_EQ(0, BLI_strnlen("", 1)); + EXPECT_EQ(0, BLI_strnlen("", 100)); + + EXPECT_EQ(0, BLI_strnlen("x", 0)); + EXPECT_EQ(1, BLI_strnlen("x", 1)); + EXPECT_EQ(1, BLI_strnlen("x", 100)); + + // ü is \xc3\xbc + EXPECT_EQ(2, BLI_strnlen("ü", 100)); + + EXPECT_EQ(0, BLI_strnlen("this is a longer string", 0)); + EXPECT_EQ(1, BLI_strnlen("this is a longer string", 1)); + EXPECT_EQ(5, BLI_strnlen("this is a longer string", 5)); + EXPECT_EQ(47, BLI_strnlen("This string writes about an agent without name.", 100)); +} + struct WordInfo { WordInfo() = default; WordInfo(int start, int end) : start(start), end(end) diff --git a/source/blender/blenloader/intern/readfile.cc b/source/blender/blenloader/intern/readfile.cc index c440dbf8c7af..29730f7f10ad 100644 --- a/source/blender/blenloader/intern/readfile.cc +++ b/source/blender/blenloader/intern/readfile.cc @@ -162,7 +162,7 @@ * which keeps large arrays in memory from data-blocks we may not even use. * * \note This is disabled when using compression, - * while ZLIB supports seek it's unusably slow, see: T61880. + * while ZLIB supports seek it's unusably slow, see: #61880. */ #define USE_BHEAD_READ_ON_DEMAND @@ -2038,7 +2038,7 @@ static void direct_link_id_common( /* No-main and other types of special IDs should never be written in .blend files. */ /* NOTE: `NO_MAIN` is commented for now as some code paths may still generate embedded IDs with - * this tag, see T103389. Related to T88555. */ + * this tag, see #103389. Related to #88555. */ BLI_assert( (id->tag & (/*LIB_TAG_NO_MAIN |*/ LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0); @@ -2111,7 +2111,7 @@ static void direct_link_id_common( /* Link direct data of overrides. */ if (id->override_library) { BLO_read_data_address(reader, &id->override_library); - /* Work around file corruption on writing, see T86853. */ + /* Work around file corruption on writing, see #86853. */ if (id->override_library != nullptr) { BLO_read_list_cb( reader, &id->override_library->properties, direct_link_id_override_property_cb); @@ -2471,7 +2471,7 @@ static void lib_link_workspace_layout_restore(IDNameLib_Map *id_map, sbuts->flag &= ~SB_PIN_CONTEXT; } - /* TODO: restore path pointers: T40046 + /* TODO: restore path pointers: #40046 * (complicated because this contains data pointers too, not just ID). */ MEM_SAFE_FREE(sbuts->path); break; @@ -2496,7 +2496,7 @@ static void lib_link_workspace_layout_restore(IDNameLib_Map *id_map, } /* force recalc of list of channels, potentially updating the active action - * while we're at it (as it can only be updated that way) T28962. + * while we're at it (as it can only be updated that way) #28962. */ saction->runtime.flag |= SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC; break; @@ -2731,7 +2731,7 @@ void blo_lib_link_restore(Main *oldmain, /* Restore all ID pointers in Main database itself * (especially IDProperties might point to some word-space of other 'weirdly unchanged' ID - * pointers, see T69146). + * pointers, see #69146). * Note that this will re-apply again a few pointers in workspaces or so, * but since we are remapping final ones already set above, * that is just some minor harmless double-processing. */ @@ -2774,7 +2774,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main) * where to add all non-library data-blocks found in file next, we have to switch that * 'dupli' found Main to latest position in the list! * Otherwise, you get weird disappearing linked data on a rather inconsistent basis. - * See also T53977 for reproducible case. */ + * See also #53977 for reproducible case. */ BLI_remlink(fd->mainlist, newmain); BLI_addtail(fd->mainlist, newmain); @@ -2817,7 +2817,7 @@ static void fix_relpaths_library(const char *basepath, Main *main) /* when loading a linked lib into a file which has not been saved, * there is nothing we can be relative to, so instead we need to make * it absolute. This can happen when appending an object with a relative - * link into an unsaved blend file. See T27405. + * link into an unsaved blend file. See #27405. * The remap relative option will make it relative again on save - campbell */ if (BLI_path_is_rel(lib->filepath)) { BLI_strncpy(lib->filepath, lib->filepath_abs, sizeof(lib->filepath)); @@ -3078,7 +3078,7 @@ static bool read_libblock_undo_restore_library(FileData *fd, Main *main, const I * (see BLO_read_from_memfile). * However, some needed by the snapshot being read may have been removed in previous one, * and would go missing. - * This leads e.g. to disappearing objects in some undo/redo case, see T34446. + * This leads e.g. to disappearing objects in some undo/redo case, see #34446. * That means we have to carefully check whether current lib or * libdata already exits in old main, if it does we merely copy it over into new main area, * otherwise we have to do a full read of that bhead... */ @@ -3982,8 +3982,8 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) BKE_lib_override_library_main_update(bfd->main); /* FIXME Temporary 'fix' to a problem in how temp ID are copied in - * `BKE_lib_override_library_main_update`, see T103062. - * Proper fix involves first addressing T90610. */ + * `BKE_lib_override_library_main_update`, see #103062. + * Proper fix involves first addressing #90610. */ BKE_main_collections_parent_relations_rebuild(bfd->main); fd->reports->duration.lib_overrides = PIL_check_seconds_timer() - @@ -4612,8 +4612,8 @@ static void library_link_end(Main *mainl, FileData **fd, const int flag) BKE_main_id_tag_all(mainvar, LIB_TAG_NEW, false); /* FIXME Temporary 'fix' to a problem in how temp ID are copied in - * `BKE_lib_override_library_main_update`, see T103062. - * Proper fix involves first addressing T90610. */ + * `BKE_lib_override_library_main_update`, see #103062. + * Proper fix involves first addressing #90610. */ BKE_main_collections_parent_relations_rebuild(mainvar); /* Make all relative paths, relative to the open blend file. */ diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 5d2072e0fd94..fb806a0b1246 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -2115,7 +2115,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 258, 1)) { - /* screen view2d settings were not properly initialized T27164. + /* screen view2d settings were not properly initialized #27164. * v2d->scroll caused the bug but best reset other values too * which are in old blend files only. * Need to make less ugly - possibly an iterator? */ diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 8cfd66576ff3..0a4211315c0c 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -1587,7 +1587,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain) /* correction for files saved in blender version when BKE_pose_copy_data * didn't copy animation visualization, which lead to deadlocks on motion - * path calculation for proxied armatures, see T32742. + * path calculation for proxied armatures, see #32742. */ if (bmain->versionfile < 264) { Object *ob; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 5d966344717b..067918976c7a 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -409,7 +409,7 @@ static void do_version_bbone_easing_fcurve_fix(ID *UNUSED(id), FMod_Stepped *data = fcm->data; /* Modifier doesn't work if the modifier's copy of start/end frame are both 0 - * as those were only getting written to the fcm->data copy (T52009) + * as those were only getting written to the fcm->data copy (#52009) */ if ((fcm->sfra == fcm->efra) && (fcm->sfra == 0)) { fcm->sfra = data->start_frame; @@ -557,7 +557,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 270, 4)) { /* ui_previews were not handled correctly when copying areas, - * leading to corrupted files (see T39847). + * leading to corrupted files (see #39847). * This will always reset situation to a valid state. */ bScreen *screen; @@ -1551,7 +1551,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /* Fix for T50736, Glare comp node using same var for two different things. */ + /* Fix for #50736, Glare comp node using same var for two different things. */ if (!DNA_struct_elem_find(fd->filesdna, "NodeGlare", "char", "star_45")) { FOREACH_NODETREE_BEGIN (bmain, ntree, id) { if (ntree->type == NTREE_COMPOSIT) { @@ -1602,7 +1602,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /* Fix related to VGroup modifiers creating named defgroup CD layers! See T51520. */ + /* Fix related to VGroup modifiers creating named defgroup CD layers! See #51520. */ for (Mesh *me = bmain->meshes.first; me; me = me->id.next) { CustomData_set_layer_name(&me->vdata, CD_MDEFORMVERT, 0, ""); } diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 2e9a16bc945e..ff8606776634 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1206,7 +1206,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) } if (collection_hidden == NULL) { /* This should never happen (objects are always supposed to be instantiated in a - * scene), but it does sometimes, see e.g. T81168. + * scene), but it does sometimes, see e.g. #81168. * Just put them in first hidden collection in those cases. */ collection_hidden = &hidden_collection_array[0]; } @@ -1739,7 +1739,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) /* NOTE: This version patch is intended for versions < 2.52.2, * but was initially introduced in 2.27 already. * But in 2.79 another case generating non-unique names was discovered - * (see T55668, involving Meta strips). */ + * (see #55668, involving Meta strips). */ static void do_versions_seq_unique_name_all_strips(Scene *sce, ListBase *seqbasep) { for (Sequence *seq = seqbasep->first; seq != NULL; seq = seq->next) { diff --git a/source/blender/blenloader/intern/versioning_290.cc b/source/blender/blenloader/intern/versioning_290.cc index 9c968e905cf9..b90e7529bbc4 100644 --- a/source/blender/blenloader/intern/versioning_290.cc +++ b/source/blender/blenloader/intern/versioning_290.cc @@ -721,7 +721,7 @@ static void do_versions_point_attributes(CustomData *pdata) static void do_versions_point_attribute_names(CustomData *pdata) { - /* Change from capital initial letter to lower case (T82693). */ + /* Change from capital initial letter to lower case (#82693). */ for (int i = 0; i < pdata->totlayer; i++) { CustomDataLayer *layer = &pdata->layers[i]; if (layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, "Position")) { @@ -841,7 +841,7 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain) } } - /** Repair files from duplicate brushes added to blend files, see: T76738. */ + /** Repair files from duplicate brushes added to blend files, see: #76738. */ if (!MAIN_VERSION_ATLEAST(bmain, 290, 2)) { { short id_codes[] = {ID_BR, ID_PAL}; @@ -1156,7 +1156,7 @@ void blo_do_versions_290(FileData *fd, Library * /*lib*/, Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 291, 5)) { - /* Fix fcurves to allow for new bezier handles behavior (T75881 and D8752). */ + /* Fix fcurves to allow for new bezier handles behavior (#75881 and D8752). */ LISTBASE_FOREACH (bAction *, act, &bmain->actions) { LISTBASE_FOREACH (FCurve *, fcu, &act->curves) { /* Only need to fix Bezier curves with at least 2 key-frames. */ diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index 4cadc4ff0285..4a1c14bd4304 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -1601,6 +1601,12 @@ static bool version_merge_still_offsets(Sequence *seq, void * /*user_data*/) return true; } +static bool version_fix_delete_flag(Sequence *seq, void * /*user_data*/) +{ + seq->flag &= ~SEQ_FLAG_DELETE; + return true; +} + /* Those `version_liboverride_rnacollections_*` functions mimic the old, pre-3.0 code to find * anchor and source items in the given list of modifiers, constraints etc., using only the * `subitem_local` data of the override property operation. @@ -2251,7 +2257,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 300, 9)) { /* Fix a bug where reordering FCurves and bActionGroups could cause some corruption. Just * reconstruct all the action groups & ensure that the FCurves of a group are continuously - * stored (i.e. not mixed with other groups) to be sure. See T89435. */ + * stored (i.e. not mixed with other groups) to be sure. See #89435. */ LISTBASE_FOREACH (bAction *, act, &bmain->actions) { BKE_action_groups_reconstruct(act); } @@ -2363,7 +2369,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } } - /* Font names were copied directly into ID names, see: T90417. */ + /* Font names were copied directly into ID names, see: #90417. */ if (!MAIN_VERSION_ATLEAST(bmain, 300, 16)) { ListBase *lb = which_libbase(bmain, ID_VF); BKE_main_id_repair_duplicate_names_listbase(bmain, lb); @@ -3606,7 +3612,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 303, 5)) { - /* Fix for T98925 - remove channels region, that was initialized in incorrect editor types. */ + /* Fix for #98925 - remove channels region, that was initialized in incorrect editor types. */ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { @@ -3636,7 +3642,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } /* Disable 'show_bounds' option of curve objects. Option was set as there was no object mode - * outline implementation. See T95933. */ + * outline implementation. See #95933. */ LISTBASE_FOREACH (Object *, ob, &bmain->objects) { if (ob->type == OB_CURVES) { ob->dtx &= ~OB_DRAWBOUNDOX; @@ -3738,7 +3744,7 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 304, 5)) { - /* Fix for T101622 - update flags of sequence editor regions that were not initialized + /* Fix for #101622 - update flags of sequence editor regions that were not initialized * properly. */ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { @@ -3892,6 +3898,81 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 305, 9)) { + /* Enable legacy normal and rotation outputs in Distribute Points on Faces node. */ + LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) { + if (ntree->type != NTREE_GEOMETRY) { + continue; + } + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type != GEO_NODE_DISTRIBUTE_POINTS_ON_FACES) { + continue; + } + node->custom2 = true; + } + } + } + + if (!MAIN_VERSION_ATLEAST(bmain, 305, 10)) { + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype != SPACE_FILE) { + continue; + } + SpaceFile *sfile = reinterpret_cast(sl); + if (!sfile->asset_params) { + continue; + } + + /* When an asset browser uses the default import method, make it follow the new + * preference setting. This means no effective default behavior change. */ + if (sfile->asset_params->import_type == FILE_ASSET_IMPORT_APPEND_REUSE) { + sfile->asset_params->import_type = FILE_ASSET_IMPORT_FOLLOW_PREFS; + } + } + } + } + + if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "int", "shadow_pool_size")) { + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + scene->eevee.flag |= SCE_EEVEE_SHADOW_ENABLED; + scene->eevee.shadow_pool_size = 512; + scene->r.simplify_shadows = 1.0f; + scene->r.simplify_shadows_render = 1.0f; + } + } + + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + v3d->overlay.flag |= V3D_OVERLAY_SCULPT_CURVES_CAGE; + v3d->overlay.sculpt_curves_cage_opacity = 0.5f; + } + } + } + } + + /* Fix possible uncleared `SEQ_FLAG_DELETE` flag */ + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + Editing *ed = SEQ_editing_get(scene); + if (ed != nullptr) { + SEQ_for_each_callback(&ed->seqbase, version_fix_delete_flag, nullptr); + } + } + + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if (brush->ob_mode == OB_MODE_SCULPT_CURVES) { + if (brush->curves_sculpt_settings->curve_parameter_falloff == nullptr) { + brush->curves_sculpt_settings->curve_parameter_falloff = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + } + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -3902,15 +3983,6 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) * \note Keep this message at the bottom of the function. */ { - if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "int", "shadow_pool_size")) { - LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { - scene->eevee.flag |= SCE_EEVEE_SHADOW_ENABLED; - scene->eevee.shadow_pool_size = 512; - scene->r.simplify_shadows = 1.0f; - scene->r.simplify_shadows_render = 1.0f; - } - } - /* Keep this block, even when empty. */ } } diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index f6fe45ddcdf4..d19616223cd9 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -82,7 +82,7 @@ static void blo_update_defaults_screen(bScreen *screen, LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { /* Some toolbars have been saved as initialized, - * we don't want them to have odd zoom-level or scrolling set, see: T47047 */ + * we don't want them to have odd zoom-level or scrolling set, see: #47047 */ if (ELEM(region->regiontype, RGN_TYPE_UI, RGN_TYPE_TOOLS, RGN_TYPE_TOOL_PROPS)) { region->v2d.flag &= ~V2D_IS_INIT; } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 10a21356c8fe..3c4b1a04d635 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -773,6 +773,12 @@ void blo_do_versions_userdef(UserDef *userdef) userdef->gpu_backend = GPU_BACKEND_OPENGL; } + if (!USER_VERSION_ATLEAST(305, 10)) { + LISTBASE_FOREACH (bUserAssetLibrary *, asset_library, &userdef->asset_libraries) { + asset_library->import_method = ASSET_IMPORT_APPEND_REUSE; + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/blenloader/intern/writefile.cc b/source/blender/blenloader/intern/writefile.cc index 57ac9d650d9b..a95e3180b677 100644 --- a/source/blender/blenloader/intern/writefile.cc +++ b/source/blender/blenloader/intern/writefile.cc @@ -788,7 +788,7 @@ static void current_screen_compat(Main *mainvar, if (wm) { if (use_active_win) { - /* write the active window into the file, needed for multi-window undo T43424 */ + /* write the active window into the file, needed for multi-window undo #43424 */ for (window = static_cast(wm->windows.first); window; window = window->next) { if (window->active) { break; @@ -1472,7 +1472,7 @@ bool BLO_write_file(Main *mainvar, if (remap_mode != BLO_WRITE_PATH_REMAP_NONE) { /* Some path processing (e.g. with libraries) may use the current `main->filepath`, if this * is not matching the path currently used for saving, unexpected paths corruptions can - * happen. See T98201. */ + * happen. See #98201. */ char mainvar_filepath_orig[FILE_MAX]; STRNCPY(mainvar_filepath_orig, mainvar->filepath); STRNCPY(mainvar->filepath, filepath); diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 16db91595ec1..8f21ed63df24 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -827,7 +827,7 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data) } if (oldpool) { - /* this should never happen but can when dissolve fails - T28960. */ + /* this should never happen but can when dissolve fails - #28960. */ BLI_assert(data->pool != oldpool); BLI_mempool_destroy(oldpool); diff --git a/source/blender/bmesh/intern/bmesh_iterators.cc b/source/blender/bmesh/intern/bmesh_iterators.cc index 91ece97fa215..d712fe8c7313 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.cc +++ b/source/blender/bmesh/intern/bmesh_iterators.cc @@ -352,7 +352,7 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const * VERT OF MESH CALLBACKS */ -/* see bug T36923 for why we need this, +/* see bug #36923 for why we need this, * allow adding but not removing, this isn't _totally_ safe since * you could add/remove within the same loop, but catches common cases */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index e4319c23c4e7..d84f163f978f 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -77,7 +77,7 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX]; BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++) /* a version of BM_ITER_MESH which keeps the next item in storage - * so we can delete the current item, see bug T36923. */ + * so we can delete the current item, see bug #36923. */ #ifdef DEBUG # define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \ diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index a8a9390f525c..e44bf2d4b098 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -305,7 +305,7 @@ static void bm_log_faces_restore(BMesh *bm, BMLog *log, GHash *faces) f->head.hflag = lf->hflag; bm_log_face_id_set(log, f, POINTER_AS_UINT(key)); - /* Ensure face sets have valid values. Fixes T80174. */ + /* Ensure face sets have valid values. Fixes #80174. */ if (cd_face_sets != -1) { BM_ELEM_CD_SET_INT(f, cd_face_sets, 1); } diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index a1c2815ab2fc..a81e70b4e67e 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -604,7 +604,7 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select) * * Rely on #BM_mesh_select_mode_flush to correct these cases. * - * \note flushing based on mode, see T46494 + * \note flushing based on mode, see #46494 */ if (bm->selectmode & SCE_SELECT_VERTEX) { l_iter = l_first = BM_FACE_FIRST_LOOP(f); diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index 35f59a2f1433..ea193cc8d85a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -85,6 +85,7 @@ #include "BLI_span.hh" #include "BLI_string_ref.hh" #include "BLI_task.hh" +#include "BLI_vector.hh" #include "BKE_attribute.hh" #include "BKE_customdata.h" @@ -110,6 +111,7 @@ using blender::IndexRange; using blender::MutableSpan; using blender::Span; using blender::StringRef; +using blender::Vector; static char bm_edge_flag_from_mflag(const short mflag) { @@ -164,6 +166,63 @@ static BMFace *bm_face_create_from_mpoly(BMesh &bm, return BM_face_create(&bm, verts.data(), edges.data(), loops.size(), nullptr, BM_CREATE_SKIP_CD); } +struct MeshToBMeshLayerInfo { + eCustomDataType type; + /** The layer's position in the BMesh element's data block. */ + int bmesh_offset; + /** The mesh's #CustomDataLayer::data. When null, the BMesh block is set to its default value. */ + const void *mesh_data; + /** The size of every custom data element. */ + size_t elem_size; +}; + +/** + * Calculate the necessary information to copy every data layer from the Mesh to the BMesh. + */ +static Vector mesh_to_bm_copy_info_calc(const CustomData &mesh_data, + CustomData &bm_data) +{ + Vector infos; + std::array per_type_index; + per_type_index.fill(0); + for (const int i : IndexRange(bm_data.totlayer)) { + const CustomDataLayer &bm_layer = bm_data.layers[i]; + const eCustomDataType type = eCustomDataType(bm_layer.type); + const int mesh_layer_index = + bm_layer.name[0] == '\0' ? + CustomData_get_layer_index_n(&mesh_data, type, per_type_index[type]) : + CustomData_get_named_layer_index(&mesh_data, type, bm_layer.name); + + MeshToBMeshLayerInfo info{}; + info.type = type; + info.bmesh_offset = bm_layer.offset; + info.mesh_data = (mesh_layer_index == -1) ? nullptr : mesh_data.layers[mesh_layer_index].data; + info.elem_size = CustomData_get_elem_size(&bm_layer); + infos.append(info); + + per_type_index[type]++; + } + return infos; +} + +static void mesh_attributes_copy_to_bmesh_block(CustomData &data, + const Span copy_info, + const int mesh_index, + BMHeader &header) +{ + CustomData_bmesh_alloc_block(&data, &header.data); + for (const MeshToBMeshLayerInfo &info : copy_info) { + if (info.mesh_data) { + CustomData_data_copy_value(info.type, + POINTER_OFFSET(info.mesh_data, info.elem_size * mesh_index), + POINTER_OFFSET(header.data, info.bmesh_offset)); + } + else { + CustomData_data_set_default_value(info.type, POINTER_OFFSET(header.data, info.bmesh_offset)); + } + } +} + void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params) { if (!me) { @@ -343,6 +402,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } } + const Vector vert_info = mesh_to_bm_copy_info_calc(mesh_vdata, bm->vdata); + const Vector edge_info = mesh_to_bm_copy_info_calc(mesh_edata, bm->edata); + const Vector poly_info = mesh_to_bm_copy_info_calc(mesh_pdata, bm->pdata); + const Vector loop_info = mesh_to_bm_copy_info_calc(mesh_ldata, bm->ldata); if (is_new) { CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT); CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE); @@ -393,8 +456,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar copy_v3_v3(v->no, vert_normals[i]); } - /* Copy Custom Data */ - CustomData_to_bmesh_block(&mesh_vdata, &bm->vdata, i, &v->head.data, true); + mesh_attributes_copy_to_bmesh_block(bm->vdata, vert_info, i, v->head); /* Set shape key original index. */ if (cd_shape_keyindex_offset != -1) { @@ -432,8 +494,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar BM_elem_flag_enable(e, BM_ELEM_SMOOTH); } - /* Copy Custom Data */ - CustomData_to_bmesh_block(&mesh_edata, &bm->edata, i, &e->head.data, true); + mesh_attributes_copy_to_bmesh_block(bm->edata, edge_info, i, e->head); } if (is_new) { bm->elem_index_dirty &= ~BM_EDGE; /* Added in order, clear dirty flag. */ @@ -491,12 +552,11 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar /* Don't use 'j' since we may have skipped some faces, hence some loops. */ BM_elem_index_set(l_iter, totloops++); /* set_ok */ - /* Save index of corresponding #MLoop. */ - CustomData_to_bmesh_block(&mesh_ldata, &bm->ldata, j++, &l_iter->head.data, true); + mesh_attributes_copy_to_bmesh_block(bm->ldata, loop_info, j, l_iter->head); + j++; } while ((l_iter = l_iter->next) != l_first); - /* Copy Custom Data */ - CustomData_to_bmesh_block(&mesh_pdata, &bm->pdata, i, &f->head.data, true); + mesh_attributes_copy_to_bmesh_block(bm->pdata, poly_info, i, f->head); if (params->calc_face_normal) { BM_face_normal_update(f); @@ -601,7 +661,7 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) * ===================== * * Key blocks locations must *not* be used. This was done from v2.67 to 3.0, - * causing bugs T35170 & T44415. + * causing bugs #35170 & #44415. * * Shape key synchronizing could work under the assumption that the key-block is * fixed-in-place when entering edit-mode allowing them to be used as a reference when exiting. @@ -776,7 +836,7 @@ static void bm_to_mesh_shape(BMesh *bm, /* Without this, the real mesh coordinates (uneditable) as soon as you create the Basis shape. * while users might not notice since the shape-key is applied in the viewport, - * exporters for example may still use the underlying coordinates, see: T30771 & T96135. + * exporters for example may still use the underlying coordinates, see: #30771 & #96135. * * Needed when editing any shape that isn't the (`key->refkey`), the vertices in mesh positions * currently have vertex coordinates set from the current-shape (initialized from #BMVert.co). @@ -846,7 +906,7 @@ static void bm_to_mesh_shape(BMesh *bm, /* Apply back new coordinates shape-keys that have offset into #BMesh. * Otherwise, in case we call again #BM_mesh_bm_to_me on same #BMesh, * we'll apply diff from previous call to #BM_mesh_bm_to_me, - * to shape-key values from original creation of the #BMesh. See T50524. */ + * to shape-key values from original creation of the #BMesh. See #50524. */ copy_v3_v3(co_orig, currkey_data[i]); } } @@ -998,6 +1058,66 @@ static void convert_bmesh_selection_flags_to_mesh_attributes(BMesh &bm, } } +struct BMeshToMeshLayerInfo { + eCustomDataType type; + /** The layer's position in the BMesh element's data block. */ + int bmesh_offset; + /** The mesh's #CustomDataLayer::data. When null, the BMesh block is set to its default value. */ + void *mesh_data; + /** The size of every custom data element. */ + size_t elem_size; +}; + +/** + * Calculate the necessary information to copy every data layer from the BMesh to the Mesh. + */ +static Vector bm_to_mesh_copy_info_calc(const CustomData &bm_data, + CustomData &mesh_data) +{ + Vector infos; + std::array per_type_index; + per_type_index.fill(0); + for (const int i : IndexRange(mesh_data.totlayer)) { + const CustomDataLayer &mesh_layer = mesh_data.layers[i]; + const eCustomDataType type = eCustomDataType(mesh_layer.type); + const int bm_layer_index = + mesh_layer.name[0] == '\0' ? + CustomData_get_layer_index_n(&bm_data, type, per_type_index[type]) : + CustomData_get_named_layer_index(&bm_data, type, mesh_layer.name); + + /* Skip layers that don't exist in `bm_data` or are explicitly set to not be + * copied. The layers are either set separately or shouldn't exist on the mesh. */ + if (bm_layer_index == -1) { + continue; + } + const CustomDataLayer &bm_layer = bm_data.layers[bm_layer_index]; + if (bm_layer.flag & CD_FLAG_NOCOPY) { + continue; + } + + BMeshToMeshLayerInfo info{}; + info.type = type; + info.bmesh_offset = bm_layer.offset; + info.mesh_data = mesh_layer.data; + info.elem_size = CustomData_get_elem_size(&mesh_layer); + infos.append(info); + + per_type_index[type]++; + } + return infos; +} + +static void bmesh_block_copy_to_mesh_attributes(const Span copy_info, + const int mesh_index, + const void *block) +{ + for (const BMeshToMeshLayerInfo &info : copy_info) { + CustomData_data_copy_value(info.type, + POINTER_OFFSET(block, info.bmesh_offset), + POINTER_OFFSET(info.mesh_data, info.elem_size * mesh_index)); + } +} + void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) { using namespace blender; @@ -1011,6 +1131,8 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh const int ototvert = me->totvert; + blender::Vector ldata_layers_marked_nocopy; + /* Free custom data. */ CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); @@ -1026,7 +1148,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh me->totloop = bm->totloop; me->totpoly = bm->totface; /* Will be overwritten with a valid value if 'dotess' is set, otherwise we - * end up with 'me->totface' and `me->mface == nullptr` which can crash T28625. */ + * end up with 'me->totface' and `me->mface == nullptr` which can crash #28625. */ me->totface = 0; me->act_face = -1; @@ -1041,9 +1163,17 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh &bm->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(layer_name, sub_layer_name)); int pin_layer_index = CustomData_get_named_layer_index( &bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(layer_name, sub_layer_name)); - int vertsel_offset = bm->ldata.layers[vertsel_layer_index].offset; - int edgesel_offset = bm->ldata.layers[edgesel_layer_index].offset; - int pin_offset = bm->ldata.layers[pin_layer_index].offset; + + /* If ever the uv map associated bool layers become optional in BMesh as well (like in Mesh) + * this assert needs to be removed. For now it is a bug if they don't exist. */ + BLI_assert(vertsel_layer_index >= 0 && edgesel_layer_index >= 0 && pin_layer_index >= 0); + + int vertsel_offset = vertsel_layer_index >= 0 ? bm->ldata.layers[vertsel_layer_index].offset : + -1; + int edgesel_offset = edgesel_layer_index >= 0 ? bm->ldata.layers[edgesel_layer_index].offset : + -1; + int pin_offset = pin_layer_index >= 0 ? bm->ldata.layers[pin_layer_index].offset : -1; + bool need_vertsel = false; bool need_edgesel = false; bool need_pin = false; @@ -1051,10 +1181,20 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { BMIter liter; BMLoop *l; - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - need_vertsel |= BM_ELEM_CD_GET_BOOL(l, vertsel_offset); - need_edgesel |= BM_ELEM_CD_GET_BOOL(l, edgesel_offset); - need_pin |= BM_ELEM_CD_GET_BOOL(l, pin_offset); + if (vertsel_layer_index >= 0) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + need_vertsel |= BM_ELEM_CD_GET_BOOL(l, vertsel_offset); + } + } + if (edgesel_layer_index >= 0) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + need_edgesel |= BM_ELEM_CD_GET_BOOL(l, edgesel_offset); + } + } + if (pin_layer_index) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + need_pin |= BM_ELEM_CD_GET_BOOL(l, pin_offset); + } } } @@ -1063,18 +1203,21 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } else { bm->ldata.layers[vertsel_layer_index].flag |= CD_FLAG_NOCOPY; + ldata_layers_marked_nocopy.append(vertsel_layer_index); } if (need_edgesel) { bm->ldata.layers[edgesel_layer_index].flag &= ~CD_FLAG_NOCOPY; } else { bm->ldata.layers[edgesel_layer_index].flag |= CD_FLAG_NOCOPY; + ldata_layers_marked_nocopy.append(edgesel_layer_index); } if (need_pin) { bm->ldata.layers[pin_layer_index].flag &= ~CD_FLAG_NOCOPY; } else { bm->ldata.layers[pin_layer_index].flag |= CD_FLAG_NOCOPY; + ldata_layers_marked_nocopy.append(pin_layer_index); } } @@ -1087,6 +1230,16 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_SET_DEFAULT, me->totpoly); } + const Vector vert_info = bm_to_mesh_copy_info_calc(bm->vdata, me->vdata); + const Vector edge_info = bm_to_mesh_copy_info_calc(bm->edata, me->edata); + const Vector poly_info = bm_to_mesh_copy_info_calc(bm->pdata, me->pdata); + const Vector loop_info = bm_to_mesh_copy_info_calc(bm->ldata, me->ldata); + + /* Clear the CD_FLAG_NOCOPY flags for the layers they were temporarily set on */ + for (const int i : ldata_layers_marked_nocopy) { + bm->ldata.layers[i].flag &= ~CD_FLAG_NOCOPY; + } + CustomData_add_layer_named( &me->vdata, CD_PROP_FLOAT3, CD_CONSTRUCT, nullptr, me->totvert, "position"); CustomData_add_layer(&me->edata, CD_MEDGE, CD_SET_DEFAULT, nullptr, me->totedge); @@ -1119,8 +1272,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_elem_index_set(v, i); /* set_inline */ - /* Copy over custom-data. */ - CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i); + bmesh_block_copy_to_mesh_attributes(vert_info, i, v->head.data); i++; @@ -1146,8 +1298,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_elem_index_set(e, i); /* set_inline */ - /* Copy over custom-data. */ - CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i); + bmesh_block_copy_to_mesh_attributes(edge_info, i, e->head.data); i++; BM_CHECK_ELEMENT(e); @@ -1176,8 +1327,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh mloop[j].e = BM_elem_index_get(l_iter->e); mloop[j].v = BM_elem_index_get(l_iter->v); - /* Copy over custom-data. */ - CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j); + bmesh_block_copy_to_mesh_attributes(loop_info, j, l_iter->head.data); j++; BM_CHECK_ELEMENT(l_iter); @@ -1189,8 +1339,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh me->act_face = i; } - /* Copy over custom-data. */ - CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i); + bmesh_block_copy_to_mesh_attributes(poly_info, i, f->head.data); i++; BM_CHECK_ELEMENT(f); @@ -1399,12 +1548,13 @@ static void bm_to_mesh_verts(const BMesh &bm, MutableSpan select_vert, MutableSpan hide_vert) { + const Vector info = bm_to_mesh_copy_info_calc(bm.vdata, mesh.vdata); MutableSpan dst_vert_positions = mesh.vert_positions_for_write(); threading::parallel_for(dst_vert_positions.index_range(), 1024, [&](const IndexRange range) { for (const int vert_i : range) { const BMVert &src_vert = *bm_verts[vert_i]; copy_v3_v3(dst_vert_positions[vert_i], src_vert.co); - CustomData_from_bmesh_block(&bm.vdata, &mesh.vdata, src_vert.head.data, vert_i); + bmesh_block_copy_to_mesh_attributes(info, vert_i, src_vert.head.data); } if (!select_vert.is_empty()) { for (const int vert_i : range) { @@ -1426,6 +1576,7 @@ static void bm_to_mesh_edges(const BMesh &bm, MutableSpan hide_edge, MutableSpan sharp_edge) { + const Vector info = bm_to_mesh_copy_info_calc(bm.edata, mesh.edata); MutableSpan dst_edges = mesh.edges_for_write(); threading::parallel_for(dst_edges.index_range(), 512, [&](const IndexRange range) { for (const int edge_i : range) { @@ -1434,7 +1585,7 @@ static void bm_to_mesh_edges(const BMesh &bm, dst_edge.v1 = BM_elem_index_get(src_edge.v1); dst_edge.v2 = BM_elem_index_get(src_edge.v2); dst_edge.flag = bm_edge_flag_to_mflag(&src_edge); - CustomData_from_bmesh_block(&bm.edata, &mesh.edata, src_edge.head.data, edge_i); + bmesh_block_copy_to_mesh_attributes(info, edge_i, src_edge.head.data); } if (!select_edge.is_empty()) { for (const int edge_i : range) { @@ -1461,6 +1612,7 @@ static void bm_to_mesh_faces(const BMesh &bm, MutableSpan hide_poly, MutableSpan material_indices) { + const Vector info = bm_to_mesh_copy_info_calc(bm.pdata, mesh.pdata); MutableSpan dst_polys = mesh.polys_for_write(); threading::parallel_for(dst_polys.index_range(), 1024, [&](const IndexRange range) { for (const int face_i : range) { @@ -1469,7 +1621,7 @@ static void bm_to_mesh_faces(const BMesh &bm, dst_poly.totloop = src_face.len; dst_poly.loopstart = BM_elem_index_get(BM_FACE_FIRST_LOOP(&src_face)); dst_poly.flag = bm_face_flag_to_mflag(&src_face); - CustomData_from_bmesh_block(&bm.pdata, &mesh.pdata, src_face.head.data, face_i); + bmesh_block_copy_to_mesh_attributes(info, face_i, src_face.head.data); } if (!select_poly.is_empty()) { for (const int face_i : range) { @@ -1491,6 +1643,7 @@ static void bm_to_mesh_faces(const BMesh &bm, static void bm_to_mesh_loops(const BMesh &bm, const Span bm_loops, Mesh &mesh) { + const Vector info = bm_to_mesh_copy_info_calc(bm.ldata, mesh.ldata); MutableSpan dst_loops = mesh.loops_for_write(); threading::parallel_for(dst_loops.index_range(), 1024, [&](const IndexRange range) { for (const int loop_i : range) { @@ -1498,7 +1651,7 @@ static void bm_to_mesh_loops(const BMesh &bm, const Span bm_loop MLoop &dst_loop = dst_loops[loop_i]; dst_loop.v = BM_elem_index_get(src_loop.v); dst_loop.e = BM_elem_index_get(src_loop.e); - CustomData_from_bmesh_block(&bm.ldata, &mesh.ldata, src_loop.head.data, loop_i); + bmesh_block_copy_to_mesh_attributes(info, loop_i, src_loop.head.data); } }); } diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.h b/source/blender/bmesh/intern/bmesh_mesh_convert.h index ef968594998a..822e7997ea35 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.h +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.h @@ -61,7 +61,7 @@ struct BMeshToMeshParams { * * This is needed when flushing changes from edit-mode into object mode, * so a second flush or edit-mode exit doesn't run with indices - * that have become invalid from updating the shape-key, see T71865. + * that have become invalid from updating the shape-key, see #71865. */ bool update_shapekey_indices; /** diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.cc b/source/blender/bmesh/intern/bmesh_mesh_normals.cc index 03bd1811fd86..28164eaec7ae 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.cc @@ -1057,7 +1057,7 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( * Will use first clnors_data array, and fallback to cd_loop_clnors_offset * (use nullptr and -1 to not use clnors). * - * \note This sets #BM_ELEM_TAG which is used in tool code (e.g. T84426). + * \note This sets #BM_ELEM_TAG which is used in tool code (e.g. #84426). * we could add a low-level API flag for this, see #BM_ELEM_API_FLAG_ENABLE and friends. */ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, @@ -1449,7 +1449,7 @@ static bool bm_mesh_loops_split_lnor_fans(BMesh *bm, /* We also have to check between last and first loops, * otherwise we may miss some sharp edges here! * This is just a simplified version of above while loop. - * See T45984. */ + * See #45984. */ loops = lnors_spacearr->lspacearr[i]->loops; if (loops && org_nor) { BMLoop *ml = static_cast(loops->link); diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index a1842b598d5a..c383237c1ae9 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -414,7 +414,7 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, /* Collapse between 2 edges */ /* in this case we want to keep all faces and not join them, - * rather just get rid of the vertex - see bug T28645. */ + * rather just get rid of the vertex - see bug #28645. */ BMVert *tv = BM_edge_other_vert(e_kill, v_kill); if (tv) { BMEdge *e2 = bmesh_disk_edge_next(e_kill, v_kill); diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 81793ee99950..b4cfeb43c8f5 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -472,7 +472,7 @@ bool BM_face_split_edgenet(BMesh *bm, } /* These arrays used to be stack memory, however they can be - * large for single faces with complex edge-nets, see: T65980. */ + * large for single faces with complex edge-nets, see: #65980. */ /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */ edge_order = MEM_mallocN(sizeof(*edge_order) * edge_order_len, __func__); @@ -501,7 +501,7 @@ bool BM_face_split_edgenet(BMesh *bm, * however in rare cases verts are added multiple times to the queue, * that on its own is harmless but in _very_ rare cases, * the queue will overflow its maximum size, - * so we better be strict about this! see: T51539 */ + * so we better be strict about this! see: #51539 */ for (i = 0; i < edge_net_len; i++) { BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET); @@ -706,7 +706,7 @@ BLI_INLINE bool edge_isect_verts_point_2d(const BMEdge *e, float r_isect[2]) { /* This bias seems like it could be too large, - * mostly its not needed, see T52329 for example where it is. */ + * mostly its not needed, see #52329 for example where it is. */ const float endpoint_bias = 1e-4f; return ((isect_seg_seg_v2_point_ex( v_a->co, v_b->co, e->v1->co, e->v2->co, endpoint_bias, r_isect) == 1) && @@ -1159,7 +1159,7 @@ static BMVert *bm_face_split_edgenet_partial_connect(BMesh *bm, BMVert *v_delimi BLI_assert(v_delimit->e != NULL); - /* Degenerate, avoid eternal loop, see: T59074. */ + /* Degenerate, avoid eternal loop, see: #59074. */ # if 0 BLI_assert(v_split->e != NULL); # else @@ -1481,7 +1481,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm, /* Now create bvh tree * * Note that a large epsilon is used because meshes with dimensions of around 100+ need it. - * see T52329. */ + * see #52329. */ BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 1e-4f, 8, 8); for (uint i = 0; i < edge_arr_len; i++) { const float e_cos[2][3] = { @@ -1633,7 +1633,7 @@ finally: struct TempVertPair *tvp = temp_vert_pairs.list; do { /* its _very_ unlikely the edge exists, - * however splicing may cause this. see: T48012 */ + * however splicing may cause this. see: #48012 */ if (!BM_edge_exists(tvp->v_orig, tvp->v_temp)) { BM_vert_splice(bm, tvp->v_orig, tvp->v_temp); } diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c index 643b5750d764..e471d4804be8 100644 --- a/source/blender/bmesh/intern/bmesh_query.c +++ b/source/blender/bmesh/intern/bmesh_query.c @@ -2042,7 +2042,7 @@ bool BM_face_is_normal_valid(const BMFace *f) /** * Use to accumulate volume calculation for faces with consistent winding. * - * Use double precision since this is prone to float precision error, see T73295. + * Use double precision since this is prone to float precision error, see #73295. */ static double bm_mesh_calc_volume_face(const BMFace *f) { diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h index 2aff7e4bc6bc..5908d639db24 100644 --- a/source/blender/bmesh/intern/bmesh_query.h +++ b/source/blender/bmesh/intern/bmesh_query.h @@ -762,7 +762,7 @@ int BM_mesh_calc_edge_groups(BMesh *bm, * * While we could call this, then create vertex & face arrays, * it requires looping over geometry connectivity twice, - * this slows down edit-mesh separate by loose parts, see: T70864. + * this slows down edit-mesh separate by loose parts, see: #70864. */ int BM_mesh_calc_edge_groups_as_arrays(BMesh *bm, BMVert **verts, diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index 2984ea93cb71..a112e69fbfa5 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -930,7 +930,7 @@ static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data) */ if ((lwalk->is_boundary == false) && /* Without checking the face count, the 3 edges could be this edge - * plus two boundary edges (which would not be stepped over), see T84906. */ + * plus two boundary edges (which would not be stepped over), see #84906. */ ((vert_edge_count[0] == 3 && vert_face_count[0] == 3) || (vert_edge_count[1] == 3 && vert_face_count[1] == 3))) { BMIter iter; @@ -1197,8 +1197,8 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data) { BMwFaceLoopWalker *lwalk, owalk, *owalk_pt; BMEdge *e = data; - /* BMesh *bm = walker->bm; */ /* UNUSED */ - /* int fcount = BM_edge_face_count(e); */ /* UNUSED */ + // BMesh *bm = walker->bm; /* UNUSED */ + // int fcount = BM_edge_face_count(e); /* UNUSED */ if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) { return; diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index 60c91183108a..872557c6ca14 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -17,7 +17,7 @@ /** * TODO(@ideasman42): Many connected edge loops can cause an error attempting * to create faces with duplicate vertices. While this needs to be investigated, - * it's simple enough to check for this case, see: T102232. + * it's simple enough to check for this case, see: #102232. */ #define USE_DUPLICATE_FACE_VERT_CHECK @@ -208,7 +208,7 @@ static void bridge_loop_pair(BMesh *bm, * the loops values of 'dir_a/b' is degenerate, * in this case compare the original directions * (before they were corrected by 'el_dir'), - * see: T43013 + * see: #43013 */ test_a = dir_a_orig; test_b = dir_b_orig; @@ -272,7 +272,7 @@ static void bridge_loop_pair(BMesh *bm, bool flip[2] = {false, false}; /* for direction aligned loops we can't rely on the directly we have, - * use the winding defined by the connected faces (see T48356). */ + * use the winding defined by the connected faces (see #48356). */ if (fabsf(dot_a) < eps) { if (winding_votes[0] < 0) { flip[0] = !flip[0]; diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index 59a12db92419..6c784758d85e 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -104,7 +104,7 @@ static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenera BMLoop *l_new; BMLoop *l_pair[2]; - /* Note that duplicate edges in this case is very unlikely but it can happen, see T70287. */ + /* Note that duplicate edges in this case is very unlikely but it can happen, see #70287. */ bool edge_exists = (BM_edge_exists(verts_pair[i][0], verts_pair[i][1]) != NULL); if ((l_pair[0] = BM_face_vert_share_loop(f, verts_pair[i][0])) && (l_pair[1] = BM_face_vert_share_loop(f, verts_pair[i][1]))) { diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c index 26f1a9e626ea..197ef3ce2647 100644 --- a/source/blender/bmesh/operators/bmo_connect_pair.c +++ b/source/blender/bmesh/operators/bmo_connect_pair.c @@ -27,7 +27,7 @@ * - store a heap of paths which are being scanned (#PathContext.states). * - continuously search the shortest path in the heap. * - never step over the same element twice (tag elements as #ELE_TOUCHED). - * this avoids going into an eternal loop if there are many possible branches (see T45582). + * this avoids going into an eternal loop if there are many possible branches (see #45582). * - when running into a branch, create a new #PathLinkState state and add to the heap. * - when the target is reached, * finish - since none of the other paths can be shorter than the one just found. @@ -109,7 +109,7 @@ typedef struct PathLinkState { /* -------------------------------------------------------------------- */ /** \name Min Dist Dir Util * - * Simply getting the closest intersecting vert/edge is _not_ good enough. see T43792 + * Simply getting the closest intersecting vert/edge is _not_ good enough. see #43792 * we need to get the closest in both directions since the absolute closest may be a dead-end. * * Logic is simple: @@ -504,7 +504,7 @@ static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3]) project_plane_normalized_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir); /* Don't normalize before combining so as normals approach the direction, - * they have less effect (T46784). */ + * they have less effect (#46784). */ /* combine the normals */ /* for flipped faces */ diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 1ed9d763e8cd..07315fce1390 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -113,7 +113,7 @@ static BMEdge *bmo_edge_copy(BMOperator *op, if (use_edge_flip_from_face) { /* Take winding from previous face (if we had one), - * otherwise extruding a duplicated edges gives bad normals, see: T62487. */ + * otherwise extruding a duplicated edges gives bad normals, see: #62487. */ if (BM_edge_is_boundary(e_src) && (e_src->l->v == e_src->v1)) { BM_edge_verts_swap(e_dst); } diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index 8083a06e0b51..11095edac02e 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -215,7 +215,7 @@ void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op) v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1; } - /* if there is ever bow-tie quads between two edges the problem is here! T30367. */ + /* if there is ever bow-tie quads between two edges the problem is here! #30367. */ #if 0 normal_tri_v3(dvec1, v1->co, v2->co, v4->co); normal_tri_v3(dvec2, v1->co, v4->co, v3->co); diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 48d8cded95d3..21b32d487114 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -367,7 +367,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) /* calculate verts to delete */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (v->e) { /* only deal with verts attached to geometry T33651. */ + if (v->e) { /* only deal with verts attached to geometry #33651. */ found = false; BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) { @@ -466,10 +466,10 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMVert *v1 = e->v1, *v2 = e->v2; /* The original edge was excluded, - * this would result in a standalone wire edge - see T30399. */ + * this would result in a standalone wire edge - see #30399. */ BM_edge_kill(bm, e); - /* kill standalone vertices from this edge - see T32341. */ + /* kill standalone vertices from this edge - see #32341. */ if (!v1->e) { BM_vert_kill(bm, v1); } @@ -480,7 +480,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) continue; } - /* skip creating face for excluded edges see T35503. */ + /* skip creating face for excluded edges see #35503. */ if (BMO_slot_map_contains(slot_edges_exclude, e)) { /* simply skip creating the face */ continue; diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index e256e261eaac..9a2d297e36cc 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -602,7 +602,7 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op) if (count != 2) { /* Note that this error message has been adjusted to make sense when called * from the operator 'MESH_OT_fill_grid' which has a 'prepare' pass which can - * extract two 'rail' loops from a single edge loop, see T72075. */ + * extract two 'rail' loops from a single edge loop, see #72075. */ BMO_error_raise(bm, op, BMO_ERROR_CANCEL, diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index f46b9158c45b..a9e8174f5568 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -20,7 +20,7 @@ #include "intern/bmesh_operators_private.h" /* own include */ -/* Merge loop-data that diverges, see: T41445 */ +/* Merge loop-data that diverges, see: #41445 */ #define USE_LOOP_CUSTOMDATA_MERGE #define ELE_NEW 1 @@ -953,10 +953,10 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) is_mid = false; } - /* Disable since this gives odd results at times, see T39288. */ + /* Disable since this gives odd results at times, see #39288. */ #if 0 else if (compare_v3v3(f_a->no, f_b->no, 0.001f) == false) { - /* epsilon increased to fix T32329. */ + /* epsilon increased to fix #32329. */ /* faces don't touch, * just get cross product of their normals, its *good enough* @@ -1183,7 +1183,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) f = BM_face_create_verts(bm, varr, j, es->l->f, BM_CREATE_NOP, true); BMO_face_flag_enable(bm, f, ELE_NEW); - /* Copy for loop data, otherwise UVs and vcols are no good. + /* Copy for loop data, otherwise UVs and vertex-colors are no good. * tiny speedup here we could be more clever and copy from known adjacent data * also - we could attempt to interpolate the loop data, * this would be much slower but more useful too. */ diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index 70984ba10bdd..1649aa7344ad 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -1391,7 +1391,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) BMFace **side_faces = MEM_mallocN(sizeof(*side_faces) * side_faces_len, __func__); for (int i = 0; i < segs; i++) { - /* Calculate with higher precision, see: T87779. */ + /* Calculate with higher precision, see: #87779. */ float sin_phi, cos_phi; sin_cos_from_fraction(i, segs, &sin_phi, &cos_phi); diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 575a88331da0..d19530edae60 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -462,7 +462,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) i = m_vertex_id; if ((sys->zerola[i] == false) && /* Non zero check is to account for vertices that aren't connected to a selected face. - * Without this wire edges become `nan`, see T89214. */ + * Without this wire edges become `nan`, see #89214. */ (sys->ring_areas[i] != 0.0f)) { w = sys->vweights[i] * sys->ring_areas[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda_factor / (4.0f * w); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index c036fe86d9e0..72509dd4f6cd 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -97,7 +97,7 @@ typedef struct SubDPattern { #define ELE_INNER 8 #define ELE_SPLIT 16 -/* see bug T32665, 0.00005 means a we get face splits at a little under 1.0 degrees */ +/* see bug #32665, 0.00005 means a we get face splits at a little under 1.0 degrees */ #define FLT_FACE_SPLIT_EPSILON 0.00005f /* @@ -1202,7 +1202,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) for (j = 0; j < numcuts; j++) { bool ok = true; - /* Check for special case, see: T32500. + /* Check for special case, see: #32500. * This edge pair could be used by more than one face, * in this case it used to (2.63), split both faces along the same verts * while it could be calculated which face should do the split, diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c index 6f41da7bb436..474b8ad6263d 100644 --- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c +++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c @@ -1095,7 +1095,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) BMFace *f; BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { - /* could support ngons, other areas would need updating too, see T48926. */ + /* could support ngons, other areas would need updating too, see #48926. */ if ((f->len <= 4) && !BMO_face_flag_test(bm, f, FACE_OUT)) { BMIter liter; BMLoop *l; diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c index 13afff41263a..1cba81cc2084 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -72,7 +72,7 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) "use_shapekey"); /* important 'flip_multires' is disabled, - * otherwise multi-res data will be reversed, see: T47788 */ + * otherwise multi-res data will be reversed, see: #47788 */ BMO_op_callf(bm, op->flag, "reverse_faces faces=%S", &op_dupe, "geom.out"); /* Weld verts */ diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 1440f5a3eaf9..5118eb792d59 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1351,7 +1351,7 @@ static void offset_meet(BevelParams *bp, /* Special case: e1 and e2 are parallel; put offset point perp to both, from v. * need to find a suitable plane. * This code used to just use offset and dir1, but that makes for visible errors - * on a circle with > 200 sides, which trips this "nearly perp" code (see T61214). + * on a circle with > 200 sides, which trips this "nearly perp" code (see #61214). * so use the average of the two, and the offset formula for angle bisector. * If offsets are different, we're out of luck: * Use the max of the two (so get consistent looking results if the same situation @@ -1504,9 +1504,9 @@ static void offset_meet(BevelParams *bp, } } -/* This was changed from 0.25f to fix bug T86768. - * Original bug T44961 remains fixed with this value. - * Update: changed again from 0.0001f to fix bug T95335. +/* This was changed from 0.25f to fix bug #86768. + * Original bug #44961 remains fixed with this value. + * Update: changed again from 0.0001f to fix bug #95335. * Original two bugs remained fixed. */ #define BEVEL_GOOD_ANGLE 0.1f diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 1ea799f64e05..082c58214041 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -41,14 +41,14 @@ /** if the cost from #BLI_quadric_evaluate is 'noise', fallback to topology */ #define USE_TOPOLOGY_FALLBACK #ifdef USE_TOPOLOGY_FALLBACK -/** cost is calculated with double precision, it's ok to use a very small epsilon, see T48154. */ +/** cost is calculated with double precision, it's ok to use a very small epsilon, see #48154. */ # define TOPOLOGY_FALLBACK_EPS 1e-12f #endif #define BOUNDARY_PRESERVE_WEIGHT 100.0f /** * Uses double precision, impacts behavior on near-flat surfaces, - * cane give issues with very small faces. 1e-2 is too big, see: T48154. + * cane give issues with very small faces. 1e-2 is too big, see: #48154. */ #define OPTIMIZE_EPS 1e-8 #define COST_INVALID FLT_MAX @@ -272,7 +272,7 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, } /* NOTE: 'cost' shouldn't be negative but happens sometimes with small values. - * this can cause faces that make up a flat surface to over-collapse, see T37121. */ + * this can cause faces that make up a flat surface to over-collapse, see #37121. */ cost = fabsf(cost); #ifdef USE_TOPOLOGY_FALLBACK diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index e15122a11e3f..0a668342ab4a 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1068,7 +1068,7 @@ bool BM_mesh_intersect(BMesh *bm, /* For self intersection this can be useful, sometimes users generate geometry * where surfaces that seem disconnected happen to share an edge. * So when performing intersection calculation allow shared vertices, - * just not shared edges. See T75946. */ + * just not shared edges. See #75946. */ const bool isect_tri_tri_no_shared = (boolean_mode != BMESH_ISECT_BOOLEAN_NONE); int flag = BVH_OVERLAP_USE_THREADING | BVH_OVERLAP_RETURN_PAIRS; @@ -1250,7 +1250,7 @@ bool BM_mesh_intersect(BMesh *bm, /* It's possible the vertex to dissolve is an edge on an existing face * that doesn't divide the face, therefor the edges are not wire - * and shouldn't be handled here, see: T63787. */ + * and shouldn't be handled here, see: #63787. */ if (!BLI_gset_haskey(s.wire_edges, e_pair[0]) || !BLI_gset_haskey(s.wire_edges, e_pair[1])) { continue; } @@ -1638,7 +1638,7 @@ bool BM_mesh_intersect(BMesh *bm, BLI_memarena_free(s.mem_arena); /* It's unlikely the selection history is useful at this point, - * if this is not called this array would need to be validated, see: T86799. */ + * if this is not called this array would need to be validated, see: #86799. */ BM_select_history_clear(bm); return (has_edit_isect || has_edit_boolean); diff --git a/source/blender/bmesh/tools/bmesh_path_region.c b/source/blender/bmesh/tools/bmesh_path_region.c index a90bf87ebb0d..5b86b06aa50b 100644 --- a/source/blender/bmesh/tools/bmesh_path_region.c +++ b/source/blender/bmesh/tools/bmesh_path_region.c @@ -23,7 +23,7 @@ * * \note Regarding manifold edge stepping: #BM_vert_is_edge_pair_manifold usage. * Logic to skip a chain of vertices is not applied at boundaries because it gives - * strange behavior from a user perspective especially with boundary quads, see: T52701 + * strange behavior from a user perspective especially with boundary quads, see: #52701 * * Restrict walking over a vertex chain to cases where the edges share the same faces. * This is more typical of what a user would consider a vertex chain. diff --git a/source/blender/bmesh/tools/bmesh_path_region_uv.c b/source/blender/bmesh/tools/bmesh_path_region_uv.c index 17812fe3bdde..25637fae949e 100644 --- a/source/blender/bmesh/tools/bmesh_path_region_uv.c +++ b/source/blender/bmesh/tools/bmesh_path_region_uv.c @@ -27,7 +27,7 @@ * * \note Regarding manifold edge stepping: #BM_vert_is_edge_pair_manifold usage. * Logic to skip a chain of vertices is not applied at boundaries because it gives - * strange behavior from a user perspective especially with boundary quads, see: T52701 + * strange behavior from a user perspective especially with boundary quads, see: #52701 * * Restrict walking over a vertex chain to cases where the edges share the same faces. * This is more typical of what a user would consider a vertex chain. diff --git a/source/blender/compositor/nodes/COM_BokehBlurNode.cc b/source/blender/compositor/nodes/COM_BokehBlurNode.cc index ebdc82b0d198..7d850915ada3 100644 --- a/source/blender/compositor/nodes/COM_BokehBlurNode.cc +++ b/source/blender/compositor/nodes/COM_BokehBlurNode.cc @@ -45,7 +45,7 @@ void BokehBlurNode::convert_to_operations(NodeConverter &converter, converter.map_input_socket(get_input_socket(1), operation->get_input_socket(1)); /* NOTE: on the bokeh blur operation the sockets are switched. - * for this reason the next two lines are correct. Fix for T43771. */ + * for this reason the next two lines are correct. Fix for #43771. */ converter.map_input_socket(get_input_socket(2), operation->get_input_socket(3)); converter.map_input_socket(get_input_socket(3), operation->get_input_socket(2)); diff --git a/source/blender/compositor/nodes/COM_ImageNode.cc b/source/blender/compositor/nodes/COM_ImageNode.cc index a7cc6bf39df5..0920f60979bf 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cc +++ b/source/blender/compositor/nodes/COM_ImageNode.cc @@ -179,7 +179,7 @@ void ImageNode::convert_to_operations(NodeConverter &converter, } BKE_image_release_ibuf(image, ibuf, nullptr); - /* without this, multilayer that fail to load will crash blender T32490. */ + /* without this, multilayer that fail to load will crash blender #32490. */ if (is_multilayer_ok == false) { for (NodeOutput *output : get_output_sockets()) { converter.set_invalid_output(output); diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cc b/source/blender/compositor/operations/COM_CompositorOperation.cc index 1ff27607d093..587f661646a2 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cc +++ b/source/blender/compositor/operations/COM_CompositorOperation.cc @@ -219,7 +219,7 @@ void CompositorOperation::determine_canvas(const rcti & /*preferred_area*/, rcti BKE_render_resolution(rd_, false, &width, &height); /* Check actual render resolution with cropping it may differ with cropped border.rendering - * Fix for T31777 Border Crop gives black (easy). */ + * Fix for #31777 Border Crop gives black (easy). */ Render *re = RE_GetSceneRender(scene_); if (re) { RenderResult *rr = RE_AcquireResultRead(re); diff --git a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc index 25d4b2d6a6c8..14b92bdcbd11 100644 --- a/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc +++ b/source/blender/compositor/operations/COM_ConvertDepthToRadiusOperation.cc @@ -71,14 +71,14 @@ void ConvertDepthToRadiusOperation::execute_pixel_sampled(float output[4], if (z != 0.0f) { float iZ = (1.0f / z); - /* bug T6656 part 2b, do not re-scale. */ + /* bug #6656 part 2b, do not re-scale. */ #if 0 bcrad = 0.5f * fabs(aperture * (dof_sp * (cam_invfdist - iZ) - 1.0f)); /* Scale crad back to original maximum and blend. */ crad->rect[px] = bcrad + wts->rect[px] * (scf * crad->rect[px] - bcrad); #endif radius = 0.5f * fabsf(aperture_ * (dof_sp_ * (inverse_focal_distance_ - iZ) - 1.0f)); - /* 'bug' T6615, limit minimum radius to 1 pixel, + /* 'bug' #6615, limit minimum radius to 1 pixel, * not really a solution, but somewhat mitigates the problem. */ if (radius < 0.0f) { radius = 0.0f; @@ -111,7 +111,7 @@ void ConvertDepthToRadiusOperation::update_memory_buffer_partial(MemoryBuffer *o const float inv_z = (1.0f / z); - /* Bug T6656 part 2b, do not re-scale. */ + /* Bug #6656 part 2b, do not re-scale. */ #if 0 bcrad = 0.5f * fabs(aperture * (dof_sp * (cam_invfdist - iZ) - 1.0f)); /* Scale crad back to original maximum and blend: @@ -119,7 +119,7 @@ void ConvertDepthToRadiusOperation::update_memory_buffer_partial(MemoryBuffer *o #endif const float radius = 0.5f * fabsf(aperture_ * (dof_sp_ * (inverse_focal_distance_ - inv_z) - 1.0f)); - /* Bug T6615, limit minimum radius to 1 pixel, + /* Bug #6615, limit minimum radius to 1 pixel, * not really a solution, but somewhat mitigates the problem. */ *it.out = CLAMPIS(radius, 0.0f, max_radius_); } diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.cc b/source/blender/compositor/operations/COM_CurveBaseOperation.cc index e7cbf0d28d5f..67e117e33ebf 100644 --- a/source/blender/compositor/operations/COM_CurveBaseOperation.cc +++ b/source/blender/compositor/operations/COM_CurveBaseOperation.cc @@ -35,7 +35,7 @@ void CurveBaseOperation::deinit_execution() void CurveBaseOperation::set_curve_mapping(const CurveMapping *mapping) { - /* duplicate the curve to avoid glitches while drawing, see bug T32374. */ + /* duplicate the curve to avoid glitches while drawing, see bug #32374. */ if (curve_mapping_) { BKE_curvemapping_free(curve_mapping_); } diff --git a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc index ba0e7eb21aca..b45b3e100e88 100644 --- a/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc +++ b/source/blender/compositor/realtime_compositor/algorithms/intern/algorithm_parallel_reduction.cc @@ -41,10 +41,10 @@ static float *parallel_reduction_dispatch(Context &context, GPUTexture *reduced_texture = context.texture_pool().acquire(reduced_size, format); GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH); - const int texture_image_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(texture_to_reduce, texture_image_unit); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(reduced_texture, image_unit); GPU_compute_dispatch(shader, reduced_size.x, reduced_size.y, 1); diff --git a/source/blender/compositor/realtime_compositor/cached_resources/intern/morphological_distance_feather_weights.cc b/source/blender/compositor/realtime_compositor/cached_resources/intern/morphological_distance_feather_weights.cc index eac88b907b8e..98e7b67dca79 100644 --- a/source/blender/compositor/realtime_compositor/cached_resources/intern/morphological_distance_feather_weights.cc +++ b/source/blender/compositor/realtime_compositor/cached_resources/intern/morphological_distance_feather_weights.cc @@ -135,7 +135,7 @@ void MorphologicalDistanceFeatherWeights::compute_distance_falloffs(int type, in void MorphologicalDistanceFeatherWeights::bind_weights_as_texture(GPUShader *shader, const char *texture_name) const { - const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture_name); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, texture_name); GPU_texture_bind(weights_texture_, texture_image_unit); } @@ -147,7 +147,7 @@ void MorphologicalDistanceFeatherWeights::unbind_weights_as_texture() const void MorphologicalDistanceFeatherWeights::bind_distance_falloffs_as_texture( GPUShader *shader, const char *texture_name) const { - const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture_name); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, texture_name); GPU_texture_bind(distance_falloffs_texture_, texture_image_unit); } diff --git a/source/blender/compositor/realtime_compositor/cached_resources/intern/symmetric_blur_weights.cc b/source/blender/compositor/realtime_compositor/cached_resources/intern/symmetric_blur_weights.cc index b3200d468c9b..db4c0f777f21 100644 --- a/source/blender/compositor/realtime_compositor/cached_resources/intern/symmetric_blur_weights.cc +++ b/source/blender/compositor/realtime_compositor/cached_resources/intern/symmetric_blur_weights.cc @@ -103,7 +103,7 @@ SymmetricBlurWeights::~SymmetricBlurWeights() void SymmetricBlurWeights::bind_as_texture(GPUShader *shader, const char *texture_name) const { - const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture_name); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, texture_name); GPU_texture_bind(texture_, texture_image_unit); } diff --git a/source/blender/compositor/realtime_compositor/cached_resources/intern/symmetric_separable_blur_weights.cc b/source/blender/compositor/realtime_compositor/cached_resources/intern/symmetric_separable_blur_weights.cc index b8c47d5a5d00..07d45531921d 100644 --- a/source/blender/compositor/realtime_compositor/cached_resources/intern/symmetric_separable_blur_weights.cc +++ b/source/blender/compositor/realtime_compositor/cached_resources/intern/symmetric_separable_blur_weights.cc @@ -81,7 +81,7 @@ SymmetricSeparableBlurWeights::~SymmetricSeparableBlurWeights() void SymmetricSeparableBlurWeights::bind_as_texture(GPUShader *shader, const char *texture_name) const { - const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture_name); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, texture_name); GPU_texture_bind(texture_, texture_image_unit); } diff --git a/source/blender/compositor/realtime_compositor/intern/evaluator.cc b/source/blender/compositor/realtime_compositor/intern/evaluator.cc index 1b52e1d381dd..f8c63cd7f6e8 100644 --- a/source/blender/compositor/realtime_compositor/intern/evaluator.cc +++ b/source/blender/compositor/realtime_compositor/intern/evaluator.cc @@ -161,7 +161,7 @@ void Evaluator::compile_and_evaluate_shader_compile_unit(CompileState &compile_s void Evaluator::map_shader_operation_inputs_to_their_results(ShaderOperation *operation, CompileState &compile_state) { - for (const auto &item : operation->get_inputs_to_linked_outputs_map().items()) { + for (const auto item : operation->get_inputs_to_linked_outputs_map().items()) { Result &result = compile_state.get_result_from_output_socket(item.value); operation->map_input_to_result(item.key, &result); } diff --git a/source/blender/compositor/realtime_compositor/intern/result.cc b/source/blender/compositor/realtime_compositor/intern/result.cc index e301aa6e0ed9..902eede7dd7f 100644 --- a/source/blender/compositor/realtime_compositor/intern/result.cc +++ b/source/blender/compositor/realtime_compositor/intern/result.cc @@ -82,7 +82,7 @@ void Result::bind_as_texture(GPUShader *shader, const char *texture_name) const /* Make sure any prior writes to the texture are reflected before reading from it. */ GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH); - const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture_name); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, texture_name); GPU_texture_bind(texture_, texture_image_unit); } @@ -93,7 +93,7 @@ void Result::bind_as_image(GPUShader *shader, const char *image_name, bool read) GPU_memory_barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS); } - const int image_unit = GPU_shader_get_texture_binding(shader, image_name); + const int image_unit = GPU_shader_get_sampler_binding(shader, image_name); GPU_texture_image_bind(texture_, image_unit); } diff --git a/source/blender/compositor/realtime_compositor/intern/shader_operation.cc b/source/blender/compositor/realtime_compositor/intern/shader_operation.cc index 4ac997db42b2..e85075f59cd3 100644 --- a/source/blender/compositor/realtime_compositor/intern/shader_operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/shader_operation.cc @@ -81,7 +81,7 @@ Map &ShaderOperation::get_inputs_to_linked_outputs_m void ShaderOperation::compute_results_reference_counts(const Schedule &schedule) { - for (const auto &item : output_sockets_to_output_identifiers_map_.items()) { + for (const auto item : output_sockets_to_output_identifiers_map_.items()) { const int reference_count = number_of_inputs_linked_to_output_conditioned( item.key, [&](DInputSocket input) { return schedule.contains(input.node()); }); @@ -95,14 +95,14 @@ void ShaderOperation::bind_material_resources(GPUShader *shader) * no uniforms. */ GPUUniformBuf *ubo = GPU_material_uniform_buffer_get(material_); if (ubo) { - GPU_uniformbuf_bind(ubo, GPU_shader_get_uniform_block_binding(shader, GPU_UBO_BLOCK_NAME)); + GPU_uniformbuf_bind(ubo, GPU_shader_get_ubo_binding(shader, GPU_UBO_BLOCK_NAME)); } /* Bind color band textures needed by curve and ramp nodes. */ ListBase textures = GPU_material_textures(material_); LISTBASE_FOREACH (GPUMaterialTexture *, texture, &textures) { if (texture->colorband) { - const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture->sampler_name); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, texture->sampler_name); GPU_texture_bind(*texture->colorband, texture_image_unit); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 0c5dfdf5ced8..9559c8a9e8dc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1831,7 +1831,7 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu) * For the sake of making the code more generic/defensive, the relation * is added for any geometry type. * - * See T96289 for more info. */ + * See #96289 for more info. */ if (object != nullptr && OB_TYPE_IS_GEOMETRY(object->type)) { StringRef rna_path(dtar->rna_path); if (rna_path == "data" || rna_path.startswith("data.")) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.cc index 009b191b91e8..c3bad9b92a95 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.cc @@ -197,7 +197,7 @@ void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node) const DriverDescriptor &driver_to = prefix_group[to_index]; Node *op_to = get_node(driver_to.depsgraph_key()); - /* Duplicate drivers can exist (see T78615), but cannot be distinguished by OperationKey + /* Duplicate drivers can exist (see #78615), but cannot be distinguished by OperationKey * and thus have the same depsgraph node. Relations between those drivers should not be * created. This not something that is expected to happen (both the UI and the Python API * prevent duplicate drivers), it did happen in a file and it is easy to deal with here. */ diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc index b997ac14f99c..60a68663bfa3 100644 --- a/source/blender/depsgraph/intern/depsgraph_eval.cc +++ b/source/blender/depsgraph/intern/depsgraph_eval.cc @@ -61,7 +61,7 @@ void DEG_evaluate_on_refresh(Depsgraph *graph) * since the undo state is stored before updates from the frame change have been applied. * In this case reading back the undo state will behave as if no updates on frame change * is needed as the #Depsgraph.ctime & frame will match the values in the input scene. - * Use #ID_RECALC_FRAME_CHANGE to detect that recalculation is necessary. see: T66913. */ + * Use #ID_RECALC_FRAME_CHANGE to detect that recalculation is necessary. see: #66913. */ deg_graph->tag_time_source(); } diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 34df9a537e14..ab3d05e7fa78 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -356,7 +356,7 @@ void DEG_iterator_objects_end(BLI_Iterator *iter) DEGObjectIterData *data = (DEGObjectIterData *)iter->data; if (data != nullptr) { /* Force crash in case the iterator data is referenced and accessed down - * the line. (T51718) */ + * the line. (#51718) */ deg_invalidate_iterator_work_data(data); } } diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index 3bdc33b8d01f..aac5366d35ac 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -388,7 +388,7 @@ void deg_evaluate_on_refresh(Depsgraph *graph) graph->debug.begin_graph_evaluation(); #ifdef WITH_PYTHON - /* Release the GIL so that Python drivers can be evaluated. See T91046. */ + /* Release the GIL so that Python drivers can be evaluated. See #91046. */ BPy_BEGIN_ALLOW_THREADS; #endif diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 4e07a7b173c9..4d2a9a7e8502 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -737,7 +737,7 @@ void update_id_after_copy(const Depsgraph *depsgraph, scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast(id_cow)); break; } - /* FIXME: This is a temporary fix to update the runtime pointers properly, see T96216. Should + /* FIXME: This is a temporary fix to update the runtime pointers properly, see #96216. Should * be removed at some point. */ case ID_GD: { bGPdata *gpd_cow = (bGPdata *)id_cow; diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index ce3d09e46d93..3560a982b901 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -225,7 +225,7 @@ set(SRC DRW_select_buffer.h intern/DRW_gpu_wrapper.hh intern/DRW_render.h - intern/draw_attributes.h + intern/draw_attributes.hh intern/draw_cache.h intern/draw_cache_extract.hh intern/draw_cache_impl.h @@ -234,7 +234,7 @@ set(SRC intern/draw_command.hh intern/draw_common.h intern/draw_common_shader_shared.h - intern/draw_curves_private.h + intern/draw_curves_private.hh intern/draw_debug.h intern/draw_debug.hh intern/draw_hair_private.h @@ -702,6 +702,7 @@ set(GLSL_SRC engines/overlay/shaders/overlay_point_varying_color_frag.glsl engines/overlay/shaders/overlay_point_varying_color_varying_outline_aa_frag.glsl engines/overlay/shaders/overlay_pointcloud_only_vert.glsl + engines/overlay/shaders/overlay_sculpt_curves_cage_vert.glsl engines/overlay/shaders/overlay_sculpt_curves_selection_frag.glsl engines/overlay/shaders/overlay_sculpt_curves_selection_vert.glsl engines/overlay/shaders/overlay_sculpt_mask_frag.glsl diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 8c5f1b70cc0f..6763d77d916c 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -197,6 +197,7 @@ void DRW_gpu_render_context_enable(void *re_gpu_context); void DRW_gpu_render_context_disable(void *re_gpu_context); void DRW_deferred_shader_remove(struct GPUMaterial *mat); +void DRW_deferred_shader_optimize_remove(struct GPUMaterial *mat); /** * Get DrawData from the given ID-block. In order for this to work, we assume that diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index e8c2dc259fca..8270367c3e6f 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -180,7 +180,7 @@ static void basic_cache_populate(void *vedata, Object *ob) DRW_object_axis_orthogonal_to_view(ob, flat_axis)); if (is_flat_object_viewed_from_side) { - /* Avoid losing flat objects when in ortho views (see T56549) */ + /* Avoid losing flat objects when in ortho views (see #56549) */ struct GPUBatch *geom = DRW_cache_object_all_edges_get(ob); if (geom) { DRW_shgroup_call(stl->g_data->depth_shgrp[do_in_front], geom, ob); diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index 1a1e3b80bad5..3d041f32bf36 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -126,7 +126,7 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData * /* Assumes that all instances have the same object pointer. This is currently the case because * instance objects are temporary objects on the stack. */ /* WORKAROUND: Duplicate object key for particle system (hairs) to be able to store dupli offset - * matrix along with the emitter obmat. (see T97380) */ + * matrix along with the emitter obmat. (see #97380) */ key.ob = (void *)((char *)ob + is_psys); DupliObject *dup = DRW_object_get_dupli(ob); if (dup) { diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 0e1cc82797ac..68e61235bead 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -93,7 +93,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata); /* Update matrices here because EEVEE_screen_raytrace_init can have reset the - * taa_current_sample. (See T66811) */ + * taa_current_sample. (See #66811) */ EEVEE_temporal_sampling_update_matrices(vedata); EEVEE_volumes_init(sldata, vedata); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 9f70a2dd72b3..48d000116814 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -53,6 +53,7 @@ static void eevee_engine_init(void *ved) stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL); stl->g_data->valid_taa_history = (txl->taa_history != NULL); stl->g_data->queued_shaders_count = 0; + stl->g_data->queued_optimise_shaders_count = 0; stl->g_data->render_timesteps = 1; stl->g_data->disable_ligthprobes = v3d && (v3d->object_type_exclude_viewport & (1 << OB_LIGHTPROBE)); @@ -178,6 +179,11 @@ static void eevee_cache_finish(void *vedata) if (g_data->queued_shaders_count > 0) { SNPRINTF(ved->info, TIP_("Compiling Shaders (%d remaining)"), g_data->queued_shaders_count); } + else if (g_data->queued_optimise_shaders_count > 0) { + SNPRINTF(ved->info, + TIP_("Optimizing Shaders (%d remaining)"), + g_data->queued_optimise_shaders_count); + } } /* As renders in an HDR off-screen buffer, we need draw everything once @@ -399,7 +405,7 @@ static void eevee_id_world_update(void *vedata, World *wo) LightCache *lcache = stl->g_data->light_cache; if (ELEM(lcache, NULL, stl->lookdev_lightcache)) { - /* Avoid Lookdev viewport clearing the update flag (see T67741). */ + /* Avoid Lookdev viewport clearing the update flag (see #67741). */ return; } diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index b28189973da1..84b4d6dda7a1 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -530,7 +530,7 @@ static void write_lightcache_texture(BlendWriter *writer, LightCacheTexture *tex } /* FIXME: We can't save more than what 32bit systems can handle. - * The solution would be to split the texture but it is too late for 2.90. (see T78529) */ + * The solution would be to split the texture but it is too late for 2.90. (see #78529) */ if (data_size < INT_MAX) { BLO_write_raw(writer, data_size, tex->data); } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index c8e571ee9d41..43bcb7faab2b 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -607,7 +607,7 @@ typedef struct EEVEE_MotionBlurData { typedef struct EEVEE_ObjectKey { /** Object or source object for duplis. */ /** WORKAROUND: The pointer is different for particle systems and do not point to the real - * object. (See T97380) */ + * object. (See #97380) */ void *ob; /** Parent object for duplis */ struct Object *parent; @@ -988,7 +988,7 @@ typedef struct EEVEE_PrivateData { float camtexcofac[4]; float size_orig[2]; - /* Cached original camera when rendering for motion blur (see T79637). */ + /* Cached original camera when rendering for motion blur (see #79637). */ struct Object *cam_original_ob; /* Mist Settings */ @@ -1000,6 +1000,8 @@ typedef struct EEVEE_PrivateData { /* Compiling shaders count. This is to track if a shader has finished compiling. */ int queued_shaders_count; int queued_shaders_count_prev; + /* Optimizing shaders count. */ + int queued_optimise_shaders_count; /* LookDev Settings */ int studiolight_index; diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 1d18056e1754..6f47007c3c5a 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -206,7 +206,7 @@ void EEVEE_render_cache(void *vedata, /* Don't print dupli objects as this can be very verbose and * increase the render time on Windows because of slow windows term. - * (see T59649) */ + * (see #59649) */ if (engine && (ob->base_flag & BASE_FROM_DUPLI) == 0) { char info[42]; BLI_snprintf(info, sizeof(info), "Syncing %s", ob->id.name + 2); @@ -571,7 +571,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl EEVEE_temporal_sampling_reset(vedata); stl->effects->ssr_was_valid_double_buffer = stl->g_data->valid_double_buffer; } - /* Don't print every samples as it can lead to bad performance. (see T59649) */ + /* Don't print every samples as it can lead to bad performance. (see #59649) */ else if ((render_samples % 25) == 0 || (render_samples + 1) == tot_sample) { char info[42]; BLI_snprintf( diff --git a/source/blender/draw/engines/eevee/eevee_sampling.c b/source/blender/draw/engines/eevee/eevee_sampling.c index 34d3cd74b36b..d47a99f7c4f6 100644 --- a/source/blender/draw/engines/eevee/eevee_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_sampling.c @@ -17,7 +17,7 @@ void EEVEE_sample_ball(int sample_ofs, float radius, float rsample[3]) BLI_halton_3d(ht_primes, ht_offset, sample_ofs, ht_point); - /* De-correlate AA and shadow samples. (see T68594) */ + /* De-correlate AA and shadow samples. (see #68594) */ ht_point[0] = fmod(ht_point[0] * 1151.0, 1.0); ht_point[1] = fmod(ht_point[1] * 1069.0, 1.0); ht_point[2] = fmod(ht_point[2] * 1151.0, 1.0); @@ -48,7 +48,7 @@ void EEVEE_sample_rectangle(int sample_ofs, BLI_halton_2d(ht_primes, ht_offset, sample_ofs, ht_point); - /* De-correlate AA and shadow samples. (see T68594) */ + /* De-correlate AA and shadow samples. (see #68594) */ ht_point[0] = fmod(ht_point[0] * 1151.0, 1.0); ht_point[1] = fmod(ht_point[1] * 1069.0, 1.0); @@ -74,7 +74,7 @@ void EEVEE_sample_ellipse(int sample_ofs, BLI_halton_2d(ht_primes, ht_offset, sample_ofs, ht_point); - /* Decorrelate AA and shadow samples. (see T68594) */ + /* Decorrelate AA and shadow samples. (see #68594) */ ht_point[0] = fmod(ht_point[0] * 1151.0, 1.0); ht_point[1] = fmod(ht_point[1] * 1069.0, 1.0); @@ -98,7 +98,7 @@ void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]) BLI_halton_3d(ht_primes, ht_offset, sample_ofs, ht_point); - /* Decorrelate AA and shadow samples. (see T68594) */ + /* Decorrelate AA and shadow samples. (see #68594) */ ht_point[0] = fmod(ht_point[0] * 1151.0, 1.0); ht_point[1] = fmod(ht_point[1] * 1069.0, 1.0); ht_point[2] = fmod(ht_point[2] * 1151.0, 1.0); diff --git a/source/blender/draw/engines/eevee/eevee_shaders.cc b/source/blender/draw/engines/eevee/eevee_shaders.cc index 3b3ff33308c9..638c3dd3cd42 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.cc +++ b/source/blender/draw/engines/eevee/eevee_shaders.cc @@ -1390,12 +1390,21 @@ struct GPUMaterial *EEVEE_material_get( return nullptr; } switch (status) { - case GPU_MAT_SUCCESS: - break; - case GPU_MAT_QUEUED: + case GPU_MAT_SUCCESS: { + /* Determine optimization status for remaining compilations counter. */ + int optimization_status = GPU_material_optimization_status(mat); + if (optimization_status == GPU_MAT_OPTIMIZATION_QUEUED) { + vedata->stl->g_data->queued_optimise_shaders_count++; + } + } break; + case GPU_MAT_QUEUED: { vedata->stl->g_data->queued_shaders_count++; - mat = EEVEE_material_default_get(scene, ma, options); - break; + GPUMaterial *default_mat = EEVEE_material_default_get(scene, ma, options); + /* Mark pending material with its default material for future cache warming.*/ + GPU_material_set_default(mat, default_mat); + /* Return default material. */ + mat = default_mat; + } break; case GPU_MAT_FAILED: default: ma = EEVEE_material_default_error_get(); diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 5644fc6f1f40..4c5b6ae5f15d 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -281,7 +281,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data effects->taa_total_sample = 1; } - /* Motion blur steps could reset the sampling when camera is animated (see T79970). */ + /* Motion blur steps could reset the sampling when camera is animated (see #79970). */ if (!DRW_state_is_scene_render()) { DRW_view_persmat_get(NULL, persmat, false); view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN); @@ -309,7 +309,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data } else { const bool all_shaders_compiled = stl->g_data->queued_shaders_count_prev == 0; - /* Fix Texture painting (see T79370) and shader compilation (see T78520). */ + /* Fix Texture painting (see #79370) and shader compilation (see #78520). */ if (DRW_state_is_navigating() || !all_shaders_compiled) { effects->taa_current_sample = 1; } diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 872696a8b7c1..72ea7a7f2035 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -300,7 +300,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, float size[3]; mat4_to_size(size, ob->object_to_world); - /* Check if any of the axes have 0 length. (see T69070) */ + /* Check if any of the axes have 0 length. (see #69070) */ const float epsilon = 1e-8f; if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) { return; diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl index e0e8975369a3..32748a71038c 100644 --- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -295,7 +295,7 @@ void occlusion_eval(OcclusionData data, bent_normal = N; } else { - /* NOTE: using pow(visibility, 6.0) produces NaN (see T87369). */ + /* NOTE: using pow(visibility, 6.0) produces NaN (see #87369). */ float tmp = saturate(pow6(visibility)); bent_normal = normalize(mix(bent_normal, N, tmp)); } diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl index 574b24b36507..965b11c8e2ef 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl @@ -92,7 +92,7 @@ void closure_Diffuse_eval_end(ClosureInputDiffuse cl_in, { cl_out.radiance = render_pass_diffuse_mask(cl_out.radiance); #if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND) - /* This makes shader resources become unused and avoid issues with samplers. (see T59747) */ + /* This makes shader resources become unused and avoid issues with samplers. (see #59747) */ cl_out.radiance = vec3(0.0); return; #endif diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl index 0deaf4054d22..83b3fafddcbb 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl @@ -147,7 +147,7 @@ void closure_Glossy_eval_end(ClosureInputGlossy cl_in, { cl_out.radiance = render_pass_glossy_mask(cl_out.radiance); #if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND) - /* This makes shader resources become unused and avoid issues with samplers. (see T59747) */ + /* This makes shader resources become unused and avoid issues with samplers. (see #59747) */ cl_out.radiance = vec3(0.0); return; #endif diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl index 5c6769b185a8..400480564dd6 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl @@ -127,7 +127,7 @@ void closure_Refraction_eval_end(ClosureInputRefraction cl_in, { cl_out.radiance = render_pass_glossy_mask(cl_out.radiance); #if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND) - /* This makes shader resources become unused and avoid issues with samplers. (see T59747) */ + /* This makes shader resources become unused and avoid issues with samplers. (see #59747) */ cl_out.radiance = vec3(0.0); return; #endif diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl index 89a6f10e634c..2702b867ef68 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl @@ -73,7 +73,7 @@ void closure_Translucent_eval_end(ClosureInputTranslucent cl_in, { cl_out.radiance = render_pass_diffuse_mask(cl_out.radiance); #if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND) - /* This makes shader resources become unused and avoid issues with samplers. (see T59747) */ + /* This makes shader resources become unused and avoid issues with samplers. (see #59747) */ cl_out.radiance = vec3(0.0); return; #endif diff --git a/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl index 2a5d456feff9..32eaa85408ab 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_downsample_frag.glsl @@ -19,7 +19,7 @@ void main() #else /* NOTE(@fclem): textureSize() does not work the same on all implementations - * when changing the min and max texture levels. Use uniform instead (see T87801). */ + * when changing the min and max texture levels. Use uniform instead (see #87801). */ vec2 uvs = gl_FragCoord.xy * texelSize; vec4 ofs = texelSize.xyxy * vec4(0.75, 0.75, -0.75, -0.75); uvs *= 2.0; diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl index 9570e542d9e6..1f81bc30b171 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl @@ -35,7 +35,7 @@ void main() float val = sampleLowerMip(uv); #else /* NOTE(@fclem): textureSize() does not work the same on all implementations - * when changing the min and max texture levels. Use uniform instead (see T87801). */ + * when changing the min and max texture levels. Use uniform instead (see #87801). */ vec2 uv = texel * 2.0 * texelSize; vec4 samp; diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl index 3e7181f2274e..ef89bd92f530 100644 --- a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl @@ -49,7 +49,7 @@ vec3 solve_cubic(vec4 coefs) /* Discriminant */ float discr = dot(vec2(4.0 * delta.x, -delta.y), delta.zy); - /* Clamping avoid NaN output on some platform. (see T67060) */ + /* Clamping avoid NaN output on some platform. (see #67060) */ float sqrt_discr = sqrt(clamp(discr, 0.0, FLT_MAX)); vec2 xlc, xsc; diff --git a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl index bf105bd907b7..e5fb19c9da7b 100644 --- a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl @@ -145,7 +145,7 @@ void main() /* Only supported attrib for world/background shaders. */ vec3 attr_load_orco(vec4 orco) { - /* Retain precision better than g_data.P (see T99128). */ + /* Retain precision better than g_data.P (see #99128). */ return -normal_view_to_world(viewCameraVec(viewPosition)); } /* Unsupported. */ diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl index 828170598542..8f4a80ce6c3c 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl @@ -52,7 +52,7 @@ void main() float ray_len = orig_ray_len * cell_depth; /* Emission does not work of there is no extinction because - * Tr evaluates to 1.0 leading to Lscat = 0.0. (See T65771) */ + * Tr evaluates to 1.0 leading to Lscat = 0.0. (See #65771) */ s_extinction = max(vec3(1e-7) * step(1e-5, Lscat), s_extinction); /* Evaluate Scattering */ diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index f27ced53e394..0207a2574b23 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -507,6 +507,8 @@ GPUMaterial *ShaderModule::material_shader_get(const char *name, this); GPU_material_status_set(gpumat, GPU_MAT_QUEUED); GPU_material_compile(gpumat); + /* Queue deferred material optimization. */ + DRW_shader_queue_optimize_material(gpumat); return gpumat; } diff --git a/source/blender/draw/engines/eevee_next/eevee_shadow.cc b/source/blender/draw/engines/eevee_next/eevee_shadow.cc index d3b4eb819256..c7d6dcb62d7f 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shadow.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shadow.cc @@ -409,7 +409,7 @@ void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera /* Offset in tiles from the origin to the center of the first tile-maps. */ int2 origin_offset = int2(round(float2(near_point) / tile_size)); - /* Offset in tiles between the first andlod the last tile-maps. */ + /* Offset in tiles between the first and the last tile-maps. */ int2 offset_vector = int2(round(farthest_tilemap_center / tile_size)); light.clipmap_base_offset = (offset_vector * (1 << 16)) / max_ii(levels_range.size() - 1, 1); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl index 366a7dc9ba01..86567b43c862 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_light_culling_debug_frag.glsl @@ -21,8 +21,7 @@ void main() float light_count = 0.0; uint light_cull = 0u; vec2 px = gl_FragCoord.xy; - LIGHT_FOREACH_BEGIN_LOCAL(light_cull_buf, light_zbin_buf, light_tile_buf, px, vP_z, l_idx) - { + LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, px, vP_z, l_idx) { LightData light = light_buf[l_idx]; light_cull |= 1u << l_idx; light_count += 1.0; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_light_eval_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_light_eval_lib.glsl index d270768acb30..4a57a850d340 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_light_eval_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_light_eval_lib.glsl @@ -95,8 +95,7 @@ void light_eval(ClosureDiffuse diffuse, uv = uv * UTIL_TEX_UV_SCALE + UTIL_TEX_UV_BIAS; vec4 ltc_mat = utility_tx_sample(utility_tx, uv, UTIL_LTC_MAT_LAYER); - LIGHT_FOREACH_BEGIN_DIRECTIONAL(light_cull_buf, l_idx) - { + LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) { light_eval_ex(diffuse, reflection, true, @@ -113,8 +112,7 @@ void light_eval(ClosureDiffuse diffuse, LIGHT_FOREACH_END vec2 px = gl_FragCoord.xy; - LIGHT_FOREACH_BEGIN_LOCAL(light_cull_buf, light_zbin_buf, light_tile_buf, px, vP_z, l_idx) - { + LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, px, vP_z, l_idx) { light_eval_ex(diffuse, reflection, false, diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ltc_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ltc_lib.glsl index 57e92b0b9b43..8255b53422e3 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ltc_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ltc_lib.glsl @@ -45,7 +45,7 @@ vec3 ltc_solve_cubic(vec4 coefs) /* Discriminant */ float discr = dot(vec2(4.0 * delta.x, -delta.y), delta.zy); - /* Clamping avoid NaN output on some platform. (see T67060) */ + /* Clamping avoid NaN output on some platform. (see #67060) */ float sqrt_discr = sqrt(clamp(discr, 0.0, FLT_MAX)); vec2 xlc, xsc; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl index afcc8b2d243b..65a9904a2098 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl @@ -82,8 +82,7 @@ LightData debug_light_get() } LIGHT_FOREACH_END - LIGHT_FOREACH_BEGIN_DIRECTIONAL(light_cull_buf, l_idx) - { + LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) { LightData light = light_buf[l_idx]; if (light.tilemap_index == debug_tilemap_index) { return light; @@ -193,4 +192,4 @@ void main() break; } } -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_allocate_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_allocate_comp.glsl index 786b2376595c..907b4e294f43 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_allocate_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_allocate_comp.glsl @@ -38,4 +38,4 @@ void main() } tile_start += lod_len; } -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl index 57de4ed4e2ef..cb95b847ea11 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl @@ -126,4 +126,4 @@ void main() clear_dispatch_buf.num_groups_x = pages_infos_buf.page_size / SHADOW_PAGE_CLEAR_GROUP_SIZE; clear_dispatch_buf.num_groups_y = pages_infos_buf.page_size / SHADOW_PAGE_CLEAR_GROUP_SIZE; clear_dispatch_buf.num_groups_z = 0; -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_free_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_free_comp.glsl index 8332da2f2730..69a69361283d 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_free_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_free_comp.glsl @@ -51,4 +51,4 @@ void main() } tile_start += lod_len; } -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_mask_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_mask_comp.glsl index 3ac32a8bb8b2..14d91f451b7d 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_mask_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_page_mask_comp.glsl @@ -52,4 +52,4 @@ void main() } } } -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_update_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_update_comp.glsl index 9e31172fd054..475d456db7a0 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_update_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_update_comp.glsl @@ -91,4 +91,4 @@ void main() } } } -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_comp.glsl index 5df9bc80ef54..d30b8b4ab930 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_comp.glsl @@ -29,4 +29,4 @@ void main() vec2 pixel = vec2(gl_GlobalInvocationID.xy); shadow_tag_usage(vP, P, pixel); -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl index 378fb870253c..23f78106ac2b 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl @@ -12,4 +12,4 @@ void main() { shadow_tag_usage(interp.vP, interp.P, gl_FragCoord.xy); -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_lib.glsl index a3371cb4b0b7..1372153f1770 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_lib.glsl @@ -92,15 +92,13 @@ void shadow_tag_usage(vec3 vP, vec3 P, vec2 pixel) { float dist_to_cam = length(vP); - LIGHT_FOREACH_BEGIN_DIRECTIONAL(light_cull_buf, l_idx) - { + LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) { shadow_tag_usage_tilemap(l_idx, P, dist_to_cam, true); } LIGHT_FOREACH_END - LIGHT_FOREACH_BEGIN_LOCAL(light_cull_buf, light_zbin_buf, light_tile_buf, pixel, vP.z, l_idx) - { + LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, pixel, vP.z, l_idx) { shadow_tag_usage_tilemap(l_idx, P, dist_to_cam, false); } LIGHT_FOREACH_END -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_vert.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_vert.glsl index 130ce6512b27..fcca152ef829 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_vert.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tag_usage_vert.glsl @@ -19,4 +19,4 @@ void main() interp.vP = point_world_to_view(interp.P); gl_Position = point_world_to_ndc(interp.P); -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_test.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_test.glsl index d7d712ae3cb6..4c4edb81006b 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_test.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_test.glsl @@ -395,4 +395,4 @@ void main() EXPECT_NEAR(shadow_slope_bias_get(atlas_size, light, lNg, lP0, vec2(0.0), 2), 0.0, 1e-4); } } -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_bounds_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_bounds_comp.glsl index 005dbffed858..6d992203e2e6 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_bounds_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_bounds_comp.glsl @@ -29,8 +29,7 @@ void main() bounds.bounding_corners[2].xyz, bounds.bounding_corners[3].xyz); - LIGHT_FOREACH_BEGIN_DIRECTIONAL(light_cull_buf, l_idx) - { + LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) { LightData light = light_buf[l_idx]; float local_min = FLT_MAX; @@ -75,4 +74,4 @@ void main() * thread 0. */ } LIGHT_FOREACH_END -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_finalize_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_finalize_comp.glsl index ef689588337f..573fe6eec1bd 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_finalize_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_finalize_comp.glsl @@ -178,4 +178,4 @@ void main() /* Clamp it as it can underflow if there is too much tile present on screen. */ pages_infos_buf.page_free_count = max(pages_infos_buf.page_free_count, 0); } -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_init_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_init_comp.glsl index 13ed490c77fc..318efcd20842 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_init_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_shadow_tilemap_init_comp.glsl @@ -90,4 +90,4 @@ void main() tiles_buf[tile_store] = tile; } } -} \ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_shadow_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_shadow_info.hh index bb6b6d1e105f..378ec8d10a57 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_shadow_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_shadow_info.hh @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ #include "eevee_defines.hh" diff --git a/source/blender/draw/engines/overlay/overlay_armature.cc b/source/blender/draw/engines/overlay/overlay_armature.cc index 6644112b1305..674ce4ceb4d8 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.cc +++ b/source/blender/draw/engines/overlay/overlay_armature.cc @@ -1486,7 +1486,7 @@ static void draw_axes(ArmatureDrawContext *ctx, if (pchan && pchan->custom && !(arm->flag & ARM_NO_CUSTOM)) { /* Special case: Custom bones can have different scale than the bone. - * Recompute display matrix without the custom scaling applied. (T65640). */ + * Recompute display matrix without the custom scaling applied. (#65640). */ float axis_mat[4][4]; float length = pchan->bone->length; copy_m4_m4(axis_mat, pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat); @@ -2096,7 +2096,7 @@ static void draw_bone_name(ArmatureDrawContext *ctx, /* -------------------------------------------------------------------- */ /** \name Pose Bone Culling * - * Used for selection since drawing many bones can be slow, see: T91253. + * Used for selection since drawing many bones can be slow, see: #91253. * * Bounding spheres are used with margins added to ensure bones are included. * An added margin is needed because #BKE_pchan_minmax only returns the bounds @@ -2231,7 +2231,7 @@ static void draw_armature_edit(ArmatureDrawContext *ctx) const Object *ob_orig = DEG_get_original_object(ob); /* FIXME(@ideasman42): We should be able to use the CoW object, * however the active bone isn't updated. Long term solution is an 'EditArmature' struct. - * for now we can draw from the original armature. See: T66773. */ + * for now we can draw from the original armature. See: #66773. */ // bArmature *arm = ob->data; bArmature *arm = static_cast(ob_orig->data); diff --git a/source/blender/draw/engines/overlay/overlay_edit_curves.cc b/source/blender/draw/engines/overlay/overlay_edit_curves.cc index c2b7e3ee92f2..4570d82781c8 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_curves.cc +++ b/source/blender/draw/engines/overlay/overlay_edit_curves.cc @@ -5,10 +5,14 @@ * \ingroup draw_engine */ +#include "BKE_curves.h" + #include "DRW_render.h" #include "ED_view3d.h" +#include "DEG_depsgraph_query.h" + #include "draw_cache_impl.h" #include "overlay_private.hh" @@ -17,7 +21,10 @@ void OVERLAY_edit_curves_init(OVERLAY_Data *vedata) { OVERLAY_PrivateData *pd = vedata->stl->pd; const DRWContextState *draw_ctx = DRW_context_state_get(); + const Object *obact_orig = DEG_get_original_object(draw_ctx->obact); + const Curves &curves_id = *static_cast(obact_orig->data); + pd->edit_curves.do_points = curves_id.selection_domain == ATTR_DOMAIN_POINT; pd->edit_curves.do_zbufclip = XRAY_FLAG_ENABLED(draw_ctx->v3d); /* Create view with depth offset. */ @@ -39,10 +46,12 @@ void OVERLAY_edit_curves_cache_init(OVERLAY_Data *vedata) /* Run Twice for in-front passes. */ for (int i = 0; i < 2; i++) { - DRW_PASS_CREATE(psl->edit_curves_points_ps[i], (state | pd->clipping_state)); - sh = OVERLAY_shader_edit_particle_point(); - grp = pd->edit_curves_points_grp[i] = DRW_shgroup_create(sh, psl->edit_curves_points_ps[i]); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + if (pd->edit_curves.do_points) { + DRW_PASS_CREATE(psl->edit_curves_points_ps[i], (state | pd->clipping_state)); + sh = OVERLAY_shader_edit_particle_point(); + grp = pd->edit_curves_points_grp[i] = DRW_shgroup_create(sh, psl->edit_curves_points_ps[i]); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + } DRW_PASS_CREATE(psl->edit_curves_lines_ps[i], (state | pd->clipping_state)); sh = OVERLAY_shader_edit_particle_strand(); @@ -56,9 +65,11 @@ static void overlay_edit_curves_add_ob_to_pass(OVERLAY_PrivateData *pd, Object * { Curves *curves = static_cast(ob->data); - DRWShadingGroup *point_shgrp = pd->edit_curves_points_grp[in_front]; - struct GPUBatch *geom_points = DRW_curves_batch_cache_get_edit_points(curves); - DRW_shgroup_call_no_cull(point_shgrp, geom_points, ob); + if (pd->edit_curves.do_points) { + DRWShadingGroup *point_shgrp = pd->edit_curves_points_grp[in_front]; + struct GPUBatch *geom_points = DRW_curves_batch_cache_get_edit_points(curves); + DRW_shgroup_call_no_cull(point_shgrp, geom_points, ob); + } DRWShadingGroup *lines_shgrp = pd->edit_curves_lines_grp[in_front]; struct GPUBatch *geom_lines = DRW_curves_batch_cache_get_edit_lines(curves); @@ -89,12 +100,16 @@ void OVERLAY_edit_curves_draw(OVERLAY_Data *vedata) if (pd->edit_curves.do_zbufclip) { DRW_view_set_active(pd->view_edit_curves); - DRW_draw_pass(psl->edit_curves_points_ps[NOT_IN_FRONT]); + if (pd->edit_curves.do_points) { + DRW_draw_pass(psl->edit_curves_points_ps[NOT_IN_FRONT]); + } DRW_draw_pass(psl->edit_curves_lines_ps[NOT_IN_FRONT]); } else { DRW_view_set_active(pd->view_edit_curves); - DRW_draw_pass(psl->edit_curves_points_ps[IN_FRONT]); + if (pd->edit_curves.do_points) { + DRW_draw_pass(psl->edit_curves_points_ps[IN_FRONT]); + } DRW_draw_pass(psl->edit_curves_lines_ps[IN_FRONT]); } } diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.cc b/source/blender/draw/engines/overlay/overlay_edit_mesh.cc index f705bde6b548..256588e56f26 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.cc +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.cc @@ -85,7 +85,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata) if ((flag & V3D_OVERLAY_EDIT_EDGES) == 0) { if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) { if ((v3d->shading.type < OB_SOLID) || (v3d->shading.flag & V3D_SHADING_XRAY)) { - /* Special case, when drawing wire, draw edges, see: T67637. */ + /* Special case, when drawing wire, draw edges, see: #67637. */ } else { pd->edit_mesh.do_edges = false; diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.cc b/source/blender/draw/engines/overlay/overlay_edit_uv.cc index 8b3c4e5d0ce2..9e95b2eca05b 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_uv.cc +++ b/source/blender/draw/engines/overlay/overlay_edit_uv.cc @@ -414,7 +414,7 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) /* HACK: When editing objects that share the same mesh we should only draw the * first one in the order that is used during uv editing. We can only trust that the first object - * has the correct batches with the correct selection state. See T83187. */ + * has the correct batches with the correct selection state. See #83187. */ if ((pd->edit_uv.do_uv_overlay || pd->edit_uv.do_uv_shadow_overlay) && draw_ctx->obact->type == OB_MESH) { uint objects_len = 0; diff --git a/source/blender/draw/engines/overlay/overlay_engine.cc b/source/blender/draw/engines/overlay/overlay_engine.cc index e8300e81f2fd..5b414c8c5f0a 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.cc +++ b/source/blender/draw/engines/overlay/overlay_engine.cc @@ -248,7 +248,7 @@ BLI_INLINE OVERLAY_DupliData *OVERLAY_duplidata_get(Object *ob, void *vedata, bo static bool overlay_object_is_edit_mode(const OVERLAY_PrivateData *pd, const Object *ob) { if (DRW_object_is_in_edit_mode(ob)) { - /* Also check for context mode as the object mode is not 100% reliable. (see T72490) */ + /* Also check for context mode as the object mode is not 100% reliable. (see #72490) */ switch (ob->type) { case OB_MESH: return pd->ctx_mode == CTX_MODE_EDIT_MESH; @@ -632,6 +632,10 @@ static void OVERLAY_draw_scene(void *vedata) GPU_framebuffer_bind(fbl->overlay_line_fb); } + if (pd->ctx_mode == CTX_MODE_SCULPT_CURVES) { + OVERLAY_sculpt_curves_draw_wires(data); + } + OVERLAY_wireframe_draw(data); OVERLAY_armature_draw(data); OVERLAY_particle_draw(data); diff --git a/source/blender/draw/engines/overlay/overlay_extra.cc b/source/blender/draw/engines/overlay/overlay_extra.cc index 8a4e8734ebec..889787507667 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.cc +++ b/source/blender/draw/engines/overlay/overlay_extra.cc @@ -645,7 +645,7 @@ void OVERLAY_light_cache_populate(OVERLAY_Data *vedata, Object *ob) } else if (la->type == LA_SPOT) { /* Previous implementation was using the clip-end distance as cone size. - * We cannot do this anymore so we use a fixed size of 10. (see T72871) */ + * We cannot do this anymore so we use a fixed size of 10. (see #72871) */ const float3 scale_vec = {10.0f, 10.0f, 10.0f}; rescale_m4(instdata.mat, scale_vec); /* For cycles and EEVEE the spot attenuation is: diff --git a/source/blender/draw/engines/overlay/overlay_image.cc b/source/blender/draw/engines/overlay/overlay_image.cc index 7b99bd6bd18e..622dc7339cac 100644 --- a/source/blender/draw/engines/overlay/overlay_image.cc +++ b/source/blender/draw/engines/overlay/overlay_image.cc @@ -375,7 +375,7 @@ void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob) { /* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead, - * see: T59347 */ + * see: #59347 */ int size[2] = {0}; if (ima != nullptr) { ImageUser iuser = *ob->iuser; diff --git a/source/blender/draw/engines/overlay/overlay_private.hh b/source/blender/draw/engines/overlay/overlay_private.hh index 5636286a8acf..b9aa77106f58 100644 --- a/source/blender/draw/engines/overlay/overlay_private.hh +++ b/source/blender/draw/engines/overlay/overlay_private.hh @@ -120,6 +120,7 @@ typedef struct OVERLAY_PassList { DRWPass *pointcloud_ps; DRWPass *sculpt_mask_ps; DRWPass *sculpt_curves_selection_ps; + DRWPass *sculpt_curves_cage_ps; DRWPass *volume_ps; DRWPass *wireframe_ps; DRWPass *wireframe_xray_ps; @@ -287,6 +288,7 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *pointcloud_dots_grp; DRWShadingGroup *sculpt_mask_grp; DRWShadingGroup *sculpt_curves_selection_grp; + DRWShadingGroup *sculpt_curves_cage_lines_grp; DRWShadingGroup *viewer_attribute_curve_grp; DRWShadingGroup *viewer_attribute_curves_grp; DRWShadingGroup *viewer_attribute_mesh_grp; @@ -362,6 +364,7 @@ typedef struct OVERLAY_PrivateData { int flag; /** Copy of #v3d->overlay.edit_flag. */ } edit_mesh; struct { + bool do_points; bool do_zbufclip; } edit_curves; struct { @@ -686,6 +689,7 @@ void OVERLAY_sculpt_draw(OVERLAY_Data *vedata); void OVERLAY_sculpt_curves_cache_init(OVERLAY_Data *vedata); void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_sculpt_curves_draw(OVERLAY_Data *vedata); +void OVERLAY_sculpt_curves_draw_wires(OVERLAY_Data *vedata); void OVERLAY_viewer_attribute_cache_init(OVERLAY_Data *vedata); void OVERLAY_viewer_attribute_cache_populate(OVERLAY_Data *vedata, Object *object); @@ -775,6 +779,7 @@ GPUShader *OVERLAY_shader_particle_dot(void); GPUShader *OVERLAY_shader_particle_shape(void); GPUShader *OVERLAY_shader_sculpt_mask(void); GPUShader *OVERLAY_shader_sculpt_curves_selection(void); +GPUShader *OVERLAY_shader_sculpt_curves_cage(void); GPUShader *OVERLAY_shader_viewer_attribute_curve(void); GPUShader *OVERLAY_shader_viewer_attribute_curves(void); GPUShader *OVERLAY_shader_viewer_attribute_mesh(void); diff --git a/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc b/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc index f84b93a487c0..c73386f78974 100644 --- a/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc +++ b/source/blender/draw/engines/overlay/overlay_sculpt_curves.cc @@ -11,23 +11,41 @@ #include "overlay_private.hh" #include "BKE_attribute.hh" +#include "BKE_crazyspace.hh" #include "BKE_curves.hh" +#include "DEG_depsgraph_query.h" + void OVERLAY_sculpt_curves_cache_init(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; OVERLAY_PrivateData *pd = vedata->stl->pd; + const View3DOverlay &overlay = vedata->stl->pd->overlay; - const DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA; - DRW_PASS_CREATE(psl->sculpt_curves_selection_ps, state | pd->clipping_state); + /* Selection overlay. */ + { + const DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA; + DRW_PASS_CREATE(psl->sculpt_curves_selection_ps, state | pd->clipping_state); - GPUShader *sh = OVERLAY_shader_sculpt_curves_selection(); - pd->sculpt_curves_selection_grp = DRW_shgroup_create(sh, psl->sculpt_curves_selection_ps); - DRWShadingGroup *grp = pd->sculpt_curves_selection_grp; + GPUShader *sh = OVERLAY_shader_sculpt_curves_selection(); + pd->sculpt_curves_selection_grp = DRW_shgroup_create(sh, psl->sculpt_curves_selection_ps); + DRWShadingGroup *grp = pd->sculpt_curves_selection_grp; - /* Reuse the same mask opacity from sculpt mode, since it wasn't worth it to add a different - * property yet. */ - DRW_shgroup_uniform_float_copy(grp, "selection_opacity", pd->overlay.sculpt_mode_mask_opacity); + /* Reuse the same mask opacity from sculpt mode, since it wasn't worth it to add a different + * property yet. */ + DRW_shgroup_uniform_float_copy(grp, "selection_opacity", pd->overlay.sculpt_mode_mask_opacity); + } + /* Cage overlay. */ + { + const DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | + DRW_STATE_BLEND_ALPHA; + DRW_PASS_CREATE(psl->sculpt_curves_cage_ps, state | pd->clipping_state); + + GPUShader *sh = OVERLAY_shader_sculpt_curves_cage(); + pd->sculpt_curves_cage_lines_grp = DRW_shgroup_create(sh, psl->sculpt_curves_cage_ps); + DRW_shgroup_uniform_float_copy( + pd->sculpt_curves_cage_lines_grp, "opacity", overlay.sculpt_curves_cage_opacity); + } } static bool everything_selected(const Curves &curves_id) @@ -39,7 +57,7 @@ static bool everything_selected(const Curves &curves_id) return selection.is_single() && selection.get_internal_single(); } -void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object) +static void populate_selection_overlay(OVERLAY_Data *vedata, Object *object) { OVERLAY_PrivateData *pd = vedata->stl->pd; Curves *curves = static_cast(object->data); @@ -68,16 +86,35 @@ void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object) DRW_shgroup_buffer_texture(grp, "selection_tx", *texture); } +static void populate_edit_overlay(OVERLAY_Data *vedata, Object *object) +{ + OVERLAY_PrivateData *pd = vedata->stl->pd; + Curves *curves = static_cast(object->data); + + GPUBatch *geom_lines = DRW_curves_batch_cache_get_edit_lines(curves); + DRW_shgroup_call_no_cull(pd->sculpt_curves_cage_lines_grp, geom_lines, object); +} + +void OVERLAY_sculpt_curves_cache_populate(OVERLAY_Data *vedata, Object *object) +{ + populate_selection_overlay(vedata, object); + const View3DOverlay &overlay = vedata->stl->pd->overlay; + if ((overlay.flag & V3D_OVERLAY_SCULPT_CURVES_CAGE) && + overlay.sculpt_curves_cage_opacity > 0.0f) { + populate_edit_overlay(vedata, object); + } +} + void OVERLAY_sculpt_curves_draw(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; - OVERLAY_PrivateData *pd = vedata->stl->pd; - OVERLAY_FramebufferList *fbl = vedata->fbl; - - if (DRW_state_is_fbo()) { - GPU_framebuffer_bind(pd->painting.in_front ? fbl->overlay_in_front_fb : - fbl->overlay_default_fb); - } DRW_draw_pass(psl->sculpt_curves_selection_ps); } + +void OVERLAY_sculpt_curves_draw_wires(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + + DRW_draw_pass(psl->sculpt_curves_cage_ps); +} diff --git a/source/blender/draw/engines/overlay/overlay_shader.cc b/source/blender/draw/engines/overlay/overlay_shader.cc index 5fd009db715e..2229316d295c 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.cc +++ b/source/blender/draw/engines/overlay/overlay_shader.cc @@ -91,6 +91,7 @@ struct OVERLAY_Shaders { GPUShader *particle_shape; GPUShader *pointcloud_dot; GPUShader *sculpt_mask; + GPUShader *sculpt_curves_cage; GPUShader *sculpt_curves_selection; GPUShader *uniform_color; GPUShader *uniform_color_pointcloud; @@ -856,6 +857,18 @@ GPUShader *OVERLAY_shader_sculpt_curves_selection(void) return sh_data->sculpt_curves_selection; } +GPUShader *OVERLAY_shader_sculpt_curves_cage(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + if (!sh_data->sculpt_curves_cage) { + sh_data->sculpt_curves_cage = GPU_shader_create_from_info_name( + (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "overlay_sculpt_curves_cage_clipped" : + "overlay_sculpt_curves_cage"); + } + return sh_data->sculpt_curves_cage; +} + GPUShader *OVERLAY_shader_viewer_attribute_mesh(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); diff --git a/source/blender/draw/engines/overlay/shaders/infos/overlay_edit_mode_info.hh b/source/blender/draw/engines/overlay/shaders/infos/overlay_edit_mode_info.hh index b1c28bcb3e34..4404eef76e45 100644 --- a/source/blender/draw/engines/overlay/shaders/infos/overlay_edit_mode_info.hh +++ b/source/blender/draw/engines/overlay/shaders/infos/overlay_edit_mode_info.hh @@ -496,7 +496,7 @@ GPU_SHADER_CREATE_INFO(overlay_edit_lattice_wire_clipped) GPU_SHADER_CREATE_INFO(overlay_edit_particle_strand) .do_static_compilation(true) .vertex_in(0, Type::VEC3, "pos") - .vertex_in(1, Type::FLOAT, "color") + .vertex_in(1, Type::FLOAT, "selection") .sampler(0, ImageType::FLOAT_1D, "weightTex") .push_constant(Type::BOOL, "useWeight") .vertex_out(overlay_edit_smooth_color_iface) @@ -512,7 +512,7 @@ GPU_SHADER_CREATE_INFO(overlay_edit_particle_strand_clipped) GPU_SHADER_CREATE_INFO(overlay_edit_particle_point) .do_static_compilation(true) .vertex_in(0, Type::VEC3, "pos") - .vertex_in(1, Type::FLOAT, "color") + .vertex_in(1, Type::FLOAT, "selection") .vertex_out(overlay_edit_flat_color_iface) .fragment_out(0, Type::VEC4, "fragColor") .vertex_source("overlay_edit_particle_point_vert.glsl") @@ -630,7 +630,7 @@ GPU_SHADER_CREATE_INFO(overlay_uniform_color_pointcloud) GPU_SHADER_CREATE_INFO(overlay_uniform_color_clipped) .do_static_compilation(true) - .additional_info("overlay_depth_only", "drw_clipped"); + .additional_info("overlay_uniform_color", "drw_clipped"); GPU_SHADER_CREATE_INFO(overlay_uniform_color_pointcloud_clipped) .do_static_compilation(true) diff --git a/source/blender/draw/engines/overlay/shaders/infos/overlay_sculpt_curves_info.hh b/source/blender/draw/engines/overlay/shaders/infos/overlay_sculpt_curves_info.hh index 46e3943b293a..b0b261ed9f17 100644 --- a/source/blender/draw/engines/overlay/shaders/infos/overlay_sculpt_curves_info.hh +++ b/source/blender/draw/engines/overlay/shaders/infos/overlay_sculpt_curves_info.hh @@ -19,3 +19,24 @@ GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_selection) GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_selection_clipped) .do_static_compilation(true) .additional_info("overlay_sculpt_curves_selection", "drw_clipped"); + +GPU_SHADER_INTERFACE_INFO(overlay_sculpt_curves_cage_iface, "") + .no_perspective(Type::VEC2, "edgePos") + .flat(Type::VEC2, "edgeStart") + .smooth(Type::VEC4, "finalColor"); + +GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_cage) + .do_static_compilation(true) + .vertex_in(0, Type::VEC3, "pos") + .vertex_in(1, Type::FLOAT, "selection") + .vertex_out(overlay_sculpt_curves_cage_iface) + .fragment_out(0, Type::VEC4, "fragColor") + .fragment_out(1, Type::VEC4, "lineOutput") + .push_constant(Type::FLOAT, "opacity") + .vertex_source("overlay_sculpt_curves_cage_vert.glsl") + .fragment_source("overlay_extra_frag.glsl") + .additional_info("draw_modelmat", "draw_view", "draw_globals"); + +GPU_SHADER_CREATE_INFO(overlay_sculpt_curves_cage_clipped) + .do_static_compilation(true) + .additional_info("overlay_sculpt_curves_cage", "drw_clipped"); diff --git a/source/blender/draw/engines/overlay/shaders/overlay_edit_mesh_geom.glsl b/source/blender/draw/engines/overlay/shaders/overlay_edit_mesh_geom.glsl index 1f6ff4e7d3aa..a3d797a3664e 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_edit_mesh_geom.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_edit_mesh_geom.glsl @@ -9,7 +9,7 @@ void do_vertex(vec4 color, vec4 pos, float coord, vec2 offset) gl_Position = pos; /* Multiply offset by 2 because gl_Position range is [-1..1]. */ gl_Position.xy += offset * 2.0 * pos.w; - /* Correct but fails due to an AMD compiler bug, see: T62792. + /* Correct but fails due to an AMD compiler bug, see: #62792. * Do inline instead. */ #if 0 view_clipping_distances_set(gl_in[i]); @@ -62,7 +62,7 @@ void main() edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz; /* Due to an AMD glitch, this line was moved out of the `do_vertex` - * function (see T62792). */ + * function (see #62792). */ view_clipping_distances_set(gl_in[0]); do_vertex(geometry_in[0].finalColor_, pos0, half_size, edge_ofs.xy); do_vertex(geometry_in[0].finalColor_, pos0, -half_size, -edge_ofs.xy); diff --git a/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_point_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_point_vert.glsl index 956b27e948d6..39c8683a5854 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_point_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_point_vert.glsl @@ -7,7 +7,7 @@ void main() vec3 world_pos = point_object_to_world(pos); gl_Position = point_world_to_ndc(world_pos); - finalColor = mix(colorWire, colorVertexSelect, color); + finalColor = mix(colorWire, colorVertexSelect, selection); gl_PointSize = sizeVertex * 2.0; diff --git a/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_strand_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_strand_vert.glsl index 6a92206d524e..5240244b1b38 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_strand_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_strand_vert.glsl @@ -25,10 +25,10 @@ void main() gl_Position = point_world_to_ndc(world_pos); if (useWeight) { - finalColor = vec4(weight_to_rgb(color), 1.0); + finalColor = vec4(weight_to_rgb(selection), 1.0); } else { - finalColor = mix(colorWire, colorVertexSelect, color); + finalColor = mix(colorWire, colorVertexSelect, selection); } view_clipping_distances(world_pos); diff --git a/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl b/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl index b401c3e7b2e9..2b333696f940 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_grid_frag.glsl @@ -81,7 +81,7 @@ void main() } else { dist = gl_FragCoord.z * 2.0 - 1.0; - /* Avoid fading in +Z direction in camera view (see T70193). */ + /* Avoid fading in +Z direction in camera view (see #70193). */ dist = flag_test(grid_flag, GRID_CAMERA) ? clamp(dist, 0.0, 1.0) : abs(dist); fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5); dist = 1.0; /* Avoid branch after. */ diff --git a/source/blender/draw/engines/overlay/shaders/overlay_image_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_image_vert.glsl index 45cddb3610da..be56c45dc9f4 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_image_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_image_vert.glsl @@ -6,7 +6,7 @@ void main() { vec3 world_pos = point_object_to_world(pos); if (isCameraBackground) { - /* Model matrix converts to view position to avoid jittering (see T91398). */ + /* Model matrix converts to view position to avoid jittering (see #91398). */ gl_Position = point_view_to_ndc(world_pos); /* Camera background images are not really part of the 3D space. * It makes no sense to apply clipping on them. */ diff --git a/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_cage_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_cage_vert.glsl new file mode 100644 index 000000000000..162934f64de1 --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/overlay_sculpt_curves_cage_vert.glsl @@ -0,0 +1,15 @@ + +#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +void main() +{ + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); + + finalColor = vec4(selection); + finalColor.a *= opacity; + + /* Convert to screen position [0..sizeVp]. */ + edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; +} diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c index 613b60f8829b..03b189a3e5b7 100644 --- a/source/blender/draw/engines/select/select_draw_utils.c +++ b/source/blender/draw/engines/select/select_draw_utils.c @@ -51,7 +51,7 @@ short select_id_get_object_select_mode(Scene *scene, Object *ob) * we need to be in SCE_SELECT_FACE mode so select_cache_init() correctly sets up * a shgroup with select_id_flat. * Note this is not working correctly for vertex-paint (yet), but has been discussed - * in T66645 and there is a solution by @mano-wii in P1032. + * in #66645 and there is a solution by @mano-wii in P1032. * So OB_MODE_VERTEX_PAINT is already included here [required for P1032 I guess]. */ Mesh *me_orig = DEG_get_original_object(ob)->data; if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) { @@ -130,7 +130,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl, } else { /* Note that `r_vert_offset` is calculated from `r_edge_offset`. - * Otherwise the first vertex is never selected, see: T53512. */ + * Otherwise the first vertex is never selected, see: #53512. */ *r_edge_offset = *r_face_offset; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl index 30daca6b7e37..d436707afc7b 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_merge_infront_frag.glsl @@ -2,7 +2,7 @@ void main() { float depth = texture(depthBuffer, uvcoordsvar.xy).r; - /* Fix issues with Intel drivers (see T80023). */ + /* Fix issues with Intel drivers (see #80023). */ fragColor = vec4(0.0); /* Discard background pixels. */ if (depth == 1.0) { diff --git a/source/blender/draw/engines/workbench/workbench_shader_shared.h b/source/blender/draw/engines/workbench/workbench_shader_shared.h index d78e3408ccbc..d7983e5eb80a 100644 --- a/source/blender/draw/engines/workbench/workbench_shader_shared.h +++ b/source/blender/draw/engines/workbench/workbench_shader_shared.h @@ -59,6 +59,6 @@ struct ExtrudedFrustum { struct ShadowPassData { float4 far_plane; - float3 light_direction_ws; + packed_float3 light_direction_ws; int _padding; }; diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c index 211c0e27418b..655093a3fd47 100644 --- a/source/blender/draw/engines/workbench/workbench_shadow.c +++ b/source/blender/draw/engines/workbench/workbench_shadow.c @@ -319,7 +319,7 @@ void workbench_shadow_cache_populate(WORKBENCH_Data *data, Object *ob, const boo use_shadow_pass_technique = false; } - /* We cannot use Shadow Pass technique on non-manifold object (see T76168). */ + /* We cannot use Shadow Pass technique on non-manifold object (see #76168). */ if (use_shadow_pass_technique && !is_manifold && (wpd->cull_state != 0)) { use_shadow_pass_technique = false; } diff --git a/source/blender/draw/engines/workbench/workbench_shadow.cc b/source/blender/draw/engines/workbench/workbench_shadow.cc index dff3314813c8..ff50fd3732c1 100644 --- a/source/blender/draw/engines/workbench/workbench_shadow.cc +++ b/source/blender/draw/engines/workbench/workbench_shadow.cc @@ -259,17 +259,16 @@ void ShadowPass::ShadowView::compute_visibility(ObjectBoundsBuf &bounds, GPU_shader_uniform_1i(shader, "visibility_word_per_draw", word_per_draw); GPU_shader_uniform_1b(shader, "force_fail_method", force_fail_method_); GPU_shader_uniform_3fv(shader, "shadow_direction", light_direction_); - GPU_uniformbuf_bind(extruded_frustum_, - GPU_shader_get_uniform_block(shader, "extruded_frustum")); - GPU_storagebuf_bind(bounds, GPU_shader_get_ssbo(shader, "bounds_buf")); + GPU_uniformbuf_bind(extruded_frustum_, GPU_shader_get_ubo_binding(shader, "extruded_frustum")); + GPU_storagebuf_bind(bounds, GPU_shader_get_ssbo_binding(shader, "bounds_buf")); if (current_pass_type_ == ShadowPass::FORCED_FAIL) { - GPU_storagebuf_bind(visibility_buf_, GPU_shader_get_ssbo(shader, "visibility_buf")); + GPU_storagebuf_bind(visibility_buf_, GPU_shader_get_ssbo_binding(shader, "visibility_buf")); } else { GPU_storagebuf_bind(pass_visibility_buf_, - GPU_shader_get_ssbo(shader, "pass_visibility_buf")); + GPU_shader_get_ssbo_binding(shader, "pass_visibility_buf")); GPU_storagebuf_bind(fail_visibility_buf_, - GPU_shader_get_ssbo(shader, "fail_visibility_buf")); + GPU_shader_get_ssbo_binding(shader, "fail_visibility_buf")); } GPU_uniformbuf_bind(data_, DRW_VIEW_UBO_SLOT); GPU_compute_dispatch(shader, divide_ceil_u(resource_len, DRW_VISIBILITY_GROUP_SIZE), 1, 1); @@ -439,7 +438,7 @@ void ShadowPass::object_sync(SceneState &scene_state, #endif /* Shadow pass technique needs object to be have all its surface opaque. */ - /* We cannot use the PASS technique on non-manifold object (see T76168). */ + /* We cannot use the PASS technique on non-manifold object (see #76168). */ bool force_fail_pass = has_transp_mat || (!is_manifold && (scene_state.cull_state != 0)); PassType fail_type = force_fail_pass ? FORCED_FAIL : FAIL; diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 0d406646f2e3..a316eef92932 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -307,6 +307,7 @@ struct GPUMaterial *DRW_shader_from_material(struct Material *ma, bool deferred, GPUCodegenCallbackFn callback, void *thunk); +void DRW_shader_queue_optimize_material(struct GPUMaterial *mat); void DRW_shader_free(struct GPUShader *shader); #define DRW_SHADER_FREE_SAFE(shader) \ do { \ diff --git a/source/blender/draw/intern/draw_attributes.cc b/source/blender/draw/intern/draw_attributes.cc index cc7c9959850d..e1d53844f5ac 100644 --- a/source/blender/draw/intern/draw_attributes.cc +++ b/source/blender/draw/intern/draw_attributes.cc @@ -1,23 +1,18 @@ /* SPDX-License-Identifier: GPL-2.0-or-later * Copyright 2022 Blender Foundation. All rights reserved. */ -#include "draw_attributes.h" +#include "draw_attributes.hh" /* Return true if the given DRW_AttributeRequest is already in the requests. */ -static bool drw_attributes_has_request(const DRW_Attributes *requests, DRW_AttributeRequest req) +static bool drw_attributes_has_request(const DRW_Attributes *requests, + const DRW_AttributeRequest &req) { for (int i = 0; i < requests->num_requests; i++) { - const DRW_AttributeRequest src_req = requests->requests[i]; - if (src_req.domain != req.domain) { - continue; + const DRW_AttributeRequest &src_req = requests->requests[i]; + if (src_req.domain == req.domain && src_req.layer_index == req.layer_index && + src_req.cd_type == req.cd_type) { + return true; } - if (src_req.layer_index != req.layer_index) { - continue; - } - if (src_req.cd_type != req.cd_type) { - continue; - } - return true; } return false; } @@ -61,14 +56,15 @@ bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b) return true; } -DRW_AttributeRequest *drw_attributes_add_request(DRW_Attributes *attrs, - const char *name, - const eCustomDataType type, - const int layer_index, - const eAttrDomain domain) +void drw_attributes_add_request(DRW_Attributes *attrs, + const char *name, + const eCustomDataType type, + const int layer_index, + const eAttrDomain domain) { - if (attrs->num_requests >= GPU_MAX_ATTR) { - return nullptr; + if (attrs->num_requests >= GPU_MAX_ATTR || + drw_attributes_has_request(attrs, {type, layer_index, domain})) { + return; } DRW_AttributeRequest *req = &attrs->requests[attrs->num_requests]; @@ -77,7 +73,6 @@ DRW_AttributeRequest *drw_attributes_add_request(DRW_Attributes *attrs, req->layer_index = layer_index; req->domain = domain; attrs->num_requests += 1; - return req; } bool drw_custom_data_match_attribute(const CustomData *custom_data, diff --git a/source/blender/draw/intern/draw_attributes.h b/source/blender/draw/intern/draw_attributes.hh similarity index 70% rename from source/blender/draw/intern/draw_attributes.h rename to source/blender/draw/intern/draw_attributes.hh index 223c2a26c60d..d5de4e1641b0 100644 --- a/source/blender/draw/intern/draw_attributes.h +++ b/source/blender/draw/intern/draw_attributes.hh @@ -9,9 +9,7 @@ #pragma once -#ifdef __cplusplus -# include -#endif +#include #include "DNA_customdata_types.h" @@ -24,33 +22,29 @@ #include "GPU_shader.h" #include "GPU_vertex_format.h" -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct DRW_AttributeRequest { +struct DRW_AttributeRequest { eCustomDataType cd_type; int layer_index; eAttrDomain domain; char attribute_name[64]; -} DRW_AttributeRequest; +}; -typedef struct DRW_Attributes { +struct DRW_Attributes { DRW_AttributeRequest requests[GPU_MAX_ATTR]; int num_requests; -} DRW_Attributes; +}; -typedef struct DRW_MeshCDMask { +struct DRW_MeshCDMask { uint32_t uv : 8; uint32_t tan : 8; uint32_t orco : 1; uint32_t tan_orco : 1; uint32_t sculpt_overlays : 1; /** - * Edit uv layer is from the base edit mesh as modifiers could remove it. (see T68857) + * Edit uv layer is from the base edit mesh as modifiers could remove it. (see #68857) */ uint32_t edit_uv : 1; -} DRW_MeshCDMask; +}; /* Keep `DRW_MeshCDMask` struct within a `uint32_t`. * bit-wise and atomic operations are used to compare and update the struct. @@ -59,26 +53,20 @@ BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint32_t), "DRW_MeshCDMask ex void drw_attributes_clear(DRW_Attributes *attributes); -#ifdef __cplusplus void drw_attributes_merge(DRW_Attributes *dst, const DRW_Attributes *src, std::mutex &render_mutex); -#endif /* Return true if all requests in b are in a. */ bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b); -DRW_AttributeRequest *drw_attributes_add_request(DRW_Attributes *attrs, - const char *name, - eCustomDataType data_type, - int layer_index, - eAttrDomain domain); +void drw_attributes_add_request(DRW_Attributes *attrs, + const char *name, + eCustomDataType data_type, + int layer_index, + eAttrDomain domain); bool drw_custom_data_match_attribute(const CustomData *custom_data, const char *name, int *r_layer_index, eCustomDataType *r_type); - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index f1f62d8aee92..abe3283bab7f 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -386,7 +386,7 @@ GPUBatch *DRW_cache_fullscreen_quad_get(void) attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); attr_id.uvs = GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); GPU_vertformat_alias_add(&format, "texCoord"); - GPU_vertformat_alias_add(&format, "orco"); /* Fix driver bug (see T70004) */ + GPU_vertformat_alias_add(&format, "orco"); /* Fix driver bug (see #70004) */ } GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); diff --git a/source/blender/draw/intern/draw_cache_extract.hh b/source/blender/draw/intern/draw_cache_extract.hh index 4fe360eecd7c..bc64be7656c4 100644 --- a/source/blender/draw/intern/draw_cache_extract.hh +++ b/source/blender/draw/intern/draw_cache_extract.hh @@ -22,7 +22,7 @@ #include "GPU_index_buffer.h" #include "GPU_vertex_buffer.h" -#include "draw_attributes.h" +#include "draw_attributes.hh" struct DRWSubdivCache; struct MeshRenderData; diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 5626b7828028..a5cb6a812148 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -684,8 +684,7 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, MeshRenderData *mr = mesh_render_data_create( object, me, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts); mr->use_hide = use_hide; - mr->use_subsurf_fdots = mr->me && - mr->me->runtime->subsurf_face_dot_tags.size() == mr->me->totvert; + mr->use_subsurf_fdots = mr->me && !mr->me->runtime->subsurf_face_dot_tags.is_empty(); mr->use_final_mesh = do_final; #ifdef DEBUG_TIME diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc index 22e1eb3ece51..7d7831391b3d 100644 --- a/source/blender/draw/intern/draw_cache_impl_curves.cc +++ b/source/blender/draw/intern/draw_cache_impl_curves.cc @@ -25,6 +25,7 @@ #include "DEG_depsgraph_query.h" +#include "BKE_crazyspace.hh" #include "BKE_curves.hh" #include "BKE_geometry_set.hh" @@ -34,17 +35,15 @@ #include "DRW_render.h" -#include "draw_attributes.h" +#include "draw_attributes.hh" #include "draw_cache_impl.h" /* own include */ #include "draw_cache_inline.h" -#include "draw_curves_private.h" /* own include */ +#include "draw_curves_private.hh" /* own include */ #include "draw_shader.h" -using blender::ColorGeometry4f; -using blender::float3; using blender::IndexRange; -using blender::MutableSpan; -using blender::Span; + +namespace blender::draw { /* ---------------------------------------------------------------------- */ /* Curves GPUBatch Cache */ @@ -55,11 +54,11 @@ struct CurvesBatchCache { GPUBatch *edit_points; GPUBatch *edit_lines; - /* Editmode (original) point positions. */ + /* Crazy-space point positions for original points. */ GPUVertBuf *edit_points_pos; - /* Editmode data (such as selection). */ - GPUVertBuf *edit_points_data; + /* Selection of original points. */ + GPUVertBuf *edit_points_selection; GPUIndexBuf *edit_lines_ibo; @@ -114,7 +113,7 @@ static void curves_batch_cache_clear_edit_data(CurvesBatchCache *cache) { /* TODO: more granular update tagging. */ GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_pos); - GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_data); + GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_selection); GPU_INDEXBUF_DISCARD_SAFE(cache->edit_lines_ibo); GPU_BATCH_DISCARD_SAFE(cache->edit_points); @@ -150,70 +149,12 @@ static void curves_batch_cache_clear(Curves &curves) curves_batch_cache_clear_edit_data(cache); } -void DRW_curves_batch_cache_validate(Curves *curves) -{ - if (!curves_batch_cache_valid(*curves)) { - curves_batch_cache_clear(*curves); - curves_batch_cache_init(*curves); - } -} - static CurvesBatchCache &curves_batch_cache_get(Curves &curves) { DRW_curves_batch_cache_validate(&curves); return *static_cast(curves.batch_cache); } -void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode) -{ - CurvesBatchCache *cache = static_cast(curves->batch_cache); - if (cache == nullptr) { - return; - } - switch (mode) { - case BKE_CURVES_BATCH_DIRTY_ALL: - cache->is_dirty = true; - break; - default: - BLI_assert_unreachable(); - } -} - -void DRW_curves_batch_cache_free(Curves *curves) -{ - curves_batch_cache_clear(*curves); - MEM_delete(static_cast(curves->batch_cache)); - curves->batch_cache = nullptr; -} - -void DRW_curves_batch_cache_free_old(Curves *curves, int ctime) -{ - CurvesBatchCache *cache = static_cast(curves->batch_cache); - if (cache == nullptr) { - return; - } - - bool do_discard = false; - - for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { - CurvesEvalFinalCache &final_cache = cache->curves_cache.final[i]; - - if (drw_attributes_overlap(&final_cache.attr_used_over_time, &final_cache.attr_used)) { - final_cache.last_attr_matching_time = ctime; - } - - if (ctime - final_cache.last_attr_matching_time > U.vbotimeout) { - do_discard = true; - } - - drw_attributes_clear(&final_cache.attr_used_over_time); - } - - if (do_discard) { - curves_discard_attributes(cache->curves_cache); - } -} - static void ensure_seg_pt_count(const Curves &curves, CurvesEvalCache &curves_cache) { if (curves_cache.proc_point_buf != nullptr) { @@ -231,13 +172,11 @@ struct PositionAndParameter { }; static void curves_batch_cache_fill_segments_proc_pos( - const Curves &curves_id, + const bke::CurvesGeometry &curves, MutableSpan posTime_data, MutableSpan hairLength_data) { - using namespace blender; /* TODO: use hair radius layer if available. */ - const bke::CurvesGeometry &curves = curves_id.geometry.wrap(); const OffsetIndices points_by_curve = curves.points_by_curve(); const Span positions = curves.positions(); @@ -270,7 +209,7 @@ static void curves_batch_cache_fill_segments_proc_pos( }); } -static void curves_batch_cache_ensure_procedural_pos(const Curves &curves, +static void curves_batch_cache_ensure_procedural_pos(const bke::CurvesGeometry &curves, CurvesEvalCache &cache, GPUMaterial * /*gpu_material*/) { @@ -301,12 +240,10 @@ static void curves_batch_cache_ensure_procedural_pos(const Curves &curves, } } -static void curves_batch_cache_ensure_edit_points_pos(const Curves &curves_id, +static void curves_batch_cache_ensure_edit_points_pos(const bke::CurvesGeometry &curves, + Span deformed_positions, CurvesBatchCache &cache) { - using namespace blender; - const bke::CurvesGeometry &curves = curves_id.geometry.wrap(); - static GPUVertFormat format_pos = {0}; static uint pos; if (format_pos.attr_len == 0) { @@ -315,35 +252,32 @@ static void curves_batch_cache_ensure_edit_points_pos(const Curves &curves_id, GPU_vertbuf_init_with_format(cache.edit_points_pos, &format_pos); GPU_vertbuf_data_alloc(cache.edit_points_pos, curves.points_num()); - - Span positions = curves.positions(); - GPU_vertbuf_attr_fill(cache.edit_points_pos, pos, positions.data()); + GPU_vertbuf_attr_fill(cache.edit_points_pos, pos, deformed_positions.data()); } -static void curves_batch_cache_ensure_edit_points_data(const Curves &curves_id, - CurvesBatchCache &cache) +static void curves_batch_cache_ensure_edit_points_selection(const bke::CurvesGeometry &curves, + const eAttrDomain selection_domain, + CurvesBatchCache &cache) { - using namespace blender; - const bke::CurvesGeometry &curves = curves_id.geometry.wrap(); - static GPUVertFormat format_data = {0}; - static uint color; + static uint selection_id; if (format_data.attr_len == 0) { - color = GPU_vertformat_attr_add(&format_data, "color", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + selection_id = GPU_vertformat_attr_add( + &format_data, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); } - GPU_vertbuf_init_with_format(cache.edit_points_data, &format_data); - GPU_vertbuf_data_alloc(cache.edit_points_data, curves.points_num()); + GPU_vertbuf_init_with_format(cache.edit_points_selection, &format_data); + GPU_vertbuf_data_alloc(cache.edit_points_selection, curves.points_num()); const OffsetIndices points_by_curve = curves.points_by_curve(); const VArray selection = curves.attributes().lookup_or_default( - ".selection", eAttrDomain(curves_id.selection_domain), true); - switch (curves_id.selection_domain) { + ".selection", selection_domain, true); + switch (selection_domain) { case ATTR_DOMAIN_POINT: for (const int point_i : selection.index_range()) { const float point_selection = selection[point_i] ? 1.0f : 0.0f; - GPU_vertbuf_attr_set(cache.edit_points_data, color, point_i, &point_selection); + GPU_vertbuf_attr_set(cache.edit_points_selection, selection_id, point_i, &point_selection); } break; case ATTR_DOMAIN_CURVE: @@ -351,18 +285,19 @@ static void curves_batch_cache_ensure_edit_points_data(const Curves &curves_id, const float curve_selection = selection[curve_i] ? 1.0f : 0.0f; const IndexRange points = points_by_curve[curve_i]; for (const int point_i : points) { - GPU_vertbuf_attr_set(cache.edit_points_data, color, point_i, &curve_selection); + GPU_vertbuf_attr_set( + cache.edit_points_selection, selection_id, point_i, &curve_selection); } } break; + default: + break; } } -static void curves_batch_cache_ensure_edit_lines(const Curves &curves_id, CurvesBatchCache &cache) +static void curves_batch_cache_ensure_edit_lines(const bke::CurvesGeometry &curves, + CurvesBatchCache &cache) { - using namespace blender; - const bke::CurvesGeometry &curves = curves_id.geometry.wrap(); - const int vert_len = curves.points_num(); const int curve_len = curves.curves_num(); const int index_len = vert_len + curve_len; @@ -383,14 +318,6 @@ static void curves_batch_cache_ensure_edit_lines(const Curves &curves_id, Curves GPU_indexbuf_build_in_place(&elb, cache.edit_lines_ibo); } -void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32]) -{ - char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - /* Attributes use auto-name. */ - BLI_snprintf(r_sampler_name, 32, "a%s", attr_safe_name); -} - static void curves_batch_cache_ensure_procedural_final_attr(CurvesEvalCache &cache, const GPUVertFormat *format, const int subdiv, @@ -413,7 +340,6 @@ static void curves_batch_ensure_attribute(const Curves &curves, const int subdiv, const int index) { - using namespace blender; GPU_VERTBUF_DISCARD_SAFE(cache.proc_attributes_buf[index]); char sampler_name[32]; @@ -458,11 +384,10 @@ static void curves_batch_ensure_attribute(const Curves &curves, } } -static void curves_batch_cache_fill_strands_data(const Curves &curves_id, +static void curves_batch_cache_fill_strands_data(const bke::CurvesGeometry &curves, GPUVertBufRaw &data_step, GPUVertBufRaw &seg_step) { - const blender::bke::CurvesGeometry &curves = curves_id.geometry.wrap(); const blender::OffsetIndices points_by_curve = curves.points_by_curve(); for (const int i : IndexRange(curves.curves_num())) { @@ -473,7 +398,7 @@ static void curves_batch_cache_fill_strands_data(const Curves &curves_id, } } -static void curves_batch_cache_ensure_procedural_strand_data(Curves &curves, +static void curves_batch_cache_ensure_procedural_strand_data(const bke::CurvesGeometry &curves, CurvesEvalCache &cache) { GPUVertBufRaw data_step, seg_step; @@ -513,15 +438,12 @@ static void curves_batch_cache_ensure_procedural_final_points(CurvesEvalCache &c cache.final[subdiv].strands_res * cache.strands_len); } -static void curves_batch_cache_fill_segments_indices(const Curves &curves, +static void curves_batch_cache_fill_segments_indices(const bke::CurvesGeometry &curves, const int res, GPUIndexBufBuilder &elb) { - const int curves_num = curves.geometry.curve_num; - uint curr_point = 0; - - for ([[maybe_unused]] const int i : IndexRange(curves_num)) { + for ([[maybe_unused]] const int i : IndexRange(curves.curves_num())) { for (int k = 0; k < res; k++) { GPU_indexbuf_add_generic_vert(&elb, curr_point++); } @@ -529,7 +451,7 @@ static void curves_batch_cache_fill_segments_indices(const Curves &curves, } } -static void curves_batch_cache_ensure_procedural_indices(Curves &curves, +static void curves_batch_cache_ensure_procedural_indices(const bke::CurvesGeometry &curves, CurvesEvalCache &cache, const int thickness_res, const int subdiv) @@ -624,64 +546,6 @@ static bool curves_ensure_attributes(const Curves &curves, return need_tf_update; } -bool curves_ensure_procedural_data(Curves *curves, - CurvesEvalCache **r_hair_cache, - GPUMaterial *gpu_material, - const int subdiv, - const int thickness_res) -{ - bool need_ft_update = false; - - CurvesBatchCache &cache = curves_batch_cache_get(*curves); - *r_hair_cache = &cache.curves_cache; - - const int steps = 3; /* TODO: don't hard-code? */ - (*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv); - - /* Refreshed on combing and simulation. */ - if ((*r_hair_cache)->proc_point_buf == nullptr) { - ensure_seg_pt_count(*curves, cache.curves_cache); - curves_batch_cache_ensure_procedural_pos(*curves, cache.curves_cache, gpu_material); - need_ft_update = true; - } - - /* Refreshed if active layer or custom data changes. */ - if ((*r_hair_cache)->proc_strand_buf == nullptr) { - curves_batch_cache_ensure_procedural_strand_data(*curves, cache.curves_cache); - } - - /* Refreshed only on subdiv count change. */ - if ((*r_hair_cache)->final[subdiv].proc_buf == nullptr) { - curves_batch_cache_ensure_procedural_final_points(cache.curves_cache, subdiv); - need_ft_update = true; - } - if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == nullptr) { - curves_batch_cache_ensure_procedural_indices( - *curves, cache.curves_cache, thickness_res, subdiv); - } - - need_ft_update |= curves_ensure_attributes(*curves, cache, gpu_material, subdiv); - - return need_ft_update; -} - -int DRW_curves_material_count_get(Curves *curves) -{ - return max_ii(1, curves->totcol); -} - -GPUBatch *DRW_curves_batch_cache_get_edit_points(Curves *curves) -{ - CurvesBatchCache &cache = curves_batch_cache_get(*curves); - return DRW_batch_request(&cache.edit_points); -} - -GPUBatch *DRW_curves_batch_cache_get_edit_lines(Curves *curves) -{ - CurvesBatchCache &cache = curves_batch_cache_get(*curves); - return DRW_batch_request(&cache.edit_lines); -} - static void request_attribute(Curves &curves, const char *name) { CurvesBatchCache &cache = curves_batch_cache_get(curves); @@ -709,10 +573,145 @@ static void request_attribute(Curves &curves, const char *name) drw_attributes_merge(&final_cache.attr_used, &attributes, cache.render_mutex); } +} // namespace blender::draw + +void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32]) +{ + char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + /* Attributes use auto-name. */ + BLI_snprintf(r_sampler_name, 32, "a%s", attr_safe_name); +} + +bool curves_ensure_procedural_data(Curves *curves_id, + CurvesEvalCache **r_hair_cache, + GPUMaterial *gpu_material, + const int subdiv, + const int thickness_res) +{ + using namespace blender; + bke::CurvesGeometry &curves = curves_id->geometry.wrap(); + bool need_ft_update = false; + + draw::CurvesBatchCache &cache = draw::curves_batch_cache_get(*curves_id); + *r_hair_cache = &cache.curves_cache; + + const int steps = 3; /* TODO: don't hard-code? */ + (*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv); + + /* Refreshed on combing and simulation. */ + if ((*r_hair_cache)->proc_point_buf == nullptr) { + draw::ensure_seg_pt_count(*curves_id, cache.curves_cache); + draw::curves_batch_cache_ensure_procedural_pos(curves, cache.curves_cache, gpu_material); + need_ft_update = true; + } + + /* Refreshed if active layer or custom data changes. */ + if ((*r_hair_cache)->proc_strand_buf == nullptr) { + draw::curves_batch_cache_ensure_procedural_strand_data(curves, cache.curves_cache); + } + + /* Refreshed only on subdiv count change. */ + if ((*r_hair_cache)->final[subdiv].proc_buf == nullptr) { + draw::curves_batch_cache_ensure_procedural_final_points(cache.curves_cache, subdiv); + need_ft_update = true; + } + if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == nullptr) { + draw::curves_batch_cache_ensure_procedural_indices( + curves, cache.curves_cache, thickness_res, subdiv); + } + + need_ft_update |= draw::curves_ensure_attributes(*curves_id, cache, gpu_material, subdiv); + + return need_ft_update; +} + +void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode) +{ + using namespace blender::draw; + CurvesBatchCache *cache = static_cast(curves->batch_cache); + if (cache == nullptr) { + return; + } + switch (mode) { + case BKE_CURVES_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + default: + BLI_assert_unreachable(); + } +} + +void DRW_curves_batch_cache_validate(Curves *curves) +{ + using namespace blender::draw; + if (!curves_batch_cache_valid(*curves)) { + curves_batch_cache_clear(*curves); + curves_batch_cache_init(*curves); + } +} + +void DRW_curves_batch_cache_free(Curves *curves) +{ + using namespace blender::draw; + curves_batch_cache_clear(*curves); + MEM_delete(static_cast(curves->batch_cache)); + curves->batch_cache = nullptr; +} + +void DRW_curves_batch_cache_free_old(Curves *curves, int ctime) +{ + using namespace blender::draw; + CurvesBatchCache *cache = static_cast(curves->batch_cache); + if (cache == nullptr) { + return; + } + + bool do_discard = false; + + for (const int i : IndexRange(MAX_HAIR_SUBDIV)) { + CurvesEvalFinalCache &final_cache = cache->curves_cache.final[i]; + + if (drw_attributes_overlap(&final_cache.attr_used_over_time, &final_cache.attr_used)) { + final_cache.last_attr_matching_time = ctime; + } + + if (ctime - final_cache.last_attr_matching_time > U.vbotimeout) { + do_discard = true; + } + + drw_attributes_clear(&final_cache.attr_used_over_time); + } + + if (do_discard) { + curves_discard_attributes(cache->curves_cache); + } +} + +int DRW_curves_material_count_get(Curves *curves) +{ + return max_ii(1, curves->totcol); +} + +GPUBatch *DRW_curves_batch_cache_get_edit_points(Curves *curves) +{ + using namespace blender::draw; + CurvesBatchCache &cache = curves_batch_cache_get(*curves); + return DRW_batch_request(&cache.edit_points); +} + +GPUBatch *DRW_curves_batch_cache_get_edit_lines(Curves *curves) +{ + using namespace blender::draw; + CurvesBatchCache &cache = curves_batch_cache_get(*curves); + return DRW_batch_request(&cache.edit_lines); +} + GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves, const char *name, bool *r_is_point_domain) { + using namespace blender::draw; CurvesBatchCache &cache = curves_batch_cache_get(*curves); const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene = draw_ctx->scene; @@ -747,28 +746,37 @@ GPUVertBuf **DRW_curves_texture_for_evaluated_attribute(Curves *curves, void DRW_curves_batch_cache_create_requested(Object *ob) { - Curves *curves = static_cast(ob->data); - Object *orig = DEG_get_original_object(ob); - Curves *curves_orig = static_cast(orig->data); + using namespace blender; + Curves *curves_id = static_cast(ob->data); + Object *ob_orig = DEG_get_original_object(ob); + if (ob_orig == nullptr) { + return; + } + Curves *curves_orig_id = static_cast(ob_orig->data); - CurvesBatchCache &cache = curves_batch_cache_get(*curves); + draw::CurvesBatchCache &cache = draw::curves_batch_cache_get(*curves_id); + bke::CurvesGeometry &curves_orig = curves_orig_id->geometry.wrap(); + + const bke::crazyspace::GeometryDeformation deformation = + bke::crazyspace::get_evaluated_curves_deformation(ob, *ob_orig); if (DRW_batch_requested(cache.edit_points, GPU_PRIM_POINTS)) { DRW_vbo_request(cache.edit_points, &cache.edit_points_pos); - DRW_vbo_request(cache.edit_points, &cache.edit_points_data); + DRW_vbo_request(cache.edit_points, &cache.edit_points_selection); } if (DRW_batch_requested(cache.edit_lines, GPU_PRIM_LINE_STRIP)) { DRW_ibo_request(cache.edit_lines, &cache.edit_lines_ibo); DRW_vbo_request(cache.edit_lines, &cache.edit_points_pos); - DRW_vbo_request(cache.edit_lines, &cache.edit_points_data); + DRW_vbo_request(cache.edit_lines, &cache.edit_points_selection); } if (DRW_vbo_requested(cache.edit_points_pos)) { - curves_batch_cache_ensure_edit_points_pos(*curves_orig, cache); + curves_batch_cache_ensure_edit_points_pos(curves_orig, deformation.positions, cache); } - if (DRW_vbo_requested(cache.edit_points_data)) { - curves_batch_cache_ensure_edit_points_data(*curves_orig, cache); + if (DRW_vbo_requested(cache.edit_points_selection)) { + curves_batch_cache_ensure_edit_points_selection( + curves_orig, eAttrDomain(curves_id->selection_domain), cache); } if (DRW_ibo_requested(cache.edit_lines_ibo)) { - curves_batch_cache_ensure_edit_lines(*curves_orig, cache); + curves_batch_cache_ensure_edit_lines(curves_orig, cache); } } diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index bfeafdf7dcb2..f8077882c12f 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -369,7 +369,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, CustomData_get_named_layer(cd_ldata, CD_PROP_FLOAT2, name) : CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2); - /* Only fallback to orco (below) when we have no UV layers, see: T56545 */ + /* Only fallback to orco (below) when we have no UV layers, see: #56545 */ if (layer == -1 && name[0] != '\0') { layer = CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2); } @@ -750,7 +750,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode) break; case BKE_MESH_BATCH_DIRTY_SELECT_PAINT: /* Paint mode selection flag is packed inside the nor attribute. - * Note that it can be slow if auto smooth is enabled. (see T63946) */ + * Note that it can be slow if auto smooth is enabled. (see #63946) */ FOREACH_MESH_BUFFER_CACHE (cache, mbc) { GPU_INDEXBUF_DISCARD_SAFE(mbc->buff.ibo.lines_paint_mask); GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.pos_nor); @@ -1315,7 +1315,7 @@ static void drw_mesh_batch_cache_check_available(struct TaskGraph *task_graph, M MeshBatchCache *cache = mesh_batch_cache_get(me); /* Make sure all requested batches have been setup. */ /* NOTE: The next line creates a different scheduling than during release builds what can lead to - * some issues (See T77867 where we needed to disable this function in order to debug what was + * some issues (See #77867 where we needed to disable this function in order to debug what was * happening in release builds). */ BLI_task_graph_work_and_wait(task_graph); for (int i = 0; i < MBC_BATCH_LEN; i++) { @@ -1941,7 +1941,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, /* Ensure that all requested batches have finished. * Ideally we want to remove this sync, but there are cases where this doesn't work. - * See T79038 for example. + * See #79038 for example. * * An idea to improve this is to separate the Object mode from the edit mode draw caches. And * based on the mode the correct one will be updated. Other option is to look into using diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index cba06eec76ca..78459eec81f2 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -89,21 +89,21 @@ typedef struct HairAttributeID { typedef struct EditStrandData { float pos[3]; - float color; + float selection; } EditStrandData; -static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_color_id) +static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_selection_id) { static GPUVertFormat edit_point_format = {0}; - static uint pos_id, color_id; + static uint pos_id, selection_id; if (edit_point_format.attr_len == 0) { /* Keep in sync with EditStrandData */ pos_id = GPU_vertformat_attr_add(&edit_point_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add( - &edit_point_format, "color", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + selection_id = GPU_vertformat_attr_add( + &edit_point_format, "selection", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); } *r_pos_id = pos_id; - *r_color_id = color_id; + *r_selection_id = selection_id; return &edit_point_format; } @@ -697,11 +697,11 @@ static int particle_batch_cache_fill_segments_edit( if (particle) { float weight = particle_key_weight(particle, i, strand_t); /* NaN or unclamped become 1.0f */ - seg_data->color = (weight < 1.0f) ? weight : 1.0f; + seg_data->selection = (weight < 1.0f) ? weight : 1.0f; } else { /* Computed in psys_cache_edit_paths_iter(). */ - seg_data->color = path[j].col[0]; + seg_data->selection = path[j].col[0]; } GPU_indexbuf_add_generic_vert(elb, curr_point); curr_point++; @@ -1530,8 +1530,8 @@ static void particle_batch_cache_ensure_edit_pos_and_seg(PTCacheEdit *edit, GPUVertBufRaw data_step; GPUIndexBufBuilder elb; - uint pos_id, color_id; - GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); + uint pos_id, selection_id; + GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &selection_id); hair_cache->pos = GPU_vertbuf_create_with_format(edit_point_format); GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len); @@ -1594,8 +1594,8 @@ static void particle_batch_cache_ensure_edit_inner_pos(PTCacheEdit *edit, return; } - uint pos_id, color_id; - GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); + uint pos_id, selection_id; + GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &selection_id); cache->edit_inner_pos = GPU_vertbuf_create_with_format(edit_point_format); GPU_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_len); @@ -1608,9 +1608,9 @@ static void particle_batch_cache_ensure_edit_inner_pos(PTCacheEdit *edit, } for (int key_index = 0; key_index < point->totkey - 1; key_index++) { PTCacheEditKey *key = &point->keys[key_index]; - float color = (key->flag & PEK_SELECT) ? 1.0f : 0.0f; + float selection = (key->flag & PEK_SELECT) ? 1.0f : 0.0f; GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co); - GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color); + GPU_vertbuf_attr_set(cache->edit_inner_pos, selection_id, global_key_index, &selection); global_key_index++; } } @@ -1652,8 +1652,8 @@ static void particle_batch_cache_ensure_edit_tip_pos(PTCacheEdit *edit, Particle return; } - uint pos_id, color_id; - GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); + uint pos_id, selection_id; + GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &selection_id); cache->edit_tip_pos = GPU_vertbuf_create_with_format(edit_point_format); GPU_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_len); @@ -1665,10 +1665,10 @@ static void particle_batch_cache_ensure_edit_tip_pos(PTCacheEdit *edit, Particle continue; } PTCacheEditKey *key = &point->keys[point->totkey - 1]; - float color = (key->flag & PEK_SELECT) ? 1.0f : 0.0f; + float selection = (key->flag & PEK_SELECT) ? 1.0f : 0.0f; GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, global_point_index, key->world_co); - GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, global_point_index, &color); + GPU_vertbuf_attr_set(cache->edit_tip_pos, selection_id, global_point_index, &selection); global_point_index++; } } diff --git a/source/blender/draw/intern/draw_cache_impl_pointcloud.cc b/source/blender/draw/intern/draw_cache_impl_pointcloud.cc index 4997aef6089c..3b9202bcb04b 100644 --- a/source/blender/draw/intern/draw_cache_impl_pointcloud.cc +++ b/source/blender/draw/intern/draw_cache_impl_pointcloud.cc @@ -25,7 +25,7 @@ #include "GPU_batch.h" #include "GPU_material.h" -#include "draw_attributes.h" +#include "draw_attributes.hh" #include "draw_cache_impl.h" #include "draw_cache_inline.h" #include "draw_pointcloud_private.hh" /* own include */ diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 25ec4a578d5b..0fe5eba26f40 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -1220,7 +1220,7 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache, /* To avoid floating point precision issues when evaluating patches at patch boundaries, * ensure that all loops sharing a vertex use the same patch coordinate. This could cause - * the mesh to not be watertight, leading to shadowing artifacts (see T97877). */ + * the mesh to not be watertight, leading to shadowing artifacts (see #97877). */ blender::Vector first_loop_index(cache->num_subdiv_verts, -1); /* Save coordinates for corners, as attributes may vary for each loop connected to the same @@ -1350,7 +1350,7 @@ static void draw_subdiv_ubo_update_and_bind(const DRWSubdivCache *cache, GPU_uniformbuf_update(cache->ubo, &storage); - const int binding = GPU_shader_get_uniform_block_binding(shader, "shader_data"); + const int binding = GPU_shader_get_ubo_binding(shader, "shader_data"); GPU_uniformbuf_bind(cache->ubo, binding); } diff --git a/source/blender/draw/intern/draw_command.cc b/source/blender/draw/intern/draw_command.cc index 775ee9f695be..86a0480b3f72 100644 --- a/source/blender/draw/intern/draw_command.cc +++ b/source/blender/draw/intern/draw_command.cc @@ -76,16 +76,16 @@ void PushConstant::execute(RecordingState &state) const } switch (type) { case PushConstant::Type::IntValue: - GPU_shader_uniform_vector_int(state.shader, location, comp_len, array_len, int4_value); + GPU_shader_uniform_int_ex(state.shader, location, comp_len, array_len, int4_value); break; case PushConstant::Type::IntReference: - GPU_shader_uniform_vector_int(state.shader, location, comp_len, array_len, int_ref); + GPU_shader_uniform_int_ex(state.shader, location, comp_len, array_len, int_ref); break; case PushConstant::Type::FloatValue: - GPU_shader_uniform_vector(state.shader, location, comp_len, array_len, float4_value); + GPU_shader_uniform_float_ex(state.shader, location, comp_len, array_len, float4_value); break; case PushConstant::Type::FloatReference: - GPU_shader_uniform_vector(state.shader, location, comp_len, array_len, float_ref); + GPU_shader_uniform_float_ex(state.shader, location, comp_len, array_len, float_ref); break; } } @@ -646,10 +646,10 @@ void DrawMultiBuf::bind(RecordingState &state, GPU_shader_uniform_1i(shader, "prototype_len", prototype_count_); GPU_shader_uniform_1i(shader, "visibility_word_per_draw", visibility_word_per_draw); GPU_shader_uniform_1i(shader, "view_shift", log2_ceil_u(view_len)); - GPU_storagebuf_bind(group_buf_, GPU_shader_get_ssbo(shader, "group_buf")); - GPU_storagebuf_bind(visibility_buf, GPU_shader_get_ssbo(shader, "visibility_buf")); - GPU_storagebuf_bind(prototype_buf_, GPU_shader_get_ssbo(shader, "prototype_buf")); - GPU_storagebuf_bind(command_buf_, GPU_shader_get_ssbo(shader, "command_buf")); + GPU_storagebuf_bind(group_buf_, GPU_shader_get_ssbo_binding(shader, "group_buf")); + GPU_storagebuf_bind(visibility_buf, GPU_shader_get_ssbo_binding(shader, "visibility_buf")); + GPU_storagebuf_bind(prototype_buf_, GPU_shader_get_ssbo_binding(shader, "prototype_buf")); + GPU_storagebuf_bind(command_buf_, GPU_shader_get_ssbo_binding(shader, "command_buf")); GPU_storagebuf_bind(resource_id_buf_, DRW_RESOURCE_ID_SLOT); GPU_compute_dispatch(shader, divide_ceil_u(prototype_count_, DRW_COMMAND_GROUP_SIZE), 1, 1); if (GPU_shader_draw_parameters_support() == false) { diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc index 45a72d67d31b..48e9cca98e0a 100644 --- a/source/blender/draw/intern/draw_curves.cc +++ b/source/blender/draw/intern/draw_curves.cc @@ -26,7 +26,7 @@ #include "DRW_render.h" #include "draw_cache_impl.h" -#include "draw_curves_private.h" +#include "draw_curves_private.hh" #include "draw_hair_private.h" #include "draw_manager.h" #include "draw_shader.h" @@ -393,7 +393,7 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); if (gpu_material) { /* NOTE: This needs to happen before the drawcall to allow correct attribute extraction. - * (see T101896) */ + * (see #101896) */ DRW_shgroup_add_material_resources(shgrp, gpu_material); } /* TODO(fclem): Until we have a better way to cull the curves and render with orco, bypass @@ -412,7 +412,7 @@ void DRW_curves_update() if (!GPU_transform_feedback_support()) { /** * Workaround to transform feedback not working on mac. - * On some system it crashes (see T58489) and on some other it renders garbage (see T60171). + * On some system it crashes (see #58489) and on some other it renders garbage (see #60171). * * So instead of using transform feedback we render to a texture, * read back the result to system memory and re-upload as VBO data. diff --git a/source/blender/draw/intern/draw_curves_private.h b/source/blender/draw/intern/draw_curves_private.hh similarity index 84% rename from source/blender/draw/intern/draw_curves_private.h rename to source/blender/draw/intern/draw_curves_private.hh index 9d02eedbbc30..be24872b1be3 100644 --- a/source/blender/draw/intern/draw_curves_private.h +++ b/source/blender/draw/intern/draw_curves_private.hh @@ -10,26 +10,23 @@ #include "BKE_attribute.h" #include "GPU_shader.h" -#include "draw_attributes.h" - -#ifdef __cplusplus -extern "C" { -#endif +#include "draw_attributes.hh" struct Curves; struct GPUVertBuf; struct GPUBatch; +struct GPUMaterial; #define MAX_THICKRES 2 /* see eHairType */ #define MAX_HAIR_SUBDIV 4 /* see hair_subdiv rna */ -typedef enum CurvesEvalShader { +enum CurvesEvalShader { CURVES_EVAL_CATMULL_ROM = 0, CURVES_EVAL_BEZIER = 1, -} CurvesEvalShader; +}; #define CURVES_EVAL_SHADER_NUM 3 -typedef struct CurvesEvalFinalCache { +struct CurvesEvalFinalCache { /* Output of the subdivision stage: vertex buffer sized to subdiv level. */ GPUVertBuf *proc_buf; @@ -58,10 +55,10 @@ typedef struct CurvesEvalFinalCache { /* Output of the subdivision stage: vertex buffers sized to subdiv level. This is only attributes * on point domain. */ GPUVertBuf *attributes_buf[GPU_MAX_ATTR]; -} CurvesEvalFinalCache; +}; /* Curves procedural display: Evaluation is done on the GPU. */ -typedef struct CurvesEvalCache { +struct CurvesEvalCache { /* Control point positions on evaluated data-block combined with parameter data. */ GPUVertBuf *proc_point_buf; @@ -82,19 +79,15 @@ typedef struct CurvesEvalCache { int strands_len; int elems_len; int point_len; -} CurvesEvalCache; +}; /** * Ensure all necessary textures and buffers exist for GPU accelerated drawing. */ -bool curves_ensure_procedural_data(struct Curves *curves, - struct CurvesEvalCache **r_hair_cache, - struct GPUMaterial *gpu_material, +bool curves_ensure_procedural_data(Curves *curves, + CurvesEvalCache **r_hair_cache, + GPUMaterial *gpu_material, int subdiv, int thickness_res); void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32]); - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/draw/intern/draw_debug.cc b/source/blender/draw/intern/draw_debug.cc index ca17aa1de824..4698d6eb5ff3 100644 --- a/source/blender/draw/intern/draw_debug.cc +++ b/source/blender/draw/intern/draw_debug.cc @@ -523,19 +523,18 @@ void DebugDraw::display_lines() GPUBatch *batch = drw_cache_procedural_lines_get(); GPUShader *shader = DRW_shader_debug_draw_display_get(); GPU_batch_set_shader(batch, shader); - int slot = GPU_shader_get_builtin_ssbo(shader, GPU_STORAGE_BUFFER_DEBUG_VERTS); GPU_shader_uniform_mat4(shader, "persmat", persmat.ptr()); if (gpu_draw_buf_used) { GPU_debug_group_begin("GPU"); - GPU_storagebuf_bind(gpu_draw_buf_, slot); + GPU_storagebuf_bind(gpu_draw_buf_, DRW_DEBUG_DRAW_SLOT); GPU_batch_draw_indirect(batch, gpu_draw_buf_, 0); GPU_storagebuf_unbind(gpu_draw_buf_); GPU_debug_group_end(); } GPU_debug_group_begin("CPU"); - GPU_storagebuf_bind(cpu_draw_buf_, slot); + GPU_storagebuf_bind(cpu_draw_buf_, DRW_DEBUG_DRAW_SLOT); GPU_batch_draw_indirect(batch, cpu_draw_buf_, 0); GPU_storagebuf_unbind(cpu_draw_buf_); GPU_debug_group_end(); @@ -556,21 +555,20 @@ void DebugDraw::display_prints() GPUBatch *batch = drw_cache_procedural_points_get(); GPUShader *shader = DRW_shader_debug_print_display_get(); GPU_batch_set_shader(batch, shader); - int slot = GPU_shader_get_builtin_ssbo(shader, GPU_STORAGE_BUFFER_DEBUG_PRINT); float f_viewport[4]; GPU_viewport_size_get_f(f_viewport); GPU_shader_uniform_2fv(shader, "viewport_size", &f_viewport[2]); if (gpu_print_buf_used) { GPU_debug_group_begin("GPU"); - GPU_storagebuf_bind(gpu_print_buf_, slot); + GPU_storagebuf_bind(gpu_print_buf_, DRW_DEBUG_PRINT_SLOT); GPU_batch_draw_indirect(batch, gpu_print_buf_, 0); GPU_storagebuf_unbind(gpu_print_buf_); GPU_debug_group_end(); } GPU_debug_group_begin("CPU"); - GPU_storagebuf_bind(cpu_print_buf_, slot); + GPU_storagebuf_bind(cpu_print_buf_, DRW_DEBUG_PRINT_SLOT); GPU_batch_draw_indirect(batch, cpu_print_buf_, 0); GPU_storagebuf_unbind(cpu_print_buf_); GPU_debug_group_end(); diff --git a/source/blender/draw/intern/draw_hair.cc b/source/blender/draw/intern/draw_hair.cc index da04f199157d..e8220346d25a 100644 --- a/source/blender/draw/intern/draw_hair.cc +++ b/source/blender/draw/intern/draw_hair.cc @@ -295,7 +295,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip); if (gpu_material) { /* NOTE: This needs to happen before the drawcall to allow correct attribute extraction. - * (see T101896) */ + * (see #101896) */ DRW_shgroup_add_material_resources(shgrp, gpu_material); } /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass @@ -311,7 +311,7 @@ void DRW_hair_update() if (!GPU_transform_feedback_support()) { /** * Workaround to transform feedback not working on mac. - * On some system it crashes (see T58489) and on some other it renders garbage (see T60171). + * On some system it crashes (see #58489) and on some other it renders garbage (see #60171). * * So instead of using transform feedback we render to a texture, * read back the result to system memory and re-upload as VBO data. diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 1af10275e2a5..a8c5e6965522 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1763,7 +1763,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_engines_draw_scene(); - /* Fix 3D view "lagging" on APPLE and WIN32+NVIDIA. (See T56996, T61474) */ + /* Fix 3D view "lagging" on APPLE and WIN32+NVIDIA. (See #56996, #61474) */ if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { GPU_flush(); } @@ -2138,7 +2138,7 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, /* The use of custom pipeline in other thread using the same * resources as the main thread (viewport) may lead to data * races and undefined behavior on certain drivers. Using - * GPU_finish to sync seems to fix the issue. (see T62997) */ + * GPU_finish to sync seems to fix the issue. (see #62997) */ eGPUBackendType type = GPU_backend_get_type(); if (type == GPU_BACKEND_OPENGL) { GPU_finish(); @@ -2251,7 +2251,7 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, drw_engines_draw_scene(); - /* Fix 3D view being "laggy" on MACOS and MS-Windows+NVIDIA. (See T56996, T61474) */ + /* Fix 3D view being "laggy" on MACOS and MS-Windows+NVIDIA. (See #56996, #61474) */ if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { GPU_flush(); } @@ -2780,7 +2780,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons drw_engines_cache_finish(); drw_task_graph_deinit(); -#if 0 /* This is a workaround to a nasty bug that seems to be a nasty driver bug. (See T69377) */ +#if 0 /* This is a workaround to a nasty bug that seems to be a nasty driver bug. (See #69377) */ DRW_render_instance_buffer_finish(); #else DST.buffer_finish_called = true; @@ -3072,7 +3072,7 @@ void DRW_engines_free(void) if (DST.gl_context == NULL) { /* Nothing has been setup. Nothing to clear. * Otherwise, DRW_opengl_context_enable can - * create a context in background mode. (see T62355) */ + * create a context in background mode. (see #62355) */ return; } diff --git a/source/blender/draw/intern/draw_manager.cc b/source/blender/draw/intern/draw_manager.cc index 74108ab2f7cd..f34650255a53 100644 --- a/source/blender/draw/intern/draw_manager.cc +++ b/source/blender/draw/intern/draw_manager.cc @@ -114,9 +114,9 @@ void Manager::end_sync() GPUShader *shader = DRW_shader_draw_resource_finalize_get(); GPU_shader_bind(shader); GPU_shader_uniform_1i(shader, "resource_len", resource_len_); - GPU_storagebuf_bind(matrix_buf.current(), GPU_shader_get_ssbo(shader, "matrix_buf")); - GPU_storagebuf_bind(bounds_buf.current(), GPU_shader_get_ssbo(shader, "bounds_buf")); - GPU_storagebuf_bind(infos_buf.current(), GPU_shader_get_ssbo(shader, "infos_buf")); + GPU_storagebuf_bind(matrix_buf.current(), GPU_shader_get_ssbo_binding(shader, "matrix_buf")); + GPU_storagebuf_bind(bounds_buf.current(), GPU_shader_get_ssbo_binding(shader, "bounds_buf")); + GPU_storagebuf_bind(infos_buf.current(), GPU_shader_get_ssbo_binding(shader, "infos_buf")); GPU_compute_dispatch(shader, thread_groups, 1, 1); GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE); diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index de78c8216de5..7a665cbc38c7 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -7,7 +7,7 @@ #include "DRW_pbvh.hh" -#include "draw_attributes.h" +#include "draw_attributes.hh" #include "draw_manager.h" #include "draw_pbvh.h" @@ -256,7 +256,7 @@ void DRW_shgroup_uniform_texture_ex(DRWShadingGroup *shgroup, eGPUSamplerState sampler_state) { BLI_assert(tex != nullptr); - int loc = GPU_shader_get_texture_binding(shgroup->shader, name); + int loc = GPU_shader_get_sampler_binding(shgroup->shader, name); drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE, tex, sampler_state, 0, 1); } @@ -271,7 +271,7 @@ void DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup *shgroup, eGPUSamplerState sampler_state) { BLI_assert(tex != nullptr); - int loc = GPU_shader_get_texture_binding(shgroup->shader, name); + int loc = GPU_shader_get_sampler_binding(shgroup->shader, name); drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, sampler_state, 0, 1); } @@ -283,14 +283,14 @@ void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, void DRW_shgroup_uniform_image(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex) { BLI_assert(tex != nullptr); - int loc = GPU_shader_get_texture_binding(shgroup->shader, name); + int loc = GPU_shader_get_sampler_binding(shgroup->shader, name); drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_IMAGE, tex, GPU_SAMPLER_DEFAULT, 0, 1); } void DRW_shgroup_uniform_image_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex) { BLI_assert(tex != nullptr); - int loc = GPU_shader_get_texture_binding(shgroup->shader, name); + int loc = GPU_shader_get_sampler_binding(shgroup->shader, name); drw_shgroup_uniform_create_ex( shgroup, loc, DRW_UNIFORM_IMAGE_REF, tex, GPU_SAMPLER_DEFAULT, 0, 1); } @@ -300,7 +300,7 @@ void DRW_shgroup_uniform_block_ex(DRWShadingGroup *shgroup, const GPUUniformBuf *ubo DRW_DEBUG_FILE_LINE_ARGS) { BLI_assert(ubo != nullptr); - int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name); + int loc = GPU_shader_get_ubo_binding(shgroup->shader, name); if (loc == -1) { #ifdef DRW_UNUSED_RESOURCE_TRACKING printf("%s:%d: Unable to locate binding of shader uniform buffer object: %s.\n", @@ -321,7 +321,7 @@ void DRW_shgroup_uniform_block_ref_ex(DRWShadingGroup *shgroup, GPUUniformBuf **ubo DRW_DEBUG_FILE_LINE_ARGS) { BLI_assert(ubo != nullptr); - int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name); + int loc = GPU_shader_get_ubo_binding(shgroup->shader, name); if (loc == -1) { #ifdef DRW_UNUSED_RESOURCE_TRACKING printf("%s:%d: Unable to locate binding of shader uniform buffer object: %s.\n", @@ -344,7 +344,7 @@ void DRW_shgroup_storage_block_ex(DRWShadingGroup *shgroup, { BLI_assert(ssbo != nullptr); /* TODO(@fclem): Fix naming inconsistency. */ - int loc = GPU_shader_get_ssbo(shgroup->shader, name); + int loc = GPU_shader_get_ssbo_binding(shgroup->shader, name); if (loc == -1) { #ifdef DRW_UNUSED_RESOURCE_TRACKING printf("%s:%d: Unable to locate binding of shader storage buffer object: %s.\n", @@ -367,7 +367,7 @@ void DRW_shgroup_storage_block_ref_ex(DRWShadingGroup *shgroup, { BLI_assert(ssbo != nullptr); /* TODO(@fclem): Fix naming inconsistency. */ - int loc = GPU_shader_get_ssbo(shgroup->shader, name); + int loc = GPU_shader_get_ssbo_binding(shgroup->shader, name); if (loc == -1) { #ifdef DRW_UNUSED_RESOURCE_TRACKING printf("%s:%d: Unable to locate binding of shader storage buffer object: %s.\n", @@ -539,7 +539,7 @@ void DRW_shgroup_vertex_buffer_ex(DRWShadingGroup *shgroup, const char *name, GPUVertBuf *vertex_buffer DRW_DEBUG_FILE_LINE_ARGS) { - int location = GPU_shader_get_ssbo(shgroup->shader, name); + int location = GPU_shader_get_ssbo_binding(shgroup->shader, name); if (location == -1) { #ifdef DRW_UNUSED_RESOURCE_TRACKING printf("%s:%d: Unable to locate binding of shader storage buffer object: %s.\n", @@ -564,7 +564,7 @@ void DRW_shgroup_vertex_buffer_ref_ex(DRWShadingGroup *shgroup, const char *name, GPUVertBuf **vertex_buffer DRW_DEBUG_FILE_LINE_ARGS) { - int location = GPU_shader_get_ssbo(shgroup->shader, name); + int location = GPU_shader_get_ssbo_binding(shgroup->shader, name); if (location == -1) { #ifdef DRW_UNUSED_RESOURCE_TRACKING printf("%s:%d: Unable to locate binding of shader storage buffer object: %s.\n", @@ -589,7 +589,7 @@ void DRW_shgroup_buffer_texture(DRWShadingGroup *shgroup, const char *name, GPUVertBuf *vertex_buffer) { - int location = GPU_shader_get_texture_binding(shgroup->shader, name); + int location = GPU_shader_get_sampler_binding(shgroup->shader, name); if (location == -1) { return; } @@ -606,7 +606,7 @@ void DRW_shgroup_buffer_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUVertBuf **vertex_buffer) { - int location = GPU_shader_get_texture_binding(shgroup->shader, name); + int location = GPU_shader_get_sampler_binding(shgroup->shader, name); if (location == -1) { return; } @@ -731,7 +731,7 @@ static void drw_call_culling_init(DRWCullingState *cull, Object *ob) mul_m4_v3(ob->object_to_world, cull->bsphere.center); cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner); - /* Bypass test for very large objects (see T67319). */ + /* Bypass test for very large objects (see #67319). */ if (UNLIKELY(cull->bsphere.radius > 1e12)) { cull->bsphere.radius = -1.0f; } @@ -1719,36 +1719,6 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) 1); } -#ifdef DEBUG - /* TODO(Metal): Support Shader debug print. - * This is not currently supported by Metal Backend. */ - if (GPU_backend_get_type() != GPU_BACKEND_METAL) { - int debug_print_location = GPU_shader_get_builtin_ssbo(shader, GPU_STORAGE_BUFFER_DEBUG_PRINT); - if (debug_print_location != -1) { - GPUStorageBuf *buf = drw_debug_gpu_print_buf_get(); - drw_shgroup_uniform_create_ex(shgroup, - debug_print_location, - DRW_UNIFORM_STORAGE_BLOCK, - buf, - GPU_SAMPLER_DEFAULT, - 0, - 1); -# ifndef DISABLE_DEBUG_SHADER_PRINT_BARRIER - /* Add a barrier to allow multiple shader writing to the same buffer. */ - DRW_shgroup_barrier(shgroup, GPU_BARRIER_SHADER_STORAGE); -# endif - } - - int debug_draw_location = GPU_shader_get_builtin_ssbo(shader, GPU_STORAGE_BUFFER_DEBUG_VERTS); - if (debug_draw_location != -1) { - GPUStorageBuf *buf = drw_debug_gpu_draw_buf_get(); - drw_shgroup_uniform_create_ex( - shgroup, debug_draw_location, DRW_UNIFORM_STORAGE_BLOCK, buf, GPU_SAMPLER_DEFAULT, 0, 1); - /* NOTE(fclem): No barrier as ordering is not important. */ - } - } -#endif - /* Not supported. */ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1); BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1); @@ -1850,15 +1820,14 @@ void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, GPUMaterial *mater const GPUUniformAttrList *uattrs = GPU_material_uniform_attributes(material); if (uattrs != nullptr) { - int loc = GPU_shader_get_uniform_block_binding(grp->shader, GPU_ATTRIBUTE_UBO_BLOCK_NAME); + int loc = GPU_shader_get_ubo_binding(grp->shader, GPU_ATTRIBUTE_UBO_BLOCK_NAME); drw_shgroup_uniform_create_ex( grp, loc, DRW_UNIFORM_BLOCK_OBATTRS, uattrs, GPU_SAMPLER_DEFAULT, 0, 1); grp->uniform_attrs = uattrs; } if (GPU_material_layer_attributes(material) != nullptr) { - int loc = GPU_shader_get_uniform_block_binding(grp->shader, - GPU_LAYER_ATTRIBUTE_UBO_BLOCK_NAME); + int loc = GPU_shader_get_ubo_binding(grp->shader, GPU_LAYER_ATTRIBUTE_UBO_BLOCK_NAME); drw_shgroup_uniform_create_ex( grp, loc, DRW_UNIFORM_BLOCK_VLATTRS, nullptr, GPU_SAMPLER_DEFAULT, 0, 1); } @@ -2511,7 +2480,7 @@ void DRW_pass_sort_shgroup_z(DRWPass *pass) /* To be sorted a shgroup needs to have at least one draw command. */ /* FIXME(fclem): In some case, we can still have empty shading group to sort. However their * final order is not well defined. - * (see T76730 & D7729). */ + * (see #76730 & D7729). */ // BLI_assert(handle != 0); DRWObjectMatrix *obmats = static_cast( diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index b68a1976f806..4139ffcb261b 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -522,10 +522,10 @@ BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup, /* Still supported for compatibility with gpu_shader_* but should be forbidden. */ DRWObjectMatrix *ob_mats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, handle); if (obmat_loc != -1) { - GPU_shader_uniform_vector(shgroup->shader, obmat_loc, 16, 1, (float *)ob_mats->model); + GPU_shader_uniform_float_ex(shgroup->shader, obmat_loc, 16, 1, (float *)ob_mats->model); } if (obinv_loc != -1) { - GPU_shader_uniform_vector(shgroup->shader, obinv_loc, 16, 1, (float *)ob_mats->modelinverse); + GPU_shader_uniform_float_ex(shgroup->shader, obinv_loc, 16, 1, (float *)ob_mats->modelinverse); } } @@ -549,7 +549,7 @@ BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup, if (baseinst_loc != -1) { /* Fallback when ARB_shader_draw_parameters is not supported. */ - GPU_shader_uniform_vector_int(shgroup->shader, baseinst_loc, 1, 1, (int *)&inst_first); + GPU_shader_uniform_int_ex(shgroup->shader, baseinst_loc, 1, 1, (int *)&inst_first); /* Avoids VAO reconfiguration on older hardware. (see GPU_batch_draw_advanced) */ inst_first = 0; } @@ -615,7 +615,7 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, memcpy(&mat4_stack[array_index], uni->fvalue, sizeof(float) * uni->length); /* Flush array data to shader. */ if (array_index <= 0) { - GPU_shader_uniform_vector(shgroup->shader, uni->location, 16, 1, mat4_stack); + GPU_shader_uniform_float_ex(shgroup->shader, uni->location, 16, 1, mat4_stack); array_uniform_loc = -1; } continue; @@ -626,23 +626,23 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, case DRW_UNIFORM_INT_COPY: BLI_assert(uni->arraysize == 1); if (uni->arraysize == 1) { - GPU_shader_uniform_vector_int( + GPU_shader_uniform_int_ex( shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue); } break; case DRW_UNIFORM_INT: - GPU_shader_uniform_vector_int( + GPU_shader_uniform_int_ex( shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue); break; case DRW_UNIFORM_FLOAT_COPY: BLI_assert(uni->arraysize == 1); if (uni->arraysize == 1) { - GPU_shader_uniform_vector( + GPU_shader_uniform_float_ex( shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue); } break; case DRW_UNIFORM_FLOAT: - GPU_shader_uniform_vector( + GPU_shader_uniform_float_ex( shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue); break; case DRW_UNIFORM_TEXTURE: @@ -687,10 +687,12 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, state->vlattrs_loc = uni->location; GPU_uniformbuf_bind(drw_ensure_layer_attribute_buffer(), uni->location); break; - case DRW_UNIFORM_RESOURCE_CHUNK: + case DRW_UNIFORM_RESOURCE_CHUNK: { state->chunkid_loc = uni->location; - GPU_shader_uniform_int(shgroup->shader, uni->location, 0); + int zero = 0; + GPU_shader_uniform_int_ex(shgroup->shader, uni->location, 1, 1, &zero); break; + } case DRW_UNIFORM_RESOURCE_ID: state->resourceid_loc = uni->location; break; @@ -807,7 +809,7 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa int chunk = DRW_handle_chunk_get(handle); if (state->resource_chunk != chunk) { if (state->chunkid_loc != -1) { - GPU_shader_uniform_int(DST.shader, state->chunkid_loc, chunk); + GPU_shader_uniform_int_ex(DST.shader, state->chunkid_loc, 1, 1, &chunk); } if (state->obmats_loc != -1) { GPU_uniformbuf_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]); @@ -827,7 +829,7 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa if (state->resourceid_loc != -1) { int id = DRW_handle_id_get(handle); if (state->resource_id != id) { - GPU_shader_uniform_int(DST.shader, state->resourceid_loc, id); + GPU_shader_uniform_int_ex(DST.shader, state->resourceid_loc, 1, 1, &id); state->resource_id = id; } } @@ -1218,7 +1220,7 @@ static void drw_draw_pass_ex(DRWPass *pass, DST.batch = NULL; } - /* Fix T67342 for some reason. AMD Pro driver bug. */ + /* Fix #67342 for some reason. AMD Pro driver bug. */ if ((DST.state & DRW_STATE_BLEND_CUSTOM) != 0 && GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL)) { drw_state_set(DST.state & ~DRW_STATE_BLEND_CUSTOM); diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index bdfe1c48c35f..c7c3cc6b7184 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -55,6 +55,9 @@ typedef struct DRWShaderCompiler { ListBase queue; /* GPUMaterial */ SpinLock list_lock; + /** Optimization queue. */ + ListBase optimize_queue; /* GPUMaterial */ + void *gl_context; GPUContext *gpu_context; bool own_context; @@ -110,8 +113,29 @@ static void drw_deferred_shader_compilation_exec( MEM_freeN(link); } else { - /* No more materials to optimize, or shaders to compile. */ - break; + /* Check for Material Optimization job once there are no more + * shaders to compile. */ + BLI_spin_lock(&comp->list_lock); + /* Pop tail because it will be less likely to lock the main thread + * if all GPUMaterials are to be freed (see DRW_deferred_shader_remove()). */ + link = (LinkData *)BLI_poptail(&comp->optimize_queue); + GPUMaterial *optimize_mat = link ? (GPUMaterial *)link->data : NULL; + if (optimize_mat) { + /* Avoid another thread freeing the material during optimization. */ + GPU_material_acquire(optimize_mat); + } + BLI_spin_unlock(&comp->list_lock); + + if (optimize_mat) { + /* Compile optimized material shader. */ + GPU_material_optimize(optimize_mat); + GPU_material_release(optimize_mat); + MEM_freeN(link); + } + else { + /* No more materials to optimize, or shaders to compile. */ + break; + } } if (GPU_type_matches_ex(GPU_DEVICE_ANY, GPU_OS_ANY, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { @@ -133,6 +157,7 @@ static void drw_deferred_shader_compilation_free(void *custom_data) BLI_spin_lock(&comp->list_lock); BLI_freelistN(&comp->queue); + BLI_freelistN(&comp->optimize_queue); BLI_spin_unlock(&comp->list_lock); if (comp->own_context) { @@ -148,34 +173,13 @@ static void drw_deferred_shader_compilation_free(void *custom_data) MEM_freeN(comp); } -static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) +/** + * Append either shader compilation or optimization job to deferred queue and + * ensure shader compilation worker is active. + * We keep two separate queue's to ensure core compilations always complete before optimization. + */ +static void drw_deferred_queue_append(GPUMaterial *mat, bool is_optimization_job) { - if (ELEM(GPU_material_status(mat), GPU_MAT_SUCCESS, GPU_MAT_FAILED)) { - return; - } - /* Do not defer the compilation if we are rendering for image. - * deferred rendering is only possible when `evil_C` is available */ - if (DST.draw_ctx.evil_C == NULL || DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION) { - deferred = false; - } - - if (!deferred) { - DRW_deferred_shader_remove(mat); - /* Shaders could already be compiling. Have to wait for compilation to finish. */ - while (GPU_material_status(mat) == GPU_MAT_QUEUED) { - PIL_sleep_ms(20); - } - if (GPU_material_status(mat) == GPU_MAT_CREATED) { - GPU_material_compile(mat); - } - return; - } - - /* Don't add material to the queue twice. */ - if (GPU_material_status(mat) == GPU_MAT_QUEUED) { - return; - } - const bool use_main_context = GPU_use_main_context_workaround(); const bool job_own_context = !use_main_context; @@ -196,6 +200,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) if (old_comp) { BLI_spin_lock(&old_comp->list_lock); BLI_movelisttolist(&comp->queue, &old_comp->queue); + BLI_movelisttolist(&comp->optimize_queue, &old_comp->optimize_queue); BLI_spin_unlock(&old_comp->list_lock); /* Do not recreate context, just pass ownership. */ if (old_comp->gl_context) { @@ -206,9 +211,18 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) } } - GPU_material_status_set(mat, GPU_MAT_QUEUED); - LinkData *node = BLI_genericNodeN(mat); - BLI_addtail(&comp->queue, node); + /* Add to either compilation or optimization queue. */ + if (is_optimization_job) { + BLI_assert(GPU_material_optimization_status(mat) != GPU_MAT_OPTIMIZATION_QUEUED); + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_QUEUED); + LinkData *node = BLI_genericNodeN(mat); + BLI_addtail(&comp->optimize_queue, node); + } + else { + GPU_material_status_set(mat, GPU_MAT_QUEUED); + LinkData *node = BLI_genericNodeN(mat); + BLI_addtail(&comp->queue, node); + } /* Create only one context. */ if (comp->gl_context == NULL) { @@ -237,6 +251,39 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) WM_jobs_start(wm, wm_job); } +static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) +{ + if (ELEM(GPU_material_status(mat), GPU_MAT_SUCCESS, GPU_MAT_FAILED)) { + return; + } + + /* Do not defer the compilation if we are rendering for image. + * deferred rendering is only possible when `evil_C` is available */ + if (DST.draw_ctx.evil_C == NULL || DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION) { + deferred = false; + } + + if (!deferred) { + DRW_deferred_shader_remove(mat); + /* Shaders could already be compiling. Have to wait for compilation to finish. */ + while (GPU_material_status(mat) == GPU_MAT_QUEUED) { + PIL_sleep_ms(20); + } + if (GPU_material_status(mat) == GPU_MAT_CREATED) { + GPU_material_compile(mat); + } + return; + } + + /* Don't add material to the queue twice. */ + if (GPU_material_status(mat) == GPU_MAT_QUEUED) { + return; + } + + /* Add deferred shader compilation to queue. */ + drw_deferred_queue_append(mat, false); +} + static void drw_register_shader_vlattrs(GPUMaterial *mat) { const ListBase *attrs = GPU_material_layer_attributes(mat); @@ -288,9 +335,42 @@ void DRW_deferred_shader_remove(GPUMaterial *mat) BLI_remlink(&comp->queue, link); GPU_material_status_set(link->data, GPU_MAT_CREATED); } - BLI_spin_unlock(&comp->list_lock); MEM_SAFE_FREE(link); + + /* Search for optimization job in queue. */ + LinkData *opti_link = (LinkData *)BLI_findptr( + &comp->optimize_queue, mat, offsetof(LinkData, data)); + if (opti_link) { + BLI_remlink(&comp->optimize_queue, opti_link); + GPU_material_optimization_status_set(opti_link->data, GPU_MAT_OPTIMIZATION_READY); + } + BLI_spin_unlock(&comp->list_lock); + + MEM_SAFE_FREE(opti_link); + } + } + } +} + +void DRW_deferred_shader_optimize_remove(GPUMaterial *mat) +{ + LISTBASE_FOREACH (wmWindowManager *, wm, &G_MAIN->wm) { + LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { + DRWShaderCompiler *comp = (DRWShaderCompiler *)WM_jobs_customdata_from_type( + wm, wm, WM_JOB_TYPE_SHADER_COMPILATION); + if (comp != NULL) { + BLI_spin_lock(&comp->list_lock); + /* Search for optimization job in queue. */ + LinkData *opti_link = (LinkData *)BLI_findptr( + &comp->optimize_queue, mat, offsetof(LinkData, data)); + if (opti_link) { + BLI_remlink(&comp->optimize_queue, opti_link); + GPU_material_optimization_status_set(opti_link->data, GPU_MAT_OPTIMIZATION_READY); + } + BLI_spin_unlock(&comp->list_lock); + + MEM_SAFE_FREE(opti_link); } } } @@ -432,6 +512,7 @@ GPUMaterial *DRW_shader_from_world(World *wo, } drw_deferred_shader_add(mat, deferred); + DRW_shader_queue_optimize_material(mat); return mat; } @@ -463,9 +544,52 @@ GPUMaterial *DRW_shader_from_material(Material *ma, } drw_deferred_shader_add(mat, deferred); + DRW_shader_queue_optimize_material(mat); return mat; } +void DRW_shader_queue_optimize_material(GPUMaterial *mat) +{ + /* Do not perform deferred optimization if performing render. + * De-queue any queued optimization jobs. */ + if (DRW_state_is_image_render()) { + if (GPU_material_optimization_status(mat) == GPU_MAT_OPTIMIZATION_QUEUED) { + /* Remove from pending optimization job queue. */ + DRW_deferred_shader_optimize_remove(mat); + /* If optimization job had already started, wait for it to complete. */ + while (GPU_material_optimization_status(mat) == GPU_MAT_OPTIMIZATION_QUEUED) { + PIL_sleep_ms(20); + } + } + return; + } + + /* We do not need to perform optimization on the material if it is already compiled or in the + * optimization queue. If optimization is not required, the status will be flagged as + * `GPU_MAT_OPTIMIZATION_SKIP`. + * We can also skip cases which have already been queued up. */ + if (ELEM(GPU_material_optimization_status(mat), + GPU_MAT_OPTIMIZATION_SKIP, + GPU_MAT_OPTIMIZATION_SUCCESS, + GPU_MAT_OPTIMIZATION_QUEUED)) { + return; + } + + /* Only queue optimization once the original shader has been successfully compiled. */ + if (GPU_material_status(mat) != GPU_MAT_SUCCESS) { + return; + } + + /* Defer optimization until sufficient time has passed beyond creation. This avoids excessive + * recompilation for shaders which are being actively modified. */ + if (!GPU_material_optimization_ready(mat)) { + return; + } + + /* Add deferred shader compilation to queue. */ + drw_deferred_queue_append(mat, true); +} + void DRW_shader_free(GPUShader *shader) { GPU_shader_free(shader); diff --git a/source/blender/draw/intern/draw_manager_text.cc b/source/blender/draw/intern/draw_manager_text.cc index 1244c46e166a..c61ff7d4beb6 100644 --- a/source/blender/draw/intern/draw_manager_text.cc +++ b/source/blender/draw/intern/draw_manager_text.cc @@ -216,7 +216,7 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region, const UnitSettings *unit) { /* Do not use ascii when using non-default unit system, some unit chars are utf8 (micro, square, - * etc.). See bug T36090. + * etc.). See bug #36090. */ DRWTextStore *dt = DRW_text_cache_ensure(); const short txt_flag = DRW_TEXT_CACHE_GLOBALSPACE; diff --git a/source/blender/draw/intern/draw_pass.hh b/source/blender/draw/intern/draw_pass.hh index 8fc8298491ee..d05564c415a4 100644 --- a/source/blender/draw/intern/draw_pass.hh +++ b/source/blender/draw/intern/draw_pass.hh @@ -861,42 +861,42 @@ template inline int PassBase::push_constant_offset(const char *name) template inline void PassBase::bind_ssbo(const char *name, GPUStorageBuf *buffer) { - this->bind_ssbo(GPU_shader_get_ssbo(shader_, name), buffer); + this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer); } template inline void PassBase::bind_ssbo(const char *name, GPUUniformBuf *buffer) { - this->bind_ssbo(GPU_shader_get_ssbo(shader_, name), buffer); + this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer); } template inline void PassBase::bind_ssbo(const char *name, GPUUniformBuf **buffer) { - this->bind_ssbo(GPU_shader_get_ssbo(shader_, name), buffer); + this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer); } template inline void PassBase::bind_ssbo(const char *name, GPUVertBuf *buffer) { - this->bind_ssbo(GPU_shader_get_ssbo(shader_, name), buffer); + this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer); } template inline void PassBase::bind_ssbo(const char *name, GPUVertBuf **buffer) { - this->bind_ssbo(GPU_shader_get_ssbo(shader_, name), buffer); + this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer); } template inline void PassBase::bind_ssbo(const char *name, GPUIndexBuf *buffer) { - this->bind_ssbo(GPU_shader_get_ssbo(shader_, name), buffer); + this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer); } template inline void PassBase::bind_ssbo(const char *name, GPUIndexBuf **buffer) { - this->bind_ssbo(GPU_shader_get_ssbo(shader_, name), buffer); + this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer); } template inline void PassBase::bind_ubo(const char *name, GPUUniformBuf *buffer) { - this->bind_ubo(GPU_shader_get_uniform_block_binding(shader_, name), buffer); + this->bind_ubo(GPU_shader_get_ubo_binding(shader_, name), buffer); } template @@ -904,22 +904,22 @@ inline void PassBase::bind_texture(const char *name, GPUTexture *texture, eGPUSamplerState state) { - this->bind_texture(GPU_shader_get_texture_binding(shader_, name), texture, state); + this->bind_texture(GPU_shader_get_sampler_binding(shader_, name), texture, state); } template inline void PassBase::bind_texture(const char *name, GPUVertBuf *buffer) { - this->bind_texture(GPU_shader_get_texture_binding(shader_, name), buffer); + this->bind_texture(GPU_shader_get_sampler_binding(shader_, name), buffer); } template inline void PassBase::bind_texture(const char *name, GPUVertBuf **buffer) { - this->bind_texture(GPU_shader_get_texture_binding(shader_, name), buffer); + this->bind_texture(GPU_shader_get_sampler_binding(shader_, name), buffer); } template inline void PassBase::bind_image(const char *name, GPUTexture *image) { - this->bind_image(GPU_shader_get_texture_binding(shader_, name), image); + this->bind_image(GPU_shader_get_sampler_binding(shader_, name), image); } template inline void PassBase::bind_ssbo(int slot, GPUStorageBuf *buffer) @@ -991,12 +991,12 @@ template inline void PassBase::bind_image(int slot, GPUTexture *imag template inline void PassBase::bind_ssbo(const char *name, GPUStorageBuf **buffer) { - this->bind_ssbo(GPU_shader_get_ssbo(shader_, name), buffer); + this->bind_ssbo(GPU_shader_get_ssbo_binding(shader_, name), buffer); } template inline void PassBase::bind_ubo(const char *name, GPUUniformBuf **buffer) { - this->bind_ubo(GPU_shader_get_uniform_block_binding(shader_, name), buffer); + this->bind_ubo(GPU_shader_get_ubo_binding(shader_, name), buffer); } template @@ -1004,12 +1004,12 @@ inline void PassBase::bind_texture(const char *name, GPUTexture **texture, eGPUSamplerState state) { - this->bind_texture(GPU_shader_get_texture_binding(shader_, name), texture, state); + this->bind_texture(GPU_shader_get_sampler_binding(shader_, name), texture, state); } template inline void PassBase::bind_image(const char *name, GPUTexture **image) { - this->bind_image(GPU_shader_get_texture_binding(shader_, name), image); + this->bind_image(GPU_shader_get_sampler_binding(shader_, name), image); } template inline void PassBase::bind_ssbo(int slot, GPUStorageBuf **buffer) diff --git a/source/blender/draw/intern/draw_pointcloud.cc b/source/blender/draw/intern/draw_pointcloud.cc index 4f228addffbc..0522c8500684 100644 --- a/source/blender/draw/intern/draw_pointcloud.cc +++ b/source/blender/draw/intern/draw_pointcloud.cc @@ -21,7 +21,7 @@ #include "DRW_gpu_wrapper.hh" #include "DRW_render.h" -#include "draw_attributes.h" +#include "draw_attributes.hh" #include "draw_cache_impl.h" #include "draw_common.h" #include "draw_manager.h" diff --git a/source/blender/draw/intern/draw_shader.h b/source/blender/draw/intern/draw_shader.h index e4c71812471f..d519775ceefe 100644 --- a/source/blender/draw/intern/draw_shader.h +++ b/source/blender/draw/intern/draw_shader.h @@ -7,36 +7,38 @@ #pragma once -#include "draw_curves_private.h" -#include "draw_hair_private.h" +#ifdef __cplusplus +# include "draw_curves_private.hh" +# include "draw_hair_private.h" + +struct GPUShader; + +enum eParticleRefineShaderType { + PART_REFINE_SHADER_TRANSFORM_FEEDBACK, + PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND, + PART_REFINE_SHADER_COMPUTE, +}; + +/* draw_shader.cc */ + +GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement, + eParticleRefineShaderType sh_type); + +GPUShader *DRW_shader_curves_refine_get(CurvesEvalShader type, eParticleRefineShaderType sh_type); + +GPUShader *DRW_shader_debug_print_display_get(); +GPUShader *DRW_shader_debug_draw_display_get(); +GPUShader *DRW_shader_draw_visibility_compute_get(); +GPUShader *DRW_shader_draw_view_finalize_get(); +GPUShader *DRW_shader_draw_resource_finalize_get(); +GPUShader *DRW_shader_draw_command_generate_get(); + +#endif #ifdef __cplusplus extern "C" { #endif -struct GPUShader; - -typedef enum eParticleRefineShaderType { - PART_REFINE_SHADER_TRANSFORM_FEEDBACK, - PART_REFINE_SHADER_TRANSFORM_FEEDBACK_WORKAROUND, - PART_REFINE_SHADER_COMPUTE, -} eParticleRefineShaderType; - -/* draw_shader.cc */ - -struct GPUShader *DRW_shader_hair_refine_get(ParticleRefineShader refinement, - eParticleRefineShaderType sh_type); - -struct GPUShader *DRW_shader_curves_refine_get(CurvesEvalShader type, - eParticleRefineShaderType sh_type); - -struct GPUShader *DRW_shader_debug_print_display_get(void); -struct GPUShader *DRW_shader_debug_draw_display_get(void); -struct GPUShader *DRW_shader_draw_visibility_compute_get(void); -struct GPUShader *DRW_shader_draw_view_finalize_get(void); -struct GPUShader *DRW_shader_draw_resource_finalize_get(void); -struct GPUShader *DRW_shader_draw_command_generate_get(void); - void DRW_shaders_free(void); #ifdef __cplusplus diff --git a/source/blender/draw/intern/draw_view.cc b/source/blender/draw/intern/draw_view.cc index 670b0c5ecf5d..46fd82a239e2 100644 --- a/source/blender/draw/intern/draw_view.cc +++ b/source/blender/draw/intern/draw_view.cc @@ -244,7 +244,7 @@ void View::compute_procedural_bounds() GPUShader *shader = DRW_shader_draw_view_finalize_get(); GPU_shader_bind(shader); - GPU_uniformbuf_bind_as_ssbo(culling_, GPU_shader_get_ssbo(shader, "view_culling_buf")); + GPU_uniformbuf_bind_as_ssbo(culling_, GPU_shader_get_ssbo_binding(shader, "view_culling_buf")); GPU_uniformbuf_bind(data_, DRW_VIEW_UBO_SLOT); GPU_compute_dispatch(shader, 1, 1, 1); GPU_memory_barrier(GPU_BARRIER_UNIFORM); @@ -289,8 +289,8 @@ void View::compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool d GPU_shader_uniform_1i(shader, "resource_len", resource_len); GPU_shader_uniform_1i(shader, "view_len", view_len_); GPU_shader_uniform_1i(shader, "visibility_word_per_draw", word_per_draw); - GPU_storagebuf_bind(bounds, GPU_shader_get_ssbo(shader, "bounds_buf")); - GPU_storagebuf_bind(visibility_buf_, GPU_shader_get_ssbo(shader, "visibility_buf")); + GPU_storagebuf_bind(bounds, GPU_shader_get_ssbo_binding(shader, "bounds_buf")); + GPU_storagebuf_bind(visibility_buf_, GPU_shader_get_ssbo_binding(shader, "visibility_buf")); GPU_uniformbuf_bind(frozen_ ? data_freeze_ : data_, DRW_VIEW_UBO_SLOT); GPU_uniformbuf_bind(frozen_ ? culling_freeze_ : culling_, DRW_VIEW_CULLING_UBO_SLOT); GPU_compute_dispatch(shader, divide_ceil_u(resource_len, DRW_VISIBILITY_GROUP_SIZE), 1, 1); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index 21201593d0c0..df52444a25b5 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -17,7 +17,7 @@ #include "BKE_attribute.hh" #include "BKE_mesh.h" -#include "draw_attributes.h" +#include "draw_attributes.hh" #include "draw_subdivision.h" #include "extract_mesh.hh" diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc index c6ba9283084c..d27af95c1901 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc @@ -44,7 +44,7 @@ static void mesh_render_data_edge_flag(const MeshRenderData *mr, } /* Use active edge color for active face edges because - * specular highlights make it hard to see T55456#510873. + * specular highlights make it hard to see #55456#510873. * * This isn't ideal since it can't be used when mixing edge/face modes * but it's still better than not being able to see the active face. */ diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc index b295a314883f..174223221fa3 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc @@ -229,7 +229,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdi * the data for the mesh when switching to the `UV Editing` workspace, and therefore the position * buffer might not be created yet. In this case, create a buffer it locally, the subdivision * data should already be evaluated if we are here. This can happen if the subsurf modifier is - * only enabled in edit-mode. See T96338. */ + * only enabled in edit-mode. See #96338. */ if (!pos_nor) { const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom; pos_nor = GPU_vertbuf_calloc(); @@ -245,7 +245,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdi CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_MESH) ? &mr->me->ldata : &mr->bm->ldata; uint32_t uv_layers = cache->cd_used.uv; - /* HACK to fix T68857 */ + /* HACK to fix #68857 */ if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) { int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2); if (layer != -1) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc index bd1c98b033f3..971fead52cf0 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc @@ -46,7 +46,7 @@ static void extract_tan_init_common(const MeshRenderData *mr, int tan_len = 0; - /* FIXME(T91838): This is to avoid a crash when orco tangent was requested but there are valid + /* FIXME(#91838): This is to avoid a crash when orco tangent was requested but there are valid * uv layers. It would be better to fix the root cause. */ if (tan_layers == 0 && use_orco_tan && CustomData_get_layer_index(cd_ldata, CD_PROP_FLOAT2) != -1) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc index 2af8fa40844e..bc73c59f556d 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc @@ -28,7 +28,7 @@ static bool mesh_extract_uv_format_init(GPUVertFormat *format, GPU_vertformat_deinterleave(format); uint32_t uv_layers = cache->cd_used.uv; - /* HACK to fix T68857 */ + /* HACK to fix #68857 */ if (extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) { int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2); if (layer != -1) { diff --git a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl index 5b79ce71739f..bb55035f9e68 100644 --- a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl +++ b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl @@ -123,7 +123,7 @@ bool gpencil_is_stroke_vertex() * * * WARNING: Max attribute count is actually 14 because OSX OpenGL implementation - * considers gl_VertexID and gl_InstanceID as vertex attribute. (see T74536) + * considers gl_VertexID and gl_InstanceID as vertex attribute. (see #74536) */ vec4 gpencil_vertex(vec4 viewport_size, gpMaterialFlag material_flags, diff --git a/source/blender/draw/intern/shaders/common_hair_lib.glsl b/source/blender/draw/intern/shaders/common_hair_lib.glsl index 0efaad47afb8..4fea4f779908 100644 --- a/source/blender/draw/intern/shaders/common_hair_lib.glsl +++ b/source/blender/draw/intern/shaders/common_hair_lib.glsl @@ -190,7 +190,7 @@ void hair_get_center_pos_tan_binor_time(bool is_persp, # if defined(OS_MAC) && defined(GPU_OPENGL) /* Generate a dummy read to avoid the driver bug with shaders having no - * vertex reads on macOS (T60171) */ + * vertex reads on macOS (#60171) */ wpos.y += dummy * 0.0; # endif diff --git a/source/blender/draw/intern/shaders/common_math_lib.glsl b/source/blender/draw/intern/shaders/common_math_lib.glsl index 6011f3398a65..59eedee7c874 100644 --- a/source/blender/draw/intern/shaders/common_math_lib.glsl +++ b/source/blender/draw/intern/shaders/common_math_lib.glsl @@ -109,7 +109,7 @@ vec3 sqr(vec3 a) { return a * a; } vec4 sqr(vec4 a) { return a * a; } /* Use manual powers for fixed powers. pow() can have unpredictable results on some implementations. - * (see T87369, T87541) */ + * (see #87369, #87541) */ float pow6(float x) { return sqr(sqr(x) * x); } float pow8(float x) { return sqr(sqr(sqr(x))); } diff --git a/source/blender/draw/intern/shaders/draw_debug_info.hh b/source/blender/draw/intern/shaders/draw_debug_info.hh index 4b5590824ba5..e2dc2d0208e5 100644 --- a/source/blender/draw/intern/shaders/draw_debug_info.hh +++ b/source/blender/draw/intern/shaders/draw_debug_info.hh @@ -18,7 +18,7 @@ GPU_SHADER_INTERFACE_INFO(draw_debug_print_display_iface, "").flat(Type::UINT, " GPU_SHADER_CREATE_INFO(draw_debug_print_display) .do_static_compilation(true) .typedef_source("draw_shader_shared.h") - .storage_buf(7, Qualifier::READ, "uint", "drw_debug_print_buf[]") + .storage_buf(DRW_DEBUG_PRINT_SLOT, Qualifier::READ, "uint", "drw_debug_print_buf[]") .vertex_out(draw_debug_print_display_iface) .fragment_out(0, Type::VEC4, "out_color") .push_constant(Type::VEC2, "viewport_size") @@ -46,7 +46,7 @@ GPU_SHADER_INTERFACE_INFO(draw_debug_draw_display_iface, "interp").flat(Type::VE GPU_SHADER_CREATE_INFO(draw_debug_draw_display) .do_static_compilation(true) .typedef_source("draw_shader_shared.h") - .storage_buf(6, Qualifier::READ, "DRWDebugVert", "drw_debug_verts_buf[]") + .storage_buf(DRW_DEBUG_DRAW_SLOT, Qualifier::READ, "DRWDebugVert", "drw_debug_verts_buf[]") .vertex_out(draw_debug_draw_display_iface) .fragment_out(0, Type::VEC4, "out_color") .push_constant(Type::MAT4, "persmat") diff --git a/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl b/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl index 511d4e496510..b70cacbc55e1 100644 --- a/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl +++ b/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl @@ -46,7 +46,7 @@ void main() -bounds_buf[resource_id].bounding_corners[1].xyz; } - /* TODO: Bypass test for very large objects (see T67319). */ + /* TODO: Bypass test for very large objects (see #67319). */ if (bounds_buf[resource_id].bounding_sphere.w > 1e12) { bounds_buf[resource_id].bounding_sphere.w = -1.0; } diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 07a6f6cda471..000bf04697f8 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -5295,7 +5295,7 @@ void ANIM_channel_draw_widgets(const bContext *C, } else { /* Cannot get property/cannot or rename for some reason, so clear rename index - * so that this doesn't hang around, and the name can be drawn normally - T47492 + * so that this doesn't hang around, and the name can be drawn normally - #47492 */ ac->ads->renameIndex = 0; WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL); diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index e1dc46a8a729..298b48a4a908 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -216,7 +216,7 @@ void ANIM_set_active_channel(bAnimContext *ac, static void select_pchan_for_action_group(bAnimContext *ac, bActionGroup *agrp, bAnimListElem *ale) { /* Armatures-Specific Feature: - * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (T38737) + * See mouse_anim_channels() -> ANIMTYPE_GROUP case for more details (#38737) */ if ((ac->ads->filterflag & ADS_FILTER_ONLYSEL) == 0) { if ((ale->id) && (GS(ale->id->name) == ID_OB)) { @@ -667,7 +667,7 @@ void ANIM_fcurve_delete_from_animdata(bAnimContext *ac, AnimData *adt, FCurve *f action_groups_remove_channel(act, fcu); /* if group has no more channels, remove it too, - * otherwise can have many dangling groups T33541. + * otherwise can have many dangling groups #33541. */ if (BLI_listbase_is_empty(&agrp->channels)) { BLI_freelinkN(&act->groups, agrp); @@ -2068,7 +2068,7 @@ static void setflag_anim_channels(bAnimContext *ac, * since we only want to apply this to channels we can "see", * and have these affect their relatives * - but for Graph Editor, this gets used also from main region - * where hierarchy doesn't apply T21276. + * where hierarchy doesn't apply #21276. */ if ((ac->spacetype == SPACE_GRAPH) && (ac->regiontype != RGN_TYPE_CHANNELS)) { /* graph editor (case 2) */ @@ -3067,10 +3067,10 @@ static int click_select_channel_object(bContext *C, } } - /* Change active object - regardless of whether it is now selected, see: T37883. + /* Change active object - regardless of whether it is now selected, see: #37883. * * Ensure we exit edit-mode on whatever object was active before - * to avoid getting stuck there, see: T48747. */ + * to avoid getting stuck there, see: #48747. */ ED_object_base_activate_with_mode_exit_if_needed(C, base); /* adds notifier */ if ((adt) && (adt->flag & ADT_UI_SELECTED)) { diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 22c14983569a..418331f84b1d 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -241,7 +241,7 @@ static void animchan_sync_gplayer(bAnimListElem *ale) * The selection flags are used in the Dopesheet only, whereas * the active flag is used everywhere else. Hence, we try to * sync these here so that it all seems to be have as the user - * expects - T50184 + * expects - #50184 * * Assume that we only really do this when the active status changes. * (NOTE: This may prove annoying if it means selection is always lost) diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 4d33723a297b..ac73b7995f2a 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -223,7 +223,7 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction) /* sync scene's "selected keys only" flag with our "only selected" flag * - * XXX: This is a workaround for T55525. We shouldn't really be syncing the flags like this, + * XXX: This is a workaround for #55525. We shouldn't really be syncing the flags like this, * but it's a simpler fix for now than also figuring out how the next/prev keyframe * tools should work in the 3D View if we allowed full access to the timeline's * dopesheet filters (i.e. we'd have to figure out where to host those settings, @@ -1360,7 +1360,7 @@ static size_t animfilter_act_group(bAnimContext *ac, * but the group isn't expanded (1)... * (1) this only matters if we actually care about the hierarchy though. * - Hierarchy matters: this hack should be applied - * - Hierarchy ignored: cases like T21276 won't work properly, unless we skip this hack + * - Hierarchy ignored: cases like #21276 won't work properly, unless we skip this hack */ if ( /* Care about hierarchy but group isn't expanded. */ @@ -3121,7 +3121,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, if (object_mode & OB_MODE_POSE) { /* When in pose-mode handle all pose-mode objects. * This avoids problems with pose-mode where objects may be unselected, - * where a selected bone of an unselected object would be hidden. see: T81922. */ + * where a selected bone of an unselected object would be hidden. see: #81922. */ if (!(base->object->mode & object_mode)) { return false; } @@ -3453,7 +3453,7 @@ size_t ANIM_animdata_filter(bAnimContext *ac, SpaceAction *saction = (SpaceAction *)ac->sl; bDopeSheet *ads = (saction) ? &saction->ads : NULL; - /* specially check for AnimData filter, see T36687. */ + /* specially check for AnimData filter, see #36687. */ if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) { /* all channels here are within the same AnimData block, hence this special case */ if (LIKELY(obact->adt)) { @@ -3474,7 +3474,7 @@ size_t ANIM_animdata_filter(bAnimContext *ac, { Key *key = (Key *)data; - /* specially check for AnimData filter, see T36687. */ + /* specially check for AnimData filter, see #36687. */ if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) { /* all channels here are within the same AnimData block, hence this special case */ if (LIKELY(key->adt)) { diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c index 93d83ff5f8eb..e319f4d8a035 100644 --- a/source/blender/editors/animation/anim_ipo_utils.c +++ b/source/blender/editors/animation/anim_ipo_utils.c @@ -184,7 +184,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) icon = RNA_struct_ui_icon(ptr.type); /* valid path - remove the invalid tag since we now know how to use it saving - * users manual effort to re-enable using "Revive Disabled FCurves" T29629. */ + * users manual effort to re-enable using "Revive Disabled FCurves" #29629. */ fcu->flag &= ~FCURVE_DISABLED; } else { diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index a2e137f854b0..694eb1f70350 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -1350,7 +1350,7 @@ static int ed_marker_select( WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); - /* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails, see T25987. */ + /* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails, see #25987. */ return ret_val | OPERATOR_PASS_THROUGH; } diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index f899e41149dd..3dfcd076f17f 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -195,7 +195,7 @@ static int add_driver_with_target(ReportList *UNUSED(reports), * - For transform properties, we want to automatically use "transform channel" instead * (The only issue is with quaternion rotations vs euler channels...) * - To avoid problems with transform properties depending on the final transform that they - * control (thus creating pseudo-cycles - see T48734), we don't use transform channels + * control (thus creating pseudo-cycles - see #48734), we don't use transform channels * when both the source and destinations are in same places. */ dvar = driver_add_new_variable(driver); diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index d0b978b7adf0..6b1fdb977ff4 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -22,6 +22,7 @@ #include "DNA_scene_types.h" #include "GPU_immediate.h" +#include "GPU_shader_shared.h" #include "GPU_state.h" #include "UI_interface.h" diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 49e40b399020..c435983be193 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -679,7 +679,7 @@ void sample_fcurve(FCurve *fcu) /* If next bezt is also selected, don't start sampling yet, * but instead wait for that one to reconsider, to avoid * changing the curve when sampling consecutive segments - * (T53229) + * (#53229) */ if (i < fcu->totvert - 1) { BezTriple *next = &fcu->bezt[i + 1]; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 96a9604a6f5e..c6e9a62ae2a2 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -2077,7 +2077,7 @@ static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UN /* Show a menu listing all keying-sets, the enum is expanded here to make use of the * operator that accesses the keying-set by name. This is important for the ability - * to assign shortcuts to arbitrarily named keying sets. See T89560. + * to assign shortcuts to arbitrarily named keying sets. See #89560. * These menu items perform the key-frame insertion (not this operator) * hence the #OPERATOR_INTERFACE return. */ uiPopupMenu *pup = UI_popup_menu_begin(C, WM_operatortype_name(op->type, op->ptr), ICON_NONE); @@ -2966,7 +2966,7 @@ static bool object_frame_has_keyframe(Object *ob, float frame, short filter) /* check own animation data - specifically, the action it contains */ if ((ob->adt) && (ob->adt->action)) { - /* T41525 - When the active action is a NLA strip being edited, + /* #41525 - When the active action is a NLA strip being edited, * we need to correct the frame number to "look inside" the * remapped action */ @@ -3167,7 +3167,7 @@ bool ED_autokeyframe_property(bContext *C, if (only_if_property_keyed) { /* NOTE: We use rnaindex instead of fcu->array_index, * because a button may control all items of an array at once. - * E.g., color wheels (see T42567). */ + * E.g., color wheels (see #42567). */ BLI_assert((fcu->array_index == rnaindex) || (rnaindex == -1)); } changed = insert_keyframe(bmain, diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 3448ba1c0170..a106ecb84e96 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -1119,7 +1119,7 @@ int ANIM_apply_keyingset( RNA_id_pointer_create(ksp->id, &id_ptr); if (RNA_path_resolve_property(&id_ptr, ksp->rna_path, &ptr, &prop)) { arraylen = RNA_property_array_length(&ptr, prop); - /* start from start of array, instead of the previously specified index - T48020 */ + /* start from start of array, instead of the previously specified index - #48020 */ i = 0; } } diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 2ec0ea57e716..0e3748ad661e 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -912,7 +912,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) armature_tag_select_mirrored(arm); /* Clear BONE_TRANSFORM flags - * - Used to prevent duplicate/canceling operations from occurring T34123. + * - Used to prevent duplicate/canceling operations from occurring #34123. * - #BONE_DONE cannot be used here as that's already used for mirroring. */ armature_clear_swap_done_flags(arm); @@ -929,7 +929,7 @@ static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) */ parent = ebo->parent; - /* skip bone if already handled, see T34123. */ + /* skip bone if already handled, see #34123. */ if ((ebo->flag & BONE_TRANSFORM) == 0) { /* only if selected and editable */ if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) { diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 26ec05cc5035..579583eb4eaa 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -337,7 +337,7 @@ void ED_armature_bone_rename(Main *bmain, /* Fix all animdata that may refer to this bone - * we can't just do the ones attached to objects, - * since other ID-blocks may have drivers referring to this bone T29822. */ + * since other ID-blocks may have drivers referring to this bone #29822. */ /* XXX: the ID here is for armatures, * but most bone drivers are actually on the object instead. */ diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 90bd59f61bc6..38b982e53426 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -151,7 +151,7 @@ void ED_operatormacros_armature(void) /* XXX would it be nicer to just be able to have standard extrude_move, * but set the forked property separate? - * that would require fixing a properties bug T19733. */ + * that would require fixing a properties bug #19733. */ ot = WM_operatortype_append_macro("ARMATURE_OT_extrude_forked", "Extrude Forked", "Create new bones from the selected joints and move them", diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index 6fb07dc7da61..39d558638cef 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -162,7 +162,7 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap) defgroup = BKE_object_defgroup_add_name(ob, bone->name); } else if (defgroup->flag & DG_LOCK_WEIGHT) { - /* In case vgroup already exists and is locked, do not modify it here. See T43814. */ + /* In case vgroup already exists and is locked, do not modify it here. See #43814. */ defgroup = NULL; } } @@ -401,9 +401,9 @@ static void add_verts_to_dgroups(ReportList *reports, vertsfilled = 1; } else if (BKE_modifiers_findby_type(ob, eModifierType_Subsurf)) { - /* is subsurf on? Lets use the verts on the limit surface then. + /* Is subdivision-surface on? Lets use the verts on the limit surface then. * = same amount of vertices as mesh, but vertices moved to the - * subsurfed position, like for 'optimal'. */ + * subdivision-surfaced position, like for 'optimal'. */ subsurf_calculate_limit_positions(mesh, verts); vertsfilled = 1; } @@ -477,7 +477,7 @@ void ED_object_vgroup_calc_from_armature(ReportList *reports, if (defbase_add) { /* It's possible there are DWeights outside the range of the current - * object's deform groups. In this case the new groups won't be empty T33889. */ + * object's deform groups. In this case the new groups won't be empty #33889. */ ED_vgroup_data_clamp_range(ob->data, defbase_tot); } } diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 0465606e6944..0391f25e922b 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -597,7 +597,7 @@ static void armature_finalize_restpose(ListBase *bonelist, ListBase *editbonelis for (curBone = bonelist->first; curBone; curBone = curBone->next) { /* Set bone's local head/tail. * Note that it's important to use final parent's restpose (arm_mat) here, - * instead of setting those values from editbone's matrix (see T46010). */ + * instead of setting those values from editbone's matrix (see #46010). */ if (curBone->parent) { float parmat_inv[4][4]; @@ -749,7 +749,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) /* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point. * Do not set bone->head/tail here anymore, * using EditBone data for that is not OK since our later fiddling with parent's arm_mat - * (for roll conversion) may have some small but visible impact on locations (T46010). */ + * (for roll conversion) may have some small but visible impact on locations (#46010). */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = eBone->temp.bone; if (eBone->parent) { diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 067b86945c16..21938ad8727d 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -230,7 +230,7 @@ bool ED_armature_pose_select_pick_bone(const Scene *scene, */ else if (arm->flag & ARM_HAS_VIZ_DEPS) { /* NOTE: ob not ob_act here is intentional - it's the source of the - * bones being selected [T37247] + * bones being selected [#37247]. */ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 510718158232..7f384c36af06 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -524,7 +524,7 @@ static int pose_visual_transform_apply_exec(bContext *C, wmOperator *UNUSED(op)) * change, thus changing the result we may be trying to record. */ /* NOTE: For some reason `pchan->chan_mat` can't be used here as it gives odd - * rotation/offset, see T38251. + * rotation/offset, see #38251. * Using `pchan->pose_mat` and bringing it back in bone space seems to work as expected! * This matches how visual key-framing works. */ BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, pchan_xform_array[i].matrix); diff --git a/source/blender/editors/asset/ED_asset_handle.h b/source/blender/editors/asset/ED_asset_handle.h index b3d9b58b30ec..436194fd885f 100644 --- a/source/blender/editors/asset/ED_asset_handle.h +++ b/source/blender/editors/asset/ED_asset_handle.h @@ -13,6 +13,7 @@ #pragma once #include "DNA_ID_enums.h" +#include "DNA_asset_types.h" #ifdef __cplusplus extern "C" { @@ -37,6 +38,13 @@ void ED_asset_handle_get_full_library_path( #ifdef __cplusplus +# include + +/** The asset library may have an import method (e.g. append vs. link) defined to use. If so, this + * returns it. Otherwise a reasonable method should be used, usually "Append (Reuse Data)". */ +std::optional ED_asset_handle_get_import_method( + const struct AssetHandle *asset); + namespace blender::ed::asset { /** If the ID already exists in the database, return it, otherwise add it. */ diff --git a/source/blender/editors/asset/intern/asset_handle.cc b/source/blender/editors/asset/intern/asset_handle.cc index 26b6f09b231b..4a6a7fda40b0 100644 --- a/source/blender/editors/asset/intern/asset_handle.cc +++ b/source/blender/editors/asset/intern/asset_handle.cc @@ -42,6 +42,12 @@ int ED_asset_handle_get_preview_icon_id(const AssetHandle *asset) return asset->file_data->preview_icon_id; } +std::optional ED_asset_handle_get_import_method( + const AssetHandle *asset_handle) +{ + return AS_asset_representation_import_method_get(asset_handle->file_data->asset); +} + void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle, char r_full_lib_path[FILE_MAX_LIBEXTRA]) { diff --git a/source/blender/editors/asset/intern/asset_library_reference_enum.cc b/source/blender/editors/asset/intern/asset_library_reference_enum.cc index d20f3205a77e..aab4bd12222c 100644 --- a/source/blender/editors/asset/intern/asset_library_reference_enum.cc +++ b/source/blender/editors/asset/intern/asset_library_reference_enum.cc @@ -47,7 +47,7 @@ AssetLibraryReference ED_asset_library_reference_from_enum_value(int value) if (value < ASSET_LIBRARY_CUSTOM) { library.type = value; library.custom_library_index = -1; - BLI_assert(ELEM(value, ASSET_LIBRARY_ALL, ASSET_LIBRARY_LOCAL)); + BLI_assert(ELEM(value, ASSET_LIBRARY_ALL, ASSET_LIBRARY_LOCAL, ASSET_LIBRARY_ESSENTIALS)); return library; } @@ -57,7 +57,7 @@ AssetLibraryReference ED_asset_library_reference_from_enum_value(int value) /* Note that there is no check if the path exists here. If an invalid library path is used, the * Asset Browser can give a nice hint on what's wrong. */ if (!user_library) { - library.type = ASSET_LIBRARY_LOCAL; + library.type = ASSET_LIBRARY_ALL; library.custom_library_index = -1; } else { @@ -77,16 +77,18 @@ const EnumPropertyItem *ED_asset_library_reference_to_rna_enum_itemf(const bool if (include_generated) { const EnumPropertyItem generated_items[] = { - {ASSET_LIBRARY_ALL, - "ALL", - ICON_NONE, - "All", - "Show assets from all of the listed asset libraries"}, + {ASSET_LIBRARY_ALL, "ALL", 0, "All", "Show assets from all of the listed asset libraries"}, + RNA_ENUM_ITEM_SEPR, {ASSET_LIBRARY_LOCAL, "LOCAL", ICON_CURRENT_FILE, "Current File", "Show the assets currently available in this Blender session"}, + {ASSET_LIBRARY_ESSENTIALS, + "ESSENTIALS", + 0, + "Essentials", + "Show the basic building blocks and utilities coming with Blender"}, {0, nullptr, 0, nullptr, nullptr}, }; diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc index 649343164135..78859a9206d1 100644 --- a/source/blender/editors/asset/intern/asset_list.cc +++ b/source/blender/editors/asset/intern/asset_list.cc @@ -372,6 +372,7 @@ std::optional AssetListStorage::asset_library_reference_to_file switch (eAssetLibraryType(library_reference.type)) { case ASSET_LIBRARY_ALL: return FILE_ASSET_LIBRARY_ALL; + case ASSET_LIBRARY_ESSENTIALS: case ASSET_LIBRARY_CUSTOM: return FILE_ASSET_LIBRARY; case ASSET_LIBRARY_LOCAL: diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index af3d439dd2ed..66fb3cb06a34 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -577,7 +577,7 @@ static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke) cdd->vc.obedit = CTX_data_edit_object(C); /* Using an empty stroke complicates logic later, - * it's simplest to disallow early on (see: T94085). */ + * it's simplest to disallow early on (see: #94085). */ if (RNA_collection_is_empty(op->ptr, "stroke")) { MEM_freeN(cdd); BKE_report(op->reports, RPT_ERROR, "The \"stroke\" cannot be empty"); diff --git a/source/blender/editors/curves/CMakeLists.txt b/source/blender/editors/curves/CMakeLists.txt index 873df89b40c2..36eb0e046474 100644 --- a/source/blender/editors/curves/CMakeLists.txt +++ b/source/blender/editors/curves/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC set(SRC intern/curves_add.cc intern/curves_data.cc + intern/curves_edit.cc intern/curves_ops.cc intern/curves_selection.cc intern/curves_undo.cc diff --git a/source/blender/editors/curves/intern/curves_edit.cc b/source/blender/editors/curves/intern/curves_edit.cc new file mode 100644 index 000000000000..9d5e7730ba07 --- /dev/null +++ b/source/blender/editors/curves/intern/curves_edit.cc @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup edcurves + */ + +#include "BLI_index_mask_ops.hh" + +#include "BKE_curves.hh" + +#include "ED_curves.h" + +namespace blender::ed::curves { + +bool remove_selection(bke::CurvesGeometry &curves, const eAttrDomain selection_domain) +{ + const bke::AttributeAccessor attributes = curves.attributes(); + const VArray selection = attributes.lookup_or_default( + ".selection", selection_domain, true); + const int domain_size_orig = attributes.domain_size(selection_domain); + Vector indices; + const IndexMask mask = index_mask_ops::find_indices_from_virtual_array( + selection.index_range(), selection, 4096, indices); + switch (selection_domain) { + case ATTR_DOMAIN_POINT: + curves.remove_points(mask); + break; + case ATTR_DOMAIN_CURVE: + curves.remove_curves(mask); + break; + default: + BLI_assert_unreachable(); + } + + return attributes.domain_size(selection_domain) != domain_size_orig; +} + +} // namespace blender::ed::curves diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index 77641d7a916d..a05ecfcaed3e 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -793,21 +793,19 @@ static int curves_set_selection_domain_exec(bContext *C, wmOperator *op) if (curves.points_num() == 0) { continue; } - const GVArray src = attributes.lookup(".selection", domain); - if (src.is_empty()) { - continue; - } - const CPPType &type = src.type(); - void *dst = MEM_malloc_arrayN(attributes.domain_size(domain), type.size(), __func__); - src.materialize(dst); + if (const GVArray src = attributes.lookup(".selection", domain)) { + const CPPType &type = src.type(); + void *dst = MEM_malloc_arrayN(attributes.domain_size(domain), type.size(), __func__); + src.materialize(dst); - attributes.remove(".selection"); - if (!attributes.add(".selection", - domain, - bke::cpp_type_to_custom_data_type(type), - bke::AttributeInitMoveArray(dst))) { - MEM_freeN(dst); + attributes.remove(".selection"); + if (!attributes.add(".selection", + domain, + bke::cpp_type_to_custom_data_type(type), + bke::AttributeInitMoveArray(dst))) { + MEM_freeN(dst); + } } /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic @@ -1010,6 +1008,60 @@ static void CURVES_OT_select_linked(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +static int select_more_exec(bContext *C, wmOperator * /*op*/) +{ + VectorSet unique_curves = get_unique_editable_curves(*C); + for (Curves *curves_id : unique_curves) { + CurvesGeometry &curves = curves_id->geometry.wrap(); + select_adjacent(curves, false); + /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic + * attribute for now. */ + DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id); + } + + return OPERATOR_FINISHED; +} + +static void CURVES_OT_select_more(wmOperatorType *ot) +{ + ot->name = "Select More"; + ot->idname = __func__; + ot->description = "Grow the selection by one point"; + + ot->exec = select_more_exec; + ot->poll = editable_curves_point_domain_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int select_less_exec(bContext *C, wmOperator * /*op*/) +{ + VectorSet unique_curves = get_unique_editable_curves(*C); + for (Curves *curves_id : unique_curves) { + CurvesGeometry &curves = curves_id->geometry.wrap(); + select_adjacent(curves, true); + /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic + * attribute for now. */ + DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id); + } + + return OPERATOR_FINISHED; +} + +static void CURVES_OT_select_less(wmOperatorType *ot) +{ + ot->name = "Select Less"; + ot->idname = __func__; + ot->description = "Shrink the selection by one point"; + + ot->exec = select_less_exec; + ot->poll = editable_curves_point_domain_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + namespace surface_set { static bool surface_set_poll(bContext *C) @@ -1093,6 +1145,35 @@ static void CURVES_OT_surface_set(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +namespace curves_delete { + +static int delete_exec(bContext *C, wmOperator * /*op*/) +{ + for (Curves *curves_id : get_unique_editable_curves(*C)) { + bke::CurvesGeometry &curves = curves_id->geometry.wrap(); + if (remove_selection(curves, eAttrDomain(curves_id->selection_domain))) { + DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id); + } + } + + return OPERATOR_FINISHED; +} + +} // namespace curves_delete + +static void CURVES_OT_delete(wmOperatorType *ot) +{ + ot->name = "Delete"; + ot->idname = __func__; + ot->description = "Remove selected control points or curves"; + + ot->exec = curves_delete::delete_exec; + ot->poll = editable_curves_in_edit_mode_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + } // namespace blender::ed::curves void ED_operatortypes_curves() @@ -1106,7 +1187,10 @@ void ED_operatortypes_curves() WM_operatortype_append(CURVES_OT_select_random); WM_operatortype_append(CURVES_OT_select_end); WM_operatortype_append(CURVES_OT_select_linked); + WM_operatortype_append(CURVES_OT_select_more); + WM_operatortype_append(CURVES_OT_select_less); WM_operatortype_append(CURVES_OT_surface_set); + WM_operatortype_append(CURVES_OT_delete); } void ED_keymap_curves(wmKeyConfig *keyconf) diff --git a/source/blender/editors/curves/intern/curves_selection.cc b/source/blender/editors/curves/intern/curves_selection.cc index c896e0a2d336..086662cc85a0 100644 --- a/source/blender/editors/curves/intern/curves_selection.cc +++ b/source/blender/editors/curves/intern/curves_selection.cc @@ -267,6 +267,85 @@ void select_linked(bke::CurvesGeometry &curves) selection.finish(); } +void select_adjacent(bke::CurvesGeometry &curves, const bool deselect) +{ + const OffsetIndices points_by_curve = curves.points_by_curve(); + bke::GSpanAttributeWriter selection = ensure_selection_attribute( + curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL); + const VArray cyclic = curves.cyclic(); + + if (deselect) { + invert_selection(selection.span); + } + + if (selection.span.type().is()) { + MutableSpan selection_typed = selection.span.typed(); + threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) { + for (const int curve_i : range) { + const IndexRange points = points_by_curve[curve_i]; + + /* Handle all cases in the forward direction. */ + for (int point_i = points.first(); point_i < points.last(); point_i++) { + if (!selection_typed[point_i] && selection_typed[point_i + 1]) { + selection_typed[point_i] = true; + } + } + + /* Handle all cases in the backwards direction. */ + for (int point_i = points.last(); point_i > points.first(); point_i--) { + if (!selection_typed[point_i] && selection_typed[point_i - 1]) { + selection_typed[point_i] = true; + } + } + + /* Handle cyclic curve case. */ + if (cyclic[curve_i]) { + if (selection_typed[points.first()] != selection_typed[points.last()]) { + selection_typed[points.first()] = true; + selection_typed[points.last()] = true; + } + } + } + }); + } + else if (selection.span.type().is()) { + MutableSpan selection_typed = selection.span.typed(); + threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) { + for (const int curve_i : range) { + const IndexRange points = points_by_curve[curve_i]; + + /* Handle all cases in the forward direction. */ + for (int point_i = points.first(); point_i < points.last(); point_i++) { + if ((selection_typed[point_i] == 0.0f) && (selection_typed[point_i + 1] > 0.0f)) { + selection_typed[point_i] = 1.0f; + } + } + + /* Handle all cases in the backwards direction. */ + for (int point_i = points.last(); point_i > points.first(); point_i--) { + if ((selection_typed[point_i] == 0.0f) && (selection_typed[point_i - 1] > 0.0f)) { + selection_typed[point_i] = 1.0f; + } + } + + /* Handle cyclic curve case. */ + if (cyclic[curve_i]) { + if (selection_typed[points.first()] != selection_typed[points.last()]) { + selection_typed[points.first()] = 1.0f; + selection_typed[points.last()] = 1.0f; + } + } + } + }); + } + + if (deselect) { + invert_selection(selection.span); + } + + selection.finish(); +} + void select_random(bke::CurvesGeometry &curves, const eAttrDomain selection_domain, uint32_t random_seed, @@ -331,7 +410,7 @@ static void apply_selection_operation_at_index(GMutableSpan selection, selection_typed[index] = false; break; case SEL_OP_XOR: - selection_typed[index] ^= selection_typed[index]; + selection_typed[index] = !selection_typed[index]; break; default: break; @@ -357,9 +436,9 @@ static void apply_selection_operation_at_index(GMutableSpan selection, } /** - * Helper struct for `find_closest_point_to_screen_co`. + * Helper struct for `select_pick`. */ -struct FindClosestPointData { +struct FindClosestData { int index = -1; float distance = FLT_MAX; }; @@ -371,7 +450,7 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph, const bke::CurvesGeometry &curves, float2 mouse_pos, float radius, - FindClosestPointData &closest_data) + FindClosestData &closest_data) { float4x4 projection; ED_view3d_ob_project_mat_get(rv3d, &object, projection.ptr()); @@ -380,12 +459,12 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph, bke::crazyspace::get_evaluated_curves_deformation(depsgraph, object); const float radius_sq = pow2f(radius); - auto [min_point_index, min_distance] = threading::parallel_reduce( + closest_data = threading::parallel_reduce( curves.points_range(), 1024, - FindClosestPointData(), - [&](const IndexRange point_range, const FindClosestPointData &init) { - FindClosestPointData best_match = init; + FindClosestData(), + [&](const IndexRange point_range, const FindClosestData &init) { + FindClosestData best_match = init; for (const int point_i : point_range) { const float3 pos = deformation.positions[point_i]; @@ -400,7 +479,7 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph, continue; } - FindClosestPointData better_candidate; + FindClosestData better_candidate; better_candidate.index = point_i; better_candidate.distance = std::sqrt(distance_proj_sq); @@ -408,18 +487,104 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph, } return best_match; }, - [](const FindClosestPointData &a, const FindClosestPointData &b) { + [](const FindClosestData &a, const FindClosestData &b) { + if (a.distance < b.distance) { + return a; + } + return b; + }); + if (closest_data.index > 0) { + return true; + } + + return false; +} + +static bool find_closest_curve_to_screen_co(const Depsgraph &depsgraph, + const ARegion *region, + const RegionView3D *rv3d, + const Object &object, + const bke::CurvesGeometry &curves, + float2 mouse_pos, + float radius, + FindClosestData &closest_data) +{ + float4x4 projection; + ED_view3d_ob_project_mat_get(rv3d, &object, projection.ptr()); + + const bke::crazyspace::GeometryDeformation deformation = + bke::crazyspace::get_evaluated_curves_deformation(depsgraph, object); + + const float radius_sq = pow2f(radius); + + const OffsetIndices points_by_curve = curves.points_by_curve(); + closest_data = threading::parallel_reduce( + curves.curves_range(), + 256, + FindClosestData(), + [&](const IndexRange curves_range, const FindClosestData &init) { + FindClosestData best_match = init; + for (const int curve_i : curves_range) { + if (points_by_curve.size(curve_i) == 1) { + const float3 pos = deformation.positions[points_by_curve[curve_i].first()]; + + /* Find the position of the point in screen space. */ + float2 pos_proj; + ED_view3d_project_float_v2_m4(region, pos, pos_proj, projection.ptr()); + + const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos); + if (distance_proj_sq > radius_sq || + distance_proj_sq > best_match.distance * best_match.distance) { + /* Ignore the point because it's too far away or there is already a better point. + */ + continue; + } + + FindClosestData better_candidate; + better_candidate.index = curve_i; + better_candidate.distance = std::sqrt(distance_proj_sq); + + best_match = better_candidate; + continue; + } + + for (const int segment_i : points_by_curve[curve_i].drop_back(1)) { + const float3 pos1 = deformation.positions[segment_i]; + const float3 pos2 = deformation.positions[segment_i + 1]; + + float2 pos1_proj, pos2_proj; + ED_view3d_project_float_v2_m4(region, pos1, pos1_proj, projection.ptr()); + ED_view3d_project_float_v2_m4(region, pos2, pos2_proj, projection.ptr()); + + const float distance_proj_sq = dist_squared_to_line_segment_v2( + mouse_pos, pos1_proj, pos2_proj); + if (distance_proj_sq > radius_sq || + distance_proj_sq > best_match.distance * best_match.distance) { + /* Ignore the segment because it's too far away or there is already a better point. + */ + continue; + } + + FindClosestData better_candidate; + better_candidate.index = curve_i; + better_candidate.distance = std::sqrt(distance_proj_sq); + + best_match = better_candidate; + } + } + return best_match; + }, + [](const FindClosestData &a, const FindClosestData &b) { if (a.distance < b.distance) { return a; } return b; }); - if (min_point_index > 0) { - closest_data.index = min_point_index; - closest_data.distance = min_distance; + if (closest_data.index > 0) { return true; } + return false; } @@ -429,15 +594,28 @@ bool select_pick(const ViewContext &vc, const SelectPick_Params ¶ms, const int2 coord) { - FindClosestPointData closest_point; - bool found = find_closest_point_to_screen_co(*vc.depsgraph, - vc.region, - vc.rv3d, - *vc.obact, - curves, - float2(coord), - ED_view3d_select_dist_px(), - closest_point); + FindClosestData closest; + bool found = false; + if (selection_domain == ATTR_DOMAIN_POINT) { + found = find_closest_point_to_screen_co(*vc.depsgraph, + vc.region, + vc.rv3d, + *vc.obact, + curves, + float2(coord), + ED_view3d_select_dist_px(), + closest); + } + else if (selection_domain == ATTR_DOMAIN_CURVE) { + found = find_closest_curve_to_screen_co(*vc.depsgraph, + vc.region, + vc.rv3d, + *vc.obact, + curves, + float2(coord), + ED_view3d_select_dist_px(), + closest); + } bool changed = false; if (params.sel_op == SEL_OP_SET) { @@ -453,17 +631,7 @@ bool select_pick(const ViewContext &vc, if (found) { bke::GSpanAttributeWriter selection = ensure_selection_attribute( curves, selection_domain, CD_PROP_BOOL); - - int elem_index = closest_point.index; - if (selection_domain == ATTR_DOMAIN_CURVE) { - /* Find the curve index for the found point. */ - auto it = std::upper_bound( - curves.offsets().begin(), curves.offsets().end(), closest_point.index); - BLI_assert(it != curves.offsets().end()); - elem_index = std::distance(curves.offsets().begin(), it) - 1; - } - - apply_selection_operation_at_index(selection.span, elem_index, params.sel_op); + apply_selection_operation_at_index(selection.span, closest.index, params.sel_op); selection.finish(); } @@ -507,13 +675,29 @@ bool select_box(const ViewContext &vc, else if (selection_domain == ATTR_DOMAIN_CURVE) { threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) { for (const int curve_i : curves_range) { - for (const int point_i : points_by_curve[curve_i]) { + if (points_by_curve.size(curve_i) == 1) { float2 pos_proj; - ED_view3d_project_float_v2_m4( - vc.region, deformation.positions[point_i], pos_proj, projection.ptr()); + ED_view3d_project_float_v2_m4(vc.region, + deformation.positions[points_by_curve[curve_i].first()], + pos_proj, + projection.ptr()); if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) { apply_selection_operation_at_index(selection.span, curve_i, sel_op); changed = true; + } + continue; + } + for (const int segment_i : points_by_curve[curve_i].drop_back(1)) { + const float3 pos1 = deformation.positions[segment_i]; + const float3 pos2 = deformation.positions[segment_i + 1]; + + float2 pos1_proj, pos2_proj; + ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr()); + ED_view3d_project_float_v2_m4(vc.region, pos2, pos2_proj, projection.ptr()); + + if (BLI_rcti_isect_segment(&rect, int2(pos1_proj), int2(pos2_proj))) { + apply_selection_operation_at_index(selection.span, curve_i, sel_op); + changed = true; break; } } @@ -569,16 +753,40 @@ bool select_lasso(const ViewContext &vc, else if (selection_domain == ATTR_DOMAIN_CURVE) { threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) { for (const int curve_i : curves_range) { - for (const int point_i : points_by_curve[curve_i]) { + if (points_by_curve.size(curve_i) == 1) { float2 pos_proj; - ED_view3d_project_float_v2_m4( - vc.region, deformation.positions[point_i], pos_proj, projection.ptr()); + ED_view3d_project_float_v2_m4(vc.region, + deformation.positions[points_by_curve[curve_i].first()], + pos_proj, + projection.ptr()); /* Check the lasso bounding box first as an optimization. */ if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) && BLI_lasso_is_point_inside( coord_array, coords.size(), int(pos_proj.x), int(pos_proj.y), IS_CLIPPED)) { apply_selection_operation_at_index(selection.span, curve_i, sel_op); changed = true; + } + continue; + } + for (const int segment_i : points_by_curve[curve_i].drop_back(1)) { + const float3 pos1 = deformation.positions[segment_i]; + const float3 pos2 = deformation.positions[segment_i + 1]; + + float2 pos1_proj, pos2_proj; + ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr()); + ED_view3d_project_float_v2_m4(vc.region, pos2, pos2_proj, projection.ptr()); + + /* Check the lasso bounding box first as an optimization. */ + if (BLI_rcti_isect_segment(&bbox, int2(pos1_proj), int2(pos2_proj)) && + BLI_lasso_is_edge_inside(coord_array, + coords.size(), + int(pos1_proj.x), + int(pos1_proj.y), + int(pos2_proj.x), + int(pos2_proj.y), + IS_CLIPPED)) { + apply_selection_operation_at_index(selection.span, curve_i, sel_op); + changed = true; break; } } @@ -629,13 +837,31 @@ bool select_circle(const ViewContext &vc, else if (selection_domain == ATTR_DOMAIN_CURVE) { threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) { for (const int curve_i : curves_range) { - for (const int point_i : points_by_curve[curve_i]) { + if (points_by_curve.size(curve_i) == 1) { float2 pos_proj; - ED_view3d_project_float_v2_m4( - vc.region, deformation.positions[point_i], pos_proj, projection.ptr()); + ED_view3d_project_float_v2_m4(vc.region, + deformation.positions[points_by_curve[curve_i].first()], + pos_proj, + projection.ptr()); if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) { apply_selection_operation_at_index(selection.span, curve_i, sel_op); changed = true; + } + continue; + } + for (const int segment_i : points_by_curve[curve_i].drop_back(1)) { + const float3 pos1 = deformation.positions[segment_i]; + const float3 pos2 = deformation.positions[segment_i + 1]; + + float2 pos1_proj, pos2_proj; + ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr()); + ED_view3d_project_float_v2_m4(vc.region, pos2, pos2_proj, projection.ptr()); + + const float distance_proj_sq = dist_squared_to_line_segment_v2( + float2(coord), pos1_proj, pos2_proj); + if (distance_proj_sq <= radius_sq) { + apply_selection_operation_at_index(selection.span, curve_i, sel_op); + changed = true; break; } } diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c index 55f7319b2f0b..436a2a676e32 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c @@ -44,6 +44,8 @@ /* The same as in `draw_cache.c` */ #define CIRCLE_RESOL 32 +static int gizmo_cage2d_transform_flag_get(const wmGizmo *gz); + static bool gizmo_calc_rect_view_scale(const wmGizmo *gz, const float dims[2], float scale[2]) { float matrix_final_no_offset[4][4]; @@ -616,7 +618,7 @@ static void gizmo_cage2d_draw_intern(wmGizmo *gz, RNA_float_get_array(gz->ptr, "dimensions", dims); float matrix_final[4][4]; - const int transform_flag = RNA_enum_get(gz->ptr, "transform"); + const int transform_flag = gizmo_cage2d_transform_flag_get(gz); const int draw_style = RNA_enum_get(gz->ptr, "draw_style"); const int draw_options = RNA_enum_get(gz->ptr, "draw_options"); @@ -831,7 +833,7 @@ static int gizmo_cage2d_test_select(bContext *C, wmGizmo *gz, const int mval[2]) /* Expand for hots-pot. */ const float size[2] = {size_real[0] + margin[0] / 2, size_real[1] + margin[1] / 2}; - const int transform_flag = RNA_enum_get(gz->ptr, "transform"); + const int transform_flag = gizmo_cage2d_transform_flag_get(gz); const int draw_options = RNA_enum_get(gz->ptr, "draw_options"); if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) { @@ -934,8 +936,21 @@ typedef struct RectTransformInteraction { float orig_matrix_offset[4][4]; float orig_matrix_final_no_offset[4][4]; Dial *dial; + bool use_temp_uniform; } RectTransformInteraction; +static int gizmo_cage2d_transform_flag_get(const wmGizmo *gz) +{ + RectTransformInteraction *data = gz->interaction_data; + int transform_flag = RNA_enum_get(gz->ptr, "transform"); + if (data) { + if (data->use_temp_uniform) { + transform_flag |= ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM; + } + } + return transform_flag; +} + static void gizmo_cage2d_setup(wmGizmo *gz) { gz->flag |= WM_GIZMO_DRAW_MODAL | WM_GIZMO_DRAW_NO_SCALE; @@ -959,55 +974,60 @@ static int gizmo_cage2d_invoke(bContext *C, wmGizmo *gz, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[2], bool r_constrain_axis[2]) +static void gizmo_constrain_from_scale_part(int part, bool r_constrain_axis[2]) +{ + r_constrain_axis[0] = (part > ED_GIZMO_CAGE2D_PART_SCALE_MAX_X && + part < ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y) ? + true : + false; + r_constrain_axis[1] = (part > ED_GIZMO_CAGE2D_PART_SCALE && + part < ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y) ? + true : + false; +} + +static void gizmo_pivot_from_scale_part(int part, float r_pt[2]) { - bool x = true, y = true; switch (part) { + case ED_GIZMO_CAGE2D_PART_SCALE: { + ARRAY_SET_ITEMS(r_pt, 0.0, 0.0); + break; + } case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X: { ARRAY_SET_ITEMS(r_pt, 0.5, 0.0); - x = false; break; } case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X: { ARRAY_SET_ITEMS(r_pt, -0.5, 0.0); - x = false; break; } case ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y: { ARRAY_SET_ITEMS(r_pt, 0.0, 0.5); - y = false; break; } case ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y: { ARRAY_SET_ITEMS(r_pt, 0.0, -0.5); - y = false; break; } case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y: { ARRAY_SET_ITEMS(r_pt, 0.5, 0.5); - x = y = false; break; } case ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y: { ARRAY_SET_ITEMS(r_pt, 0.5, -0.5); - x = y = false; break; } case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y: { ARRAY_SET_ITEMS(r_pt, -0.5, 0.5); - x = y = false; break; } case ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y: { ARRAY_SET_ITEMS(r_pt, -0.5, -0.5); - x = y = false; break; } default: BLI_assert(0); } - r_constrain_axis[0] = x; - r_constrain_axis[1] = y; } static int gizmo_cage2d_modal(bContext *C, @@ -1015,9 +1035,6 @@ static int gizmo_cage2d_modal(bContext *C, const wmEvent *event, eWM_GizmoFlagTweak UNUSED(tweak_flag)) { - if (event->type != MOUSEMOVE) { - return OPERATOR_RUNNING_MODAL; - } /* For transform logic to be manageable we operate in -0.5..0.5 2D space, * no matter the size of the rectangle, mouse coords are scaled to unit space. * The mouse coords have been projected into the matrix @@ -1027,6 +1044,25 @@ static int gizmo_cage2d_modal(bContext *C, * - Matrix translation is also multiplied by 'dims'. */ RectTransformInteraction *data = gz->interaction_data; + int transform_flag = RNA_enum_get(gz->ptr, "transform"); + if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) == 0) { + /* WARNING: Checking the events modifier only makes sense as long as `tweak_flag` + * remains unused (this controls #WM_GIZMO_TWEAK_PRECISE by default). */ + const bool use_temp_uniform = (event->modifier & KM_SHIFT) != 0; + const bool changed = data->use_temp_uniform != use_temp_uniform; + data->use_temp_uniform = data->use_temp_uniform; + if (use_temp_uniform) { + transform_flag |= ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM; + } + + if (changed) { + /* Always refresh. */ + } + else if (event->type != MOUSEMOVE) { + return OPERATOR_RUNNING_MODAL; + } + } + float point_local[2]; float dims[2]; @@ -1045,7 +1081,6 @@ static int gizmo_cage2d_modal(bContext *C, } } - const int transform_flag = RNA_enum_get(gz->ptr, "transform"); wmGizmoProperty *gz_prop; gz_prop = WM_gizmo_target_property_find(gz, "matrix"); @@ -1105,46 +1140,52 @@ static int gizmo_cage2d_modal(bContext *C, else { /* scale */ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset); - float pivot[2]; - bool constrain_axis[2] = {false}; + const int draw_style = RNA_enum_get(gz->ptr, "draw_style"); + float pivot[2]; if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) { - gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis); + gizmo_pivot_from_scale_part(gz->highlight_part, pivot); } else { zero_v2(pivot); } - /* Cursor deltas scaled to (-0.5..0.5). */ - float delta_orig[2], delta_curr[2]; - for (int i = 0; i < 2; i++) { - delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) - - pivot[i]; - delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i]; - } + bool constrain_axis[2] = {false}; + gizmo_constrain_from_scale_part(gz->highlight_part, constrain_axis); float scale[2] = {1.0f, 1.0f}; for (int i = 0; i < 2; i++) { if (constrain_axis[i] == false) { - if (delta_orig[i] < 0.0f) { - delta_orig[i] *= -1.0f; - delta_curr[i] *= -1.0f; - } - const int sign = signum_i(scale[i]); - - scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i])); + /* Original cursor position relative to pivot, remapped to [-1, 1] */ + const float delta_orig = (data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / + (dims[i] * len_v3(data->orig_matrix_offset[i])) - + pivot[i]; + const float delta_curr = (point_local[i] - data->orig_matrix_offset[3][i]) / + (dims[i] * len_v3(data->orig_matrix_offset[i])) - + pivot[i]; if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED) == 0) { - if (sign != signum_i(scale[i])) { + if (signum_i(delta_orig) != signum_i(delta_curr)) { scale[i] = 0.0f; + continue; } } + + /* Original cursor position does not exactly lie on the cage boundary due to margin. */ + const float delta_boundary = signf(delta_orig) * 0.5f - pivot[i]; + scale[i] = delta_curr / delta_boundary; } } if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM) { if (constrain_axis[0] == false && constrain_axis[1] == false) { - scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f; + if (draw_style == ED_GIZMO_CAGE2D_STYLE_CIRCLE) { + /* So that the cursor lies on the circle. */ + scale[1] = scale[0] = len_v2(scale); + } + else { + scale[1] = scale[0] = (scale[1] + scale[0]) / 2.0f; + } } else if (constrain_axis[0] == false) { scale[1] = scale[0]; diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c index 598d437e2468..7dd69f722fc2 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c @@ -88,7 +88,10 @@ static void gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[3], /* -------------------------------------------------------------------- */ -static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[3], bool r_constrain_axis[3]) +static void gizmo_rect_pivot_from_scale_part(int part, + float r_pt[3], + bool r_constrain_axis[3], + bool has_translation) { if (part >= ED_GIZMO_CAGE3D_PART_SCALE_MIN_X_MIN_Y_MIN_Z && part <= ED_GIZMO_CAGE3D_PART_SCALE_MAX_X_MAX_Y_MAX_Z) { @@ -102,7 +105,7 @@ static void gizmo_rect_pivot_from_scale_part(int part, float r_pt[3], bool r_con const float sign[3] = {0.5f, 0.0f, -0.5f}; for (int i = 0; i < 3; i++) { - r_pt[i] = sign[range[i]]; + r_pt[i] = has_translation ? sign[range[i]] : 0.0f; r_constrain_axis[i] = (range[i] == 1); } } @@ -512,41 +515,33 @@ static int gizmo_cage3d_modal(bContext *C, else { /* scale */ copy_m4_m4(gz->matrix_offset, data->orig_matrix_offset); + float pivot[3]; bool constrain_axis[3] = {false}; - - if (transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE) { - gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis); - } - else { - zero_v3(pivot); - } - - /* Cursor deltas scaled to (-0.5..0.5). */ - float delta_orig[3], delta_curr[3]; - - for (int i = 0; i < 3; i++) { - delta_orig[i] = ((data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / dims[i]) - - pivot[i]; - delta_curr[i] = ((point_local[i] - data->orig_matrix_offset[3][i]) / dims[i]) - pivot[i]; - } + bool has_translation = transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_TRANSLATE; + gizmo_rect_pivot_from_scale_part(gz->highlight_part, pivot, constrain_axis, has_translation); float scale[3] = {1.0f, 1.0f, 1.0f}; for (int i = 0; i < 3; i++) { if (constrain_axis[i] == false) { - if (delta_orig[i] < 0.0f) { - delta_orig[i] *= -1.0f; - delta_curr[i] *= -1.0f; - } - const int sign = signum_i(scale[i]); - - scale[i] = 1.0f + ((delta_curr[i] - delta_orig[i]) / len_v3(data->orig_matrix_offset[i])); + /* Original cursor position relative to pivot, remapped to [-1, 1] */ + const float delta_orig = (data->orig_mouse[i] - data->orig_matrix_offset[3][i]) / + (dims[i] * len_v3(data->orig_matrix_offset[i])) - + pivot[i]; + const float delta_curr = (point_local[i] - data->orig_matrix_offset[3][i]) / + (dims[i] * len_v3(data->orig_matrix_offset[i])) - + pivot[i]; if ((transform_flag & ED_GIZMO_CAGE_XFORM_FLAG_SCALE_SIGNED) == 0) { - if (sign != signum_i(scale[i])) { + if (signum_i(delta_orig) != signum_i(delta_curr)) { scale[i] = 0.0f; + continue; } } + + /* Original cursor position does not exactly lie on the cage boundary due to margin. */ + const float delta_boundary = signf(delta_orig) * 0.5f - pivot[i]; + scale[i] = delta_curr / delta_boundary; } } diff --git a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c index d7ae9be6c33d..bb7d4cb8b127 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c @@ -86,8 +86,7 @@ struct Dial3dParams { float arc_inner_factor; float *clip_plane; }; -static void dial_3d_draw_util(const float matrix_basis[4][4], - const float matrix_final[4][4], +static void dial_3d_draw_util(const float matrix_final[4][4], const float line_width, const float color[4], const bool select, @@ -96,7 +95,7 @@ static void dial_3d_draw_util(const float matrix_basis[4][4], static void dial_geom_draw(const float color[4], const float line_width, const bool select, - const float axis_modal_mat[4][4], + const float clip_plane_mat[4][4], const float clip_plane[4], const float arc_partial_angle, const float arc_inner_factor, @@ -118,7 +117,7 @@ static void dial_geom_draw(const float color[4], immBindBuiltinProgram(filled ? GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR : GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR); immUniform4fv("ClipPlane", clip_plane); - immUniformMatrix4fv("ModelMatrix", axis_modal_mat); + immUniformMatrix4fv("ModelMatrix", clip_plane_mat); } else { immBindBuiltinProgram(filled ? GPU_SHADER_3D_UNIFORM_COLOR : @@ -432,8 +431,7 @@ static void dial_draw_intern( } } - dial_3d_draw_util(gz->matrix_basis, - matrix_final, + dial_3d_draw_util(matrix_final, gz->line_width, color, select, @@ -613,8 +611,7 @@ static int gizmo_dial_invoke(bContext *UNUSED(C), wmGizmo *gz, const wmEvent *ev /** \name Dial Gizmo API * \{ */ -static void dial_3d_draw_util(const float matrix_basis[4][4], - const float matrix_final[4][4], +static void dial_3d_draw_util(const float matrix_final[4][4], const float line_width, const float color[4], const bool select, @@ -650,7 +647,7 @@ static void dial_3d_draw_util(const float matrix_basis[4][4], dial_geom_draw(color, line_width, select, - matrix_basis, + matrix_final, params->clip_plane, params->arc_partial_angle, params->arc_inner_factor, diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index ae09aea28d39..8021d976add1 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -279,7 +279,7 @@ static void annotation_draw_stroke_point(const bGPDspoint *points, immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); } else { - immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); /* get 2D coordinates of point */ float co[3] = {0.0f}; diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 44a3eae4072c..8526a98f0be9 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -528,7 +528,7 @@ static short annotation_stroke_addpoint(tGPsdata *p, /* store settings */ copy_v2_v2(pt->m_xy, mval); - /* T44932 - Pressure vals are unreliable, so ignore for now */ + /* Pressure values are unreliable, so ignore for now, see #44932. */ pt->pressure = 1.0f; pt->strength = 1.0f; pt->time = (float)(curtime - p->inittime); @@ -544,7 +544,7 @@ static short annotation_stroke_addpoint(tGPsdata *p, /* store settings */ copy_v2_v2(pt->m_xy, mval); - /* T44932 - Pressure vals are unreliable, so ignore for now */ + /* Pressure values are unreliable, so ignore for now, see #44932. */ pt->pressure = 1.0f; pt->strength = 1.0f; pt->time = (float)(curtime - p->inittime); @@ -620,7 +620,7 @@ static short annotation_stroke_addpoint(tGPsdata *p, /* store settings */ copy_v2_v2(pt->m_xy, mval); - /* T44932 - Pressure vals are unreliable, so ignore for now */ + /* Pressure values are unreliable, so ignore for now, see #44932. */ pt->pressure = 1.0f; pt->strength = 1.0f; pt->time = (float)(curtime - p->inittime); @@ -2064,7 +2064,7 @@ static void annotation_draw_apply_event( /* Convert from window-space to area-space mouse coordinates * add any x,y override position for fake events. */ if (p->flags & GP_PAINTFLAG_FIRSTRUN) { - /* The first run may be a drag event, see: T99368. */ + /* The first run may be a drag event, see: #99368. */ WM_event_drag_start_mval_fl(event, p->region, p->mval); p->mval[0] -= x; p->mval[1] -= y; @@ -2136,7 +2136,7 @@ static void annotation_draw_apply_event( /* Hack for pressure sensitive eraser on D+RMB when using a tablet: * The pen has to float over the tablet surface, resulting in - * zero pressure (T47101). Ignore pressure values if floating + * zero pressure (#47101). Ignore pressure values if floating * (i.e. "effectively zero" pressure), and only when the "active" * end is the stylus (i.e. the default when not eraser) */ @@ -2357,7 +2357,7 @@ static tGPsdata *annotation_stroke_begin(bContext *C, wmOperator *op) tGPsdata *p = op->customdata; /* we must check that we're still within the area that we're set up to work from - * otherwise we could crash (see bug T20586) + * otherwise we could crash (see bug #20586) */ if (CTX_wm_area(C) != p->area) { printf("\t\t\tGP - wrong area execution abort!\n"); @@ -2466,7 +2466,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve EVT_UPARROWKEY, EVT_ZKEY)) { /* allow some keys: - * - For frame changing T33412. + * - For frame changing #33412. * - For undo (during sketching sessions). */ } @@ -2503,7 +2503,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve /* Exit painting mode (and/or end current stroke) * * NOTE: cannot do RIGHTMOUSE (as is standard for canceling) - * as that would break polyline T32647. + * as that would break polyline #32647. */ if (event->val == KM_PRESS && ELEM(event->type, EVT_RETKEY, EVT_PADENTER, EVT_ESCKEY, EVT_SPACEKEY, EVT_EKEY)) { @@ -2516,7 +2516,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox * only) * - RIGHTMOUSE = polyline (hotkey) / eraser (all) - * (Disabling RIGHTMOUSE case here results in bugs like T32647) + * (Disabling RIGHTMOUSE case here results in bugs like #32647) * also making sure we have a valid event value, to not exit too early */ if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && ELEM(event->val, KM_PRESS, KM_RELEASE)) { @@ -2704,7 +2704,7 @@ static int annotation_draw_modal(bContext *C, wmOperator *op, const wmEvent *eve else { /* update status indicators - cursor, header, etc. */ annotation_draw_status_indicators(C, p); - /* cursor may have changed outside our control - T44084 */ + /* cursor may have changed outside our control - #44084 */ annotation_draw_cursor_set(p); } diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 24de50db397c..7041dd25750a 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -188,7 +188,7 @@ static void gpencil_draw_stroke_3d(tGPDdraw *tgpw, int keep_size = (int)((tgpw->gpd) && (tgpw->gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS)); gpencil_stroke_data.keep_size = keep_size; gpencil_stroke_data.pixfactor = tgpw->gpd->pixfactor; - /* xray mode always to 3D space to avoid wrong zdepth calculation (T60051) */ + /* xray mode always to 3D space to avoid wrong zdepth calculation (#60051) */ gpencil_stroke_data.xraymode = GP_XRAY_3DSPACE; gpencil_stroke_data.caps_start = tgpw->gps->caps[0]; gpencil_stroke_data.caps_end = tgpw->gps->caps[1]; diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index 2b7e09b7f052..664988d395c4 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -207,7 +207,7 @@ static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap) defgroup = BKE_object_defgroup_add_name(ob, bone->name); } else if (defgroup->flag & DG_LOCK_WEIGHT) { - /* In case vgroup already exists and is locked, do not modify it here. See T43814. */ + /* In case vgroup already exists and is locked, do not modify it here. See #43814. */ defgroup = NULL; } } diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 17ec33dc2bd3..5cea5cc0780d 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -1208,7 +1208,7 @@ static void gpencil_stroke_norm_curve_weights(Curve *cu, const float minmax_weig { const float delta = minmax_weights[0]; - /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero T35686. */ + /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero #35686. */ float fac; if (IS_EQF(delta, minmax_weights[1])) { fac = 1.0f; diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index c6108f761a82..6ede47268219 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -4059,12 +4059,11 @@ void GPENCIL_OT_reproject(wmOperatorType *ot) ot->prop = RNA_def_enum( ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", ""); - prop = RNA_def_boolean( - ot->srna, - "keep_original", - 0, - "Keep Original", - "Keep original strokes and create a copy before reprojecting instead of reproject them"); + prop = RNA_def_boolean(ot->srna, + "keep_original", + 0, + "Keep Original", + "Keep original strokes and create a copy before reprojecting"); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP); RNA_def_float(ot->srna, "offset", 0.0f, 0.0f, 10.0f, "Surface Offset", "", 0.0f, 10.0f); @@ -4771,7 +4770,7 @@ void GPENCIL_OT_stroke_simplify(wmOperatorType *ot) /* identifiers */ ot->name = "Simplify Stroke"; ot->idname = "GPENCIL_OT_stroke_simplify"; - ot->description = "Simplify selected stroked reducing number of points"; + ot->description = "Simplify selected strokes, reducing number of points"; /* api callbacks */ ot->exec = gpencil_stroke_simplify_exec; @@ -4832,7 +4831,7 @@ void GPENCIL_OT_stroke_simplify_fixed(wmOperatorType *ot) /* identifiers */ ot->name = "Simplify Fixed Stroke"; ot->idname = "GPENCIL_OT_stroke_simplify_fixed"; - ot->description = "Simplify selected stroked reducing number of points using fixed algorithm"; + ot->description = "Simplify selected strokes, reducing number of points using fixed algorithm"; /* api callbacks */ ot->exec = gpencil_stroke_simplify_fixed_exec; diff --git a/source/blender/editors/gpencil/gpencil_edit_curve.c b/source/blender/editors/gpencil/gpencil_edit_curve.c index b669168aea76..cf29ce0755b9 100644 --- a/source/blender/editors/gpencil/gpencil_edit_curve.c +++ b/source/blender/editors/gpencil/gpencil_edit_curve.c @@ -188,7 +188,7 @@ void GPENCIL_OT_stroke_editcurve_set_handle_type(wmOperatorType *ot) /* identifiers */ ot->name = "Set handle type"; ot->idname = "GPENCIL_OT_stroke_editcurve_set_handle_type"; - ot->description = "Set the type of a edit curve handle"; + ot->description = "Set the type of an edit curve handle"; /* api callbacks */ ot->invoke = WM_menu_invoke; diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 0401fdfc963d..20e9cc32c691 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -917,6 +917,7 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, const bool is_line_mode = (tgpf->fill_extend_mode == GP_FILL_EMODE_EXTEND); const bool use_stroke_collide = (tgpf->flag & GP_BRUSH_FILL_STROKE_COLLIDE) != 0; const bool stroke_collide = (gps->flag & GP_STROKE_COLLIDE) != 0; + bool circle_contact = false; if (!gpencil_stroke_is_drawable(tgpf, gps)) { return; @@ -933,7 +934,11 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, /* If there is contact, hide the circles to avoid noise and keep the focus * in the pending gaps. */ - col[3] = (gps->flag & GP_STROKE_TAG) ? 0.0f : 0.5f; + col[3] = 0.5f; + if (gps->flag & GP_STROKE_TAG) { + circle_contact = true; + col[3] = 0.0f; + } } else if ((is_extend) && (!tgpf->is_render)) { if (stroke_collide || !use_stroke_collide || !is_line_mode) { @@ -962,14 +967,16 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, for (int i = 0; i < totpoints; i++, pt++) { - /* This flag is inverted in the UI. */ - if ((flag & GP_BRUSH_FILL_HIDE) == 0) { - float alpha = gp_style->stroke_rgba[3] * pt->strength; - CLAMP(alpha, 0.0f, 1.0f); - col[3] = alpha <= thershold ? 0.0f : 1.0f; - } - else if (!is_help) { - col[3] = 1.0f; + if (!circle_contact) { + /* This flag is inverted in the UI. */ + if ((flag & GP_BRUSH_FILL_HIDE) == 0) { + float alpha = gp_style->stroke_rgba[3] * pt->strength; + CLAMP(alpha, 0.0f, 1.0f); + col[3] = alpha <= thershold ? 0.0f : 1.0f; + } + else if (!is_help) { + col[3] = 1.0f; + } } /* set point */ immAttr4fv(color, col); @@ -993,23 +1000,25 @@ static void draw_mouse_position(tGPDfill *tgpf) if (tgpf->gps_mouse == NULL) { return; } - uchar mouse_color[4] = {0, 0, 255, 255}; bGPDspoint *pt = &tgpf->gps_mouse->points[0]; float point_size = (tgpf->zoom == 1.0f) ? 4.0f * tgpf->fill_factor : (0.5f * tgpf->zoom) + tgpf->fill_factor; GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); /* Draw mouse click position in Blue. */ - immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); - GPU_point_size(point_size); + GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); immBegin(GPU_PRIM_POINTS, 1); - immAttr4ubv(col, mouse_color); + immAttr1f(size, point_size * M_SQRT2); + immAttr4f(color, 0.0f, 0.0f, 1.0f, 1.0f); immVertex3fv(pos, &pt->x); immEnd(); immUnbindProgram(); + GPU_program_point_size(false); } /* Helper: Check if must skip the layer */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 5814248f24c2..669b09ed279d 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -764,7 +764,7 @@ static short gpencil_stroke_addpoint(tGPsdata *p, /* store settings */ copy_v2_v2(pt->m_xy, mval); - /* T44932 - Pressure vals are unreliable, so ignore for now */ + /* Pressure values are unreliable, so ignore for now, see #44932. */ pt->pressure = 1.0f; pt->strength = 1.0f; pt->time = (float)(curtime - p->inittime); @@ -780,7 +780,7 @@ static short gpencil_stroke_addpoint(tGPsdata *p, /* store settings */ copy_v2_v2(pt->m_xy, mval); - /* T44932 - Pressure vals are unreliable, so ignore for now */ + /* Pressure values are unreliable, so ignore for now, see #44932. */ pt->pressure = 1.0f; pt->strength = 1.0f; pt->time = (float)(curtime - p->inittime); @@ -2935,7 +2935,7 @@ static void gpencil_draw_apply_event(bContext *C, /* Hack for pressure sensitive eraser on D+RMB when using a tablet: * The pen has to float over the tablet surface, resulting in - * zero pressure (T47101). Ignore pressure values if floating + * zero pressure (#47101). Ignore pressure values if floating * (i.e. "effectively zero" pressure), and only when the "active" * end is the stylus (i.e. the default when not eraser) */ @@ -3343,7 +3343,7 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) tGPsdata *p = op->customdata; /* we must check that we're still within the area that we're set up to work from - * otherwise we could crash (see bug T20586) + * otherwise we could crash (see bug #20586) */ if (CTX_wm_area(C) != p->area) { printf("\t\t\tGP - wrong area execution abort!\n"); @@ -3685,11 +3685,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* We don't pass on key events, GP is used with key-modifiers - - * prevents Dkey to insert drivers. */ + * prevents D-key to insert drivers. */ if (ISKEYBOARD(event->type)) { if (ELEM(event->type, EVT_LEFTARROWKEY, EVT_DOWNARROWKEY, EVT_RIGHTARROWKEY, EVT_UPARROWKEY)) { /* allow some keys: - * - For frame changing T33412. + * - For frame changing #33412. * - For undo (during sketching sessions). */ } @@ -3735,7 +3735,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* toggle painting mode upon mouse-button movement * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) * - RIGHTMOUSE = eraser (all) - * (Disabling RIGHTMOUSE case here results in bugs like T32647) + * (Disabling RIGHTMOUSE case here results in bugs like #32647) * also making sure we have a valid event value, to not exit too early */ if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && ELEM(event->val, KM_PRESS, KM_RELEASE)) { diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 0b11d6bf2ba4..05718eb95e09 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -2487,7 +2487,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) /* check if point is inside */ if (pt_distance <= radius_squared) { - /* only use this point if it is a better match than the current hit - T44685 */ + /* only use this point if it is a better match than the current hit - #44685 */ if (pt_distance < hit_distance) { hit_layer = gpl; hit_stroke = gps_active; diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index 84512653a24e..931e0c105750 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -34,7 +34,7 @@ typedef struct IMMDrawPixelsTexState { * To be used before calling #immDrawPixelsTex * Default shader is #GPU_SHADER_2D_IMAGE_COLOR * You can still set uniforms with: - * `GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0);` + * `GPU_shader_uniform_*(shader, "name", value);` */ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin); diff --git a/source/blender/editors/include/ED_curves.h b/source/blender/editors/include/ED_curves.h index aee355c3769a..178ec7a5b19b 100644 --- a/source/blender/editors/include/ED_curves.h +++ b/source/blender/editors/include/ED_curves.h @@ -111,8 +111,8 @@ IndexMask retrieve_selected_points(const Curves &curves_id, Vector &r_i * If the ".selection" attribute doesn't exist, create it with the requested type (bool or float). */ bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves, - const eAttrDomain selection_domain, - const eCustomDataType create_type); + eAttrDomain selection_domain, + eCustomDataType create_type); /** * (De)select all the curves. @@ -120,7 +120,7 @@ bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves * \param action: One of SEL_TOGGLE, SEL_SELECT, SEL_DESELECT, or SEL_INVERT. See * "ED_select_utils.h". */ -void select_all(bke::CurvesGeometry &curves, const eAttrDomain selection_domain, int action); +void select_all(bke::CurvesGeometry &curves, eAttrDomain selection_domain, int action); /** * Select the ends (front or back) of all the curves. @@ -135,6 +135,11 @@ void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points); */ void select_linked(bke::CurvesGeometry &curves); +/** + * (De)select all the adjacent points of the current selected points. + */ +void select_adjacent(bke::CurvesGeometry &curves, bool deselect); + /** * Select random points or curves. * @@ -143,7 +148,7 @@ void select_linked(bke::CurvesGeometry &curves); * will be selected, if set to 1.0 everything will be selected. */ void select_random(bke::CurvesGeometry &curves, - const eAttrDomain selection_domain, + eAttrDomain selection_domain, uint32_t random_seed, float probability); @@ -152,18 +157,18 @@ void select_random(bke::CurvesGeometry &curves, */ bool select_pick(const ViewContext &vc, bke::CurvesGeometry &curves, - const eAttrDomain selection_domain, + eAttrDomain selection_domain, const SelectPick_Params ¶ms, - const int2 coord); + int2 coord); /** * Select points or curves in a (screen-space) rectangle. */ bool select_box(const ViewContext &vc, bke::CurvesGeometry &curves, - const eAttrDomain selection_domain, + eAttrDomain selection_domain, const rcti &rect, - const eSelectOp sel_op); + eSelectOp sel_op); /** * Select points or curves in a (screen-space) poly shape. @@ -185,5 +190,17 @@ bool select_circle(const ViewContext &vc, eSelectOp sel_op); /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Editing + * \{ */ + +/** + * Remove (dissolve) selected curves or points based on the ".selection" attribute. + * \returns true if any point or curve was removed. + */ +bool remove_selection(bke::CurvesGeometry &curves, eAttrDomain selection_domain); + +/** \} */ + } // namespace blender::ed::curves #endif diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index d4470c017bd5..df6fe03bf053 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -150,6 +150,22 @@ struct ID *ED_fileselect_active_asset_get(const struct SpaceFile *sfile); void ED_fileselect_activate_asset_catalog(const struct SpaceFile *sfile, bUUID catalog_id); +/** + * Resolve this space's #eFileAssetImportMethod to the #eAssetImportMethod (note the different + * type) to be used for the actual import of a specific asset. + * - If the asset system dictates a certain import method, this will be returned. + * - If the Asset Browser is set to follow the Preferences (#FILE_ASSET_IMPORT_FOLLOW_PREFS), the + * asset system determines the import method (which is the default from the Preferences). -1 is + * returned if the asset system doesn't specify a method (e.g. because the asset library doesn't + * come from the Preferences). + * - Otherwise, the Asset Browser determines (possibly overrides) the import method. + * + * \return -1 on error, for example when #FILE_ASSET_IMPORT_FOLLOW_PREFS was requested but the + * active asset library reference couldn't be found in the preferences. + */ +int /* #eAssetImportMethod */ ED_fileselect_asset_import_method_get( + const struct SpaceFile *sfile, const struct FileDirEntry *file); + /** * Activate and select the file that corresponds to the given ID. * Pass deferred=true to wait for the next refresh before activating. @@ -192,7 +208,7 @@ void ED_file_read_bookmarks(void); /** * Support updating the directory even when this isn't the active space - * needed so RNA properties update function isn't context sensitive, see T70255. + * needed so RNA properties update function isn't context sensitive, see #70255. */ void ED_file_change_dir_ex(struct bContext *C, struct ScrArea *area); void ED_file_change_dir(struct bContext *C); diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index a53042b70d6a..5d779095d4e4 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -79,7 +79,7 @@ struct FCurve *ED_action_fcurve_find(struct bAction *act, const char rna_path[], * \brief Lesser Key-framing API call. * * Update integer/discrete flags of the FCurve (used when creating/inserting keyframes, - * but also through RNA when editing an ID prop, see T37103). + * but also through RNA when editing an ID prop, see #37103). */ void update_autoflags_fcurve(struct FCurve *fcu, struct bContext *C, diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 248ce8ec6b54..cfb715646711 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -88,7 +88,7 @@ void EDBM_mesh_make(struct Object *ob, int select_mode, bool add_key_index); void EDBM_mesh_free_data(struct BMEditMesh *em); /** * \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates). - * Most callers should run #DEG_id_tag_update on `ob->data`, see: T46738, T46913. + * Most callers should run #DEG_id_tag_update on `ob->data`, see: #46738, #46913. * This ensures #BKE_object_free_derived_caches runs on all objects that use this mesh. */ void EDBM_mesh_load_ex(struct Main *bmain, struct Object *ob, bool free_data); diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h index 39bbd8adc754..3308391cca48 100644 --- a/source/blender/editors/include/ED_undo.h +++ b/source/blender/editors/include/ED_undo.h @@ -68,7 +68,7 @@ bool ED_undo_is_memfile_compatible(const struct bContext *C); * This is to avoid changes to a property making undo pushes * which are ignored by the undo-system. * For example, changing a brush property isn't stored by sculpt-mode undo steps. - * This workaround is needed until the limitation is removed, see: T61948. + * This workaround is needed until the limitation is removed, see: #61948. */ bool ED_undo_is_legacy_compatible_for_property(struct bContext *C, struct ID *id); @@ -120,7 +120,7 @@ struct MemFile *ED_undosys_stack_memfile_get_active(struct UndoStack *ustack); * with memfile ones, this has to be called manually by relevant undo code. * * \note Only current known case for this is undoing a switch from Object to Sculpt mode (see - * T82388). + * #82388). * * \note Calling this ID by ID is not optimal, as it will loop over all #MemFile.chunks until it * finds the expected one. If this becomes an issue we'll have to add a mapping from session UUID diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 349975e11819..3337fb3c1d16 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -86,7 +86,6 @@ bool ED_uvedit_test(struct Object *obedit); /* Visibility and selection tests. */ -bool uvedit_face_visible_test_ex(const struct ToolSettings *ts, struct BMFace *efa); bool uvedit_face_select_test_ex(const struct ToolSettings *ts, struct BMFace *efa, BMUVOffsets offsets); @@ -194,30 +193,6 @@ void uvedit_uv_select_set_with_sticky(const struct Scene *scene, bool do_history, BMUVOffsets offsets); -/* Low level functions for sticky element selection (sticky mode independent). Type of sticky - * selection is specified explicitly (using sticky_flag, except for face selection). */ - -void uvedit_face_select_shared_vert(const struct Scene *scene, - struct BMEditMesh *em, - struct BMFace *efa, - const bool select, - const bool do_history, - BMUVOffsets offsets); -void uvedit_edge_select_shared_vert(const struct Scene *scene, - struct BMEditMesh *em, - struct BMLoop *l, - const bool select, - const int sticky_flag, - const bool do_history, - BMUVOffsets offsets); -void uvedit_uv_select_shared_vert(const struct Scene *scene, - struct BMEditMesh *em, - struct BMLoop *l, - const bool select, - const int sticky_flag, - const bool do_history, - BMUVOffsets offsets); - /* Sets required UV edge flags as specified by the sticky_flag. */ void uvedit_edge_select_set_noflush(const struct Scene *scene, struct BMLoop *l, @@ -259,19 +234,6 @@ bool ED_uvedit_nearest_uv_multi(const struct View2D *v2d, float *dist_sq, float r_uv[2]); -struct BMFace **ED_uvedit_selected_faces(const struct Scene *scene, - struct BMesh *bm, - int len_max, - int *r_faces_len); -struct BMLoop **ED_uvedit_selected_edges(const struct Scene *scene, - struct BMesh *bm, - int len_max, - int *r_edges_len); -struct BMLoop **ED_uvedit_selected_verts(const struct Scene *scene, - struct BMesh *bm, - int len_max, - int *r_verts_len); - void ED_uvedit_get_aspect(struct Object *obedit, float *r_aspx, float *r_aspy); /** diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 57939bd1f465..dc3951ab770b 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -245,7 +245,7 @@ typedef enum { * Clamp the edge within the viewport limits defined by * #V3D_PROJ_TEST_CLIP_WIN, #V3D_PROJ_TEST_CLIP_NEAR & #V3D_PROJ_TEST_CLIP_FAR. * This resolves the problem of a visible edge having one of it's vertices - * behind the viewport. See: T32214. + * behind the viewport. See: #32214. * * This is not default behavior as it may be important for the screen-space location * of an edges vertex to represent that vertices location (instead of a location along the edge). @@ -760,7 +760,7 @@ bool ED_view3d_viewplane_get(struct Depsgraph *depsgraph, float *r_pixsize); /** - * Use instead of: `GPU_polygon_offset(rv3d->dist, ...)` see bug T37727. + * Use instead of: `GPU_polygon_offset(rv3d->dist, ...)` see bug #37727. */ void ED_view3d_polygon_offset(const struct RegionView3D *rv3d, float dist); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index cf2c0ea2ebb1..161179370003 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -239,6 +239,17 @@ enum { UI_BUT_OVERRIDDEN = 1u << 31u, }; +/** #uiBut.dragflag */ +enum { + /** By default only the left part of a button triggers dragging. A questionable design to make + * the icon but not other parts of the button draggable. Set this flag so the entire button can + * be dragged. */ + UI_BUT_DRAG_FULL_BUT = (1 << 0), + + /* --- Internal flags. --- */ + UI_BUT_DRAGPOIN_FREE = (1 << 1), +}; + /* Default font size for normal text. */ #define UI_DEFAULT_TEXT_POINTS 11.0f @@ -881,6 +892,9 @@ bool UI_but_flag_is_set(uiBut *but, int flag); void UI_but_drawflag_enable(uiBut *but, int flag); void UI_but_drawflag_disable(uiBut *but, int flag); +void UI_but_dragflag_enable(uiBut *but, int flag); +void UI_but_dragflag_disable(uiBut *but, int flag); + void UI_but_disable(uiBut *but, const char *disabled_hint); void UI_but_type_set_menu_from_pulldown(uiBut *but); @@ -903,7 +917,7 @@ bool UI_but_active_only(const struct bContext *C, uiBut *but); /** * \warning This must run after other handlers have been added, - * otherwise the handler won't be removed, see: T71112. + * otherwise the handler won't be removed, see: #71112. */ bool UI_block_active_only_flagged_buttons(const struct bContext *C, struct ARegion *region, @@ -1789,15 +1803,18 @@ void UI_but_drag_set_id(uiBut *but, struct ID *id); /** * Set an image to display while dragging. This works for any drag type (`WM_DRAG_XXX`). * Not to be confused with #UI_but_drag_set_image(), which sets up dragging of an image. + * + * Sets #UI_BUT_DRAG_FULL_BUT so the full button can be dragged. */ void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, float scale); /** + * Sets #UI_BUT_DRAG_FULL_BUT so the full button can be dragged. * \param asset: May be passed from a temporary variable, drag data only stores a copy of this. */ void UI_but_drag_set_asset(uiBut *but, const struct AssetHandle *asset, const char *path, - int import_type, /* eFileAssetImportType */ + int import_type, /* eAssetImportType */ int icon, struct ImBuf *imb, float scale); @@ -1808,6 +1825,8 @@ void UI_but_drag_set_name(uiBut *but, const char *name); * Value from button itself. */ void UI_but_drag_set_value(uiBut *but); + +/** Sets #UI_BUT_DRAG_FULL_BUT so the full button can be dragged. */ void UI_but_drag_set_image( uiBut *but, const char *path, int icon, struct ImBuf *imb, float scale, bool use_free); @@ -3061,7 +3080,7 @@ int UI_fontstyle_string_width(const struct uiFontStyle *fs, * only applying scale when drawing. This causes problems for fonts since kerning at * smaller sizes often makes them wider than a scaled down version of the larger text. * Resolve this by calculating the text at the on-screen size, - * returning the result scaled back to 1:1. See T92361. + * returning the result scaled back to 1:1. See #92361. */ int UI_fontstyle_string_width_with_block_aspect(const struct uiFontStyle *fs, const char *str, diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 9a46728097c8..9023f1662abb 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -236,6 +236,7 @@ typedef enum ThemeColorID { TH_PATH_KEYFRAME_BEFORE, TH_PATH_KEYFRAME_AFTER, TH_CAMERA_PATH, + TH_CAMERA_PASSEPARTOUT, TH_LOCK_MARKER, TH_STITCH_PREVIEW_FACE, diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_color.cc b/source/blender/editors/interface/eyedroppers/eyedropper_color.cc index 94200e0ab4c9..b051adc6c71d 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_color.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_color.cc @@ -501,7 +501,7 @@ static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent * /*even /* init */ if (eyedropper_init(C, op)) { wmWindow *win = CTX_wm_window(C); - /* Workaround for de-activating the button clearing the cursor, see T76794 */ + /* Workaround for de-activating the button clearing the cursor, see #76794 */ UI_context_active_but_clear(C, win, CTX_wm_region(C)); WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_colorband.cc b/source/blender/editors/interface/eyedroppers/eyedropper_colorband.cc index 0f0155529c9c..3b92d2d4cb33 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_colorband.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_colorband.cc @@ -286,7 +286,7 @@ static int eyedropper_colorband_invoke(bContext *C, wmOperator *op, const wmEven /* init */ if (eyedropper_colorband_init(C, op)) { wmWindow *win = CTX_wm_window(C); - /* Workaround for de-activating the button clearing the cursor, see T76794 */ + /* Workaround for de-activating the button clearing the cursor, see #76794 */ UI_context_active_but_clear(C, win, CTX_wm_region(C)); WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_datablock.cc b/source/blender/editors/interface/eyedroppers/eyedropper_datablock.cc index 81b8ca961702..db03a1e3301e 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_datablock.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_datablock.cc @@ -307,7 +307,7 @@ static int datadropper_invoke(bContext *C, wmOperator *op, const wmEvent * /*eve /* init */ if (datadropper_init(C, op)) { wmWindow *win = CTX_wm_window(C); - /* Workaround for de-activating the button clearing the cursor, see T76794 */ + /* Workaround for de-activating the button clearing the cursor, see #76794 */ UI_context_active_but_clear(C, win, CTX_wm_region(C)); WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_depth.cc b/source/blender/editors/interface/eyedroppers/eyedropper_depth.cc index c026f3669ea9..50c85aae494f 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_depth.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_depth.cc @@ -302,7 +302,7 @@ static int depthdropper_invoke(bContext *C, wmOperator *op, const wmEvent * /*ev /* init */ if (depthdropper_init(C, op)) { wmWindow *win = CTX_wm_window(C); - /* Workaround for de-activating the button clearing the cursor, see T76794 */ + /* Workaround for de-activating the button clearing the cursor, see #76794 */ UI_context_active_but_clear(C, win, CTX_wm_region(C)); WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_driver.cc b/source/blender/editors/interface/eyedroppers/eyedropper_driver.cc index b5245fae2a99..9c2510056d16 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_driver.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_driver.cc @@ -161,7 +161,7 @@ static int driverdropper_invoke(bContext *C, wmOperator *op, const wmEvent * /*e /* init */ if (driverdropper_init(C, op)) { wmWindow *win = CTX_wm_window(C); - /* Workaround for de-activating the button clearing the cursor, see T76794 */ + /* Workaround for de-activating the button clearing the cursor, see #76794 */ UI_context_active_but_clear(C, win, CTX_wm_region(C)); WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.cc b/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.cc index ca54fbc15c4c..0c33b9034ada 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.cc @@ -49,12 +49,17 @@ #include "eyedropper_intern.hh" #include "interface_intern.hh" +typedef enum eGP_EyeMode { + GP_EYE_MATERIAL = 0, + GP_EYE_PALETTE = 1, +} eGP_EyeMode; + struct EyedropperGPencil { struct ColorManagedDisplay *display; /** color under cursor RGB */ float color[3]; /** Mode */ - int mode; + eGP_EyeMode mode; }; /* Helper: Draw status message while the user is running the operator */ @@ -79,7 +84,7 @@ static bool eyedropper_gpencil_init(bContext *C, wmOperator *op) display_device = scene->display_settings.display_device; eye->display = IMB_colormanagement_display_get_named(display_device); - eye->mode = RNA_enum_get(op->ptr, "mode"); + eye->mode = (eGP_EyeMode)RNA_enum_get(op->ptr, "mode"); return true; } @@ -228,10 +233,10 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed float col_conv[4]; - /* Convert from linear rgb space to display space because grease pencil colors are in display + /* Convert from linear rgb space to display space because palette colors are in display * space, and this conversion is needed to undo the conversion to linear performed by * eyedropper_color_sample_fl. */ - if (eye->display) { + if ((eye->display) && (eye->mode == GP_EYE_PALETTE)) { copy_v3_v3(col_conv, eye->color); IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display); } @@ -240,7 +245,7 @@ static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, Eyed } /* Add material or Palette color. */ - if (eye->mode == 0) { + if (eye->mode == GP_EYE_MATERIAL) { eyedropper_add_material(C, col_conv, only_stroke, only_fill, both); } else { @@ -348,8 +353,8 @@ static bool eyedropper_gpencil_poll(bContext *C) void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot) { static const EnumPropertyItem items_mode[] = { - {0, "MATERIAL", 0, "Material", ""}, - {1, "PALETTE", 0, "Palette", ""}, + {GP_EYE_MATERIAL, "MATERIAL", 0, "Material", ""}, + {GP_EYE_PALETTE, "PALETTE", 0, "Palette", ""}, {0, nullptr, 0, nullptr, nullptr}, }; @@ -369,5 +374,5 @@ void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot) ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; /* properties */ - ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, 0, "Mode", ""); + ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, GP_EYE_MATERIAL, "Mode", ""); } diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc index 583fbf7e3a69..652750dc5317 100644 --- a/source/blender/editors/interface/interface.cc +++ b/source/blender/editors/interface/interface.cc @@ -572,7 +572,7 @@ static void ui_block_bounds_calc_popup( /* If given, adjust input coordinates such that they would generate real final popup position. * Needed to handle correctly floating panels once they have been dragged around, - * see T52999. */ + * see #52999. */ if (r_xy) { r_xy[0] = xy[0] + block->rect.xmin - raw_x; r_xy[1] = xy[1] + block->rect.ymin - raw_y; @@ -685,7 +685,7 @@ static int ui_but_calc_float_precision(uiBut *but, double value) int prec = int(ui_but_get_float_precision(but)); /* first check for various special cases: - * * If button is radians, we want additional precision (see T39861). + * * If button is radians, we want additional precision (see #39861). * * If prec is not set, we fallback to a simple default */ if (ui_but_is_unit_radians(but) && prec < 5) { prec = 5; @@ -886,7 +886,7 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but) } /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position - * when scrolling without moving mouse (see T28432) */ + * when scrolling without moving mouse (see #28432) */ if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { oldbut->hardmax = but->hardmax; } @@ -1063,7 +1063,7 @@ bool UI_but_active_only(const bContext *C, ARegion *region, uiBlock *block, uiBu bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *region, uiBlock *block) { /* Running this command before end-block has run, means buttons that open menus - * won't have those menus correctly positioned, see T83539. */ + * won't have those menus correctly positioned, see #83539. */ BLI_assert(block->endblock); bool done = false; @@ -2130,7 +2130,7 @@ void UI_block_draw(const bContext *C, uiBlock *block) } /* XXX: figure out why invalid coordinates happen when closing render window */ - /* and material preview is redrawn in main window (temp fix for bug T23848) */ + /* and material preview is redrawn in main window (temp fix for bug #23848) */ if (rect.xmin < rect.xmax && rect.ymin < rect.ymax) { ui_draw_but(C, region, &style, but, &rect); } @@ -4224,6 +4224,10 @@ static uiBut *ui_def_but(uiBlock *block, but->flag |= UI_BUT_UNDO; } + if (ELEM(but->type, UI_BTYPE_COLOR)) { + but->dragflag |= UI_BUT_DRAG_FULL_BUT; + } + BLI_addtail(&block->buttons, but); if (block->curlayout) { @@ -4287,6 +4291,7 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p int totitems = 0; int categories = 0; int entries_nosepr_count = 0; + bool has_item_with_icon = false; for (const EnumPropertyItem *item = item_array; item->identifier; item++, totitems++) { if (!item->identifier[0]) { /* inconsistent, but menus with categories do not look good flipped */ @@ -4298,6 +4303,9 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p /* We do not want simple separators in `entries_nosepr_count`. */ continue; } + if (item->icon) { + has_item_with_icon = true; + } entries_nosepr_count++; } @@ -4402,11 +4410,18 @@ static void ui_def_but_rna__menu(bContext * /*C*/, uiLayout *layout, void *but_p uiItemS(column); } else { - if (item->icon) { + int icon = item->icon; + /* Use blank icon if there is none for this item (but for some other one) to make sure labels + * align. */ + if (icon == ICON_NONE && has_item_with_icon) { + icon = ICON_BLANK1; + } + + if (icon) { uiDefIconTextButI(block, UI_BTYPE_BUT_MENU, B_NOP, - item->icon, + icon, item->name, 0, 0, @@ -4690,7 +4705,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, } else if (type == UI_BTYPE_SEARCH_MENU) { if (proptype == PROP_POINTER) { - /* Search buttons normally don't get undo, see: T54580. */ + /* Search buttons normally don't get undo, see: #54580. */ but->flag |= UI_BUT_UNDO; } } @@ -5879,6 +5894,16 @@ void UI_but_drawflag_disable(uiBut *but, int flag) but->drawflag &= ~flag; } +void UI_but_dragflag_enable(uiBut *but, int flag) +{ + but->dragflag |= flag; +} + +void UI_but_dragflag_disable(uiBut *but, int flag) +{ + but->dragflag &= ~flag; +} + void UI_but_disable(uiBut *but, const char *disabled_hint) { UI_but_flag_enable(but, UI_BUT_DISABLED); @@ -6272,7 +6297,7 @@ void UI_but_func_search_set(uiBut *but, if (search_exec_fn) { #ifdef DEBUG if (but->func) { - /* watch this, can be cause of much confusion, see: T47691 */ + /* watch this, can be cause of much confusion, see: #47691 */ printf("%s: warning, overwriting button callback with search function callback!\n", __func__); } diff --git a/source/blender/editors/interface/interface_align.cc b/source/blender/editors/interface/interface_align.cc index 2f7d4fc68ea3..4ae92e38842d 100644 --- a/source/blender/editors/interface/interface_align.cc +++ b/source/blender/editors/interface/interface_align.cc @@ -396,7 +396,7 @@ void ui_block_align_calc(uiBlock *block, const ARegion *region) /* Note that this is typically less than ~20, and almost always under ~100. * Even so, we can't ensure this value won't exceed available stack memory. - * Fallback to allocation instead of using #alloca, see: T78636. */ + * Fallback to allocation instead of using #alloca, see: #78636. */ ButAlign butal_array_buf[256]; if (num_buttons <= ARRAY_SIZE(butal_array_buf)) { butal_array = butal_array_buf; @@ -537,7 +537,7 @@ static bool buts_are_horiz(uiBut *but1, uiBut *but2) float dx, dy; /* simple case which can fail if buttons shift apart - * with proportional layouts, see: T38602. */ + * with proportional layouts, see: #38602. */ if ((but1->rect.ymin == but2->rect.ymin) && (but1->rect.xmin != but2->rect.xmin)) { return true; } diff --git a/source/blender/editors/interface/interface_anim.cc b/source/blender/editors/interface/interface_anim.cc index 877f2a2af82c..e4263b7fc51d 100644 --- a/source/blender/editors/interface/interface_anim.cc +++ b/source/blender/editors/interface/interface_anim.cc @@ -85,7 +85,7 @@ void ui_but_anim_flag(uiBut *but, const AnimationEvalContext *anim_eval_context) but->flag |= UI_BUT_ANIMATED; - /* T41525 - When the active action is a NLA strip being edited, + /* #41525 - When the active action is a NLA strip being edited, * we need to correct the frame number to "look inside" the * remapped action */ diff --git a/source/blender/editors/interface/interface_context_menu.cc b/source/blender/editors/interface/interface_context_menu.cc index fb6213e13ab1..0d697cb268fa 100644 --- a/source/blender/editors/interface/interface_context_menu.cc +++ b/source/blender/editors/interface/interface_context_menu.cc @@ -44,7 +44,7 @@ #include "WM_types.h" /* This hack is needed because we don't have a good way to - * re-reference keymap items once added: T42944 */ + * re-reference keymap items once added: #42944 */ #define USE_KEYMAP_ADD_HACK /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/interface/interface_drag.cc b/source/blender/editors/interface/interface_drag.cc index 462cef50317a..4156ec0f4a25 100644 --- a/source/blender/editors/interface/interface_drag.cc +++ b/source/blender/editors/interface/interface_drag.cc @@ -24,6 +24,7 @@ void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, const float scale) { but->imb = imb; but->imb_scale = scale; + UI_but_dragflag_enable(but, UI_BUT_DRAG_FULL_BUT); } void UI_but_drag_set_asset(uiBut *but, diff --git a/source/blender/editors/interface/interface_draw.cc b/source/blender/editors/interface/interface_draw.cc index 53a7d896427c..79cfb2c50c98 100644 --- a/source/blender/editors/interface/interface_draw.cc +++ b/source/blender/editors/interface/interface_draw.cc @@ -1798,7 +1798,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, } /* Using some extra margin (-1.0f) for the coordinates used to complete the polygon * avoids the profile line crossing itself in some common situations, which can lead to - * incorrect triangulation. See T841183. */ + * incorrect triangulation. See #841183. */ if (add_left_tri && add_bottom_tri) { /* Add left side, bottom left corner, and bottom side points. */ table_coords[tot_points - 3][0] = profile->view_rect.xmin - 1.0f; diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index 6b2786ed77b1..9a9c0d841604 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -94,7 +94,7 @@ /** * Check to avoid very small mouse-moves from jumping away from keyboard navigation, - * while larger mouse motion will override keyboard input, see: T34936. + * while larger mouse motion will override keyboard input, see: #34936. */ #define USE_KEYNAV_LIMIT @@ -140,7 +140,7 @@ * Instead of mapping cursor motion to the min/max, map the motion to the click-step. * * This value is multiplied by the click step to calculate a range to clamp the soft-range by. - * See: T68130 + * See: #68130 */ #define UI_DRAG_MAP_SOFT_RANGE_PIXEL_MAX 1000 @@ -384,7 +384,7 @@ struct uiHandleButtonData { /** * Behave as if #UI_BUT_DISABLED is set (without drawing grayed out). * Needed so non-interactive labels can be activated for the purpose of showing tool-tips, - * without them blocking interaction with nodes, see: T97386. + * without them blocking interaction with nodes, see: #97386. */ bool disable_force; @@ -549,7 +549,7 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val) const int dy = WM_event_absolute_delta_y(event); /* This event should be originally from event->type, - * converting wrong event into wheel is bad, see T33803. */ + * converting wrong event into wheel is bad, see #33803. */ BLI_assert(*type == MOUSEPAN); /* sign differs, reset */ @@ -752,7 +752,7 @@ static uiAfterFunc *ui_afterfunc_new() /** * For executing operators after the button is pressed. - * (some non operator buttons need to trigger operators), see: T37795. + * (some non operator buttons need to trigger operators), see: #37795. * * \param context_but: A button from which to get the context from (`uiBut.context`) for the * operator execution. @@ -932,7 +932,7 @@ static void ui_apply_but_undo(uiBut *but) /* Optionally override undo when undo system doesn't support storing properties. */ if (but->rnapoin.owner_id) { /* Exception for renaming ID data, we always need undo pushes in this case, - * because undo systems track data by their ID, see: T67002. */ + * because undo systems track data by their ID, see: #67002. */ /* Exception for active shape-key, since changing this in edit-mode updates * the shape key from object mode data. */ if (ELEM(but->rnaprop, &rna_ID_name, &rna_Object_active_shape_key_index)) { @@ -949,7 +949,7 @@ static void ui_apply_but_undo(uiBut *but) if (skip_undo == false) { /* XXX: disable all undo pushes from UI changes from sculpt mode as they cause memfile undo - * steps to be written which cause lag: T71434. */ + * steps to be written which cause lag: #71434. */ if (BKE_paintmode_get_active_from_context(static_cast(but->block->evil_C)) == PAINT_MODE_SCULPT) { skip_undo = true; @@ -1261,8 +1261,8 @@ static void ui_apply_but_NUM(bContext *C, uiBut *but, uiHandleButtonData *data) if (data->str) { /* This is intended to avoid unnecessary updates when the value stays the same, however there * are issues with the current implementation. It does not work with multi-button editing - * (T89996) or operator popups where a number button requires an update even if the value is - * unchanged (T89996). + * (#89996) or operator popups where a number button requires an update even if the value is + * unchanged (#89996). * * Trying to detect changes at this level is not reliable. Instead it could be done at the * level of RNA update/set, skipping RNA update if RNA set did not change anything, instead @@ -1517,7 +1517,7 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl /* Highly unlikely. */ printf("%s: Can't find button\n", __func__); /* While this avoids crashing, multi-button dragging will fail, - * which is still a bug from the user perspective. See T83651. */ + * which is still a bug from the user perspective. See #83651. */ continue; } @@ -1557,7 +1557,7 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl but->active->value = mbut_state->origvalue + value_delta; } - /* Clamp based on soft limits, see T40154. */ + /* Clamp based on soft limits, see #40154. */ CLAMP(but->active->value, double(but->softmin), double(but->softmax)); } @@ -3370,7 +3370,7 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) #ifdef USE_DRAG_MULTINUM /* this can happen from multi-drag */ if (data->applied_interactive) { - /* remove any small changes so canceling edit doesn't restore invalid value: T40538 */ + /* remove any small changes so canceling edit doesn't restore invalid value: #40538 */ data->cancel = true; ui_apply_but(C, but->block, but, data, true); data->cancel = false; @@ -3695,7 +3695,7 @@ static void ui_do_but_textedit( } else if (inbox) { /* if we allow activation on key press, - * it gives problems launching operators T35713. */ + * it gives problems launching operators #35713. */ if (event->val == KM_RELEASE) { button_activate_state(C, but, BUTTON_STATE_EXIT); retval = WM_UI_HANDLER_BREAK; @@ -4689,7 +4689,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons do_activate = (event->val == KM_RELEASE); } else if (!ui_do_but_extra_operator_icon(C, but, data, event)) { - /* Also use double-clicks to prevent fast clicks to leak to other handlers (T76481). */ + /* Also use double-clicks to prevent fast clicks to leak to other handlers (#76481). */ do_activate = ELEM(event->val, KM_PRESS, KM_DBL_CLICK); } } @@ -5903,7 +5903,7 @@ static int ui_do_but_GRIP( /* NOTE: Having to store org point in window space and recompute it to block "space" each time * is not ideal, but this is a way to hack around behavior of ui_window_to_block(), which * returns different results when the block is inside a panel or not... - * See T37739. + * See #37739. */ int mx = event->xy[0]; @@ -6511,7 +6511,7 @@ static bool ui_numedit_but_HSVCUBE(uiBut *but, ui_color_picker_to_rgb_HSVCUBE_v(hsv_but, hsv, rgb); ui_perceptual_to_scene_linear_space(but, rgb); - /* clamp because with color conversion we can exceed range T34295. */ + /* clamp because with color conversion we can exceed range #34295. */ if (hsv_but->gradient_type == UI_GRAD_V_ALT) { clamp_axis_max_v3(rgb, but->softmax); } @@ -7954,10 +7954,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * * * An example of where this is needed is dragging node-sockets, where dragging a node-socket * could exit the button before the drag threshold was reached, disable the button then break - * handling of the #MOUSEMOVE event preventing the socket being dragged entirely, see: T96255. + * handling of the #MOUSEMOVE event preventing the socket being dragged entirely, see: #96255. * * Region level event handling is responsible for preventing events being passed - * through to parts of the UI that are logically behind this button, see: T92364. */ + * through to parts of the UI that are logically behind this button, see: #92364. */ return WM_UI_HANDLER_CONTINUE; } @@ -8261,7 +8261,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s /* Automatic open pull-down block timer. */ if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER) || /* Menu button types may draw as popovers, check for this case - * ignoring other kinds of menus (mainly enums). (see T66538). */ + * ignoring other kinds of menus (mainly enums). (see #66538). */ ((but->type == UI_BTYPE_MENU) && (UI_but_paneltype_get(but) || ui_but_menu_draw_as_popover(but)))) { if (data->used_mouse && !data->autoopentimer) { @@ -9039,7 +9039,7 @@ static void ui_handle_button_activate(bContext *C, */ static bool ui_handle_button_activate_by_type(bContext *C, ARegion *region, uiBut *but) { - if (but->type == UI_BTYPE_BUT_MENU) { + if (ELEM(but->type, UI_BTYPE_BUT_MENU, UI_BTYPE_ROW)) { /* mainly for operator buttons */ ui_handle_button_activate(C, region, but, BUTTON_ACTIVATE_APPLY); } @@ -9363,7 +9363,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) * * This is needed to make sure if a button was active, * it stays active while the mouse is over it. - * This avoids adding mouse-moves, see: T33466. */ + * This avoids adding mouse-moves, see: #33466. */ if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT, BUTTON_STATE_WAIT_DRAG)) { if (ui_but_find_mouse_over(region, event) == but) { button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER); @@ -9810,7 +9810,7 @@ static bool ui_mouse_motion_towards_check(uiBlock *block, { BLI_assert(block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)); - /* annoying fix for T36269, this is a bit odd but in fact works quite well + /* annoying fix for #36269, this is a bit odd but in fact works quite well * don't mouse-out of a menu if another menu has been created after it. * if this causes problems we could remove it and check on a different fix - campbell */ if (menu->region->next) { @@ -10606,7 +10606,7 @@ static int ui_handle_menu_event(bContext *C, * popups which you can click again to close. * * Events handled above may have already set the return value, - * don't overwrite them, see: T61015. + * don't overwrite them, see: #61015. */ if ((inside == false) && (menu->menuretval == 0)) { uiSafetyRct *saferct = static_cast(block->saferct.first); @@ -11210,7 +11210,7 @@ static int ui_handle_menus_recursive(bContext *C, if (block->flag & (UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_POPOVER)) { /* when there is a active search button and we close it, - * we need to reinit the mouse coords T35346. */ + * we need to reinit the mouse coords #35346. */ if (ui_region_find_active_but(menu->region) != but) { do_towards_reinit = true; } @@ -11358,15 +11358,15 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void * /*us if ((data->state == BUTTON_STATE_MENU_OPEN) && /* Make sure this popup isn't dragging a button. - * can happen with popovers (see T67882). */ + * can happen with popovers (see #67882). */ (ui_region_find_active_but(data->menu->region) == nullptr) && - /* make sure mouse isn't inside another menu (see T43247) */ + /* make sure mouse isn't inside another menu (see #43247) */ (ui_screen_region_find_mouse_over(screen, event) == nullptr) && ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER, UI_BTYPE_MENU) && (but_other = ui_but_find_mouse_over(region, event)) && (but != but_other) && ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER, UI_BTYPE_MENU) && /* Hover-opening menu's doesn't work well for buttons over one another - * along the same axis the menu is opening on (see T71719). */ + * along the same axis the menu is opening on (see #71719). */ (((data->menu->direction & (UI_DIR_LEFT | UI_DIR_RIGHT)) && BLI_rctf_isect_rect_x(&but->rect, &but_other->rect, nullptr)) || ((data->menu->direction & (UI_DIR_DOWN | UI_DIR_UP)) && @@ -11452,7 +11452,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) * them into blender, even if there's opened popup like splash screen (sergey). * KM_DBL_CLICK: * Continue in case of double click so wm_handlers_do calls handler again with KM_PRESS - * event. This is needed to ensure correct button handling for fast clicking (T47532). + * event. This is needed to ensure correct button handling for fast clicking (#47532). */ retval = WM_UI_HANDLER_CONTINUE; diff --git a/source/blender/editors/interface/interface_icons.cc b/source/blender/editors/interface/interface_icons.cc index 7959339980a0..7e0b17aa1282 100644 --- a/source/blender/editors/interface/interface_icons.cc +++ b/source/blender/editors/interface/interface_icons.cc @@ -1620,12 +1620,12 @@ static void icon_draw_cache_texture_flush_ex(GPUTexture *texture, GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR); GPU_shader_bind(shader); - const int data_binding = GPU_shader_get_uniform_block_binding(shader, "multi_rect_data"); + const int data_binding = GPU_shader_get_ubo_binding(shader, "multi_rect_data"); GPUUniformBuf *ubo = GPU_uniformbuf_create_ex( sizeof(MultiRectCallData), texture_draw_calls->drawcall_cache, __func__); GPU_uniformbuf_bind(ubo, data_binding); - const int img_binding = GPU_shader_get_texture_binding(shader, "image"); + const int img_binding = GPU_shader_get_sampler_binding(shader, "image"); GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false); GPUBatch *quad = GPU_batch_preset_quad(); @@ -1797,25 +1797,25 @@ static void icon_draw_texture(float x, GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_ICON); GPU_shader_bind(shader); - const int img_binding = GPU_shader_get_texture_binding(shader, "image"); + const int img_binding = GPU_shader_get_sampler_binding(shader, "image"); const int color_loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR); const int rect_tex_loc = GPU_shader_get_uniform(shader, "rect_icon"); const int rect_geom_loc = GPU_shader_get_uniform(shader, "rect_geom"); if (rgb) { const float color[4] = {rgb[0], rgb[1], rgb[2], alpha}; - GPU_shader_uniform_vector(shader, color_loc, 4, 1, color); + GPU_shader_uniform_float_ex(shader, color_loc, 4, 1, color); } else { const float color[4] = {alpha, alpha, alpha, alpha}; - GPU_shader_uniform_vector(shader, color_loc, 4, 1, color); + GPU_shader_uniform_float_ex(shader, color_loc, 4, 1, color); } const float tex_color[4] = {x1, y1, x2, y2}; const float geom_color[4] = {x, y, x + w, y + h}; - GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, tex_color); - GPU_shader_uniform_vector(shader, rect_geom_loc, 4, 1, geom_color); + GPU_shader_uniform_float_ex(shader, rect_tex_loc, 4, 1, tex_color); + GPU_shader_uniform_float_ex(shader, rect_geom_loc, 4, 1, geom_color); GPU_shader_uniform_1f(shader, "text_width", text_width); GPU_texture_bind_ex(texture, GPU_SAMPLER_ICON, img_binding, false); diff --git a/source/blender/editors/interface/interface_intern.hh b/source/blender/editors/interface/interface_intern.hh index 68a81de4e4a9..accb6ecab2e6 100644 --- a/source/blender/editors/interface/interface_intern.hh +++ b/source/blender/editors/interface/interface_intern.hh @@ -86,11 +86,6 @@ enum { /* WARNING: rest of #uiBut.flag in UI_interface.h */ }; -/** #uiBut.dragflag */ -enum { - UI_BUT_DRAGPOIN_FREE = (1 << 0), -}; - /** #uiBut.pie_dir */ enum RadialDirection { UI_RADIAL_NONE = -1, diff --git a/source/blender/editors/interface/interface_layout.cc b/source/blender/editors/interface/interface_layout.cc index 7366c1b051af..c2a786866089 100644 --- a/source/blender/editors/interface/interface_layout.cc +++ b/source/blender/editors/interface/interface_layout.cc @@ -43,7 +43,7 @@ #include "interface_intern.hh" /* Show an icon button after each RNA button to use to quickly set keyframes, - * this is a way to display animation/driven/override status, see T54951. */ + * this is a way to display animation/driven/override status, see #54951. */ #define UI_PROP_DECORATE /* Alternate draw mode where some buttons can use single icon width, * giving more room for the text at the expense of nicely aligned text. */ @@ -1009,7 +1009,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, ) { /* Also avoid setting 'align' if possible. Set the space to zero instead as aligning a large * number of labels can end up aligning thousands of buttons when displaying key-map search (a - * heavy operation), see: T78636. */ + * heavy operation), see: #78636. */ sub = uiLayoutRow(layout, layout->align); sub->space = 0; } @@ -3516,7 +3516,7 @@ void uiItemMenuFN(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc struct MenuItemLevel { wmOperatorCallContext opcontext; /* don't use pointers to the strings because python can dynamically - * allocate strings and free before the menu draws, see T27304. */ + * allocate strings and free before the menu draws, see #27304. */ char opname[OP_MAX_TYPENAME]; char propname[MAX_IDPROP_NAME]; PointerRNA rnapoin; @@ -3960,8 +3960,7 @@ static void ui_litem_layout_radial(uiLayout *litem) /* For the radial layout we will use Matt Ebb's design * for radiation, see http://mattebb.com/weblog/radiation/ - * also the old code at http://developer.blender.org/T5103 - */ + * also the old code at #5103. */ const int pie_radius = U.pie_menu_radius * UI_DPI_FAC; diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc index 445f6cc53378..6e9d73f9847c 100644 --- a/source/blender/editors/interface/interface_ops.cc +++ b/source/blender/editors/interface/interface_ops.cc @@ -1245,7 +1245,7 @@ bool UI_context_copy_to_selected_list(bContext *C, else if (GS(id->name) == ID_SCE) { /* Sequencer's ID is scene :/ */ /* Try to recursively find an RNA_Sequence ancestor, - * to handle situations like T41062... */ + * to handle situations like #41062... */ if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != nullptr) { /* Special case when we do this for 'Sequence.lock'. diff --git a/source/blender/editors/interface/interface_panel.cc b/source/blender/editors/interface/interface_panel.cc index 28aae7d779fe..48fa0b9f0a33 100644 --- a/source/blender/editors/interface/interface_panel.cc +++ b/source/blender/editors/interface/interface_panel.cc @@ -1486,7 +1486,7 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) GPU_blend(GPU_BLEND_NONE); - /* Not essential, but allows events to be handled right up to the region edge (T38171). */ + /* Not essential, but allows events to be handled right up to the region edge (#38171). */ if (is_left) { pc_dyn->rect.xmin = v2d->mask.xmin; } @@ -2320,7 +2320,7 @@ int ui_handler_panel_region(bContext *C, UI_panel_category_active_set(region, pc_dyn->idname); ED_region_tag_redraw(region); - /* Reset scroll to the top (T38348). */ + /* Reset scroll to the top (#38348). */ UI_view2d_offset(®ion->v2d, -1.0f, 1.0f); retval = WM_UI_HANDLER_BREAK; diff --git a/source/blender/editors/interface/interface_query.cc b/source/blender/editors/interface/interface_query.cc index 84e2b488ccb0..1d5eb9e72502 100644 --- a/source/blender/editors/interface/interface_query.cc +++ b/source/blender/editors/interface/interface_query.cc @@ -247,7 +247,7 @@ bool ui_but_contains_point_px_icon(const uiBut *but, ARegion *region, const wmEv BLI_rcti_rctf_copy(&rect, &but->rect); - if (but->imb || but->type == UI_BTYPE_COLOR) { + if (but->dragflag & UI_BUT_DRAG_FULL_BUT) { /* use button size itself */ } else if (but->drawflag & UI_BUT_ICON_LEFT) { diff --git a/source/blender/editors/interface/interface_region_menu_popup.cc b/source/blender/editors/interface/interface_region_menu_popup.cc index c02b13998683..7da9cbeb37bf 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.cc +++ b/source/blender/editors/interface/interface_region_menu_popup.cc @@ -408,7 +408,7 @@ static uiPopupBlockHandle *ui_popup_menu_create( #if 0 /* if this is an rna button then we can assume its an enum * flipping enums is generally not good since the order can be - * important T28786. */ + * important #28786. */ if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) { pup->block->flag |= UI_BLOCK_NO_FLIP; } @@ -745,7 +745,7 @@ void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block) ui_popup_block_free(C, block->handle); /* In the case we have nested popups, - * closing one may need to redraw another, see: T48874 */ + * closing one may need to redraw another, see: #48874 */ LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { ED_region_tag_refresh_ui(region); } diff --git a/source/blender/editors/interface/interface_region_popup.cc b/source/blender/editors/interface/interface_region_popup.cc index 520c3e9dc820..7943e7dc6fa8 100644 --- a/source/blender/editors/interface/interface_region_popup.cc +++ b/source/blender/editors/interface/interface_region_popup.cc @@ -48,7 +48,7 @@ void ui_popup_translate(ARegion *region, const int mdiff[2]) /* update blocks */ LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { uiPopupBlockHandle *handle = block->handle; - /* Make empty, will be initialized on next use, see T60608. */ + /* Make empty, will be initialized on next use, see #60608. */ BLI_rctf_init(&handle->prev_block_rect, 0, 0, 0, 0); LISTBASE_FOREACH (uiSafetyRct *, saferct, &block->saferct) { @@ -214,7 +214,7 @@ static void ui_popup_block_position(wmWindow *window, /* Compute offset based on direction. */ float offset_x = 0, offset_y = 0; - /* Ensure buttons don't come between the parent button and the popup, see: T63566. */ + /* Ensure buttons don't come between the parent button and the popup, see: #63566. */ const float offset_overlap = max_ff(U.pixelsize, 1.0f); if (dir1 == UI_DIR_LEFT) { diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc index 3e707031dd24..55b2e780a9e7 100644 --- a/source/blender/editors/interface/interface_template_asset_view.cc +++ b/source/blender/editors/interface/interface_template_asset_view.cc @@ -49,12 +49,15 @@ static void asset_view_item_but_drag_set(uiBut *but, AssetHandle *asset_handle) * away before too long. */ ED_asset_handle_get_full_library_path(asset_handle, blend_path); + const eAssetImportMethod import_method = + ED_asset_handle_get_import_method(asset_handle).value_or(ASSET_IMPORT_APPEND_REUSE); + if (blend_path[0]) { ImBuf *imbuf = ED_assetlist_asset_image_get(asset_handle); UI_but_drag_set_asset(but, asset_handle, BLI_strdup(blend_path), - FILE_ASSET_IMPORT_APPEND, + import_method, ED_asset_handle_get_preview_icon_id(asset_handle), imbuf, 1.0f); diff --git a/source/blender/editors/interface/interface_template_attribute_search.cc b/source/blender/editors/interface/interface_template_attribute_search.cc index 55ca945671f0..2ac8e96b9967 100644 --- a/source/blender/editors/interface/interface_template_attribute_search.cc +++ b/source/blender/editors/interface/interface_template_attribute_search.cc @@ -92,15 +92,9 @@ void attribute_search_add_items(StringRefNull str, StringSearch *search = BLI_string_search_new(); for (const GeometryAttributeInfo *item : infos) { - - /* Don't show the legacy "normal" attribute. */ - if (item->name == "normal" && item->domain == ATTR_DOMAIN_FACE) { - continue; - } if (!bke::allow_procedural_attribute_access(item->name)) { continue; } - BLI_string_search_add(search, item->name.c_str(), (void *)item, 0); } diff --git a/source/blender/editors/interface/interface_template_search_menu.cc b/source/blender/editors/interface/interface_template_search_menu.cc index e953119dfdcf..547811ef1f81 100644 --- a/source/blender/editors/interface/interface_template_search_menu.cc +++ b/source/blender/editors/interface/interface_template_search_menu.cc @@ -468,7 +468,7 @@ static MenuSearch_Data *menu_items_from_ui_create( /* Exclude context menus because: * - The menu items are available elsewhere (and will show up multiple times). * - Menu items depend on exact context, making search results unpredictable - * (exact number of items selected for example). See design doc T74158. + * (exact number of items selected for example). See design doc #74158. * There is one exception, * as the outliner only exposes functionality via the context menu. */ GHashIterator iter; @@ -897,7 +897,7 @@ static MenuSearch_Data *menu_items_from_ui_create( * unless searching for something that isn't already in a menu (or scroll down). * * Keep this behind a developer only check: - * - Many operators need options to be set to give useful results, see: T74157. + * - Many operators need options to be set to give useful results, see: #74157. * - User who really prefer to list all operators can use #WM_OT_search_operator. */ if (U.flag & USER_DEVELOPER_UI) { diff --git a/source/blender/editors/interface/interface_templates.cc b/source/blender/editors/interface/interface_templates.cc index 7b8fb7344b49..42c4bfd983e1 100644 --- a/source/blender/editors/interface/interface_templates.cc +++ b/source/blender/editors/interface/interface_templates.cc @@ -2813,7 +2813,7 @@ static eAutoPropButsReturn template_operator_property_buts_draw_single( /* no undo for buttons for operator redo panels */ UI_but_flag_disable(but, UI_BUT_UNDO); - /* only for popups, see T36109. */ + /* only for popups, see #36109. */ /* if button is operator's default property, and a text-field, enable focus for it * - this is used for allowing operators with popups to rename stuff with fewer clicks @@ -6553,12 +6553,12 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) /* attach callbacks to compensate for missing properties update, * we don't know which keymap (item) is being modified there */ for (; but; but = but->next) { - /* operator buttons may store props for use (file selector, T36492) */ + /* operator buttons may store props for use (file selector, #36492) */ if (but->rnaprop) { UI_but_func_set(but, keymap_item_modified, ptr->data, nullptr); /* Otherwise the keymap will be re-generated which we're trying to edit, - * see: T47685 */ + * see: #47685 */ UI_but_flag_enable(but, UI_BUT_UPDATE_DELAY); } } diff --git a/source/blender/editors/interface/interface_utils.cc b/source/blender/editors/interface/interface_utils.cc index 4835e4c4f7fa..af3e31837f7a 100644 --- a/source/blender/editors/interface/interface_utils.cc +++ b/source/blender/editors/interface/interface_utils.cc @@ -978,7 +978,7 @@ void UI_butstore_free(uiBlock *block, uiButStore *bs_handle) * which then can't use the previous buttons state * ('ui_but_update_from_old_block' fails to find a match), * keeping the active button in the old block holding a reference - * to the button-state in the new block: see T49034. + * to the button-state in the new block: see #49034. * * Ideally we would manage moving the 'uiButStore', keeping a correct state. * All things considered this is the most straightforward fix - Campbell. diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index b0de628f0b11..086b583d9363 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -1186,7 +1186,7 @@ void UI_widgetbase_draw_cache_end() static bool draw_widgetbase_batch_skip_draw_cache() { /* MacOS is known to have issues on Mac Mini and MacBook Pro with Intel Iris GPU. - * For example, T78307. */ + * For example, #78307. */ if (GPU_type_matches_ex(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { return true; } @@ -2133,7 +2133,7 @@ static void widget_draw_text(const uiFontStyle *fstyle, int pos_x = rect->xmin + font_xofs + bounds.xmin + (bounds.xmax - bounds.xmin - ul_width) / 2; int pos_y = rect->ymin + font_yofs + bounds.ymin - U.pixelsize; - /* Use text output because direct drawing doesn't always work. See T89246. */ + /* Use text output because direct drawing doesn't always work. See #89246. */ BLF_position(fstyle->uifont_id, float(pos_x), pos_y, 0.0f); BLF_color4ubv(fstyle->uifont_id, wcol->text); BLF_draw(fstyle->uifont_id, "_", 2); @@ -2585,7 +2585,7 @@ static void widget_state_numslider(uiWidgetType *wt, if (color_blend != nullptr) { /* Set the slider 'item' so that it reflects state settings too. * De-saturate so the color of the slider doesn't conflict with the blend color, - * which can make the color hard to see when the slider is set to full (see T66102). */ + * which can make the color hard to see when the slider is set to full (see #66102). */ wt->wcol.item[0] = wt->wcol.item[1] = wt->wcol.item[2] = rgb_to_grayscale_byte(wt->wcol.item); color_blend_v3_v3(wt->wcol.item, color_blend, wcol_state->blend); color_ensure_contrast_v3(wt->wcol.item, wt->wcol.inner, 30); diff --git a/source/blender/editors/interface/resources.cc b/source/blender/editors/interface/resources.cc index 606f9d5a11f7..5982f8ad1c93 100644 --- a/source/blender/editors/interface/resources.cc +++ b/source/blender/editors/interface/resources.cc @@ -803,6 +803,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_CAMERA_PATH: cp = ts->camera_path; break; + case TH_CAMERA_PASSEPARTOUT: + cp = ts->camera_passepartout; + break; case TH_LOCK_MARKER: cp = ts->lock_marker; break; diff --git a/source/blender/editors/interface/view2d.cc b/source/blender/editors/interface/view2d.cc index 51a3bd008af0..a8d5b1ad22c9 100644 --- a/source/blender/editors/interface/view2d.cc +++ b/source/blender/editors/interface/view2d.cc @@ -150,7 +150,7 @@ static void view2d_masks(View2D *v2d, const rcti *mask_scroll) } /* Do not use mapped scroll here because we want to update scroller rects - * even if they are not displayed. For initialization purposes. See T75003. */ + * even if they are not displayed. For initialization purposes. See #75003. */ scroll = v2d->scroll; /* Scrollers are based off region-size: @@ -1034,7 +1034,7 @@ void UI_view2d_zoom_cache_reset(void) return; } /* While scaling we can accumulate fonts at many sizes (~20 or so). - * Not an issue with embedded font, but can use over 500Mb with i18n ones! See T38244. */ + * Not an issue with embedded font, but can use over 500Mb with i18n ones! See #38244. */ /* NOTE: only some views draw text, we could check for this case to avoid cleaning cache. */ BLF_cache_clear(); diff --git a/source/blender/editors/interface/view2d_ops.cc b/source/blender/editors/interface/view2d_ops.cc index b76f5f1e49fd..37e5626b2040 100644 --- a/source/blender/editors/interface/view2d_ops.cc +++ b/source/blender/editors/interface/view2d_ops.cc @@ -1858,7 +1858,7 @@ static void scroller_activate_init(bContext *C, UI_view2d_scrollers_calc(v2d, nullptr, &scrollers); /* Use a union of 'cur' & 'tot' in case the current view is far outside 'tot'. In this cases - * moving the scroll bars has far too little effect and the view can get stuck T31476. */ + * moving the scroll bars has far too little effect and the view can get stuck #31476. */ rctf tot_cur_union = v2d->tot; BLI_rctf_union(&tot_cur_union, &v2d->cur); diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 100d56a6b0db..10857f534140 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -633,7 +633,7 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op) } } - /* Switch out of edit mode to avoid being stuck in it (T54326). */ + /* Switch out of edit mode to avoid being stuck in it (#54326). */ Object *obedit = CTX_data_edit_object(C); if (obedit) { ED_object_mode_set(C, OB_MODE_OBJECT); diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c index e6426732584c..b3cce1eabcf2 100644 --- a/source/blender/editors/io/io_usd.c +++ b/source/blender/editors/io/io_usd.c @@ -75,7 +75,7 @@ const EnumPropertyItem rna_enum_usd_mtl_name_collision_mode_items[] = { const EnumPropertyItem rna_enum_usd_tex_import_mode_items[] = { {USD_TEX_IMPORT_NONE, "IMPORT_NONE", 0, "None", "Don't import textures"}, {USD_TEX_IMPORT_PACK, "IMPORT_PACK", 0, "Packed", "Import textures as packed data"}, - {USD_TEX_IMPORT_COPY, "IMPORT_COPY", 0, "Copy", "Copy files to Textures Directory"}, + {USD_TEX_IMPORT_COPY, "IMPORT_COPY", 0, "Copy", "Copy files to textures directory"}, {0, NULL, 0, NULL, NULL}, }; @@ -382,6 +382,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op) const bool import_materials = RNA_boolean_get(op->ptr, "import_materials"); const bool import_meshes = RNA_boolean_get(op->ptr, "import_meshes"); const bool import_volumes = RNA_boolean_get(op->ptr, "import_volumes"); + const bool import_shapes = RNA_boolean_get(op->ptr, "import_shapes"); const bool import_subdiv = RNA_boolean_get(op->ptr, "import_subdiv"); @@ -413,7 +414,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op) int offset = 0; int sequence_len = 1; - /* Switch out of edit mode to avoid being stuck in it (T54326). */ + /* Switch out of edit mode to avoid being stuck in it (#54326). */ Object *obedit = CTX_data_edit_object(C); if (obedit) { ED_object_mode_set(C, OB_MODE_EDIT); @@ -443,6 +444,7 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op) .import_materials = import_materials, .import_meshes = import_meshes, .import_volumes = import_volumes, + .import_shapes = import_shapes, .import_subdiv = import_subdiv, .import_instance_proxies = import_instance_proxies, .create_collection = create_collection, @@ -488,6 +490,7 @@ static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op) uiItemR(col, ptr, "import_materials", 0, NULL, ICON_NONE); uiItemR(col, ptr, "import_meshes", 0, NULL, ICON_NONE); uiItemR(col, ptr, "import_volumes", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "import_shapes", 0, NULL, ICON_NONE); uiItemR(box, ptr, "prim_path_mask", 0, NULL, ICON_NONE); uiItemR(box, ptr, "scale", 0, NULL, ICON_NONE); @@ -577,6 +580,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot) RNA_def_boolean(ot->srna, "import_materials", true, "Materials", ""); RNA_def_boolean(ot->srna, "import_meshes", true, "Meshes", ""); RNA_def_boolean(ot->srna, "import_volumes", true, "Volumes", ""); + RNA_def_boolean(ot->srna, "import_shapes", true, "Shapes", ""); RNA_def_boolean(ot->srna, "import_subdiv", @@ -675,7 +679,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot) "//textures/", FILE_MAXDIR, "Textures Directory", - "Path to the directory where imported textures will be copied "); + "Path to the directory where imported textures will be copied"); RNA_def_enum( ot->srna, diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 77014fde8a85..ea4050d0ba06 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -722,7 +722,7 @@ void ED_mask_draw_region( GPU_matrix_mul(stabmat); } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); - GPU_shader_uniform_vector( + GPU_shader_uniform_float_ex( state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, buf_col); if (overlay_mode == MASK_OVERLAY_COMBINED) { diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index a0769fbaa5f4..db25aeea2895 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -12,6 +12,7 @@ set(INC ../../draw ../../geometry ../../gpu + ../../functions ../../imbuf ../../makesdna ../../makesrna @@ -27,6 +28,7 @@ set(SRC editface.cc editmesh_add.c editmesh_add_gizmo.c + editmesh_attribute.cc editmesh_automerge.c editmesh_bevel.c editmesh_bisect.c diff --git a/source/blender/editors/mesh/editmesh_attribute.cc b/source/blender/editors/mesh/editmesh_attribute.cc new file mode 100644 index 000000000000..8594f3ebc1c7 --- /dev/null +++ b/source/blender/editors/mesh/editmesh_attribute.cc @@ -0,0 +1,393 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup edmesh + */ + +#include "BLI_color.hh" +#include "BLI_generic_pointer.hh" + +#include "BKE_attribute.h" +#include "BKE_context.h" +#include "BKE_editmesh.h" +#include "BKE_layer.h" +#include "BKE_mesh.h" +#include "BKE_report.h" +#include "BKE_type_conversions.hh" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "ED_mesh.h" +#include "ED_object.h" +#include "ED_screen.h" +#include "ED_transform.h" +#include "ED_view3d.h" + +#include "BLT_translation.h" + +#include "DNA_object_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "bmesh_tools.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "mesh_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ + +namespace blender::ed::mesh { + +static char domain_to_htype(const eAttrDomain domain) +{ + switch (domain) { + case ATTR_DOMAIN_POINT: + return BM_VERT; + case ATTR_DOMAIN_EDGE: + return BM_EDGE; + case ATTR_DOMAIN_FACE: + return BM_FACE; + case ATTR_DOMAIN_CORNER: + return BM_LOOP; + default: + BLI_assert_unreachable(); + return BM_VERT; + } +} + +static bool mesh_active_attribute_poll(bContext *C) +{ + if (!ED_operator_editmesh(C)) { + return false; + } + const Mesh *mesh = ED_mesh_context(C); + const CustomDataLayer *layer = BKE_id_attributes_active_get(&const_cast(mesh->id)); + if (!layer) { + CTX_wm_operator_poll_msg_set(C, "No active attribute"); + return false; + } + if (layer->type == CD_PROP_STRING) { + CTX_wm_operator_poll_msg_set(C, "Active string attribute not supported"); + return false; + } + return true; +} + +namespace set_attribute { + +static StringRefNull rna_property_name_for_type(const eCustomDataType type) +{ + switch (type) { + case CD_PROP_FLOAT: + return "value_float"; + case CD_PROP_FLOAT2: + return "value_float_vector_2d"; + case CD_PROP_FLOAT3: + return "value_float_vector_3d"; + case CD_PROP_COLOR: + case CD_PROP_BYTE_COLOR: + return "value_color"; + case CD_PROP_BOOL: + return "value_bool"; + case CD_PROP_INT8: + case CD_PROP_INT32: + return "value_int"; + default: + BLI_assert_unreachable(); + return ""; + } +} + +static void bmesh_vert_edge_face_layer_selected_values_set(BMesh &bm, + const BMIterType iter_type, + const GPointer value, + const int offset) +{ + const CPPType &type = *value.type(); + BMIter iter; + BMElem *elem; + BM_ITER_MESH (elem, &iter, &bm, iter_type) { + if (BM_elem_flag_test(elem, BM_ELEM_SELECT)) { + type.copy_assign(value.get(), POINTER_OFFSET(elem->head.data, offset)); + } + } +} + +/** + * For face select mode, set face corner values of any selected face. For edge and vertex + * select mode, set face corner values of loops connected to selected vertices. + */ +static void bmesh_loop_layer_selected_values_set(BMEditMesh &em, + const GPointer value, + const int offset) +{ + /* In the separate select modes we may set the same loop values more than once. + * This is okay because we're always setting the same value. */ + BMesh &bm = *em.bm; + const CPPType &type = *value.type(); + if (em.selectmode & SCE_SELECT_FACE) { + BMIter face_iter; + BMFace *face; + BM_ITER_MESH (face, &face_iter, &bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(face, BM_ELEM_SELECT)) { + BMIter loop_iter; + BMLoop *loop; + BM_ITER_ELEM (loop, &loop_iter, face, BM_LOOPS_OF_FACE) { + type.copy_assign(value.get(), POINTER_OFFSET(loop->head.data, offset)); + } + } + } + } + if (em.selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { + BMIter vert_iter; + BMVert *vert; + BM_ITER_MESH (vert, &vert_iter, &bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(vert, BM_ELEM_SELECT)) { + BMIter loop_iter; + BMLoop *loop; + BM_ITER_ELEM (loop, &loop_iter, vert, BM_LOOPS_OF_VERT) { + type.copy_assign(value.get(), POINTER_OFFSET(loop->head.data, offset)); + } + } + } + } +} + +static int mesh_set_attribute_exec(bContext *C, wmOperator *op) +{ + const Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + scene, view_layer, CTX_wm_view3d(C), &objects_len); + + Mesh *mesh = ED_mesh_context(C); + CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&mesh->id); + const eCustomDataType active_type = eCustomDataType(active_attribute->type); + const CPPType &type = *bke::custom_data_type_to_cpp_type(active_type); + + BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); + BLI_SCOPED_DEFER([&]() { type.destruct(buffer); }); + + const StringRefNull prop_name = rna_property_name_for_type(active_type); + switch (active_type) { + case CD_PROP_FLOAT: + *static_cast(buffer) = RNA_float_get(op->ptr, prop_name.c_str()); + break; + case CD_PROP_FLOAT2: + RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast(buffer)); + break; + case CD_PROP_FLOAT3: + RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast(buffer)); + break; + case CD_PROP_COLOR: + RNA_float_get_array(op->ptr, prop_name.c_str(), static_cast(buffer)); + break; + case CD_PROP_BYTE_COLOR: + ColorGeometry4f value; + RNA_float_get_array(op->ptr, prop_name.c_str(), value); + *static_cast(buffer) = value.encode(); + break; + case CD_PROP_BOOL: + *static_cast(buffer) = RNA_boolean_get(op->ptr, prop_name.c_str()); + break; + case CD_PROP_INT8: + *static_cast(buffer) = RNA_int_get(op->ptr, prop_name.c_str()); + break; + case CD_PROP_INT32: + *static_cast(buffer) = RNA_int_get(op->ptr, prop_name.c_str()); + break; + default: + BLI_assert_unreachable(); + } + const GPointer value(type, buffer); + const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions(); + + bool changed = false; + for (const int i : IndexRange(objects_len)) { + Object *object = objects[i]; + Mesh *mesh = static_cast(object->data); + BMEditMesh *em = BKE_editmesh_from_object(object); + BMesh *bm = em->bm; + + CustomDataLayer *layer = BKE_id_attributes_active_get(&mesh->id); + if (!layer) { + continue; + } + /* Use implicit conversions to try to handle the case where the active attribute has a + * different type on multiple objects. */ + const eCustomDataType dst_data_type = eCustomDataType(active_attribute->type); + const CPPType &dst_type = *bke::custom_data_type_to_cpp_type(dst_data_type); + if (&type != &dst_type && !conversions.is_convertible(type, dst_type)) { + continue; + } + BUFFER_FOR_CPP_TYPE_VALUE(dst_type, dst_buffer); + BLI_SCOPED_DEFER([&]() { dst_type.destruct(dst_buffer); }); + conversions.convert_to_uninitialized(type, dst_type, value.get(), dst_buffer); + const GPointer dst_value(dst_type, dst_buffer); + switch (BKE_id_attribute_domain(&mesh->id, layer)) { + case ATTR_DOMAIN_POINT: + bmesh_vert_edge_face_layer_selected_values_set( + *bm, BM_VERTS_OF_MESH, dst_value, layer->offset); + break; + case ATTR_DOMAIN_EDGE: + bmesh_vert_edge_face_layer_selected_values_set( + *bm, BM_EDGES_OF_MESH, dst_value, layer->offset); + break; + case ATTR_DOMAIN_FACE: + bmesh_vert_edge_face_layer_selected_values_set( + *bm, BM_FACES_OF_MESH, dst_value, layer->offset); + break; + case ATTR_DOMAIN_CORNER: + bmesh_loop_layer_selected_values_set(*em, dst_value, layer->offset); + break; + default: + BLI_assert_unreachable(); + break; + } + + changed = true; + EDBMUpdate_Params update{}; + update.calc_looptri = false; + update.calc_normals = false; + update.is_destructive = false; + EDBM_update(mesh, &update); + } + + MEM_freeN(objects); + + return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +static int mesh_set_attribute_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Mesh *mesh = ED_mesh_context(C); + BMesh *bm = mesh->edit_mesh->bm; + + const CustomDataLayer *layer = BKE_id_attributes_active_get(&mesh->id); + const eCustomDataType data_type = eCustomDataType(layer->type); + const eAttrDomain domain = BKE_id_attribute_domain(&mesh->id, layer); + const BMElem *active_elem = BM_mesh_active_elem_get(bm); + if (!active_elem) { + return WM_operator_props_popup(C, op, event); + } + + /* Only support filling the active data when the active selection mode matches the active + * attribute domain. NOTE: This doesn't work well for corner domain attributes. */ + if (active_elem->head.htype != domain_to_htype(domain)) { + return WM_operator_props_popup(C, op, event); + } + + const StringRefNull prop_name = rna_property_name_for_type(data_type); + const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type); + const GPointer active_value(type, POINTER_OFFSET(active_elem->head.data, layer->offset)); + + PropertyRNA *prop = RNA_struct_find_property(op->ptr, prop_name.c_str()); + if (!RNA_property_is_set(op->ptr, prop)) { + switch (data_type) { + case CD_PROP_FLOAT: + RNA_property_float_set(op->ptr, prop, *active_value.get()); + break; + case CD_PROP_FLOAT2: + RNA_property_float_set_array(op->ptr, prop, *active_value.get()); + break; + case CD_PROP_FLOAT3: + RNA_property_float_set_array(op->ptr, prop, *active_value.get()); + break; + case CD_PROP_BYTE_COLOR: + RNA_property_float_set_array(op->ptr, prop, active_value.get()->decode()); + break; + case CD_PROP_COLOR: + RNA_property_float_set_array(op->ptr, prop, *active_value.get()); + break; + case CD_PROP_BOOL: + RNA_property_boolean_set(op->ptr, prop, *active_value.get()); + break; + case CD_PROP_INT8: + RNA_property_int_set(op->ptr, prop, *active_value.get()); + break; + case CD_PROP_INT32: + RNA_property_int_set(op->ptr, prop, *active_value.get()); + break; + default: + BLI_assert_unreachable(); + } + } + + return WM_operator_props_popup(C, op, event); +} + +static void mesh_set_attribute_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = uiLayoutColumn(op->layout, true); + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + + Mesh *mesh = ED_mesh_context(C); + CustomDataLayer *active_attribute = BKE_id_attributes_active_get(&mesh->id); + const eCustomDataType active_type = eCustomDataType(active_attribute->type); + const StringRefNull prop_name = rna_property_name_for_type(active_type); + const char *name = active_attribute->name; + uiItemR(layout, op->ptr, prop_name.c_str(), 0, name, ICON_NONE); +} + +} // namespace set_attribute + +} // namespace blender::ed::mesh + +void MESH_OT_attribute_set(wmOperatorType *ot) +{ + using namespace blender::ed::mesh; + using namespace blender::ed::mesh::set_attribute; + ot->name = "Set Attribute"; + ot->description = "Set values of the active attribute for selected elements"; + ot->idname = "MESH_OT_attribute_set"; + + ot->exec = mesh_set_attribute_exec; + ot->invoke = mesh_set_attribute_invoke; + ot->poll = mesh_active_attribute_poll; + ot->ui = mesh_set_attribute_ui; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + static blender::float4 color_default(1); + + RNA_def_float(ot->srna, "value_float", 0.0f, -FLT_MAX, FLT_MAX, "Value", "", -FLT_MAX, FLT_MAX); + RNA_def_float_array(ot->srna, + "value_float_vector_2d", + 2, + nullptr, + -FLT_MAX, + FLT_MAX, + "Value", + "", + -FLT_MAX, + FLT_MAX); + RNA_def_float_array(ot->srna, + "value_float_vector_3d", + 3, + nullptr, + -FLT_MAX, + FLT_MAX, + "Value", + "", + -FLT_MAX, + FLT_MAX); + RNA_def_int(ot->srna, "value_int", 0, INT_MIN, INT_MAX, "Value", "", INT_MIN, INT_MAX); + RNA_def_float_color( + ot->srna, "value_color", 4, color_default, -FLT_MAX, FLT_MAX, "Value", "", 0.0f, 1.0f); + RNA_def_boolean(ot->srna, "value_bool", false, "Value", ""); +} + +/** \} */ diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index aab33678beca..9114b4770dd2 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -528,15 +528,7 @@ static void gizmo_mesh_bisect_update_from_op(GizmoGroup *ggd) normalize_v3(ggd->data.rotate_up); WM_gizmo_set_matrix_rotation_from_z_axis(ggd->translate_c, plane_no); - - float plane_no_cross[3]; - cross_v3_v3v3(plane_no_cross, plane_no, ggd->data.rotate_axis); - - WM_gizmo_set_matrix_offset_rotation_from_yz_axis( - ggd->rotate_c, plane_no_cross, ggd->data.rotate_axis); - RNA_enum_set(ggd->rotate_c->ptr, - "draw_options", - ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_MIRROR | ED_GIZMO_DIAL_DRAW_FLAG_ANGLE_START_Y); + WM_gizmo_set_matrix_rotation_from_z_axis(ggd->rotate_c, ggd->data.rotate_axis); } } diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c index 19e23f4f2123..e2f5bdacac79 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c @@ -455,7 +455,7 @@ void MESH_GGT_spin(struct wmGizmoGroupType *gzgt) gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; gzgt->setup = gizmo_mesh_spin_init_setup; /* This works well with right click selection but overrides left-mouse selection - * when clicking which is needed to create a full 360 degree revolution, see: T89912. */ + * when clicking which is needed to create a full 360 degree revolution, see: #89912. */ // gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; gzgt->refresh = gizmo_mesh_spin_init_refresh; gzgt->message_subscribe = gizmo_mesh_spin_init_message_subscribe; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index b7129b4b4d4a..736555d678cd 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -69,7 +69,7 @@ #define KMAXDIST (10 * U.dpi_fac) /* Max mouse distance from edge before not detecting it. */ /* WARNING: Knife float precision is fragile: - * Be careful before making changes here see: (T43229, T42864, T42459, T41164). + * Be careful before making changes here see: (#43229, #42864, #42459, #41164). */ #define KNIFE_FLT_EPS 0.00001f #define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS) @@ -198,7 +198,7 @@ typedef struct KnifeObjectInfo { * Optionally allocate triangle indices, these are needed for non-interactive knife * projection as multiple cuts are made without the BVH being updated. * Using these indices the it's possible to access `cagecos` even if the face has been cut - * and the loops in `em->looptris` no longer refer to the original triangles, see: T97153. + * and the loops in `em->looptris` no longer refer to the original triangles, see: #97153. */ const int (*tri_indices)[3]; @@ -2684,7 +2684,7 @@ static bool coinciding_edges(BMEdge *e1, BMEdge *e2) /* Callback used in point_is_visible to exclude hits on the faces that are the same * as or contain the hitting element (which is in user_data). - * Also (see T44492) want to exclude hits on faces that butt up to the hitting element + * Also (see #44492) want to exclude hits on faces that butt up to the hitting element * (e.g., when you double an edge by an edge split). */ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data) @@ -2975,10 +2975,10 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) face_tol = KNIFE_FLT_EPS_PX_FACE; } else { - /* Use 1/100th of a pixel, see T43896 (too big), T47910 (too small). + /* Use 1/100th of a pixel, see #43896 (too big), #47910 (too small). * * Update, leave this as is until we investigate not using pixel coords - * for geometry calculations: T48023. */ + * for geometry calculations: #48023. */ vert_tol = line_tol = face_tol = 0.5f; } @@ -3017,7 +3017,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) /* If this isn't from an existing BMVert, it may have been added to a BMEdge originally. * Knowing if the hit comes from an edge is important for edge-in-face checks later on. - * See: #knife_add_single_cut -> #knife_verts_edge_in_face, T42611. */ + * See: #knife_add_single_cut -> #knife_verts_edge_in_face, #42611. */ if (kfe_hit) { hit.kfe = kfe_hit; } @@ -4082,7 +4082,7 @@ static void knifetool_init(ViewContext *vc, const bool is_interactive) { /* Needed so multiple non-interactive cuts (also called knife-project) - * doesn't access indices of loops that were created by cutting, see: T97153. */ + * doesn't access indices of loops that were created by cutting, see: #97153. */ bool use_tri_indices = !is_interactive; kcd->vc = *vc; @@ -4303,7 +4303,7 @@ static void knifetool_finish_single_pre(KnifeTool_OpData *kcd, Object *ob) /** * A post version is needed to delay recalculating tessellation after making cuts. - * Without this, knife-project can't use the BVH tree to select geometry after a cut, see: T98349. + * Without this, knife-project can't use the BVH tree to select geometry after a cut, see: #98349. */ static void knifetool_finish_single_post(KnifeTool_OpData *UNUSED(kcd), Object *ob) { @@ -4322,7 +4322,7 @@ static void knifetool_finish_ex(KnifeTool_OpData *kcd) { /* Separate pre/post passes are needed because `em->looptris` recalculation from the 'post' pass * causes triangle indices in #KnifeTool_OpData.bvh to get out of sync. - * So perform all the cuts before doing any mesh recalculation, see: T101721. */ + * So perform all the cuts before doing any mesh recalculation, see: #101721. */ for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) { Object *ob = kcd->objects[ob_index]; knifetool_finish_single_pre(kcd, ob); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 9a91d7836fea..b3a74be6f0cf 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -176,7 +176,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) /* Enable grid-fill, so that intersecting loop-cut works as one would expect. * Note though that it will break edge-slide in this specific case. - * See T31939. */ + * See #31939. */ BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, smoothness, @@ -193,7 +193,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) 0); /* when used in a macro the tessfaces will be recalculated anyway, - * this is needed here because modifiers depend on updated tessellation, see T45920 */ + * this is needed here because modifiers depend on updated tessellation, see #45920 */ EDBM_update(lcd->ob->data, &(const struct EDBMUpdate_Params){ .calc_looptri = true, diff --git a/source/blender/editors/mesh/editmesh_mask_extract.cc b/source/blender/editors/mesh/editmesh_mask_extract.cc index cea882b0db7d..83580b328840 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.cc +++ b/source/blender/editors/mesh/editmesh_mask_extract.cc @@ -289,7 +289,7 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op) * the OPTYPE_UNDO flag; having an initial undo step here * is just needed to preserve the active object pointer. * - * Fixes T103261. + * Fixes #103261. */ ED_undo_push_op(C, op); diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 533b2b43b164..cbc217fe5ae3 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -768,7 +768,7 @@ static int edbm_rip_invoke__vert(bContext *C, const wmEvent *event, Object *obed if (do_fill) { /* Only needed when filling... * Also, we never want to tag best edge, - * that one won't change during split. See T44618. */ + * that one won't change during split. See #44618. */ if (larr[larr_len]->e == e_best) { BM_elem_flag_enable(larr[larr_len]->prev->e, BM_ELEM_TAG); } diff --git a/source/blender/editors/mesh/editmesh_select.cc b/source/blender/editors/mesh/editmesh_select.cc index b911da376b4b..94c2e3352b35 100644 --- a/source/blender/editors/mesh/editmesh_select.cc +++ b/source/blender/editors/mesh/editmesh_select.cc @@ -5203,7 +5203,7 @@ static int verg_radial(const void *va, const void *vb) * This function leaves faces tagged which are a part of the new region. * * \note faces already tagged are ignored, to avoid finding the same regions twice: - * important when we have regions with equal face counts, see: T40309 + * important when we have regions with equal face counts, see: #40309 */ static int loop_find_regions(BMEditMesh *em, const bool selbigger) { diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index d9721db326a1..78a54c978557 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -1427,7 +1427,7 @@ void MESH_OT_select_similar(wmOperatorType *ot) RNA_def_enum(ot->srna, "compare", prop_similar_compare_types, SIM_CMP_EQ, "Compare", ""); prop = RNA_def_float(ot->srna, "threshold", 0.0f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f); - /* Very small values are needed sometimes, similar area of small faces for e.g: see T87823 */ + /* Very small values are needed sometimes, similar area of small faces for e.g: see #87823 */ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 5); } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index caa94a3f49dd..2c13d09aa4fe 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -849,7 +849,7 @@ static BMElem *edbm_add_edge_face_exec__tricky_extend_sel(BMesh *bm) (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) && (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) || -# if 1 /* better support mixed cases T37203. */ +# if 1 /* better support mixed cases #37203. */ ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) == 1) && (edbm_add_edge_face_exec__vert_edge_lookup( @@ -5184,7 +5184,7 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op) int offset; /* Only reuse on redo because these settings need to match the current selection. - * We never want to use them on other geometry, repeat last for eg, see: T60777. */ + * We never want to use them on other geometry, repeat last for eg, see: #60777. */ if (((op->flag & OP_IS_INVOKE) || (op->flag & OP_IS_REPEAT_LAST) == 0) && RNA_property_is_set(op->ptr, prop_span)) { span = RNA_property_int_get(op->ptr, prop_span); @@ -8774,7 +8774,7 @@ static int edbm_point_normals_modal(bContext *C, wmOperator *op, const wmEvent * } /* If we allow other tools to run, we can't be sure if they will re-allocate - * the data this operator uses, see: T68159. + * the data this operator uses, see: #68159. * Free the data here, then use #point_normals_ensure to add it back on demand. */ if (ret == OPERATOR_PASS_THROUGH) { /* Don't free on mouse-move, causes creation/freeing of the loop data in an inefficient way. */ @@ -9055,7 +9055,7 @@ static int normals_split_merge(bContext *C, const bool do_merge) BKE_editmesh_lnorspace_update(em, obedit->data); /* Note that we need temp lnor editing data for all loops of all affected vertices, since by - * setting some faces/edges as smooth we are going to change clnors spaces... See also T65809. + * setting some faces/edges as smooth we are going to change clnors spaces... See also #65809. */ BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm, true) : diff --git a/source/blender/editors/mesh/editmesh_undo.cc b/source/blender/editors/mesh/editmesh_undo.cc index 565ce28a3c17..2278a96c0776 100644 --- a/source/blender/editors/mesh/editmesh_undo.cc +++ b/source/blender/editors/mesh/editmesh_undo.cc @@ -92,7 +92,7 @@ struct UndoMesh { /** \note * This isn't a perfect solution, if you edit keys and change shapes this works well - * (fixing T32442), but editing shape keys, going into object mode, removing or changing their + * (fixing #32442), but editing shape keys, going into object mode, removing or changing their * order, then go back into editmode and undo will give issues - where the old index will be * out of sync with the new object index. * @@ -156,7 +156,7 @@ static void um_arraystore_cd_compact(CustomData *cdata, * Unfortunately we can't compare dynamic layer types as they contain allocated pointers, * which burns CPU cycles looking for duplicate data that doesn't exist. * The array data isn't comparable once copied from the mesh, - * this bottlenecks on high poly meshes, see T84114. + * this bottlenecks on high poly meshes, see #84114. * * Notes: * diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index cde57c7226b2..b9cc57791396 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -294,7 +294,7 @@ void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) Mesh *me = ob->data; BMesh *bm = me->edit_mesh->bm; - /* Workaround for T42360, 'ob->shapenr' should be 1 in this case. + /* Workaround for #42360, 'ob->shapenr' should be 1 in this case. * however this isn't synchronized between objects at the moment. */ if (UNLIKELY((ob->shapenr == 0) && (me->key && !BLI_listbase_is_empty(&me->key->block)))) { bm->shapenr = 1; @@ -958,7 +958,7 @@ static bool seam_connected(BMLoop *loop_a, BMLoop *loop_b, GSet *visited, int cd loop_a->e, luv_anchor, luv_next_fan, loop_b, visited, cd_loop_uv_offset); if (!result) { /* Search around `loop_a` in the opposite direction, as one of the edges may be delimited by - * a boundary, seam or disjoint UV, or itself be one of these. See: T103670, T103787. */ + * a boundary, seam or disjoint UV, or itself be one of these. See: #103670, #103787. */ const float *luv_prev_fan = BM_ELEM_CD_GET_FLOAT_P(loop_a->prev, cd_loop_uv_offset); result = seam_connected_recursive( loop_a->prev->e, luv_anchor, luv_prev_fan, loop_b, visited, cd_loop_uv_offset); @@ -1428,7 +1428,7 @@ BMEdge *EDBM_verts_mirror_get_edge(BMEditMesh *em, BMEdge *e) BMVert *v1_mirr, *v2_mirr; if ((v1_mirr = EDBM_verts_mirror_get(em, e->v1)) && (v2_mirr = EDBM_verts_mirror_get(em, e->v2)) && - /* While highly unlikely, a zero length central edges vertices can match, see T89342. */ + /* While highly unlikely, a zero length central edges vertices can match, see #89342. */ LIKELY(v1_mirr != v2_mirr)) { return BM_edge_exists(v1_mirr, v2_mirr); } @@ -1924,31 +1924,40 @@ void EDBM_project_snap_verts( ED_view3d_init_mats_rv3d(obedit, region->regiondata); - struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create( - CTX_data_scene(C), 0); + Scene *scene = CTX_data_scene(C); + struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create(scene, 0); + + eSnapTargetOP target_op = SCE_SNAP_TARGET_NOT_ACTIVE; + const int snap_flag = scene->toolsettings->snap_flag; + + SET_FLAG_FROM_TEST( + target_op, !(snap_flag & SCE_SNAP_TO_INCLUDE_EDITED), SCE_SNAP_TARGET_NOT_EDITED); + SET_FLAG_FROM_TEST( + target_op, !(snap_flag & SCE_SNAP_TO_INCLUDE_NONEDITED), SCE_SNAP_TARGET_NOT_NONEDITED); + SET_FLAG_FROM_TEST( + target_op, (snap_flag & SCE_SNAP_TO_ONLY_SELECTABLE), SCE_SNAP_TARGET_ONLY_SELECTABLE); BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { float mval[2], co_proj[3]; if (ED_view3d_project_float_object(region, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - if (ED_transform_snap_object_project_view3d( - snap_context, - depsgraph, - region, - CTX_wm_view3d(C), - SCE_SNAP_MODE_FACE_RAYCAST, - &(const struct SnapObjectParams){ - .snap_target_select = SCE_SNAP_TARGET_NOT_ACTIVE, - .edit_mode_type = SNAP_GEOM_FINAL, - .use_occlusion_test = true, - }, - NULL, - mval, - NULL, - NULL, - co_proj, - NULL)) { + if (ED_transform_snap_object_project_view3d(snap_context, + depsgraph, + region, + CTX_wm_view3d(C), + SCE_SNAP_MODE_FACE_RAYCAST, + &(const struct SnapObjectParams){ + .snap_target_select = target_op, + .edit_mode_type = SNAP_GEOM_FINAL, + .use_occlusion_test = true, + }, + NULL, + mval, + NULL, + NULL, + co_proj, + NULL)) { mul_v3_m4v3(eve->co, obedit->world_to_object, co_proj); } } diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 263f7164fe6b..5f9af1480159 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -1534,8 +1534,13 @@ void ED_mesh_split_faces(Mesh *mesh) const Span polys = mesh->polys(); const Span loops = mesh->loops(); const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI); + const bke::AttributeAccessor attributes = mesh->attributes(); + const VArray mesh_sharp_edges = attributes.lookup_or_default( + "sharp_edge", ATTR_DOMAIN_EDGE, false); + + Array sharp_edges(mesh->totedge); + mesh_sharp_edges.materialize(sharp_edges); - Array sharp_edges(mesh->totedge, false); BKE_edges_sharp_from_angle_set(mesh->totedge, loops.data(), loops.size(), diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 856918fa3652..ae22458a2980 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -120,6 +120,10 @@ void MESH_OT_primitive_ico_sphere_add(struct wmOperatorType *ot); void MESH_OT_primitive_cube_add_gizmo(struct wmOperatorType *ot); +/* *** editmesh_attribute.cc *** */ + +void MESH_OT_attribute_set(struct wmOperatorType *ot); + /* *** editmesh_bevel.c *** */ void MESH_OT_bevel(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index b9afeae275b4..226c35a0637f 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -54,6 +54,8 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_primitive_cube_add_gizmo); + WM_operatortype_append(MESH_OT_attribute_set); + WM_operatortype_append(MESH_OT_duplicate); WM_operatortype_append(MESH_OT_remove_doubles); WM_operatortype_append(MESH_OT_spin); diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc index b2cbb8c47eac..1534d2c14644 100644 --- a/source/blender/editors/mesh/meshtools.cc +++ b/source/blender/editors/mesh/meshtools.cc @@ -421,7 +421,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) /* Clear any run-time data. * Even though this mesh wont typically have run-time data, the Python API can for e.g. - * create loop-triangle cache here, which is confusing when left in the mesh, see: T90798. */ + * create loop-triangle cache here, which is confusing when left in the mesh, see: #90798. */ BKE_mesh_runtime_clear_geometry(me); /* new material indices and material array */ @@ -601,7 +601,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) /* Add back active mesh first. * This allows to keep things similar as they were, as much as possible * (i.e. data from active mesh will remain first ones in new result of the merge, - * in same order for CD layers, etc). See also T50084. + * in same order for CD layers, etc). See also #50084. */ join_mesh_single(depsgraph, bmain, diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index 3035fdd381bf..3d24e09b53cd 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -2846,7 +2846,7 @@ static Base *duplibase_for_convert( * having same 'family name' as orig ones, they will affect end result of meta-ball computation. * For until we get rid of that name-based thingy in meta-balls, that should do the trick * (this is weak, but other solution (to change name of `obn`) is even worse IMHO). - * See T65996. */ + * See #65996. */ const bool is_meta_ball = (obn->type == OB_MBALL); void *obdata = obn->data; if (is_meta_ball) { @@ -2930,7 +2930,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* Ensure we get all meshes calculated with a sufficient data-mask, * needed since re-evaluating single modifiers causes bugs if they depend - * on other objects data masks too, see: T50950. */ + * on other objects data masks too, see: #50950. */ { LISTBASE_FOREACH (CollectionPointerLink *, link, &selected_editable_bases) { Base *base = static_cast(link->ptr.data); @@ -2975,7 +2975,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) /* obdata already modified */ if (!IS_TAGGED(ob->data)) { /* When 2 objects with linked data are selected, converting both - * would keep modifiers on all but the converted object T26003. */ + * would keep modifiers on all but the converted object #26003. */ if (ob->type == OB_MESH) { BKE_object_free_modifiers(ob, 0); /* after derivedmesh calls! */ } @@ -3708,7 +3708,7 @@ Base *ED_object_add_duplicate( ob = basen->object; - /* Link own references to the newly duplicated data T26816. + /* Link own references to the newly duplicated data #26816. * Note that this function can be called from edit-mode code, in which case we may have to * enforce remapping obdata (by default this is forbidden in edit mode). */ const int remap_flag = BKE_object_is_in_editmode(ob) ? ID_REMAP_FORCE_OBDATA_IN_EDITMODE : 0; @@ -4156,7 +4156,7 @@ static int object_join_exec(bContext *C, wmOperator *op) if (ret & OPERATOR_FINISHED) { /* Even though internally failure to invert is accounted for with a fallback, - * show a warning since the result may not be what the user expects. See T80077. + * show a warning since the result may not be what the user expects. See #80077. * * Failure to invert the matrix is typically caused by zero scaled axes * (which can be caused by constraints, even if the input scale isn't zero). diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index d1473f8dd7a0..ec0f48d62084 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -608,7 +608,7 @@ static bool ED_object_editmode_load_free_ex(Main *bmain, if (load_data == false) { /* Don't keep unused pose channels created by duplicating bones - * which may have been deleted/undone, see: T87631. */ + * which may have been deleted/undone, see: #87631. */ if (obedit->pose != NULL) { BKE_pose_channels_clear_with_null_bone(obedit->pose, true); } @@ -701,10 +701,10 @@ bool ED_object_editmode_exit_ex(Main *bmain, Scene *scene, Object *obedit, int f if (ED_object_editmode_load_free_ex(bmain, obedit, true, free_data) == false) { /* in rare cases (background mode) its possible active object - * is flagged for editmode, without 'obedit' being set T35489. */ + * is flagged for editmode, without 'obedit' being set #35489. */ if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) { obedit->mode &= ~OB_MODE_EDIT; - /* Also happens when mesh is shared across multiple objects. [#T69834] */ + /* Also happens when mesh is shared across multiple objects. #69834. */ DEG_id_tag_update(&obedit->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); } return true; @@ -789,7 +789,7 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag /* This checks actual `ob->data`, for cases when other scenes have it in edit-mode context. * Currently multiple objects sharing a mesh being in edit-mode at once isn't supported, - * see: T86767. */ + * see: #86767. */ if (BKE_object_is_in_editmode(ob)) { return true; } diff --git a/source/blender/editors/object/object_modes.cc b/source/blender/editors/object/object_modes.cc index 95b487c199dc..f0874c48f6e4 100644 --- a/source/blender/editors/object/object_modes.cc +++ b/source/blender/editors/object/object_modes.cc @@ -142,12 +142,7 @@ bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode) } break; case OB_CURVES: - if (U.experimental.use_new_curves_tools) { - if (mode & OB_MODE_EDIT) { - return true; - } - } - if (mode & OB_MODE_SCULPT_CURVES) { + if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT_CURVES)) { return true; } break; diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index 15d90729e9f3..c332c8a91fcc 100644 --- a/source/blender/editors/object/object_modifier.cc +++ b/source/blender/editors/object/object_modifier.cc @@ -155,7 +155,7 @@ ModifierData *ED_object_modifier_add( ModifierData *md = nullptr, *new_md = nullptr; const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)type); - /* Check compatibility of modifier [T25291, T50373]. */ + /* Check compatibility of modifier [#25291, #50373]. */ if (!BKE_object_support_modifier_type_check(ob, type)) { BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2); return nullptr; @@ -742,7 +742,7 @@ static void add_shapekey_layers(Mesh &mesh_dest, const Mesh &mesh_src) /** * \param use_virtual_modifiers: When enabled, calculate virtual-modifiers before applying * `md_eval`. This is supported because virtual-modifiers are not modifiers from a user - * perspective, allowing shape keys to be included with the modifier being applied, see: T91923. + * perspective, allowing shape keys to be included with the modifier being applied, see: #91923. */ static Mesh *create_applied_mesh_for_modifier(Depsgraph *depsgraph, Scene *scene, @@ -983,7 +983,7 @@ static bool modifier_apply_obdata( DEG_get_evaluated_object(depsgraph, ob), md_eval, /* It's important not to apply virtual modifiers (e.g. shape-keys) because they're kept, - * causing them to be applied twice, see: T97758. */ + * causing them to be applied twice, see: #97758. */ false, true, reports); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 0af1e9087899..0ceec68e0dbc 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -414,7 +414,7 @@ void ED_object_parent_clear(Object *ob, const int type) } } - /* Always clear parentinv matrix for sake of consistency, see T41950. */ + /* Always clear parentinv matrix for sake of consistency, see #41950. */ unit_m4(ob->parentinv); DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION); @@ -462,7 +462,7 @@ void OBJECT_OT_parent_clear(wmOperatorType *ot) void ED_object_parent(Object *ob, Object *par, const int type, const char *substr) { - /* Always clear parentinv matrix for sake of consistency, see T41950. */ + /* Always clear parentinv matrix for sake of consistency, see #41950. */ unit_m4(ob->parentinv); if (!par || BKE_object_parent_loop_check(par, ob)) { @@ -584,15 +584,15 @@ bool ED_object_parent_set(ReportList *reports, /* Apply transformation of previous parenting. */ if (keep_transform) { - /* Was removed because of bug T23577, - * but this can be handy in some cases too T32616, so make optional. */ + /* Was removed because of bug #23577, + * but this can be handy in some cases too #32616, so make optional. */ BKE_object_apply_mat4(ob, ob->object_to_world, false, false); } /* Set the parent (except for follow-path constraint option). */ if (partype != PAR_PATH_CONST) { ob->parent = par; - /* Always clear parentinv matrix for sake of consistency, see T41950. */ + /* Always clear parentinv matrix for sake of consistency, see #41950. */ unit_m4(ob->parentinv); DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); } @@ -1754,7 +1754,7 @@ static Collection *single_object_users_collection(Main *bmain, /* Since master collection has already be duplicated as part of scene copy, * we do not duplicate it here. * However, this means its children need to be re-added manually here, - * otherwise their parent lists are empty (which will lead to crashes, see T63101). */ + * otherwise their parent lists are empty (which will lead to crashes, see #63101). */ CollectionChild *child_next, *child = collection->children.first; CollectionChild *orig_child_last = collection->children.last; for (; child != NULL; child = child_next) { @@ -2074,7 +2074,7 @@ static void tag_localizable_objects(bContext *C, const int mode) /** * Instance indirectly referenced zero user objects, - * otherwise they're lost on reload, see T40595. + * otherwise they're lost on reload, see #40595. */ static bool make_local_all__instance_indirect_unused(Main *bmain, const Scene *scene, @@ -2727,7 +2727,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "obdata")) { single_obdata_users(bmain, scene, view_layer, v3d, flag); - /* Needed since some IDs were remapped? (incl. me->texcomesh, see T73797). */ + /* Needed since some IDs were remapped? (incl. me->texcomesh, see #73797). */ update_deps = true; } diff --git a/source/blender/editors/object/object_vgroup.cc b/source/blender/editors/object/object_vgroup.cc index b1066c02ee4c..987fb545264c 100644 --- a/source/blender/editors/object/object_vgroup.cc +++ b/source/blender/editors/object/object_vgroup.cc @@ -2945,7 +2945,7 @@ void OBJECT_OT_vertex_group_remove(wmOperatorType *ot) /* flags */ /* redo operator will fail in this case because vertex groups aren't stored * in local edit mode stack and toggling "all" property will lead to - * all groups deleted without way to restore them (see T29527, sergey) */ + * all groups deleted without way to restore them (see #29527, sergey) */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ @@ -2988,7 +2988,7 @@ void OBJECT_OT_vertex_group_assign(wmOperatorType *ot) /* flags */ /* redo operator will fail in this case because vertex group assignment * isn't stored in local edit mode stack and toggling "new" property will - * lead to creating plenty of new vertex groups (see T29527, sergey) */ + * lead to creating plenty of new vertex groups (see #29527, sergey) */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; } @@ -3023,7 +3023,7 @@ void OBJECT_OT_vertex_group_assign_new(wmOperatorType *ot) /* flags */ /* redo operator will fail in this case because vertex group assignment * isn't stored in local edit mode stack and toggling "new" property will - * lead to creating plenty of new vertex groups (see T29527, sergey) */ + * lead to creating plenty of new vertex groups (see #29527, sergey) */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; } @@ -3075,7 +3075,7 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) /* flags */ /* redo operator will fail in this case because vertex groups assignment * isn't stored in local edit mode stack and toggling "all" property will lead to - * removing vertices from all groups (see T29527, sergey) */ + * removing vertices from all groups (see #29527, sergey) */ ot->flag = /*OPTYPE_REGISTER|*/ OPTYPE_UNDO; /* properties */ diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index a3117f46bb99..ccee930d769f 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3958,7 +3958,7 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) /* blend between the current and straight position */ sub_v3_v3v3(dco, kco, co); madd_v3_v3fl(co, dco, fac); - /* keep the same distance from the root or we get glitches T35406. */ + /* keep the same distance from the root or we get glitches #35406. */ dist_ensure_v3_v3fl(co, co_root, length_accum); /* Re-use dco to compare before and after translation and add to the offset. */ diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 8c26b9caf919..846e138e958b 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -676,7 +676,7 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) ot->exec = disconnect_hair_exec; /* flags */ - /* No REGISTER, redo does not work due to missing update, see T47750. */ + /* No REGISTER, redo does not work due to missing update, see #47750. */ ot->flag = OPTYPE_UNDO; RNA_def_boolean( @@ -978,7 +978,7 @@ void PARTICLE_OT_connect_hair(wmOperatorType *ot) ot->exec = connect_hair_exec; /* flags */ - /* No REGISTER, redo does not work due to missing update, see T47750. */ + /* No REGISTER, redo does not work due to missing update, see #47750. */ ot->flag = OPTYPE_UNDO; RNA_def_boolean(ot->srna, "all", 0, "All Hair", "Connect all hair systems to the emitter mesh"); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index d5e55c99444d..7c6747285287 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -166,7 +166,7 @@ static bool fluid_validatepaths(FluidJob *job, ReportList *reports) const char *relbase = BKE_modifier_path_relbase(job->bmain, job->ob); - /* We do not accept empty paths, they can end in random places silently, see T51176. */ + /* We do not accept empty paths, they can end in random places silently, see #51176. */ if (fds->cache_directory[0] == '\0') { char cache_name[64]; BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name); diff --git a/source/blender/editors/render/render_internal.cc b/source/blender/editors/render/render_internal.cc index 5abf5867f926..39ac4b95159a 100644 --- a/source/blender/editors/render/render_internal.cc +++ b/source/blender/editors/render/render_internal.cc @@ -716,7 +716,7 @@ static void render_endjob(void *rjv) /* This render may be used again by the sequencer without the active * 'Render' where the callbacks would be re-assigned. assign dummy callbacks - * to avoid referencing freed render-jobs bug T24508. */ + * to avoid referencing freed render-jobs bug #24508. */ RE_InitRenderCB(rj->re); if (rj->main != G_MAIN) { @@ -1073,7 +1073,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even /* store actual owner of job, so modal operator could check for it, * the reason of this is that active scene could change when rendering - * several layers from compositor T31800. */ + * several layers from compositor #31800. */ op->customdata = scene; WM_jobs_start(CTX_wm_manager(C), wm_job); diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 18bfad0d0428..57245558f705 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -661,7 +661,7 @@ static bool ed_preview_draw_rect(ScrArea *area, int split, int first, rcti *rect rv = RE_RenderViewGetById(&rres, 0); } else { - /* possible the job clears the views but we're still drawing T45496 */ + /* possible the job clears the views but we're still drawing #45496 */ rv = nullptr; } @@ -1372,7 +1372,7 @@ static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect) scaledy = float(h); } - /* Scaling down must never assign zero width/height, see: T89868. */ + /* Scaling down must never assign zero width/height, see: #89868. */ ex = MAX2(1, short(scaledx)); ey = MAX2(1, short(scaledy)); diff --git a/source/blender/editors/render/render_shading.cc b/source/blender/editors/render/render_shading.cc index c62483daf6be..5ea01677a8e8 100644 --- a/source/blender/editors/render/render_shading.cc +++ b/source/blender/editors/render/render_shading.cc @@ -216,7 +216,7 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* Removing material slots in edit mode screws things up, see bug T21822. */ + /* Removing material slots in edit mode screws things up, see bug #21822. */ if (ob == CTX_data_edit_object(C)) { BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode"); return OPERATOR_CANCELLED; @@ -663,7 +663,7 @@ void OBJECT_OT_material_slot_move(wmOperatorType *ot) static int material_slot_remove_unused_exec(bContext *C, wmOperator *op) { - /* Removing material slots in edit mode screws things up, see bug T21822. */ + /* Removing material slots in edit mode screws things up, see bug #21822. */ Object *ob_active = CTX_data_active_object(C); if (ob_active && BKE_object_is_in_editmode(ob_active)) { BKE_report(op->reports, RPT_ERROR, "Unable to remove material slot in edit mode"); @@ -771,7 +771,7 @@ static int new_material_exec(bContext *C, wmOperator * /*op*/) if (prop) { if (ob != nullptr) { /* Add slot follows user-preferences for creating new slots, - * RNA pointer assignment doesn't, see: T60014. */ + * RNA pointer assignment doesn't, see: #60014. */ if (BKE_object_material_get_p(ob, ob->actcol) == nullptr) { BKE_object_material_slot_add(bmain, ob); } @@ -1434,7 +1434,7 @@ static int light_cache_bake_invoke(bContext *C, wmOperator *op, const wmEvent * /* store actual owner of job, so modal operator could check for it, * the reason of this is that active scene could change when rendering - * several layers from compositor T31800. */ + * several layers from compositor #31800. */ op->customdata = scene; WM_jobs_start(wm, wm_job); @@ -1509,7 +1509,7 @@ static int light_cache_free_exec(bContext *C, wmOperator * /*op*/) { Scene *scene = CTX_data_scene(C); - /* kill potential bake job first (see T57011) */ + /* kill potential bake job first (see #57011) */ wmWindowManager *wm = CTX_wm_manager(C); WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_LIGHT_BAKE); diff --git a/source/blender/editors/render/render_update.cc b/source/blender/editors/render/render_update.cc index 8aadb9edf6a7..c61e26d4c7c6 100644 --- a/source/blender/editors/render/render_update.cc +++ b/source/blender/editors/render/render_update.cc @@ -128,7 +128,7 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, const bool return; } - /* Do not call if no WM available, see T42688. */ + /* Do not call if no WM available, see #42688. */ if (BLI_listbase_is_empty(&bmain->wm)) { return; } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c3df23500d46..574cefceb36c 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1510,7 +1510,7 @@ static void region_rect_recursive( } /* Fix any negative dimensions. This can happen when a quad split 3d view gets too small. - * (see T72200). */ + * (see #72200). */ BLI_rcti_sanitize(®ion->winrct); quad++; @@ -1622,7 +1622,7 @@ static void area_calc_totrct(ScrArea *area, const rcti *window_rect) /* Although the following asserts are correct they lead to a very unstable Blender. * And the asserts would fail even in 2.7x * (they were added in 2.8x as part of the top-bar commit). - * For more details see T54864. */ + * For more details see #54864. */ #if 0 BLI_assert(area->totrct.xmin >= 0); BLI_assert(area->totrct.xmax >= 0); @@ -1738,7 +1738,7 @@ static void ed_default_handlers( WM_event_add_keymap_handler(®ion->handlers, keymap); } - /* Keep last because of LMB/RMB handling, see: T57527. */ + /* Keep last because of LMB/RMB handling, see: #57527. */ if (flag & ED_KEYMAP_GPENCIL) { /* grease pencil */ /* NOTE: This is now 4 keymaps - One for basic functionality, @@ -2082,7 +2082,7 @@ void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *reg if (region->flag & RGN_FLAG_HIDDEN) { WM_event_remove_handlers(C, ®ion->handlers); /* Needed to close any open pop-overs which would otherwise remain open, - * crashing on attempting to refresh. See: T93410. + * crashing on attempting to refresh. See: #93410. * * When #ED_area_init frees buttons via #UI_blocklist_free a NULL context * is passed, causing the free not to remove menus or their handlers. */ @@ -2430,7 +2430,7 @@ void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_regi * changing the header-type is jarring (especially when using Ctrl-MouseWheel). * * However, add-on install for example, forces the header to the top which shouldn't - * be applied back to the previous space type when closing - see: T57724 + * be applied back to the previous space type when closing - see: #57724 * * Newly-created windows won't have any space data, use the alignment * the space type defaults to in this case instead @@ -3362,7 +3362,7 @@ void ED_region_header_layout(const bContext *C, ARegion *region) UI_block_end(C, block); /* In most cases there is only ever one header, it never makes sense to draw more than one - * header in the same region, this results in overlapping buttons, see: T60195. */ + * header in the same region, this results in overlapping buttons, see: #60195. */ break; } @@ -3516,7 +3516,7 @@ void ED_region_info_draw_multiline(ARegion *region, /* background box */ rcti rect = *ED_region_visible_rect(region); - /* Needed in case scripts leave the font size at an unexpected value, see: T102213. */ + /* Needed in case scripts leave the font size at an unexpected value, see: #102213. */ BLF_size(fontid, style->widget.points * U.dpi_fac); /* Box fill entire width or just around text. */ diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 065cb3a61a24..384aeccfc4c7 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -175,7 +175,7 @@ void ED_screen_draw_edges(wmWindow *win) if (GPU_type_matches_ex(GPU_DEVICE_INTEL_UHD, GPU_OS_UNIX, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) { /* For some reason, on linux + Intel UHD Graphics 620 the driver - * hangs if we don't flush before this. (See T57455) */ + * hangs if we don't flush before this. (See #57455) */ GPU_flush(); } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index d1ec6d8b7b16..2ec1f499a4a6 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -377,7 +377,7 @@ static bool screen_areas_can_align(bScreen *screen, ScrArea *sa1, ScrArea *sa2, return false; } - /* Areas that are _smaller_ than minimum sizes, sharing an edge to be moved. See T100772. */ + /* Areas that are _smaller_ than minimum sizes, sharing an edge to be moved. See #100772. */ if (SCREEN_DIR_IS_VERTICAL(dir)) { const short xmin = MIN2(sa1->v1->vec.x, sa2->v1->vec.x); const short xmax = MAX2(sa1->v3->vec.x, sa2->v3->vec.x); @@ -1531,7 +1531,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const /* After we've restored back to SCREENNORMAL, we have to wait with * screen handling as it uses the area coords which aren't updated yet. * Without doing so, the screen handling gets wrong area coords, - * which in worst case can lead to crashes (see T43139) */ + * which in worst case can lead to crashes (see #43139) */ screen->skip_handling = true; } else { @@ -1555,7 +1555,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const /* Setting the area is only needed for Python scripts that call * operators in succession before returning to the main event loop. * Without this, scripts can't run any operators that require - * an area after toggling full-screen for example (see: T89526). + * an area after toggling full-screen for example (see: #89526). * NOTE: an old comment stated this was "bad code", * however it doesn't cause problems so leave as-is. */ CTX_wm_area_set(C, screen->areabase.first); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index a064f4632b55..80e5da43423d 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2742,7 +2742,7 @@ static void region_scale_validate_size(RegionMoveData *rmd) static void region_scale_toggle_hidden(bContext *C, RegionMoveData *rmd) { /* hidden areas may have bad 'View2D.cur' value, - * correct before displaying. see T45156 */ + * correct before displaying. see #45156 */ if (rmd->region->flag & RGN_FLAG_HIDDEN) { UI_view2d_curRect_validate(&rmd->region->v2d); } @@ -3946,7 +3946,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op) rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT; rv3d->viewlock = 0; - /* FIXME: This fixes missing update to workbench TAA. (see T76216) + /* FIXME: This fixes missing update to workbench TAA. (see #76216) * However, it would be nice if the tagging should be done in a more conventional way. */ rv3d->rflag |= RV3D_GPULIGHT_UPDATE; @@ -3988,7 +3988,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op) /* run ED_view3d_lock() so the correct 'rv3d->viewquat' is set, * otherwise when restoring rv3d->localvd the 'viewquat' won't - * match the 'view', set on entering localview See: T26315, + * match the 'view', set on entering localview See: #26315, * * We could avoid manipulating rv3d->localvd here if exiting * localview with a 4-split would assign these view locks */ diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc index b9e1673742ec..c3d7734dd36d 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc @@ -22,6 +22,8 @@ #include "BLT_translation.h" +#include "GEO_curve_constraints.hh" + /** * The code below uses a prefix naming convention to indicate the coordinate space: * cu: Local space of the curves object that is being edited. @@ -431,4 +433,40 @@ void report_invalid_uv_map(ReportList *reports) BKE_report(reports, RPT_WARNING, TIP_("Invalid UV map: UV islands must not overlap")); } +void CurvesConstraintSolver::initialize(const bke::CurvesGeometry &curves, + const IndexMask curve_selection, + const bool use_surface_collision) +{ + use_surface_collision_ = use_surface_collision; + segment_lengths_.reinitialize(curves.points_num()); + geometry::curve_constraints::compute_segment_lengths( + curves.points_by_curve(), curves.positions(), curve_selection, segment_lengths_); + if (use_surface_collision_) { + start_positions_ = curves.positions(); + } +} + +void CurvesConstraintSolver::solve_step(bke::CurvesGeometry &curves, + const IndexMask curve_selection, + const Mesh *surface, + const CurvesSurfaceTransforms &transforms) +{ + if (use_surface_collision_ && surface != nullptr) { + geometry::curve_constraints::solve_length_and_collision_constraints( + curves.points_by_curve(), + curve_selection, + segment_lengths_, + start_positions_, + *surface, + transforms, + curves.positions_for_write()); + start_positions_ = curves.positions(); + } + else { + geometry::curve_constraints::solve_length_constraints( + curves.points_by_curve(), curve_selection, segment_lengths_, curves.positions_for_write()); + } + curves.tag_positions_changed(); +} + } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc b/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc index 24a6a47555ca..79c175caf5f1 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc @@ -18,6 +18,7 @@ #include "BKE_attribute_math.hh" #include "BKE_brush.h" #include "BKE_bvhutils.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_crazyspace.hh" #include "BKE_curves.hh" @@ -66,8 +67,10 @@ class CombOperation : public CurvesSculptStrokeOperation { /** Only used when a 3D brush is used. */ CurvesBrush3D brush_3d_; - /** Length of each segment indexed by the index of the first point in the segment. */ - Array segment_lengths_cu_; + /** Solver for length and collision constraints. */ + CurvesConstraintSolver constraint_solver_; + + Array curve_lengths_; friend struct CombOperationExecutor; @@ -144,12 +147,24 @@ struct CombOperationExecutor { if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) { this->initialize_spherical_brush_reference_point(); } - this->initialize_segment_lengths(); + self_->constraint_solver_.initialize( + *curves_orig_, curve_selection_, curves_id_orig_->flag & CV_SCULPT_COLLISION_ENABLED); + + self_->curve_lengths_.reinitialize(curves_orig_->curves_num()); + const Span segment_lengths = self_->constraint_solver_.segment_lengths(); + const OffsetIndices points_by_curve = curves_orig_->points_by_curve(); + threading::parallel_for(curve_selection_.index_range(), 512, [&](const IndexRange range) { + for (const int curve_i : curve_selection_.slice(range)) { + const IndexRange points = points_by_curve[curve_i]; + const Span lengths = segment_lengths.slice(points.drop_back(1)); + self_->curve_lengths_[curve_i] = std::accumulate(lengths.begin(), lengths.end(), 0.0f); + } + }); /* Combing does nothing when there is no mouse movement, so return directly. */ return; } - EnumerableThreadSpecific> changed_curves; + Array changed_curves(curves_orig_->curves_num(), false); if (falloff_shape_ == PAINT_FALLOFF_SHAPE_TUBE) { this->comb_projected_with_symmetry(changed_curves); @@ -161,7 +176,14 @@ struct CombOperationExecutor { BLI_assert_unreachable(); } - this->restore_segment_lengths(changed_curves); + const Mesh *surface = curves_id_orig_->surface && curves_id_orig_->surface->type == OB_MESH ? + static_cast(curves_id_orig_->surface->data) : + nullptr; + + Vector indices; + const IndexMask changed_curves_mask = index_mask_ops::find_indices_from_array(changed_curves, + indices); + self_->constraint_solver_.solve_step(*curves_orig_, changed_curves_mask, surface, transforms_); curves_orig_->tag_positions_changed(); DEG_id_tag_update(&curves_id_orig_->id, ID_RECALC_GEOMETRY); @@ -172,7 +194,7 @@ struct CombOperationExecutor { /** * Do combing in screen space. */ - void comb_projected_with_symmetry(EnumerableThreadSpecific> &r_changed_curves) + void comb_projected_with_symmetry(MutableSpan r_changed_curves) { const Vector symmetry_brush_transforms = get_symmetry_brush_transforms( eCurvesSymmetryType(curves_id_orig_->symmetry)); @@ -181,8 +203,7 @@ struct CombOperationExecutor { } } - void comb_projected(EnumerableThreadSpecific> &r_changed_curves, - const float4x4 &brush_transform) + void comb_projected(MutableSpan r_changed_curves, const float4x4 &brush_transform) { const float4x4 brush_transform_inv = math::invert(brush_transform); @@ -197,12 +218,23 @@ struct CombOperationExecutor { const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_; const float brush_radius_sq_re = pow2f(brush_radius_re); + CurveMapping &curve_parameter_falloff_mapping = + *brush_->curves_sculpt_settings->curve_parameter_falloff; + BKE_curvemapping_init(&curve_parameter_falloff_mapping); + + const Span segment_lengths = self_->constraint_solver_.segment_lengths(); + threading::parallel_for(curve_selection_.index_range(), 256, [&](const IndexRange range) { - Vector &local_changed_curves = r_changed_curves.local(); for (const int curve_i : curve_selection_.slice(range)) { bool curve_changed = false; const IndexRange points = points_by_curve[curve_i]; + + const float total_length = self_->curve_lengths_[curve_i]; + const float total_length_inv = safe_divide(1.0f, total_length); + float current_length = 0.0f; for (const int point_i : points.drop_front(1)) { + current_length += segment_lengths[point_i - 1]; + const float3 old_pos_cu = deformation.positions[point_i]; const float3 old_symm_pos_cu = math::transform_point(brush_transform_inv, old_pos_cu); @@ -222,8 +254,12 @@ struct CombOperationExecutor { /* A falloff that is based on how far away the point is from the stroke. */ const float radius_falloff = BKE_brush_curve_strength( brush_, distance_to_brush_re, brush_radius_re); + const float curve_parameter = current_length * total_length_inv; + const float curve_falloff = BKE_curvemapping_evaluateF( + &curve_parameter_falloff_mapping, 0, curve_parameter); /* Combine the falloff and brush strength. */ - const float weight = brush_strength_ * radius_falloff * point_factors_[point_i]; + const float weight = brush_strength_ * curve_falloff * radius_falloff * + point_factors_[point_i]; /* Offset the old point position in screen space and transform it back into 3D space. */ @@ -246,7 +282,7 @@ struct CombOperationExecutor { curve_changed = true; } if (curve_changed) { - local_changed_curves.append(curve_i); + r_changed_curves[curve_i] = true; } } }); @@ -255,7 +291,7 @@ struct CombOperationExecutor { /** * Do combing in 3D space. */ - void comb_spherical_with_symmetry(EnumerableThreadSpecific> &r_changed_curves) + void comb_spherical_with_symmetry(MutableSpan r_changed_curves) { float4x4 projection; ED_view3d_ob_project_mat_get(ctx_.rv3d, curves_ob_orig_, projection.ptr()); @@ -289,7 +325,7 @@ struct CombOperationExecutor { } } - void comb_spherical(EnumerableThreadSpecific> &r_changed_curves, + void comb_spherical(MutableSpan r_changed_curves, const float3 &brush_start_cu, const float3 &brush_end_cu, const float brush_radius_cu) @@ -298,16 +334,26 @@ struct CombOperationExecutor { const float brush_radius_sq_cu = pow2f(brush_radius_cu); const float3 brush_diff_cu = brush_end_cu - brush_start_cu; + CurveMapping &curve_parameter_falloff_mapping = + *brush_->curves_sculpt_settings->curve_parameter_falloff; + BKE_curvemapping_init(&curve_parameter_falloff_mapping); + const bke::crazyspace::GeometryDeformation deformation = bke::crazyspace::get_evaluated_curves_deformation(*ctx_.depsgraph, *curves_ob_orig_); const OffsetIndices points_by_curve = curves_orig_->points_by_curve(); + const Span segment_lengths = self_->constraint_solver_.segment_lengths(); threading::parallel_for(curve_selection_.index_range(), 256, [&](const IndexRange range) { - Vector &local_changed_curves = r_changed_curves.local(); for (const int curve_i : curve_selection_.slice(range)) { bool curve_changed = false; const IndexRange points = points_by_curve[curve_i]; + + const float total_length = self_->curve_lengths_[curve_i]; + const float total_length_inv = safe_divide(1.0f, total_length); + float current_length = 0.0f; for (const int point_i : points.drop_front(1)) { + current_length += segment_lengths[point_i - 1]; + const float3 pos_old_cu = deformation.positions[point_i]; /* Compute distance to the brush. */ @@ -323,8 +369,12 @@ struct CombOperationExecutor { /* A falloff that is based on how far away the point is from the stroke. */ const float radius_falloff = BKE_brush_curve_strength( brush_, distance_to_brush_cu, brush_radius_cu); + const float curve_parameter = current_length * total_length_inv; + const float curve_falloff = BKE_curvemapping_evaluateF( + &curve_parameter_falloff_mapping, 0, curve_parameter); /* Combine the falloff and brush strength. */ - const float weight = brush_strength_ * radius_falloff * point_factors_[point_i]; + const float weight = brush_strength_ * curve_falloff * radius_falloff * + point_factors_[point_i]; const float3 translation_eval_cu = weight * brush_diff_cu; const float3 translation_orig_cu = deformation.translation_from_deformed_to_original( @@ -335,7 +385,7 @@ struct CombOperationExecutor { curve_changed = true; } if (curve_changed) { - local_changed_curves.append(curve_i); + r_changed_curves[curve_i] = true; } } }); @@ -357,53 +407,6 @@ struct CombOperationExecutor { self_->brush_3d_ = *brush_3d; } } - - /** - * Remember the initial length of all curve segments. This allows restoring the length after - * combing. - */ - void initialize_segment_lengths() - { - const Span positions_cu = curves_orig_->positions(); - const OffsetIndices points_by_curve = curves_orig_->points_by_curve(); - self_->segment_lengths_cu_.reinitialize(curves_orig_->points_num()); - threading::parallel_for(curves_orig_->curves_range(), 128, [&](const IndexRange range) { - for (const int curve_i : range) { - const IndexRange points = points_by_curve[curve_i]; - for (const int point_i : points.drop_back(1)) { - const float3 &p1_cu = positions_cu[point_i]; - const float3 &p2_cu = positions_cu[point_i + 1]; - const float length_cu = math::distance(p1_cu, p2_cu); - self_->segment_lengths_cu_[point_i] = length_cu; - } - } - }); - } - - /** - * Restore previously stored length for each segment in the changed curves. - */ - void restore_segment_lengths(EnumerableThreadSpecific> &changed_curves) - { - const Span expected_lengths_cu = self_->segment_lengths_cu_; - const OffsetIndices points_by_curve = curves_orig_->points_by_curve(); - MutableSpan positions_cu = curves_orig_->positions_for_write(); - - threading::parallel_for_each(changed_curves, [&](const Vector &changed_curves) { - threading::parallel_for(changed_curves.index_range(), 256, [&](const IndexRange range) { - for (const int curve_i : changed_curves.as_span().slice(range)) { - const IndexRange points = points_by_curve[curve_i]; - for (const int segment_i : points.drop_back(1)) { - const float3 &p1_cu = positions_cu[segment_i]; - float3 &p2_cu = positions_cu[segment_i + 1]; - const float3 direction = math::normalize(p2_cu - p1_cu); - const float expected_length_cu = expected_lengths_cu[segment_i]; - p2_cu = p1_cu + direction * expected_length_cu; - } - } - }); - }); - } }; void CombOperation::on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh index eb670d089e5a..11ee5628d425 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh @@ -144,4 +144,30 @@ void report_missing_uv_map_on_original_surface(ReportList *reports); void report_missing_uv_map_on_evaluated_surface(ReportList *reports); void report_invalid_uv_map(ReportList *reports); +/** + * Utility class to make it easy for brushes to implement length preservation and surface + * collision. + */ +struct CurvesConstraintSolver { + private: + bool use_surface_collision_; + Array start_positions_; + Array segment_lengths_; + + public: + void initialize(const bke::CurvesGeometry &curves, + const IndexMask curve_selection, + const bool use_surface_collision); + + void solve_step(bke::CurvesGeometry &curves, + const IndexMask curve_selection, + const Mesh *surface, + const CurvesSurfaceTransforms &transforms); + + Span segment_lengths() const + { + return segment_lengths_; + } +}; + } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index 89f0f9031df4..2b024c22b7d1 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -966,9 +966,8 @@ static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *cust const uint pos3d = GPU_vertformat_attr_add(format3d, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); const uint col3d = GPU_vertformat_attr_add(format3d, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); - - GPU_point_size(3.0f); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immUniform1f("size", 4.0f); immBegin(GPU_PRIM_POINTS, points_wo.size()); float3 brush_origin_wo = math::transform_point(op_data.curves_to_world_mat, op_data.pos_cu); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_pinch.cc b/source/blender/editors/sculpt_paint/curves_sculpt_pinch.cc index 9e3528d96eb5..dc854dc166d1 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_pinch.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_pinch.cc @@ -4,6 +4,7 @@ #include "curves_sculpt_intern.hh" +#include "BLI_index_mask_ops.hh" #include "BLI_math_matrix_types.hh" #include "BLI_task.hh" #include "BLI_vector.hh" @@ -42,7 +43,9 @@ namespace blender::ed::sculpt_paint { class PinchOperation : public CurvesSculptStrokeOperation { private: bool invert_pinch_; - Array segment_lengths_cu_; + + /** Solver for length and collision constraints. */ + CurvesConstraintSolver constraint_solver_; /** Only used when a 3D brush is used. */ CurvesBrush3D brush_3d_; @@ -115,8 +118,6 @@ struct PinchOperationExecutor { brush_->falloff_shape); if (stroke_extension.is_first) { - this->initialize_segment_lengths(); - if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) { self_->brush_3d_ = *sample_curves_3d_brush(*ctx_.depsgraph, *ctx_.region, @@ -126,6 +127,9 @@ struct PinchOperationExecutor { brush_pos_re_, brush_radius_base_re_); } + + self_->constraint_solver_.initialize( + *curves_, curve_selection_, curves_id_->flag & CV_SCULPT_COLLISION_ENABLED); } Array changed_curves(curves_->curves_num(), false); @@ -139,7 +143,14 @@ struct PinchOperationExecutor { BLI_assert_unreachable(); } - this->restore_segment_lengths(changed_curves); + Vector indices; + const IndexMask changed_curves_mask = index_mask_ops::find_indices_from_array(changed_curves, + indices); + const Mesh *surface = curves_id_->surface && curves_id_->surface->type == OB_MESH ? + static_cast(curves_id_->surface->data) : + nullptr; + self_->constraint_solver_.solve_step(*curves_, changed_curves_mask, surface, transforms_); + curves_->tag_positions_changed(); DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY); WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id_->id); @@ -270,47 +281,6 @@ struct PinchOperationExecutor { } }); } - - void initialize_segment_lengths() - { - const Span positions_cu = curves_->positions(); - const OffsetIndices points_by_curve = curves_->points_by_curve(); - self_->segment_lengths_cu_.reinitialize(curves_->points_num()); - threading::parallel_for(curve_selection_.index_range(), 256, [&](const IndexRange range) { - for (const int curve_i : curve_selection_.slice(range)) { - const IndexRange points = points_by_curve[curve_i]; - for (const int point_i : points.drop_back(1)) { - const float3 &p1_cu = positions_cu[point_i]; - const float3 &p2_cu = positions_cu[point_i + 1]; - const float length_cu = math::distance(p1_cu, p2_cu); - self_->segment_lengths_cu_[point_i] = length_cu; - } - } - }); - } - - void restore_segment_lengths(const Span changed_curves) - { - const Span expected_lengths_cu = self_->segment_lengths_cu_; - const OffsetIndices points_by_curve = curves_->points_by_curve(); - MutableSpan positions_cu = curves_->positions_for_write(); - - threading::parallel_for(changed_curves.index_range(), 256, [&](const IndexRange range) { - for (const int curve_i : range) { - if (!changed_curves[curve_i]) { - continue; - } - const IndexRange points = points_by_curve[curve_i]; - for (const int segment_i : IndexRange(points.size() - 1)) { - const float3 &p1_cu = positions_cu[points[segment_i]]; - float3 &p2_cu = positions_cu[points[segment_i] + 1]; - const float3 direction = math::normalize(p2_cu - p1_cu); - const float expected_length_cu = expected_lengths_cu[points[segment_i]]; - p2_cu = p1_cu + direction * expected_length_cu; - } - } - }); - } }; void PinchOperation::on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc index 503639614ded..26af897c0bf6 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc @@ -19,6 +19,7 @@ #include "WM_api.h" +#include "BLI_index_mask_ops.hh" #include "BLI_length_parameterize.hh" #include "BLI_math_matrix.hh" #include "BLI_task.hh" @@ -34,8 +35,8 @@ class PuffOperation : public CurvesSculptStrokeOperation { /** Only used when a 3D brush is used. */ CurvesBrush3D brush_3d_; - /** Length of each segment indexed by the index of the first point in the segment. */ - Array segment_lengths_cu_; + /** Solver for length and collision constraints. */ + CurvesConstraintSolver constraint_solver_; friend struct PuffOperationExecutor; @@ -130,7 +131,6 @@ struct PuffOperationExecutor { BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_); }); if (stroke_extension.is_first) { - this->initialize_segment_lengths(); if (falloff_shape_ == PAINT_FALLOFF_SHAPE_SPHERE) { self.brush_3d_ = *sample_curves_3d_brush(*ctx_.depsgraph, *ctx_.region, @@ -140,6 +140,9 @@ struct PuffOperationExecutor { brush_pos_re_, brush_radius_base_re_); } + + self_->constraint_solver_.initialize( + *curves_, curve_selection_, curves_id_->flag & CV_SCULPT_COLLISION_ENABLED); } Array curve_weights(curve_selection_.size(), 0.0f); @@ -155,7 +158,17 @@ struct PuffOperationExecutor { } this->puff(curve_weights); - this->restore_segment_lengths(); + + Vector changed_curves_indices; + changed_curves_indices.reserve(curve_selection_.size()); + for (int64_t select_i : curve_selection_.index_range()) { + if (curve_weights[select_i] > 0.0f) { + changed_curves_indices.append(curve_selection_[select_i]); + } + } + + self_->constraint_solver_.solve_step( + *curves_, IndexMask(changed_curves_indices), surface_, transforms_); curves_->tag_positions_changed(); DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY); @@ -344,44 +357,6 @@ struct PuffOperationExecutor { } }); } - - void initialize_segment_lengths() - { - const OffsetIndices points_by_curve = curves_->points_by_curve(); - const Span positions_cu = curves_->positions(); - self_->segment_lengths_cu_.reinitialize(curves_->points_num()); - threading::parallel_for(curves_->curves_range(), 128, [&](const IndexRange range) { - for (const int curve_i : range) { - const IndexRange points = points_by_curve[curve_i]; - for (const int point_i : points.drop_back(1)) { - const float3 &p1_cu = positions_cu[point_i]; - const float3 &p2_cu = positions_cu[point_i + 1]; - const float length_cu = math::distance(p1_cu, p2_cu); - self_->segment_lengths_cu_[point_i] = length_cu; - } - } - }); - } - - void restore_segment_lengths() - { - const Span expected_lengths_cu = self_->segment_lengths_cu_; - const OffsetIndices points_by_curve = curves_->points_by_curve(); - MutableSpan positions_cu = curves_->positions_for_write(); - - threading::parallel_for(curves_->curves_range(), 256, [&](const IndexRange range) { - for (const int curve_i : range) { - const IndexRange points = points_by_curve[curve_i]; - for (const int segment_i : points.drop_back(1)) { - const float3 &p1_cu = positions_cu[segment_i]; - float3 &p2_cu = positions_cu[segment_i + 1]; - const float3 direction = math::normalize(p2_cu - p1_cu); - const float expected_length_cu = expected_lengths_cu[segment_i]; - p2_cu = p1_cu + direction * expected_length_cu; - } - } - }); - } }; void PuffOperation::on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) diff --git a/source/blender/editors/sculpt_paint/paint_cursor.cc b/source/blender/editors/sculpt_paint/paint_cursor.cc index 11b8ae1b3fbc..53b56397adbc 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.cc +++ b/source/blender/editors/sculpt_paint/paint_cursor.cc @@ -37,6 +37,7 @@ #include "WM_api.h" #include "wm_cursors.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "ED_image.h" @@ -200,10 +201,18 @@ static void load_tex_task_cb_ex(void *__restrict userdata, y = len * sinf(angle); } - if (col) { - float rgba[4]; + float avg; + float rgba[4]; + paint_get_tex_pixel(mtex, x, y, pool, thread_id, &avg, rgba); - paint_get_tex_pixel_col(mtex, x, y, rgba, pool, thread_id, convert_to_linear, colorspace); + if (col) { + if (convert_to_linear) { + IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace); + } + + linearrgb_to_srgb_v3_v3(rgba, rgba); + + clamp_v4(rgba, 0.0f, 1.0f); buffer[index * 4] = rgba[0] * 255; buffer[index * 4 + 1] = rgba[1] * 255; @@ -211,8 +220,6 @@ static void load_tex_task_cb_ex(void *__restrict userdata, buffer[index * 4 + 3] = rgba[3] * 255; } else { - float avg = paint_get_tex_pixel(mtex, x, y, pool, thread_id); - avg += br->texture_sample_bias; /* Clamp to avoid precision overflow. */ @@ -1403,7 +1410,7 @@ static void paint_update_mouse_cursor(PaintCursorContext *pcontext) { if (pcontext->win->grabcursor != 0) { /* Don't set the cursor while it's grabbed, since this will show the cursor when interacting - * with the UI (dragging a number button for e.g.), see: T102792. */ + * with the UI (dragging a number button for e.g.), see: #102792. */ return; } WM_cursor_set(pcontext->win, WM_CURSOR_PAINT); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.cc b/source/blender/editors/sculpt_paint/paint_image_proj.cc index 9bf9f668a6b7..1800f8f862b1 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.cc +++ b/source/blender/editors/sculpt_paint/paint_image_proj.cc @@ -1354,7 +1354,7 @@ static void uv_image_outset(const ProjPaintState *ps, len_fact = cosf(tri_ang); len_fact = UNLIKELY(len_fact < FLT_EPSILON) ? FLT_MAX : (1.0f / len_fact); - /* Clamp the length factor, see: T62236. */ + /* Clamp the length factor, see: #62236. */ len_fact = MIN2(len_fact, 10.0f); mul_v2_fl(no, ps->seam_bleed_px * len_fact); @@ -3939,7 +3939,7 @@ static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_th ps->thread_tot = BKE_scene_num_threads(ps->scene); - /* workaround for T35057, disable threading if diameter is less than is possible for + /* workaround for #35057, disable threading if diameter is less than is possible for * optimum bucket number generation */ if (reset_threads) { ps->thread_tot = 1; @@ -5150,7 +5150,7 @@ static void copy_original_alpha_channel(ProjPixel *pixel, bool is_floatbuf) /* Use the original alpha channel data instead of the modified one */ if (is_floatbuf) { /* slightly more involved case since floats are in premultiplied space we need - * to make sure alpha is consistent, see T44627 */ + * to make sure alpha is consistent, see #44627 */ float rgb_straight[4]; premul_to_straight_v4_v4(rgb_straight, pixel->pixel.f_pt); rgb_straight[3] = pixel->origColor.f_pt[3]; diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 313941ee654a..cdf1256a097e 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -352,16 +352,17 @@ void paint_calc_redraw_planes(float planes[4][4], float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius); -float paint_get_tex_pixel( - const struct MTex *mtex, float u, float v, struct ImagePool *pool, int thread); -void paint_get_tex_pixel_col(const struct MTex *mtex, - float u, - float v, - float rgba[4], - struct ImagePool *pool, - int thread, - bool convert, - struct ColorSpace *colorspace); + +/** + * Returns true when a color was sampled and false when a value was sampled. + */ +bool paint_get_tex_pixel(const struct MTex *mtex, + float u, + float v, + struct ImagePool *pool, + int thread, + float *r_intensity, + float r_rgba[4]); /** * Used for both 3D view and image window. @@ -372,6 +373,7 @@ void paint_sample_color( void paint_stroke_operator_properties(struct wmOperatorType *ot); void BRUSH_OT_curve_preset(struct wmOperatorType *ot); +void BRUSH_OT_sculpt_curves_falloff_preset(struct wmOperatorType *ot); void PAINT_OT_face_select_linked(struct wmOperatorType *ot); void PAINT_OT_face_select_linked_pick(struct wmOperatorType *ot); @@ -480,7 +482,7 @@ void PAINT_OT_hide_show(struct wmOperatorType *ot); * We must thus map the modes here to the desired * eSelectOp modes. * - * Fixes T102349. + * Fixes #102349. */ typedef enum { PAINT_MASK_FLOOD_VALUE = SEL_OP_SUB, diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index 0ca6e9e0d740..bde6e25dec22 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -1109,7 +1109,7 @@ static void sculpt_gesture_trim_calculate_depth(SculptGestureContext *sgcontext) else { /* ss->cursor_radius is only valid if the stroke started * over the sculpt mesh. If it's not we must - * compute the radius ourselves. See T81452. + * compute the radius ourselves. See #81452. */ Sculpt *sd = CTX_data_tool_settings(vc->C)->sculpt; diff --git a/source/blender/editors/sculpt_paint/paint_ops.cc b/source/blender/editors/sculpt_paint/paint_ops.cc index c7c317508dd2..ca102b5a0b89 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.cc +++ b/source/blender/editors/sculpt_paint/paint_ops.cc @@ -832,6 +832,36 @@ static Brush *brush_tool_toggle(Main *bmain, Paint *paint, Brush *brush_orig, co return nullptr; } +/** The name of the active tool is "builtin_brush." concatenated with the returned string. */ +static blender::StringRefNull curves_active_tool_name_get(const eBrushCurvesSculptTool tool) +{ + switch (tool) { + case CURVES_SCULPT_TOOL_COMB: + return "comb"; + case CURVES_SCULPT_TOOL_DELETE: + return "delete"; + case CURVES_SCULPT_TOOL_SNAKE_HOOK: + return "snake_hook"; + case CURVES_SCULPT_TOOL_ADD: + return "add"; + case CURVES_SCULPT_TOOL_GROW_SHRINK: + return "grow_shrink"; + case CURVES_SCULPT_TOOL_SELECTION_PAINT: + return "selection_paint"; + case CURVES_SCULPT_TOOL_PINCH: + return "pinch"; + case CURVES_SCULPT_TOOL_SMOOTH: + return "smooth"; + case CURVES_SCULPT_TOOL_PUFF: + return "puff"; + case CURVES_SCULPT_TOOL_DENSITY: + return "density"; + case CURVES_SCULPT_TOOL_SLIDE: + return "slide"; + } + return ""; +} + static bool brush_generic_tool_set(bContext *C, Main *bmain, Paint *paint, @@ -869,8 +899,14 @@ static bool brush_generic_tool_set(bContext *C, * tool_name again. */ int tool_result = brush_tool(brush, paint->runtime.tool_offset); ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C); - const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); - RNA_enum_name_from_value(items, tool_result, &tool_name); + + if (paint_mode == PAINT_MODE_SCULPT_CURVES) { + tool_name = curves_active_tool_name_get(eBrushCurvesSculptTool(tool)).c_str(); + } + else { + const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); + RNA_enum_name_from_value(items, tool_result, &tool_name); + } char tool_id[MAX_NAME]; SNPRINTF(tool_id, "builtin_brush.%s", tool_name); @@ -921,8 +957,14 @@ static int brush_select_exec(bContext *C, wmOperator *op) if (paint == nullptr) { return OPERATOR_CANCELLED; } - const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); - RNA_enum_name_from_value(items, tool, &tool_name); + + if (paint_mode == PAINT_MODE_SCULPT_CURVES) { + tool_name = curves_active_tool_name_get(eBrushCurvesSculptTool(tool)).c_str(); + } + else { + const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); + RNA_enum_name_from_value(items, tool, &tool_name); + } if (brush_generic_tool_set(C, bmain, paint, tool, tool_name, create_missing, toggle)) { return OPERATOR_FINISHED; @@ -1421,6 +1463,7 @@ void ED_operatortypes_paint(void) WM_operatortype_append(BRUSH_OT_add_gpencil); WM_operatortype_append(BRUSH_OT_scale_size); WM_operatortype_append(BRUSH_OT_curve_preset); + WM_operatortype_append(BRUSH_OT_sculpt_curves_falloff_preset); WM_operatortype_append(BRUSH_OT_reset); WM_operatortype_append(BRUSH_OT_stencil_control); WM_operatortype_append(BRUSH_OT_stencil_fit_image_aspect); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.cc b/source/blender/editors/sculpt_paint/paint_stroke.cc index 1665fc4fedb9..c64751965f74 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.cc +++ b/source/blender/editors/sculpt_paint/paint_stroke.cc @@ -692,7 +692,7 @@ static float paint_space_stroke_spacing(bContext *C, } else { /* brushes can have a minimum size of 1.0 but with pressure it can be smaller than a pixel - * causing very high step sizes, hanging blender T32381. */ + * causing very high step sizes, hanging blender #32381. */ size_clamp = max_ff(1.0f, size); } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 98fefd86d959..4953ab846870 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -25,6 +25,7 @@ #include "BLT_translation.h" #include "BKE_brush.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_image.h" @@ -146,45 +147,29 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo return len_v3(delta) / scale; } -float paint_get_tex_pixel(const MTex *mtex, float u, float v, struct ImagePool *pool, int thread) -{ - float intensity; - float rgba_dummy[4]; - const float co[3] = {u, v, 0.0f}; - - RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba_dummy); - - return intensity; -} - -void paint_get_tex_pixel_col(const MTex *mtex, - float u, - float v, - float rgba[4], - struct ImagePool *pool, - int thread, - bool convert_to_linear, - struct ColorSpace *colorspace) +bool paint_get_tex_pixel(const MTex *mtex, + float u, + float v, + struct ImagePool *pool, + int thread, + /* Return arguments. */ + float *r_intensity, + float r_rgba[4]) { const float co[3] = {u, v, 0.0f}; float intensity; + const bool has_rgb = RE_texture_evaluate( + mtex, co, thread, pool, false, false, &intensity, r_rgba); + *r_intensity = intensity; - const bool hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); - - if (!hasrgb) { - rgba[0] = intensity; - rgba[1] = intensity; - rgba[2] = intensity; - rgba[3] = 1.0f; + if (!has_rgb) { + r_rgba[0] = intensity; + r_rgba[1] = intensity; + r_rgba[2] = intensity; + r_rgba[3] = 1.0f; } - if (convert_to_linear) { - IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace); - } - - linearrgb_to_srgb_v3_v3(rgba, rgba); - - clamp_v4(rgba, 0.0f, 1.0f); + return has_rgb; } void paint_stroke_operator_properties(wmOperatorType *ot) @@ -585,19 +570,18 @@ static bool brush_curve_preset_poll(bContext *C) return br && br->curve; } +static const EnumPropertyItem prop_shape_items[] = { + {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""}, + {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""}, + {CURVE_PRESET_MAX, "MAX", 0, "Max", ""}, + {CURVE_PRESET_LINE, "LINE", 0, "Line", ""}, + {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""}, + {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""}, + {0, NULL, 0, NULL, NULL}, +}; + void BRUSH_OT_curve_preset(wmOperatorType *ot) { - PropertyRNA *prop; - static const EnumPropertyItem prop_shape_items[] = { - {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""}, - {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""}, - {CURVE_PRESET_MAX, "MAX", 0, "Max", ""}, - {CURVE_PRESET_LINE, "LINE", 0, "Line", ""}, - {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""}, - {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""}, - {0, NULL, 0, NULL, NULL}, - }; - ot->name = "Preset"; ot->description = "Set brush shape"; ot->idname = "BRUSH_OT_curve_preset"; @@ -605,6 +589,38 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot) ot->exec = brush_curve_preset_exec; ot->poll = brush_curve_preset_poll; + PropertyRNA *prop; + prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); + RNA_def_property_translation_context(prop, + BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */ +} + +static bool brush_sculpt_curves_falloff_preset_poll(bContext *C) +{ + Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C)); + return br && br->curves_sculpt_settings && br->curves_sculpt_settings->curve_parameter_falloff; +} + +static int brush_sculpt_curves_falloff_preset_exec(bContext *C, wmOperator *op) +{ + Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C)); + CurveMapping *mapping = brush->curves_sculpt_settings->curve_parameter_falloff; + mapping->preset = RNA_enum_get(op->ptr, "shape"); + CurveMap *map = mapping->cm; + BKE_curvemap_reset(map, &mapping->clipr, mapping->preset, CURVEMAP_SLOPE_POSITIVE); + return OPERATOR_FINISHED; +} + +void BRUSH_OT_sculpt_curves_falloff_preset(wmOperatorType *ot) +{ + ot->name = "Curve Falloff Preset"; + ot->description = "Set Curve Falloff Preset"; + ot->idname = "BRUSH_OT_sculpt_curves_falloff_preset"; + + ot->exec = brush_sculpt_curves_falloff_preset_exec; + ot->poll = brush_sculpt_curves_falloff_preset_poll; + + PropertyRNA *prop; prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", ""); RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index e2ca932fbc79..635331b6d6c3 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -965,7 +965,7 @@ static void do_weight_paint_vertex_single( dw->weight = weight; /* WATCH IT: take care of the ordering of applying mirror -> normalize, - * can give wrong results T26193, least confusing if normalize is done last */ + * can give wrong results #26193, least confusing if normalize is done last */ /* apply mirror */ if (index_mirr != -1) { diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 10ce391c3975..6b5e24380682 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -54,6 +54,7 @@ #include "BKE_scene.h" #include "BKE_subdiv_ccg.h" #include "BKE_subsurf.h" +#include "BLI_math_vector.hh" #include "NOD_texture.h" @@ -1620,7 +1621,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) /** * Disable multi-threading when dynamic-topology is enabled. Otherwise, * new entries might be inserted by #SCULPT_undo_push_node() into the #GHash - * used internally by #BM_log_original_vert_co() by a different thread. See T33787. + * used internally by #BM_log_original_vert_co() by a different thread. See #33787. */ SculptThreadedTaskData data{}; data.sd = sd; @@ -2555,80 +2556,12 @@ static float brush_strength(const Sculpt *sd, } } -float SCULPT_brush_strength_factor(SculptSession *ss, - const Brush *br, - const float brush_point[3], - float len, - const float vno[3], - const float fno[3], - float mask, - const PBVHVertRef vertex, - const int thread_id, - AutomaskingNodeData *automask_data) +static float sculpt_apply_hardness(const SculptSession *ss, const float input_len) { - StrokeCache *cache = ss->cache; - const Scene *scene = cache->vc->scene; - const MTex *mtex = BKE_brush_mask_texture_get(br, OB_MODE_SCULPT); - float avg = 1.0f; - float rgba[4]; - float point[3]; - - sub_v3_v3v3(point, brush_point, cache->plane_offset); - - if (!mtex->tex) { - avg = 1.0f; - } - else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { - /* Get strength by feeding the vertex location directly into a texture. */ - avg = BKE_brush_sample_tex_3d(scene, br, mtex, point, rgba, 0, ss->tex_pool); - } - else { - float symm_point[3], point_2d[2]; - /* Quite warnings. */ - float x = 0.0f, y = 0.0f; - - /* If the active area is being applied for symmetry, flip it - * across the symmetry axis and rotate it back to the original - * position in order to project it. This insures that the - * brush texture will be oriented correctly. */ - if (cache->radial_symmetry_pass) { - mul_m4_v3(cache->symm_rot_mat_inv, point); - } - flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass); - - ED_view3d_project_float_v2_m4(cache->vc->region, symm_point, point_2d, cache->projection_mat); - - /* Still no symmetry supported for other paint modes. - * Sculpt does it DIY. */ - if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) { - /* Similar to fixed mode, but projects from brush angle - * rather than view direction. */ - - mul_m4_v3(cache->brush_local_mat, symm_point); - - x = symm_point[0]; - y = symm_point[1]; - - x *= mtex->size[0]; - y *= mtex->size[1]; - - x += mtex->ofs[0]; - y += mtex->ofs[1]; - - avg = paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id); - - avg += br->texture_sample_bias; - } - else { - const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f}; - avg = BKE_brush_sample_tex_3d(scene, br, mtex, point_3d, rgba, 0, ss->tex_pool); - } - } - - /* Hardness. */ - float final_len = len; + const StrokeCache *cache = ss->cache; + float final_len = input_len; const float hardness = cache->paint_brush.hardness; - float p = len / cache->radius; + float p = input_len / cache->radius; if (p < hardness) { final_len = 0.0f; } @@ -2640,9 +2573,100 @@ float SCULPT_brush_strength_factor(SculptSession *ss, final_len = p * cache->radius; } + return final_len; +} + +static void sculpt_apply_texture(const SculptSession *ss, + const Brush *brush, + const float brush_point[3], + const int thread_id, + float *r_value, + float r_rgba[4]) +{ + StrokeCache *cache = ss->cache; + const Scene *scene = cache->vc->scene; + const MTex *mtex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT); + + if (!mtex->tex) { + *r_value = 1.0f; + copy_v4_fl(r_rgba, 1.0f); + return; + } + + float point[3]; + sub_v3_v3v3(point, brush_point, cache->plane_offset); + + if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { + /* Get strength by feeding the vertex location directly into a texture. */ + *r_value = BKE_brush_sample_tex_3d(scene, brush, mtex, point, r_rgba, 0, ss->tex_pool); + } + else { + float symm_point[3]; + + /* If the active area is being applied for symmetry, flip it + * across the symmetry axis and rotate it back to the original + * position in order to project it. This insures that the + * brush texture will be oriented correctly. */ + if (cache->radial_symmetry_pass) { + mul_m4_v3(cache->symm_rot_mat_inv, point); + } + flip_v3_v3(symm_point, point, cache->mirror_symmetry_pass); + + /* Still no symmetry supported for other paint modes. + * Sculpt does it DIY. */ + if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) { + /* Similar to fixed mode, but projects from brush angle + * rather than view direction. */ + + mul_m4_v3(cache->brush_local_mat, symm_point); + + float x = symm_point[0]; + float y = symm_point[1]; + + x *= mtex->size[0]; + y *= mtex->size[1]; + + x += mtex->ofs[0]; + y += mtex->ofs[1]; + + paint_get_tex_pixel(mtex, x, y, ss->tex_pool, thread_id, r_value, r_rgba); + + add_v3_fl(r_rgba, brush->texture_sample_bias); // v3 -> Ignore alpha + *r_value -= brush->texture_sample_bias; + } + else { + float point_2d[2]; + ED_view3d_project_float_v2_m4( + cache->vc->region, symm_point, point_2d, cache->projection_mat); + const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f}; + *r_value = BKE_brush_sample_tex_3d(scene, brush, mtex, point_3d, r_rgba, 0, ss->tex_pool); + } + } +} + +float SCULPT_brush_strength_factor(SculptSession *ss, + const Brush *brush, + const float brush_point[3], + float len, + const float vno[3], + const float fno[3], + float mask, + const PBVHVertRef vertex, + int thread_id, + AutomaskingNodeData *automask_data) +{ + StrokeCache *cache = ss->cache; + + float avg = 1.0f; + float rgba[4]; + sculpt_apply_texture(ss, brush, brush_point, thread_id, &avg, rgba); + + /* Hardness. */ + const float final_len = sculpt_apply_hardness(ss, len); + /* Falloff curve. */ - avg *= BKE_brush_curve_strength(br, final_len, cache->radius); - avg *= frontface(br, cache->view_normal, vno, fno); + avg *= BKE_brush_curve_strength(brush, final_len, cache->radius); + avg *= frontface(brush, cache->view_normal, vno, fno); /* Paint mask. */ avg *= 1.0f - mask; @@ -2653,6 +2677,69 @@ float SCULPT_brush_strength_factor(SculptSession *ss, return avg; } +void SCULPT_brush_strength_color(SculptSession *ss, + const Brush *brush, + const float brush_point[3], + float len, + const float vno[3], + const float fno[3], + float mask, + const PBVHVertRef vertex, + int thread_id, + AutomaskingNodeData *automask_data, + float r_rgba[4]) +{ + StrokeCache *cache = ss->cache; + + float avg = 1.0f; + sculpt_apply_texture(ss, brush, brush_point, thread_id, &avg, r_rgba); + + /* Hardness. */ + const float final_len = sculpt_apply_hardness(ss, len); + + /* Falloff curve. */ + const float falloff = BKE_brush_curve_strength(brush, final_len, cache->radius) * + frontface(brush, cache->view_normal, vno, fno); + + /* Paint mask. */ + const float paint_mask = 1.0f - mask; + + /* Auto-masking. */ + const float automasking_factor = SCULPT_automasking_factor_get( + cache->automasking, ss, vertex, automask_data); + + const float masks_combined = falloff * paint_mask * automasking_factor; + + mul_v4_fl(r_rgba, masks_combined); +} + +void SCULPT_calc_vertex_displacement(SculptSession *ss, + const Brush *brush, + float rgba[3], + float out_offset[3]) +{ + mul_v3_fl(rgba, ss->cache->bstrength); + /* Handle brush inversion */ + if (ss->cache->bstrength < 0) { + rgba[0] *= -1; + rgba[1] *= -1; + } + + /* Apply texture size */ + for (int i = 0; i < 3; ++i) { + rgba[i] *= blender::math::safe_divide(1.0f, pow2f(brush->mtex.size[i])); + } + + /* Transform vector to object space */ + mul_mat3_m4_v3(ss->cache->brush_local_mat_inv, rgba); + + /* Handle symmetry */ + if (ss->cache->radial_symmetry_pass) { + mul_m4_v3(ss->cache->symm_rot_mat, rgba); + } + flip_v3_v3(out_offset, rgba, ss->cache->mirror_symmetry_pass); +} + bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v) { SculptSearchSphereData *data = static_cast(data_v); @@ -2920,7 +3007,10 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3]) mul_m4_v3(ob->world_to_object, y); } -static void calc_brush_local_mat(const MTex *mtex, Object *ob, float local_mat[4][4]) +static void calc_brush_local_mat(const MTex *mtex, + Object *ob, + float local_mat[4][4], + float local_mat_inv[4][4]) { const StrokeCache *cache = ob->sculpt->cache; float tmat[4][4]; @@ -2966,6 +3056,8 @@ static void calc_brush_local_mat(const MTex *mtex, Object *ob, float local_mat[4 scale_m4_fl(scale, radius); mul_m4_m4m4(tmat, mat, scale); + /* Return tmat as is (for converting from local area coords to model-space coords). */ + copy_m4_m4(local_mat_inv, tmat); /* Return inverse (for converting from model-space coords to local area coords). */ invert_m4_m4(local_mat, tmat); } @@ -3000,7 +3092,7 @@ static void update_brush_local_mat(Sculpt *sd, Object *ob) if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0) { const Brush *brush = BKE_paint_brush(&sd->paint); const MTex *mask_tex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT); - calc_brush_local_mat(mask_tex, ob, cache->brush_local_mat); + calc_brush_local_mat(mask_tex, ob, cache->brush_local_mat, cache->brush_local_mat_inv); } } @@ -5405,7 +5497,7 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags) BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB); /* Update the object's bounding box too so that the object * doesn't get incorrectly clipped during drawing in - * draw_mesh_object(). T33790. */ + * draw_mesh_object(). #33790. */ SCULPT_update_object_bounding_box(ob); } @@ -5586,7 +5678,7 @@ static bool sculpt_stroke_test_start(bContext *C, wmOperator *op, const float mv /* Don't start the stroke until `mval` goes over the mesh. * NOTE: `mval` will only be null when re-executing the saved stroke. * We have exception for 'exec' strokes since they may not set `mval`, - * only 'location', see: T52195. */ + * only 'location', see: #52195. */ if (((op->flag & OP_IS_INVOKE) == 0) || (mval == nullptr) || over_mesh(C, op, mval)) { Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; @@ -5865,7 +5957,7 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op) const Brush *brush = BKE_paint_brush(&sd->paint); /* XXX Canceling strokes that way does not work with dynamic topology, - * user will have to do real undo for now. See T46456. */ + * user will have to do real undo for now. See #46456. */ if (ss->cache && !SCULPT_stroke_is_dynamic_topology(ss, brush)) { paint_mesh_restore_co(sd, ob); } @@ -5893,7 +5985,7 @@ static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent * * Having blank global undo steps interleaved with sculpt steps * corrupts the DynTopo undo stack. - * See T101430. + * See #101430. * * NOTE: simply returning #OPERATOR_CANCELLED was not * sufficient to prevent this. */ diff --git a/source/blender/editors/sculpt_paint/sculpt_brush_types.cc b/source/blender/editors/sculpt_paint/sculpt_brush_types.cc index 8bec48bfb651..9e6ce8131ef3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_brush_types.cc +++ b/source/blender/editors/sculpt_paint/sculpt_brush_types.cc @@ -265,18 +265,35 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, SCULPT_automasking_node_update(ss, &automask_data, &vd); /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.vertex, - thread_id, - &automask_data); - - mul_v3_v3fl(proxy[vd.i], offset, fade); + if (ss->cache->brush->flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT && + (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA)) { + float r_rgba[4]; + SCULPT_brush_strength_color(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.vertex, + thread_id, + &automask_data, + r_rgba); + SCULPT_calc_vertex_displacement(ss, brush, r_rgba, proxy[vd.i]); + } + else { + float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.vertex, + thread_id, + &automask_data); + mul_v3_v3fl(proxy[vd.i], offset, fade); + } if (vd.is_mesh) { BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); @@ -1052,7 +1069,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, SCULPT_automasking_node_update(ss, &automask_data, &vd); - /* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */ + /* The normal from the vertices is ignored, it causes glitch with planes, see: #44390. */ const float fade = bstrength * SCULPT_brush_strength_factor(ss, brush, vd.co, diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc index 986974f2e209..570e2e1cab30 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc @@ -91,7 +91,7 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & SCULPT_DYNTOPO_SMOOTH_SHADING) != 0; - /* Dynamic topology doesn't ensure selection state is valid, so remove T36280. */ + /* Dynamic topology doesn't ensure selection state is valid, so remove #36280. */ BKE_mesh_mselect_clear(me); /* Create triangles-only BMesh. */ @@ -188,7 +188,7 @@ static void SCULPT_dynamic_topology_disable_ex( /* Clear data. */ me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; - /* Typically valid but with global-undo they can be nullptr, see: T36234. */ + /* Typically valid but with global-undo they can be nullptr, see: #36234. */ if (ss->bm) { BM_mesh_free(ss->bm); ss->bm = nullptr; diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 51ecaa168f32..de06fa3541ae 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -410,7 +410,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) const bke::AttributeAccessor attributes = mesh->attributes(); const VArraySpan select_poly = attributes.lookup_or_default( ".select_poly", ATTR_DOMAIN_FACE, false); - threading::parallel_for(IndexRange(mesh->totvert), 4096, [&](const IndexRange range) { + threading::parallel_for(select_poly.index_range(), 4096, [&](const IndexRange range) { for (const int i : range) { if (select_poly[i]) { ss->face_sets[i] = next_face_set; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index 37e7a522ccf5..5117b49407f2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -586,8 +586,13 @@ struct StrokeCache { float sculpt_normal_symm[3]; /* Used for area texture mode, local_mat gets calculated by - * calc_brush_local_mat() and used in tex_strength(). */ + * calc_brush_local_mat() and used in sculpt_apply_texture(). + * Transforms from model-space coords to local area coords. + */ float brush_local_mat[4][4]; + /* The matrix from local area coords to model-space coords is used to calculate the vector + * displacement in area plane mode. */ + float brush_local_mat_inv[4][4]; float plane_offset[3]; /* used to shift the plane around when doing tiled strokes */ int tile_pass; @@ -1241,6 +1246,30 @@ float SCULPT_brush_strength_factor(SculptSession *ss, int thread_id, AutomaskingNodeData *automask_data); +/** + * Return a color of a brush texture on a particular vertex multiplied by active masks. + */ +void SCULPT_brush_strength_color(SculptSession *ss, + const Brush *brush, + const float brush_point[3], + float len, + const float vno[3], + const float fno[3], + float mask, + const PBVHVertRef vertex, + int thread_id, + AutomaskingNodeData *automask_data, + float r_rgba[4]); + +/** + * Calculates the vertex offset for a single vertex depending on the brush setting rgb as vector + * displacement. + */ +void SCULPT_calc_vertex_displacement(SculptSession *ss, + const Brush *brush, + float rgba[3], + float out_offset[3]); + /** * Tilts a normal by the x and y tilt values using the view axis. */ diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index 091bd0d08525..d9738b11215e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -514,7 +514,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) /* Dyntopo adds its own undo step. */ if ((me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) == 0) { /* Without this the memfile undo step is used, - * while it works it causes lag when undoing the first undo step, see T71564. */ + * while it works it causes lag when undoing the first undo step, see #71564. */ wmWindowManager *wm = CTX_wm_manager(C); if (wm->op_undo_depth <= 1) { SCULPT_undo_push_begin(ob, op); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.cc b/source/blender/editors/sculpt_paint/sculpt_undo.cc index f5e47b8a8687..ed52ee553125 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_undo.cc @@ -1839,7 +1839,7 @@ static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr CustomDataLayer *layer; layer = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain); - /* Temporary fix for T97408. This is a fundamental + /* Temporary fix for #97408. This is a fundamental * bug in the undo stack; the operator code needs to push * an extra undo step before running an operator if a * non-memfile undo system is active. diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 998fe50b9ace..f881eda74065 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -50,83 +50,84 @@ #define MARK_BOUNDARY 1 typedef struct UvAdjacencyElement { - /* pointer to original uvelement */ + /** pointer to original UV-element. */ UvElement *element; - /* uv pointer for convenience. Caution, this points to the original UVs! */ + /** UV pointer for convenience. Caution, this points to the original UVs! */ float *uv; - /* Are we on locked in place? */ + /** Are we on locked in place? */ bool is_locked; - /* Are we on the boundary? */ + /** Are we on the boundary? */ bool is_boundary; } UvAdjacencyElement; typedef struct UvEdge { uint uv1; uint uv2; - /* Are we in the interior? */ + /** Are we in the interior? */ bool is_interior; } UvEdge; typedef struct UVInitialStrokeElement { - /* index to unique uv */ + /** index to unique UV. */ int uv; - /* strength of brush on initial position */ + /** Strength of brush on initial position. */ float strength; - /* initial uv position */ + /** initial UV position. */ float initial_uv[2]; } UVInitialStrokeElement; typedef struct UVInitialStroke { - /* Initial Selection,for grab brushes for instance */ + /** Initial Selection,for grab brushes for instance. */ UVInitialStrokeElement *initialSelection; - /* Total initially selected UVs. */ + /** Total initially selected UVs. */ int totalInitialSelected; - /* initial mouse coordinates */ + /** Initial mouse coordinates. */ float init_coord[2]; } UVInitialStroke; -/* custom data for uv smoothing brush */ +/** Custom data for UV smoothing brush. */ typedef struct UvSculptData { - /* Contains the first of each set of coincident UVs. - * These will be used to perform smoothing on and propagate the changes - * to their coincident UVs */ + /** + * Contains the first of each set of coincident UVs. + * These will be used to perform smoothing on and propagate the changes to their coincident UVs. + */ UvAdjacencyElement *uv; - /* Total number of unique UVs. */ + /** Total number of unique UVs. */ int totalUniqueUvs; - /* Edges used for adjacency info, used with laplacian smoothing */ + /** Edges used for adjacency info, used with laplacian smoothing */ UvEdge *uvedges; - /* Total number of #UvEdge. */ + /** Total number of #UvEdge. */ int totalUvEdges; - /* data for initial stroke, used by tools like grab */ + /** data for initial stroke, used by tools like grab */ UVInitialStroke *initial_stroke; - /* timer to be used for airbrush-type brush */ + /** Timer to be used for airbrush-type brush. */ wmTimer *timer; - /* to determine quickly adjacent UVs */ + /** To determine quickly adjacent UVs. */ UvElementMap *elementMap; - /* uvsmooth Paint for fast reference */ + /** UV-smooth Paint for fast reference. */ Paint *uvsculpt; - /* tool to use. duplicating here to change if modifier keys are pressed */ + /** Tool to use. duplicating here to change if modifier keys are pressed. */ char tool; - /* store invert flag here */ + /** Store invert flag here. */ char invert; - /* Is constrain to image bounds active? */ + /** Is constrain to image bounds active? */ bool constrain_to_bounds; - /* Base for constrain_to_bounds. */ + /** Base for constrain_to_bounds. */ float uv_base_offset[2]; } UvSculptData; @@ -685,7 +686,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm /* Winding was added to island detection in 5197aa04c6bd * However the sculpt tools can flip faces, potentially creating orphaned islands. - * See T100132 */ + * See #100132 */ const bool use_winding = false; const bool use_seams = true; data->elementMap = BM_uv_element_map_create( diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index 79047b171ef9..1bd28b068f9a 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -586,11 +586,11 @@ void ED_animedit_unlink_action( if (strip->act == act) { /* Remove this strip, and the track too if it doesn't have anything else */ - BKE_nlastrip_free(&nlt->strips, strip, true); + BKE_nlastrip_remove_and_free(&nlt->strips, strip, true); if (nlt->strips.first == NULL) { BLI_assert(nstrip == NULL); - BKE_nlatrack_free(&adt->nla_tracks, nlt, true); + BKE_nlatrack_remove_and_free(&adt->nla_tracks, nlt, true); } } } diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 9b0ef405a6a2..094eccf41149 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -524,7 +524,7 @@ static eKeyPasteError paste_action_keys(bAnimContext *ac, * - First time we try to filter more strictly, allowing only selected channels * to allow copying animation between channels * - Second time, we loosen things up if nothing was found the first time, allowing - * users to just paste keyframes back into the original curve again T31670. + * users to just paste keyframes back into the original curve again #31670. */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_FCURVESONLY | ANIMFILTER_NODUPLIS); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 8dc349645909..0c416712a0e2 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -1784,7 +1784,7 @@ static int mouse_action_keys(bAnimContext *ac, /* apply selection to keyframes */ if (column) { /* select all keyframes in the same frame as the one we hit on the active channel - * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here + * [#41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here * does that itself again as it needs to work on multiple data-blocks. */ actkeys_mselect_column(ac, select_mode, frame); diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 2f22121f7de0..5a7be3be4a5b 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -534,7 +534,7 @@ static void action_listener(const wmSpaceTypeListenerParams *params) } /* for simple edits to the curve data though (or just plain selections), * a simple redraw should work - * (see T39851 for an example of how this can go wrong) + * (see #39851 for an example of how this can go wrong) */ else { ED_area_tag_redraw(area); @@ -637,7 +637,7 @@ static void action_listener(const wmSpaceTypeListenerParams *params) break; case NC_WINDOW: if (saction->runtime.flag & SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC) { - /* force redraw/refresh after undo/redo, see: T28962. */ + /* force redraw/refresh after undo/redo, see: #28962. */ ED_area_tag_refresh(area); } break; @@ -781,7 +781,7 @@ static void action_refresh(const bContext *C, ScrArea *area) /* Tag everything for redraw * - Regions (such as header) need to be manually tagged for redraw too - * or else they don't update T28962. + * or else they don't update #28962. */ ED_area_tag_redraw(area); for (region = area->regionbase.first; region; region = region->next) { diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index c5f457b3fd89..463e1a149542 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -965,7 +965,7 @@ int /*eContextResult*/ buttons_context(const bContext *C, Object *ob = ptr->data; if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type) && ob->totcol) { - /* a valid actcol isn't ensured T27526. */ + /* a valid actcol isn't ensured #27526. */ int matnr = ob->actcol - 1; if (matnr < 0) { matnr = 0; diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index b45abcf80688..6ccb8d6ca398 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -233,7 +233,7 @@ static int file_browse_exec(bContext *C, wmOperator *op) ED_undo_push(C, undostr); } - /* Special annoying exception, filesel on redo panel T26618. */ + /* Special annoying exception, filesel on redo panel #26618. */ { wmOperator *redo_op = WM_operator_last_redo(C); if (redo_op) { diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 5a333869deaf..90d8d0c30612 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -793,7 +793,7 @@ static void buttons_area_listener(const wmSpaceTypeListenerParams *params) } break; case NC_ID: - if (wmn->action == NA_RENAME) { + if (ELEM(wmn->action, NA_RENAME, NA_EDITED)) { ED_area_tag_redraw(area); } break; diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 5ebc41d9cc76..b9abcfaa6f52 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -232,7 +232,7 @@ int ED_space_clip_get_clip_frame_number(const SpaceClip *sc) { MovieClip *clip = ED_space_clip_get_clip(sc); - /* Caller must ensure space does have a valid clip, otherwise it will crash, see T45017. */ + /* Caller must ensure space does have a valid clip, otherwise it will crash, see #45017. */ return BKE_movieclip_remap_scene_to_clip_frame(clip, sc->user.framenr); } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index d94228a2dadc..3a2cbfdfad3b 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -897,7 +897,7 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) /* callback */ /* TODO(sergey): For being consistent with space image the projection needs to be configured * the way how the commented out code does it. This works correct for tracking data, but it - * causes wrong aspect correction for mask editor (see T84990). */ + * causes wrong aspect correction for mask editor (see #84990). */ // GPU_matrix_push_projection(); // wmOrtho2(region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, // region->v2d.cur.ymax); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index e85a6cbc0d4a..bfc1903ae7d9 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -55,6 +55,8 @@ #include "GPU_immediate_util.h" #include "GPU_state.h" +#include "AS_asset_representation.h" + #include "filelist.h" #include "file_intern.h" /* own include */ @@ -126,16 +128,55 @@ static void draw_tile_background(const rcti *draw_rect, int colorid, int shade) UI_draw_roundbox_aa(&draw_rect_fl, true, 5.0f, color); } -static void file_draw_icon(const SpaceFile *sfile, - uiBlock *block, - const FileDirEntry *file, - const char *path, - const rcti *tile_draw_rect, - int icon, - int width, - int height, - bool drag, - bool dimmed) +static void file_but_enable_drag(uiBut *but, + const SpaceFile *sfile, + const FileDirEntry *file, + const char *path, + ImBuf *preview_image, + int icon, + float scale) +{ + ID *id; + + if ((id = filelist_file_get_id(file))) { + UI_but_drag_set_id(but, id); + if (preview_image) { + UI_but_drag_attach_image(but, preview_image, scale); + } + } + else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS && + (file->typeflag & FILE_TYPE_ASSET) != 0) { + char blend_path[FILE_MAX_LIBEXTRA]; + if (BLO_library_path_explode(path, blend_path, NULL, NULL)) { + const int import_method = ED_fileselect_asset_import_method_get(sfile, file); + BLI_assert(import_method > -1); + + UI_but_drag_set_asset(but, + &(AssetHandle){.file_data = file}, + BLI_strdup(blend_path), + import_method, + icon, + preview_image, + scale); + } + } + else if (preview_image) { + UI_but_drag_set_image(but, BLI_strdup(path), icon, preview_image, scale, true); + } + else { + /* path is no more static, cannot give it directly to but... */ + UI_but_drag_set_path(but, BLI_strdup(path), true); + } +} + +static uiBut *file_add_icon_but(const SpaceFile *sfile, + uiBlock *block, + const char *path, + const rcti *tile_draw_rect, + int icon, + int width, + int height, + bool dimmed) { uiBut *but; @@ -149,39 +190,7 @@ static void file_draw_icon(const SpaceFile *sfile, block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, a1, a2, NULL); UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path), MEM_freeN); - if (drag) { - /* TODO: duplicated from file_draw_preview(). */ - ID *id; - - if ((id = filelist_file_get_id(file))) { - UI_but_drag_set_id(but, id); - ImBuf *preview_image = filelist_file_getimage(file); - if (preview_image) { - UI_but_drag_attach_image(but, preview_image, UI_DPI_FAC); - } - } - else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS && - (file->typeflag & FILE_TYPE_ASSET) != 0) { - ImBuf *preview_image = filelist_file_getimage(file); - char blend_path[FILE_MAX_LIBEXTRA]; - if (BLO_library_path_explode(path, blend_path, NULL, NULL)) { - const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); - BLI_assert(asset_params != NULL); - - UI_but_drag_set_asset(but, - &(AssetHandle){.file_data = file}, - BLI_strdup(blend_path), - asset_params->import_type, - icon, - preview_image, - UI_DPI_FAC); - } - } - else { - /* path is no more static, cannot give it directly to but... */ - UI_but_drag_set_path(but, BLI_strdup(path), true); - } - } + return but; } static void file_draw_string(int sx, @@ -292,21 +301,50 @@ void file_calc_previews(const bContext *C, ARegion *region) UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height); } -static void file_draw_preview(const SpaceFile *sfile, - uiBlock *block, - const FileDirEntry *file, - const char *path, +static void file_add_preview_drag_but(const SpaceFile *sfile, + uiBlock *block, + FileLayout *layout, + const FileDirEntry *file, + const char *path, + const rcti *tile_draw_rect, + ImBuf *preview_image, + const int icon, + const float scale) +{ + /* Invisible button for dragging. */ + rcti drag_rect = *tile_draw_rect; + /* A bit smaller than the full tile, to increase the gap between items that users can drag from + * for box select. */ + BLI_rcti_pad(&drag_rect, -layout->tile_border_x, -layout->tile_border_y); + + uiBut *but = uiDefBut(block, + UI_BTYPE_LABEL, + 0, + "", + drag_rect.xmin, + drag_rect.ymin, + BLI_rcti_size_x(&drag_rect), + BLI_rcti_size_y(&drag_rect), + NULL, + 0.0, + 0.0, + 0, + 0, + NULL); + file_but_enable_drag(but, sfile, file, path, preview_image, icon, scale); +} + +static void file_draw_preview(const FileDirEntry *file, const rcti *tile_draw_rect, const float icon_aspect, ImBuf *imb, const int icon, FileLayout *layout, const bool is_icon, - const bool drag, const bool dimmed, - const bool is_link) + const bool is_link, + float *r_scale) { - uiBut *but; float fx, fy; float dx, dy; int xco, yco; @@ -523,59 +561,11 @@ static void file_draw_preview(const SpaceFile *sfile, immUnbindProgram(); } - /* Invisible button for dragging. */ - rcti drag_rect = *tile_draw_rect; - /* A bit smaller than the full tile, to increase the gap between items that users can drag from - * for box select. */ - BLI_rcti_pad(&drag_rect, -layout->tile_border_x, -layout->tile_border_y); - - but = uiDefBut(block, - UI_BTYPE_LABEL, - 0, - "", - drag_rect.xmin, - drag_rect.ymin, - BLI_rcti_size_x(&drag_rect), - BLI_rcti_size_y(&drag_rect), - NULL, - 0.0, - 0.0, - 0, - 0, - NULL); - - /* Drag-region. */ - if (drag) { - ID *id; - - if ((id = filelist_file_get_id(file))) { - UI_but_drag_set_id(but, id); - UI_but_drag_attach_image(but, imb, scale); - } - /* path is no more static, cannot give it directly to but... */ - else if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS && - (file->typeflag & FILE_TYPE_ASSET) != 0) { - char blend_path[FILE_MAX_LIBEXTRA]; - - if (BLO_library_path_explode(path, blend_path, NULL, NULL)) { - const FileAssetSelectParams *asset_params = ED_fileselect_get_asset_params(sfile); - BLI_assert(asset_params != NULL); - - UI_but_drag_set_asset(but, - &(AssetHandle){.file_data = file}, - BLI_strdup(blend_path), - asset_params->import_type, - icon, - imb, - scale); - } - } - else { - UI_but_drag_set_image(but, BLI_strdup(path), icon, imb, scale, true); - } - } - GPU_blend(GPU_BLEND_NONE); + + if (r_scale) { + *r_scale = scale; + } } static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) @@ -986,7 +976,7 @@ void file_draw_list(const bContext *C, ARegion *region) UI_GetThemeColor4ubv(TH_TEXT, text_col); for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) { - uint file_selflag; + eDirEntry_SelectFlag file_selflag; const int padx = 0.1f * UI_UNIT_X; int icon_ofs = 0; @@ -1028,31 +1018,36 @@ void file_draw_list(const bContext *C, ARegion *region) is_icon = 1; } - file_draw_preview(sfile, - block, - file, - path, + float scale = 0; + file_draw_preview(file, &tile_draw_rect, thumb_icon_aspect, imb, icon, layout, is_icon, - do_drag, is_hidden, - is_link); + is_link, + /* Returns the scale which is needed below. */ + &scale); + if (do_drag) { + file_add_preview_drag_but( + sfile, block, layout, file, path, &tile_draw_rect, imb, icon, scale); + } } else { - file_draw_icon(sfile, - block, - file, - path, - &tile_draw_rect, - filelist_geticon(files, i, true), - ICON_DEFAULT_WIDTH_SCALE, - ICON_DEFAULT_HEIGHT_SCALE, - do_drag, - is_hidden); + const int icon = filelist_geticon(files, i, true); + uiBut *icon_but = file_add_icon_but(sfile, + block, + path, + &tile_draw_rect, + icon, + ICON_DEFAULT_WIDTH_SCALE, + ICON_DEFAULT_HEIGHT_SCALE, + is_hidden); + if (do_drag) { + file_but_enable_drag(icon_but, sfile, file, path, NULL, icon, UI_DPI_FAC); + } icon_ofs += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X; } diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index ec9c8be42e33..1e0f86e995d8 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -137,7 +137,7 @@ FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d, float file_string_width(const char *str); float file_font_pointsize(void); -void file_select_deselect_all(SpaceFile *sfile, uint flag); +void file_select_deselect_all(SpaceFile *sfile, eDirEntry_SelectFlag flag); int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matched_file); int autocomplete_directory(struct bContext *C, char *str, void *arg_v); int autocomplete_file(struct bContext *C, char *str, void *arg_v); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index e9a7080ff358..8616707e42e5 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -1403,7 +1403,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *region, int mx, int my) params = ED_fileselect_get_active_params(sfile); /* In case #SpaceFile.browse_mode just changed, the area may be pending a refresh still, which is - * what creates the params for the current browse mode. See T93508. */ + * what creates the params for the current browse mode. See #93508. */ if (!params) { return false; } @@ -2203,7 +2203,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w int deltay = 0; /* We adjust speed of scrolling to avoid tens of seconds of it in e.g. directories with tens of - * thousands of folders... See T65782. */ + * thousands of folders... See #65782. */ /* This will slow down scrolling when approaching final goal, also avoids going too far and * having to bounce back... */ @@ -2485,7 +2485,7 @@ static void file_expand_directory(bContext *C) { BLI_windows_get_default_root_dir(params->dir); } - /* change "C:" --> "C:\", T28102. */ + /* change "C:" --> "C:\", #28102. */ else if ((isalpha(params->dir[0]) && (params->dir[1] == ':')) && (params->dir[2] == '\0')) { params->dir[2] = '\\'; params->dir[3] = '\0'; diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index 2c63c3460dea..caea344bc979 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -185,7 +185,7 @@ struct FileListEntryPreview { }; /* Dummy wrapper around FileListEntryPreview to ensure we do not access freed memory when freeing - * tasks' data (see T74609). */ + * tasks' data (see #74609). */ struct FileListEntryPreviewTaskData { FileListEntryPreview *preview; }; @@ -233,11 +233,15 @@ struct FileList { FileListEntryCache filelist_cache; - /* We need to keep those info outside of actual filelist items, + /** + * We need to keep those info outside of actual file-list items, * because those are no more persistent * (only generated on demand, and freed as soon as possible). * Persistent part (mere list of paths + stat info) * is kept as small as possible, and file-browser agnostic. + * + * - The key is a #FileDirEntry::uid + * - The value is an #eDirEntry_SelectFlag. */ GHash *selection_state; @@ -633,7 +637,7 @@ static bool is_hidden_dot_filename(const char *filename, const FileListInternEnt while (sep) { /* This happens when a path contains 'ALTSEP', '\' on Unix for e.g. * Supporting alternate slashes in paths is a bigger task involving changes - * in many parts of the code, for now just prevent an assert, see T74579. */ + * in many parts of the code, for now just prevent an assert, see #74579. */ #if 0 BLI_assert(sep[1] != '\0'); #endif @@ -2737,13 +2741,13 @@ int filelist_needs_reading(FileList *filelist) uint filelist_entry_select_set(const FileList *filelist, const FileDirEntry *entry, FileSelType select, - uint flag, + const eDirEntry_SelectFlag flag, FileCheckType check) { /* Default nullptr pointer if not found is fine here! */ void **es_p = BLI_ghash_lookup_p(filelist->selection_state, POINTER_FROM_UINT(entry->uid)); - uint entry_flag = es_p ? POINTER_AS_UINT(*es_p) : 0; - const uint org_entry_flag = entry_flag; + eDirEntry_SelectFlag entry_flag = eDirEntry_SelectFlag(es_p ? POINTER_AS_UINT(*es_p) : 0); + const eDirEntry_SelectFlag org_entry_flag = entry_flag; BLI_assert(entry); BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL)); @@ -2782,8 +2786,11 @@ uint filelist_entry_select_set(const FileList *filelist, return entry_flag; } -void filelist_entry_select_index_set( - FileList *filelist, const int index, FileSelType select, uint flag, FileCheckType check) +void filelist_entry_select_index_set(FileList *filelist, + const int index, + FileSelType select, + const eDirEntry_SelectFlag flag, + FileCheckType check) { FileDirEntry *entry = filelist_file(filelist, index); @@ -2792,8 +2799,11 @@ void filelist_entry_select_index_set( } } -void filelist_entries_select_index_range_set( - FileList *filelist, FileSelection *sel, FileSelType select, uint flag, FileCheckType check) +void filelist_entries_select_index_range_set(FileList *filelist, + FileSelection *sel, + FileSelType select, + const eDirEntry_SelectFlag flag, + FileCheckType check) { /* select all valid files between first and last indicated */ if ((sel->first >= 0) && (sel->first < filelist->filelist.entries_filtered_num) && @@ -2805,7 +2815,9 @@ void filelist_entries_select_index_range_set( } } -uint filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileCheckType check) +eDirEntry_SelectFlag filelist_entry_select_get(FileList *filelist, + FileDirEntry *entry, + FileCheckType check) { BLI_assert(entry); BLI_assert(ELEM(check, CHECK_DIRS, CHECK_FILES, CHECK_ALL)); @@ -2813,14 +2825,16 @@ uint filelist_entry_select_get(FileList *filelist, FileDirEntry *entry, FileChec if ((check == CHECK_ALL) || ((check == CHECK_DIRS) && (entry->typeflag & FILE_TYPE_DIR)) || ((check == CHECK_FILES) && !(entry->typeflag & FILE_TYPE_DIR))) { /* Default nullptr pointer if not found is fine here! */ - return POINTER_AS_UINT( - BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(entry->uid))); + return eDirEntry_SelectFlag(POINTER_AS_UINT( + BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(entry->uid)))); } - return 0; + return eDirEntry_SelectFlag(0); } -uint filelist_entry_select_index_get(FileList *filelist, const int index, FileCheckType check) +eDirEntry_SelectFlag filelist_entry_select_index_get(FileList *filelist, + const int index, + FileCheckType check) { FileDirEntry *entry = filelist_file(filelist, index); @@ -2828,7 +2842,7 @@ uint filelist_entry_select_index_get(FileList *filelist, const int index, FileCh return filelist_entry_select_get(filelist, entry, check); } - return 0; + return eDirEntry_SelectFlag(0); } bool filelist_entry_is_selected(FileList *filelist, const int index) @@ -2838,15 +2852,15 @@ bool filelist_entry_is_selected(FileList *filelist, const int index) /* BLI_ghash_lookup returns nullptr if not found, which gets mapped to 0, which gets mapped to * "not selected". */ - const uint selection_state = POINTER_AS_UINT( - BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid))); + const eDirEntry_SelectFlag selection_state = eDirEntry_SelectFlag(POINTER_AS_UINT( + BLI_ghash_lookup(filelist->selection_state, POINTER_FROM_UINT(intern_entry->uid)))); return selection_state != 0; } void filelist_entry_parent_select_set(FileList *filelist, FileSelType select, - uint flag, + const eDirEntry_SelectFlag flag, FileCheckType check) { if ((filelist->filter_data.flags & FLF_HIDE_PARENT) == 0) { @@ -3587,7 +3601,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, /* ARRRG! We have to be very careful *not to use* common BLI_path_util helpers over * entry->relpath itself (nor any path containing it), since it may actually be a datablock - * name inside .blend file, which can have slashes and backslashes! See T46827. + * name inside .blend file, which can have slashes and backslashes! See #46827. * Note that in the end, this means we 'cache' valid relative subdir once here, * this is actually better. */ BLI_strncpy(rel_subdir, subdir, sizeof(rel_subdir)); @@ -4062,7 +4076,7 @@ void filelist_readjob_start(FileList *filelist, const int space_notifier, const /* The file list type may not support threading so execute immediately. Same when only rereading * #Main data (which we do quite often on changes to #Main, since it's the easiest and safest way * to ensure the displayed data is up to date), because some operations executing right after - * main data changed may need access to the ID files (see T93691). */ + * main data changed may need access to the ID files (see #93691). */ const bool no_threads = (filelist->tags & FILELIST_TAGS_NO_THREADS) || flrj->only_main_data; if (no_threads) { diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index e96ced3fa631..df0f82cf707d 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -148,31 +148,31 @@ bool filelist_is_ready(struct FileList *filelist); unsigned int filelist_entry_select_set(const struct FileList *filelist, const struct FileDirEntry *entry, FileSelType select, - unsigned int flag, + const eDirEntry_SelectFlag flag, FileCheckType check); void filelist_entry_select_index_set(struct FileList *filelist, int index, FileSelType select, - unsigned int flag, + eDirEntry_SelectFlag flag, FileCheckType check); void filelist_entries_select_index_range_set(struct FileList *filelist, FileSelection *sel, FileSelType select, - unsigned int flag, - FileCheckType check); -unsigned int filelist_entry_select_get(struct FileList *filelist, - struct FileDirEntry *entry, - FileCheckType check); -unsigned int filelist_entry_select_index_get(struct FileList *filelist, - int index, + eDirEntry_SelectFlag flag, FileCheckType check); +eDirEntry_SelectFlag filelist_entry_select_get(struct FileList *filelist, + struct FileDirEntry *entry, + FileCheckType check); +eDirEntry_SelectFlag filelist_entry_select_index_get(struct FileList *filelist, + int index, + FileCheckType check); bool filelist_entry_is_selected(struct FileList *filelist, int index); /** * Set selection of the '..' parent entry, but only if it's actually visible. */ void filelist_entry_parent_select_set(struct FileList *filelist, FileSelType select, - unsigned int flag, + eDirEntry_SelectFlag flag, FileCheckType check); void filelist_setrecursion(struct FileList *filelist, int recursion_level); diff --git a/source/blender/editors/space_file/filesel.cc b/source/blender/editors/space_file/filesel.cc index 12d05054e9b0..45bbb25a4deb 100644 --- a/source/blender/editors/space_file/filesel.cc +++ b/source/blender/editors/space_file/filesel.cc @@ -23,6 +23,8 @@ # include #endif +#include "AS_asset_representation.hh" + #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_userdef_types.h" @@ -58,6 +60,9 @@ #include "UI_interface_icons.h" #include "UI_view2d.h" +#include "AS_asset_representation.h" +#include "AS_essentials_library.hh" + #include "file_intern.h" #include "filelist.h" @@ -85,7 +90,7 @@ static void fileselect_initialize_params_common(SpaceFile *sfile, FileSelectPara folder_history_list_ensure_for_active_browse_mode(sfile); folderlist_pushdir(sfile->folders_prev, params->dir); - /* Switching thumbnails needs to recalc layout T28809. */ + /* Switching thumbnails needs to recalc layout #28809. */ if (sfile->layout) { sfile->layout->dirty = true; } @@ -102,9 +107,9 @@ static void fileselect_ensure_updated_asset_params(SpaceFile *sfile) asset_params = sfile->asset_params = static_cast( MEM_callocN(sizeof(*asset_params), "FileAssetSelectParams")); asset_params->base_params.details_flags = U_default.file_space_data.details_flags; - asset_params->asset_library_ref.type = ASSET_LIBRARY_LOCAL; + asset_params->asset_library_ref.type = ASSET_LIBRARY_ALL; asset_params->asset_library_ref.custom_library_index = -1; - asset_params->import_type = FILE_ASSET_IMPORT_APPEND_REUSE; + asset_params->import_type = FILE_ASSET_IMPORT_FOLLOW_PREFS; } FileSelectParams *base_params = &asset_params->base_params; @@ -420,11 +425,17 @@ static void fileselect_refresh_asset_params(FileAssetSelectParams *asset_params) user_library = BKE_preferences_asset_library_find_from_index(&U, library->custom_library_index); if (!user_library) { - library->type = ASSET_LIBRARY_LOCAL; + library->type = ASSET_LIBRARY_ALL; } } - switch (library->type) { + switch (eAssetLibraryType(library->type)) { + case ASSET_LIBRARY_ESSENTIALS: + BLI_strncpy(base_params->dir, + blender::asset_system::essentials_directory_path().c_str(), + sizeof(base_params->dir)); + base_params->type = FILE_ASSET_LIBRARY; + break; case ASSET_LIBRARY_ALL: base_params->dir[0] = '\0'; base_params->type = FILE_ASSET_LIBRARY_ALL; @@ -495,6 +506,43 @@ void ED_fileselect_activate_asset_catalog(const SpaceFile *sfile, const bUUID ca WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, nullptr); } +int ED_fileselect_asset_import_method_get(const SpaceFile *sfile, const FileDirEntry *file) +{ + if (!ED_fileselect_is_asset_browser(sfile) || !file->asset) { + return -1; + } + + /* First handle the case where the asset system dictates a certain import method. */ + if (AS_asset_representation_may_override_import_method(file->asset) == false) { + BLI_assert(AS_asset_representation_import_method_get(file->asset).has_value()); + + return *AS_asset_representation_import_method_get(file->asset); + } + + const FileAssetSelectParams *params = ED_fileselect_get_asset_params(sfile); + + if (params->import_type == FILE_ASSET_IMPORT_FOLLOW_PREFS) { + std::optional import_method = AS_asset_representation_import_method_get(file->asset); + return import_method ? *import_method : -1; + } + + switch (eFileAssetImportType(params->import_type)) { + case FILE_ASSET_IMPORT_LINK: + return ASSET_IMPORT_LINK; + case FILE_ASSET_IMPORT_APPEND: + return ASSET_IMPORT_APPEND; + case FILE_ASSET_IMPORT_APPEND_REUSE: + return ASSET_IMPORT_APPEND_REUSE; + + /* Should be handled above already. Break and fail below. */ + case FILE_ASSET_IMPORT_FOLLOW_PREFS: + break; + } + + BLI_assert_unreachable(); + return -1; +} + static void on_reload_activate_by_id(SpaceFile *sfile, onReloadFnData custom_data) { ID *asset_id = (ID *)custom_data; @@ -1124,7 +1172,7 @@ void ED_file_change_dir(bContext *C) ED_file_change_dir_ex(C, area); } -void file_select_deselect_all(SpaceFile *sfile, uint flag) +void file_select_deselect_all(SpaceFile *sfile, const eDirEntry_SelectFlag flag) { FileSelection sel; sel.first = 0; @@ -1144,7 +1192,7 @@ int file_select_match(struct SpaceFile *sfile, const char *pattern, char *matche */ for (int i = 0; i < n; i++) { FileDirEntry *file = filelist_file(sfile->files, i); - /* Do not check whether file is a file or dir here! Causes: T44243 + /* Do not check whether file is a file or dir here! Causes: #44243 * (we do accept directories at this stage). */ if (fnmatch(pattern, file->relpath, 0) == 0) { filelist_entry_select_set(sfile->files, file, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL); @@ -1228,7 +1276,7 @@ int autocomplete_file(struct bContext *C, char *str, void * /*arg_v*/) void ED_fileselect_clear(wmWindowManager *wm, SpaceFile *sfile) { - /* Only null in rare cases, see: T29734. */ + /* Only null in rare cases, see: #29734. */ if (sfile->files) { filelist_readjob_stop(sfile->files, wm); filelist_freelib(sfile->files); diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 959f8b01ec8e..0e46a2eafe38 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -332,7 +332,7 @@ void fsmenu_entry_refresh_valid(struct FSMenuEntry *fsentry) #ifdef WIN32 /* XXX Special case, always consider those as valid. * Thanks to Windows, which can spend five seconds to perform a mere stat() call on those paths - * See T43684. */ + * See #43684. */ const char *exceptions[] = {"A:\\", "B:\\", NULL}; const size_t exceptions_len[] = {strlen(exceptions[0]), strlen(exceptions[1]), 0}; int i; @@ -653,7 +653,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) /* Skip over floppy disks A & B. */ if (i > 1) { - /* Friendly volume descriptions without using SHGetFileInfoW (T85689). */ + /* Friendly volume descriptions without using SHGetFileInfoW (#85689). */ BLI_strncpy_wchar_from_utf8(wline, tmps, 4); IShellFolder *desktop; if (SHGetDesktopFolder(&desktop) == S_OK) { diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 8ada6d31a2d5..4b51da66ac5b 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -304,7 +304,7 @@ static void graphedit_activekey_handles_cb(bContext *C, void *fcu_ptr, void *bez /* update callback for editing coordinates of right handle in active keyframe properties * NOTE: we cannot just do graphedit_activekey_handles_cb() due to "order of computation" - * weirdness (see calchandleNurb_intern() and T39911) + * weirdness (see calchandleNurb_intern() and #39911) */ static void graphedit_activekey_left_handle_coord_cb(bContext *C, void *fcu_ptr, void *bezt_ptr) { @@ -528,7 +528,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel) /* next handle - only if current is Bezier interpolation */ if (bezt->ipo == BEZT_IPO_BEZ) { - /* NOTE: special update callbacks are needed on the coords here due to T39911 */ + /* NOTE: special update callbacks are needed on the coords here due to #39911 */ col = uiLayoutColumn(layout, true); uiItemL_respect_property_split(col, IFACE_("Right Handle Type"), ICON_NONE); diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index fd4282aaaff7..f315690a50d9 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -606,7 +606,7 @@ static void draw_fcurve_curve(bAnimContext *ac, * * Although the "Beauty Draw" flag was originally for AA'd * line drawing, the sampling rate here has a much greater - * impact on performance (e.g. for T40372)! + * impact on performance (e.g. for #40372)! * * This one still amounts to 10 sample-frames for each 1-frame interval * which should be quite a decent approximation in many situations. @@ -616,7 +616,7 @@ static void draw_fcurve_curve(bAnimContext *ac, } } else { - /* "Higher Precision" but slower - especially on larger windows (e.g. T40372) */ + /* "Higher Precision" but slower - especially on larger windows (e.g. #40372) */ if (samplefreq < 0.00001f) { samplefreq = 0.00001f; } diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 1ad68eef2f55..34c34613cf61 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -485,7 +485,7 @@ static eKeyPasteError paste_graph_keys(bAnimContext *ac, * - First time we try to filter more strictly, allowing only selected channels * to allow copying animation between channels * - Second time, we loosen things up if nothing was found the first time, allowing - * users to just paste keyframes back into the original curve again T31670. + * users to just paste keyframes back into the original curve again #31670. */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index da302378ec22..f92fe71455b5 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -1809,7 +1809,7 @@ static int mouse_graph_keys(bAnimContext *ac, /* Set active F-Curve when something was actually selected (so not on a deselect), except when * dragging the selected keys. Needs to be called with (sipo->flag & SIPO_SELCUVERTSONLY), - * otherwise the active flag won't be set T26452. */ + * otherwise the active flag won't be set #26452. */ if (!run_modal && (nvi->fcu->flag & FCURVE_SELECTED) && something_was_selected) { /* NOTE: Sync the filter flags with findnearest_fcurve_vert. */ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FCURVESONLY | diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 1dc02fee59db..de96cad8de62 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -149,7 +149,7 @@ static void graph_init(struct wmWindowManager *wm, ScrArea *area) /* force immediate init of any invalid F-Curve colors */ /* XXX: but, don't do SIPO_TEMP_NEEDCHANSYNC (i.e. channel select state sync) * as this is run on each region resize; setting this here will cause selection - * state to be lost on area/region resizing. T35744. + * state to be lost on area/region resizing. #35744. */ ED_area_tag_refresh(area); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index f6d21633bb3b..13d3681b10e8 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -2601,7 +2601,7 @@ static int image_new_exec(bContext *C, wmOperator *op) } else { /* #BKE_image_add_generated creates one user by default, remove it if image is not linked to - * anything. ref. T94599. */ + * anything. ref. #94599. */ id_us_min(&ima->id); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index fd8c161687e3..be899d423237 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -407,7 +407,7 @@ static void image_listener(const wmSpaceTypeListenerParams *params) Object *ob = BKE_view_layer_active_object_get(view_layer); /* \note With a geometry nodes modifier, the UVs on `ob` can change in response to * any change on `wmn->reference`. If we could track the upstream dependencies, - * unnecessary redraws could be reduced. Until then, just redraw. See T98594. */ + * unnecessary redraws could be reduced. Until then, just redraw. See #98594. */ if (ob && (ob->mode & OB_MODE_EDIT)) { if (sima->lock && (sima->flag & SI_DRAWSHADOW)) { ED_area_tag_refresh(area); diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 3c0238806bff..1d7645d4e67a 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -145,7 +145,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, int channel_index, } } - /* change active object - regardless of whether it is now selected [T37883] */ + /* change active object - regardless of whether it is now selected [#37883] */ ED_object_base_activate_with_mode_exit_if_needed(C, base); /* adds notifier */ if ((adt) && (adt->flag & ADT_UI_SELECTED)) { @@ -736,7 +736,7 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op)) } /* call delete on this track - deletes all strips too */ - BKE_nlatrack_free(&adt->nla_tracks, nlt, true); + BKE_nlatrack_remove_and_free(&adt->nla_tracks, nlt, true); ale->update = ANIM_UPDATE_DEPS; } } diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 8a3c67452597..b61b5d8e63b0 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -1305,15 +1305,15 @@ static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op)) if (strip->flag & NLASTRIP_FLAG_SELECT) { /* if a strip either side of this was a transition, delete those too */ if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) { - BKE_nlastrip_free(&nlt->strips, strip->prev, true); + BKE_nlastrip_remove_and_free(&nlt->strips, strip->prev, true); } if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) { nstrip = nstrip->next; - BKE_nlastrip_free(&nlt->strips, strip->next, true); + BKE_nlastrip_remove_and_free(&nlt->strips, strip->next, true); } /* finally, delete this strip */ - BKE_nlastrip_free(&nlt->strips, strip, true); + BKE_nlastrip_remove_and_free(&nlt->strips, strip, true); } } } @@ -1824,7 +1824,7 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op)) if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) { /* remove from its current track, and add to the one above * (it 'should' work, so no need to worry) */ - BLI_remlink(&nlt->strips, strip); + BKE_nlatrack_remove_strip(nlt, strip); BKE_nlatrack_add_strip(nltn, strip, is_liboverride); } } @@ -1916,7 +1916,7 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op)) if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) { /* remove from its current track, and add to the one above * (it 'should' work, so no need to worry) */ - BLI_remlink(&nlt->strips, strip); + BKE_nlatrack_remove_strip(nlt, strip); BKE_nlatrack_add_strip(nltp, strip, is_liboverride); } } diff --git a/source/blender/editors/space_node/add_node_search.cc b/source/blender/editors/space_node/add_node_search.cc index 07fc06d0dde2..16505620e6ac 100644 --- a/source/blender/editors/space_node/add_node_search.cc +++ b/source/blender/editors/space_node/add_node_search.cc @@ -132,7 +132,7 @@ static void gather_search_items_for_node_groups(const bContext &C, if (node_group->typeinfo->group_idname != group_node_id) { continue; } - if (local_assets.contains(node_group->id.name)) { + if (local_assets.contains(node_group->id.name + 2)) { continue; } if (!nodeGroupPoll(&node_tree, node_group, nullptr)) { diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index d84f1100c79d..efe3adb2fa55 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -1464,7 +1464,13 @@ static void std_node_socket_interface_draw(bContext * /*C*/, uiLayout *layout, P } } - uiItemR(layout, ptr, "hide_value", DEFAULT_FLAGS, nullptr, 0); + col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "hide_value", DEFAULT_FLAGS, nullptr, 0); + + const bNodeTree *node_tree = reinterpret_cast(ptr->owner_id); + if (sock->in_out == SOCK_IN && node_tree->type == NTREE_GEOMETRY) { + uiItemR(col, ptr, "hide_in_modifier", DEFAULT_FLAGS, nullptr, 0); + } } static void node_socket_virtual_draw_color(bContext * /*C*/, diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 53a86e23ce10..31dc2695c97e 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -51,6 +51,7 @@ #include "GPU_immediate.h" #include "GPU_immediate_util.h" #include "GPU_matrix.h" +#include "GPU_shader_shared.h" #include "GPU_state.h" #include "GPU_viewport.h" diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 3ce4a9bf22fa..54dc0772c966 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -329,7 +329,7 @@ void ED_node_composite_job(const bContext *C, bNodeTree *nodetree, Scene *scene_ Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - /* See T32272. */ + /* See #32272. */ if (G.is_rendering) { return; } diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc index 7a025f05b107..6f5225c04919 100644 --- a/source/blender/editors/space_node/node_group.cc +++ b/source/blender/editors/space_node/node_group.cc @@ -235,7 +235,7 @@ static bool node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) * This also removes remaining links to and from interface nodes. */ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) { - /* We must delay removal since sockets will reference this node. see: T52092 */ + /* We must delay removal since sockets will reference this node. see: #52092 */ nodes_delayed_free.append(node); } diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index b2c12fe2ea40..73cc64bbf61b 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -353,7 +353,7 @@ static void snode_autoconnect(SpaceNode &snode, const bool allow_multiple, const bNode *node_fr = sorted_nodes[i]; bNode *node_to = sorted_nodes[i + 1]; - /* Corner case: input/output node aligned the wrong way around (T47729). */ + /* Corner case: input/output node aligned the wrong way around (#47729). */ if (BLI_listbase_is_empty(&node_to->inputs) || BLI_listbase_is_empty(&node_fr->outputs)) { std::swap(node_fr, node_to); } diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index fbd625932dd9..663a235b8340 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -55,7 +55,7 @@ static bool is_event_over_node_or_socket(const bContext &C, const wmEvent &event /** * Function to detect if there is a visible view3d that uses workbench in texture mode. - * This function is for fixing T76970 for Blender 2.83. The actual fix should add a mechanism in + * This function is for fixing #76970 for Blender 2.83. The actual fix should add a mechanism in * the depsgraph that can be used by the draw engines to check if they need to be redrawn. * * We don't want to add these risky changes this close before releasing 2.83 without good testing @@ -148,7 +148,7 @@ static bool node_under_mouse_tweak(const bNodeTree &ntree, const float2 &mouse) switch (node->type) { case NODE_REROUTE: { const float2 location = node_to_view(*node, {node->locx, node->locy}); - if (math::distance(mouse, location) < 24.0f) { + if (math::distance_squared(mouse, location) < square_f(24.0f)) { return true; } break; diff --git a/source/blender/editors/space_node/node_view.cc b/source/blender/editors/space_node/node_view.cc index f64b44b00dc2..b11997ba1b6f 100644 --- a/source/blender/editors/space_node/node_view.cc +++ b/source/blender/editors/space_node/node_view.cc @@ -60,7 +60,7 @@ bool space_node_view_flag( int tot = 0; bool has_frame = false; if (snode.edittree) { - LISTBASE_FOREACH (const bNode *, node, &snode.edittree->nodes) { + for (const bNode *node : snode.edittree->all_nodes()) { if ((node->flag & node_flag) == node_flag) { BLI_rctf_union(&cur_new, &node->runtime->totr); tot++; @@ -645,7 +645,7 @@ static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) ImageSampleInfo *info; /* Don't handle events intended for nodes (which rely on click/drag distinction). - * which this operator would use since sampling is normally activated on press, see: T98191. */ + * which this operator would use since sampling is normally activated on press, see: #98191. */ if (node_or_socket_isect_event(*C, *event)) { return OPERATOR_PASS_THROUGH; } diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index def49ad883b9..de89bd075e4b 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -71,7 +71,7 @@ void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from) if (ntree->type != NTREE_GEOMETRY) { /* This can probably be removed for all node tree types. It mainly exists because it was not - * possible to store id references in custom properties. Also see T36024. I don't want to + * possible to store id references in custom properties. Also see #36024. I don't want to * remove it for all tree types in bcon3 though. */ id_us_ensure_real(&ntree->id); } @@ -821,7 +821,7 @@ static void node_region_listener(const wmRegionListenerParams *params) } break; case NC_ID: - if (wmn->action == NA_RENAME) { + if (ELEM(wmn->action, NA_RENAME, NA_EDITED)) { ED_region_tag_redraw(region); } break; diff --git a/source/blender/editors/space_outliner/outliner_select.cc b/source/blender/editors/space_outliner/outliner_select.cc index 20319a8befe3..c2975833dcc1 100644 --- a/source/blender/editors/space_outliner/outliner_select.cc +++ b/source/blender/editors/space_outliner/outliner_select.cc @@ -363,7 +363,7 @@ static void tree_element_object_activate(bContext *C, /* Only in object mode so we can switch the active object, * keeping all objects in the current 'mode' selected, useful for multi-pose/edit mode. * This keeps the convention that all objects in the current mode are also selected. - * see T55246. */ + * see #55246. */ if ((scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? (ob->mode == OB_MODE_OBJECT) : true) { @@ -416,7 +416,7 @@ static void tree_element_material_activate(bContext *C, } /* Tagging object for update seems a bit stupid here, but looks like we have to do it - * for render views to update. See T42973. + * for render views to update. See #42973. * Note that RNA material update does it too, see e.g. rna_MaterialSlot_update(). */ DEG_id_tag_update((ID *)ob, ID_RECALC_TRANSFORM); WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, nullptr); @@ -1402,7 +1402,7 @@ static void do_outliner_item_activate_tree_element(bContext *C, TSE_EBONE, TSE_LAYER_COLLECTION)) { /* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several - * objects, we do not want to switch out of edit mode (see T48328 for details). */ + * objects, we do not want to switch out of edit mode (see #48328 for details). */ } else if (do_activate_data) { tree_element_object_activate(C, diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc index 1502b6915de7..e1cc1a74c7a0 100644 --- a/source/blender/editors/space_outliner/outliner_tree.cc +++ b/source/blender/editors/space_outliner/outliner_tree.cc @@ -1570,7 +1570,7 @@ static int outliner_filter_subtree(SpaceOutliner *space_outliner, te_next = te->next; if (outliner_element_visible_get(scene, view_layer, te, exclude_filter) == false) { /* Don't free the tree, but extract the children from the parent and add to this tree. */ - /* This also needs filtering the subtree prior (see T69246). */ + /* This also needs filtering the subtree prior (see #69246). */ outliner_filter_subtree( space_outliner, scene, view_layer, &te->subtree, search_string, exclude_filter); te_next = outliner_extract_children_from_subtree(te, lb); diff --git a/source/blender/editors/space_outliner/space_outliner.cc b/source/blender/editors/space_outliner/space_outliner.cc index af2da7fa8724..d6b72c4eb7fd 100644 --- a/source/blender/editors/space_outliner/space_outliner.cc +++ b/source/blender/editors/space_outliner/space_outliner.cc @@ -432,7 +432,7 @@ static void outliner_id_remap(ScrArea *area, SpaceLink *slink, const struct IDRe if (unassigned) { /* Redraw is needed when removing data for multiple outlines show the same data. * without this, the stale data won't get fully flushed when this outliner - * is not the active outliner the user is interacting with. See T85976. */ + * is not the active outliner the user is interacting with. See #85976. */ ED_area_tag_redraw(area); } } diff --git a/source/blender/editors/space_script/script_edit.c b/source/blender/editors/space_script/script_edit.c index 05e9338a136a..a8cdf2b6642b 100644 --- a/source/blender/editors/space_script/script_edit.c +++ b/source/blender/editors/space_script/script_edit.c @@ -108,7 +108,7 @@ static int script_reload_exec(bContext *C, wmOperator *op) if (true) { /* Postpone when called from Python so this can be called from an operator * that might be re-registered, crashing Blender when we try to read from the - * freed operator type which, see T80694. */ + * freed operator type which, see #80694. */ BPY_run_string_exec(C, (const char *[]){"bpy", NULL}, "def fn():\n" diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5d74ca966137..a4c1a9b11390 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -769,7 +769,7 @@ static void draw_seq_outline(Scene *scene, immUniformColor3ubv(col); /* 2px wide outline for selected strips. */ - /* XXX: some platforms don't support OpenGL lines wider than 1px (see T57570), + /* XXX: some platforms don't support OpenGL lines wider than 1px (see #57570), * draw outline as four boxes instead. */ if (seq->flag & SELECT) { /* Left */ diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 4a0cf7e77c35..1c5063b8aacf 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1220,7 +1220,7 @@ int seq_effect_find_selected(Scene *scene, *r_selseq2 = seq2; *r_selseq3 = seq3; - /* TODO(Richard): This function needs some refactoring, this is just quick hack for T73828. */ + /* TODO(Richard): This function needs some refactoring, this is just quick hack for #73828. */ if (SEQ_effect_get_num_inputs(type) < 3) { *r_selseq3 = NULL; } @@ -1262,6 +1262,12 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op) int old_start = last_seq->start; + /* Force time position update for reassigned effects. + * TODO(Richard): This is because internally startdisp is still used, due to poor performance of + * mapping effect range to inputs. This mapping could be cached though. */ + SEQ_sequence_lookup_tag(scene, SEQ_LOOKUP_TAG_INVALID); + SEQ_time_left_handle_frame_set(scene, seq1, SEQ_time_left_handle_frame_get(scene, seq1)); + SEQ_relations_invalidate_cache_preprocessed(scene, last_seq); SEQ_offset_animdata(scene, last_seq, (last_seq->start - old_start)); diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index a7a741b3ce2a..c04fe2cc543d 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -134,7 +134,9 @@ static int preferences_asset_library_add_exec(bContext *UNUSED(C), wmOperator *o BLI_split_file_part(path, dirname, sizeof(dirname)); /* NULL is a valid directory path here. A library without path will be created then. */ - BKE_preferences_asset_library_add(&U, dirname, path); + const bUserAssetLibrary *new_library = BKE_preferences_asset_library_add(&U, dirname, path); + /* Activate new library in the UI for further setup. */ + U.active_asset_library = BLI_findindex(&U.asset_libraries, new_library); U.runtime.is_dirty = true; /* There's no dedicated notifier for the Preferences. */ @@ -182,16 +184,32 @@ static void PREFERENCES_OT_asset_library_add(wmOperatorType *ot) /** \name Remove Asset Library Operator * \{ */ +static bool preferences_asset_library_remove_poll(bContext *C) +{ + if (BLI_listbase_is_empty(&U.asset_libraries)) { + CTX_wm_operator_poll_msg_set(C, "There is no asset library to remove"); + return false; + } + return true; +} + static int preferences_asset_library_remove_exec(bContext *UNUSED(C), wmOperator *op) { const int index = RNA_int_get(op->ptr, "index"); bUserAssetLibrary *library = BLI_findlink(&U.asset_libraries, index); - if (library) { - BKE_preferences_asset_library_remove(&U, library); - U.runtime.is_dirty = true; - /* Trigger refresh for the Asset Browser. */ - WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL); + if (!library) { + return OPERATOR_CANCELLED; } + + BKE_preferences_asset_library_remove(&U, library); + const int count_remaining = BLI_listbase_count(&U.asset_libraries); + /* Update active library index to be in range. */ + CLAMP(U.active_asset_library, 0, count_remaining - 1); + U.runtime.is_dirty = true; + + /* Trigger refresh for the Asset Browser. */ + WM_main_add_notifier(NC_SPACE | ND_SPACE_ASSET_PARAMS, NULL); + return OPERATOR_FINISHED; } @@ -203,6 +221,7 @@ static void PREFERENCES_OT_asset_library_remove(wmOperatorType *ot) "Remove a path to a .blend file, so the Asset Browser will not attempt to show it anymore"; ot->exec = preferences_asset_library_remove_exec; + ot->poll = preferences_asset_library_remove_poll; ot->flag = OPTYPE_INTERNAL; diff --git a/source/blender/editors/space_view3d/space_view3d.cc b/source/blender/editors/space_view3d/space_view3d.cc index cd7794300f6e..25708ee7a670 100644 --- a/source/blender/editors/space_view3d/space_view3d.cc +++ b/source/blender/editors/space_view3d/space_view3d.cc @@ -1022,6 +1022,7 @@ static void view3d_widgets() WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_xform_gizmo_context); WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_spot); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_point); WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_area); WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_target); WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_force_field); @@ -1968,7 +1969,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes * it's simplest if all these methods behave consistently - respecting the object-mode * without showing the object. * - * See T85532 for alternatives that were considered. */ + * See #85532 for alternatives that were considered. */ const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); BKE_view_layer_synced_ensure(scene, view_layer); @@ -2045,7 +2046,7 @@ static void view3d_id_remap(ScrArea *area, SpaceLink *slink, const struct IDRema view3d_id_remap_v3d(area, slink, view3d, mappings, false); view3d_id_remap_v3d_ob_centers(view3d, mappings); if (view3d->localvd != nullptr) { - /* Object centers in local-view aren't used, see: T52663 */ + /* Object centers in local-view aren't used, see: #52663 */ view3d_id_remap_v3d(area, slink, view3d->localvd, mappings, true); } BKE_viewer_path_id_remap(&view3d->viewer_path, mappings); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index f71ce54729c2..380a0c47b3ea 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -223,7 +223,7 @@ static float compute_scale_factor(const float ve_median, const float median) * Apply helpers. * \note In case we only have one element, * copy directly the value instead of applying the diff or scale factor. - * Avoids some glitches when going e.g. from 3 to 0.0001 (see T37327). + * Avoids some glitches when going e.g. from 3 to 0.0001 (see #37327). */ static void apply_raw_diff(float *val, const int tot, const float ve_median, const float median) { @@ -1117,7 +1117,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float if (bezt->f2 & SELECT) { if (apply_vcos) { /* Here we always have to use the diff... :/ - * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see T37327), + * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see #37327), * unless we use doubles. */ add_v3_v3(bezt->vec[0], median->location); diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index b0590fba294d..80ec3cae4929 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -153,7 +153,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, /* Calculate pixel-size factor once, this is used for lights and object-centers. */ { /* NOTE: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' - * because of float point precision problems at large values T23908. */ + * because of float point precision problems at large values #23908. */ float v1[3], v2[3]; float len_px, len_sc; @@ -585,7 +585,7 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, alpha = ca->passepartalpha; } - immUniformColor4f(0.0f, 0.0f, 0.0f, alpha); + immUniformThemeColorAlpha(TH_CAMERA_PASSEPARTOUT, alpha); if (x1i > 0.0f) { immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f); @@ -1104,8 +1104,8 @@ static void draw_rotation_guide(const RegionView3D *rv3d) immUnbindProgram(); /* -- draw rotation center -- */ - immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); - GPU_point_size(5.0f); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immUniform1f("size", 7.0f); immBegin(GPU_PRIM_POINTS, 1); immAttr4ubv(col, color); immVertex3fv(pos, o); @@ -2266,7 +2266,7 @@ void view3d_depths_rect_create(ARegion *region, rcti *rect, ViewDepths *r_d) } } -/* NOTE: with NOUVEAU drivers the #glReadPixels() is very slow. T24339. */ +/* NOTE: with NOUVEAU drivers the #glReadPixels() is very slow. #24339. */ static ViewDepths *view3d_depths_create(ARegion *region) { ViewDepths *d = MEM_cnew("ViewDepths"); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 23e06c895fcf..d5b96e03f13b 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -957,7 +957,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C, /* As the tangent is arbitrary from the users point of view, * make the cursor 'roll' on the shortest angle. - * otherwise this can cause noticeable 'flipping', see T72419. */ + * otherwise this can cause noticeable 'flipping', see #72419. */ for (int axis = 0; axis < 2; axis++) { float tan_src[3] = {0, 0, 0}; tan_src[axis] = 1.0f; @@ -1032,7 +1032,7 @@ void ED_view3d_cursor3d_update(bContext *C, } else { /* Cursor may be outside of the view, - * prevent it getting 'lost', see: T40353 & T45301 */ + * prevent it getting 'lost', see: #40353 & #45301 */ zero_v2(rv3d->ofs_lock); } } diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c index d967b950bc57..f3db63b9a202 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_light.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c @@ -42,6 +42,7 @@ typedef struct LightSpotWidgetGroup { wmGizmo *spot_angle; wmGizmo *spot_blend; + wmGizmo *spot_radius; } LightSpotWidgetGroup; static void gizmo_spot_blend_prop_matrix_get(const wmGizmo *UNUSED(gz), @@ -94,6 +95,48 @@ static void gizmo_spot_blend_prop_matrix_set(const wmGizmo *UNUSED(gz), RNA_property_update_main(CTX_data_main(C), scene, &light_ptr, spot_blend_prop); } +/* Used by spot light and point light. */ +static void gizmo_light_radius_prop_matrix_get(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + void *value_p) +{ + BLI_assert(gz_prop->type->array_length == 16); + float(*matrix)[4] = value_p; + + const bContext *C = gz_prop->custom_func.user_data; + ViewLayer *view_layer = CTX_data_view_layer(C); + BKE_view_layer_synced_ensure(CTX_data_scene(C), view_layer); + const Light *la = BKE_view_layer_active_object_get(view_layer)->data; + + /* Draw gizmo even when radius is zero. */ + const float diameter = fmaxf(2.0f * la->radius, 1e-2f); + matrix[0][0] = diameter; + matrix[1][1] = diameter; +} + +static void gizmo_light_radius_prop_matrix_set(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + const void *value_p) +{ + const float(*matrix)[4] = value_p; + BLI_assert(gz_prop->type->array_length == 16); + + const bContext *C = gz_prop->custom_func.user_data; + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + BKE_view_layer_synced_ensure(scene, view_layer); + Light *la = BKE_view_layer_active_object_get(view_layer)->data; + + const float radius = 0.5f * len_v3(matrix[0]); + + PointerRNA light_ptr; + RNA_pointer_create(&la->id, &RNA_Light, la, &light_ptr); + PropertyRNA *radius_prop = RNA_struct_find_property(&light_ptr, "shadow_soft_size"); + RNA_property_float_set(&light_ptr, radius_prop, radius); + + RNA_property_update_main(CTX_data_main(C), scene, &light_ptr, radius_prop); +} + static bool WIDGETGROUP_light_spot_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { View3D *v3d = CTX_wm_view3d(C); @@ -154,6 +197,28 @@ static void WIDGETGROUP_light_spot_setup(const bContext *C, wmGizmoGroup *gzgrou .user_data = (void *)C, }); } + + /* Spot radius gizmo. */ + { + ls_gzgroup->spot_radius = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); + wmGizmo *gz = ls_gzgroup->spot_radius; + RNA_enum_set(gz->ptr, + "transform", + ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM); + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_CIRCLE); + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + + WM_gizmo_target_property_def_func(gz, + "matrix", + &(const struct wmGizmoPropertyFnParams){ + .value_get_fn = gizmo_light_radius_prop_matrix_get, + .value_set_fn = gizmo_light_radius_prop_matrix_set, + .range_get_fn = NULL, + .user_data = (void *)C, + }); + } } static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgroup) @@ -165,6 +230,7 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr Object *ob = BKE_view_layer_active_object_get(view_layer); Light *la = ob->data; + /* Spot angle gizmo. */ { PointerRNA lamp_ptr; RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr); @@ -179,6 +245,7 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr WM_gizmo_target_property_def_rna(gz, "offset", &lamp_ptr, propname, -1); } + /* Spot blend gizmo. */ { wmGizmo *gz = ls_gzgroup->spot_blend; @@ -192,6 +259,23 @@ static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgr } } +static void WIDGETGROUP_light_spot_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) +{ + LightSpotWidgetGroup *ls_gzgroup = gzgroup->customdata; + ViewLayer *view_layer = CTX_data_view_layer(C); + BKE_view_layer_synced_ensure(CTX_data_scene(C), view_layer); + Object *ob = BKE_view_layer_active_object_get(view_layer); + + /* Spot radius gizmo. */ + wmGizmo *gz = ls_gzgroup->spot_radius; + + /* Draw circle in the screen space. */ + RegionView3D *rv3d = CTX_wm_region(C)->regiondata; + WM_gizmo_set_matrix_rotation_from_z_axis(gz, rv3d->viewinv[2]); + + WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]); +} + void VIEW3D_GGT_light_spot(wmGizmoGroupType *gzgt) { gzgt->name = "Spot Light Widgets"; @@ -203,6 +287,93 @@ void VIEW3D_GGT_light_spot(wmGizmoGroupType *gzgt) gzgt->setup = WIDGETGROUP_light_spot_setup; gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; gzgt->refresh = WIDGETGROUP_light_spot_refresh; + gzgt->draw_prepare = WIDGETGROUP_light_spot_draw_prepare; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Point Light Gizmo + * \{ */ + +static bool WIDGETGROUP_light_point_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) +{ + const View3D *v3d = CTX_wm_view3d(C); + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) { + return false; + } + + const Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + BKE_view_layer_synced_ensure(scene, view_layer); + const Base *base = BKE_view_layer_active_base_get(view_layer); + if (base && BASE_SELECTABLE(v3d, base)) { + const Object *ob = base->object; + if (ob->type == OB_LAMP) { + const Light *la = ob->data; + return (la->type == LA_LOCAL); + } + } + return false; +} + +static void WIDGETGROUP_light_point_setup(const bContext *C, wmGizmoGroup *gzgroup) +{ + wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); + wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); + /* Point radius gizmo. */ + wmGizmo *gz = wwrapper->gizmo; + gzgroup->customdata = wwrapper; + + RNA_enum_set(gz->ptr, + "transform", + ED_GIZMO_CAGE_XFORM_FLAG_SCALE | ED_GIZMO_CAGE_XFORM_FLAG_SCALE_UNIFORM); + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_CIRCLE); + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + + WM_gizmo_target_property_def_func(gz, + "matrix", + &(const struct wmGizmoPropertyFnParams){ + .value_get_fn = gizmo_light_radius_prop_matrix_get, + .value_set_fn = gizmo_light_radius_prop_matrix_set, + .range_get_fn = NULL, + .user_data = (void *)C, + }); +} + +static void WIDGETGROUP_light_point_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) +{ + wmGizmoWrapper *wwrapper = gzgroup->customdata; + ViewLayer *view_layer = CTX_data_view_layer(C); + BKE_view_layer_synced_ensure(CTX_data_scene(C), view_layer); + const Object *ob = BKE_view_layer_active_object_get(view_layer); + + /* Point radius gizmo. */ + wmGizmo *gz = wwrapper->gizmo; + + /* Draw circle in the screen space. */ + const RegionView3D *rv3d = CTX_wm_region(C)->regiondata; + WM_gizmo_set_matrix_rotation_from_z_axis(gz, rv3d->viewinv[2]); + + WM_gizmo_set_matrix_location(gz, ob->object_to_world[3]); +} + +void VIEW3D_GGT_light_point(wmGizmoGroupType *gzgt) +{ + gzgt->name = "Point Light Widgets"; + gzgt->idname = "VIEW3D_GGT_light_point"; + + gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D); + + gzgt->poll = WIDGETGROUP_light_point_poll; + gzgt->setup = WIDGETGROUP_light_point_setup; + gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag; + gzgt->draw_prepare = WIDGETGROUP_light_point_draw_prepare; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc index bf30f8b9f038..b3310f6084bd 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.cc @@ -46,7 +46,7 @@ /** * Check if drawing should be performed, clear the pre-selection in the case it's disabled. - * Without this, the gizmo would be visible while transforming. See T92954. + * Without this, the gizmo would be visible while transforming. See #92954. * * NOTE(@ideasman42): This is a workaround for the gizmo system, since typically poll * would be used for this purpose. The problem with using poll is once the gizmo is visible again diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index b9a30eac3c6a..4ab1e1d4ae48 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -467,7 +467,7 @@ static bool view3d_ruler_item_mousemove(const bContext *C, * in 3.0 this happened because left-click drag would both select and add a new ruler, * significantly increasing the likelihood of this happening. * Workaround this crash by checking the gizmo's custom-data has not been cleared. - * The key-map has also been modified not to trigger this bug, see T95591. + * The key-map has also been modified not to trigger this bug, see #95591. */ static bool gizmo_ruler_check_for_operator(const wmGizmoGroup *gzgroup) { diff --git a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c index aa287403e232..3519a30e2225 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_tool_generic.c @@ -50,7 +50,7 @@ static bool WIDGETGROUP_tool_generic_poll(const bContext *C, wmGizmoGroupType *g return false; } - /* Without this, refreshing the gizmo jitters in some cases with edit-mesh smooth. See T72948. */ + /* Without this, refreshing the gizmo jitters in some cases with edit-mesh smooth. See #72948. */ if (G.moving & G_TRANSFORM_EDIT) { return false; } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index bfc2cf5214a2..b94833dd2769 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -212,6 +212,7 @@ extern const char *view3d_context_dir[]; /* doc access */ /* view3d_widgets.c */ void VIEW3D_GGT_light_spot(struct wmGizmoGroupType *gzgt); +void VIEW3D_GGT_light_point(struct wmGizmoGroupType *gzgt); void VIEW3D_GGT_light_area(struct wmGizmoGroupType *gzgt); void VIEW3D_GGT_light_target(struct wmGizmoGroupType *gzgt); void VIEW3D_GGT_camera(struct wmGizmoGroupType *gzgt); @@ -235,7 +236,7 @@ void VIEW3D_GT_navigate_rotate(struct wmGizmoType *gzt); void VIEW3D_GGT_placement(struct wmGizmoGroupType *gzgt); /* workaround for trivial but noticeable camera bug caused by imprecision - * between view border calculation in 2D/3D space, workaround for bug T28037. + * between view border calculation in 2D/3D space, workaround for bug #28037. * without this define we get the old behavior which is to try and align them * both which _mostly_ works fine, but when the camera moves beyond ~1000 in * any direction it starts to fail */ diff --git a/source/blender/editors/space_view3d/view3d_iterators.cc b/source/blender/editors/space_view3d/view3d_iterators.cc index 09ff3fa6574a..e7e8eb5b2758 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.cc +++ b/source/blender/editors/space_view3d/view3d_iterators.cc @@ -96,7 +96,7 @@ static int content_planes_from_clip_flag(const ARegion *region, * Edge projection is more involved since part of the edge may be behind the view * or extend beyond the far limits. In the case of single points, these can be ignored. * However it just may still be visible on screen, so constrained the edge to planes - * defined by the port to ensure both ends of the edge can be projected, see T32214. + * defined by the port to ensure both ends of the edge can be projected, see #32214. * * \note This is unrelated to #V3D_PROJ_TEST_CLIP_BB which must be checked separately. */ @@ -577,12 +577,13 @@ void mesh_foreachScreenFace( BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE); - if (me->runtime->subsurf_face_dot_tags.size() == me->totvert) { - BKE_mesh_foreach_mapped_face_center( + const int face_dot_tags_num = me->runtime->subsurf_face_dot_tags.size(); + if (face_dot_tags_num && (face_dot_tags_num != me->totvert)) { + BKE_mesh_foreach_mapped_subdiv_face_center( me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP); } else { - BKE_mesh_foreach_mapped_subdiv_face_center( + BKE_mesh_foreach_mapped_face_center( me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP); } } diff --git a/source/blender/editors/space_view3d/view3d_navigate.c b/source/blender/editors/space_view3d/view3d_navigate.c index ed0225f578bb..9f4710b28a04 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.c +++ b/source/blender/editors/space_view3d/view3d_navigate.c @@ -819,7 +819,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) * object, but in this case there is no change in the scene, * only the cursor so I choice a ED_region_tag like * view3d_smooth_view do for the center_cursor. - * See bug T22640. + * See bug #22640. */ return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/view3d_navigate_ndof.c b/source/blender/editors/space_view3d/view3d_navigate_ndof.c index 47405f397752..0ddfa8dc0f31 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_ndof.c +++ b/source/blender/editors/space_view3d/view3d_navigate_ndof.c @@ -549,7 +549,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev } } else { - /* NOTE: based on feedback from T67579, users want to have pan and orbit enabled at once. + /* NOTE: based on feedback from #67579, users want to have pan and orbit enabled at once. * It's arguable that orbit shouldn't pan (since we have a pan only operator), * so if there are users who like to separate orbit/pan operations - it can be a preference. */ const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) || diff --git a/source/blender/editors/space_view3d/view3d_navigate_roll.c b/source/blender/editors/space_view3d/view3d_navigate_roll.c index 51b92cb23b33..266fafaec9e7 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_roll.c +++ b/source/blender/editors/space_view3d/view3d_navigate_roll.c @@ -109,7 +109,7 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event) } else if (event->type == vod->init.event_type) { /* Check `vod->init.event_type` first in case RMB was used to invoke. - * in this case confirming takes precedence over canceling, see: T102937. */ + * in this case confirming takes precedence over canceling, see: #102937. */ if (event->val == KM_RELEASE) { event_code = VIEW_CONFIRM; } diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index c0eaca859e1b..0d76c1bc7f81 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -2007,7 +2007,7 @@ static int selectbuffer_ret_hits_5(GPUSelectResult *buffer, * * \param do_nearest_xray_if_supported: When set, read in hits that don't stop * at the nearest surface. The hits must still be ordered by depth. - * Needed so we can step to the next, non-active object when it's already selected, see: T76445. + * Needed so we can step to the next, non-active object when it's already selected, see: #76445. */ static int mixed_bones_object_selectbuffer(ViewContext *vc, GPUSelectResult *buffer, @@ -2614,7 +2614,7 @@ static bool ed_object_select_pick(bContext *C, ViewLayer *view_layer = vc.view_layer; BKE_view_layer_synced_ensure(scene, view_layer); - /* Don't set when the context has no active object (hidden), see: T60807. */ + /* Don't set when the context has no active object (hidden), see: #60807. */ const Base *oldbasact = vc.obact ? BKE_view_layer_active_base_get(view_layer) : nullptr; /* Always start list from `basact` when cycling the selection. */ Base *startbase = (oldbasact && oldbasact->next) ? @@ -2628,7 +2628,7 @@ static bool ed_object_select_pick(bContext *C, /* For the most part this is equivalent to `(object_mode & OB_MODE_POSE) != 0` * however this logic should also run with weight-paint + pose selection. * Without this, selection in weight-paint mode can de-select armatures which isn't useful, - * see: T101686. */ + * see: #101686. */ const bool has_pose_old = (oldbasact && BKE_object_pose_armature_get_with_wpaint_check(oldbasact->object)); @@ -3028,7 +3028,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op) if (obedit && enumerate) { /* Enumerate makes no sense in edit-mode unless also explicitly picking objects or bones. - * Pass the event through so the event may be handled by loop-select for e.g. see: T100204. */ + * Pass the event through so the event may be handled by loop-select for e.g. see: #100204. */ if (obedit->type != OB_ARMATURE) { return OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED; } @@ -3077,7 +3077,6 @@ static int view3d_select_exec(bContext *C, wmOperator *op) * generic attribute for now. */ DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, &curves_id); - return true; } } } @@ -3153,8 +3152,8 @@ void VIEW3D_OT_select(wmOperatorType *ot) ot->srna, "object", false, "Object", "Use object selection (edit mode only)"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - /* Needed for select-through to usefully drag handles, see: T98254. - * NOTE: this option may be removed and become default behavior, see design task: T98552. */ + /* Needed for select-through to usefully drag handles, see: #98254. + * NOTE: this option may be removed and become default behavior, see design task: #98552. */ prop = RNA_def_boolean(ot->srna, "vert_without_handles", false, @@ -3796,7 +3795,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const } } - /* The draw order doesn't always match the order we populate the engine, see: T51695. */ + /* The draw order doesn't always match the order we populate the engine, see: #51695. */ qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp); for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end; @@ -3857,7 +3856,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e if (hits > 0) { /* no need to loop if there's no hit */ - /* The draw order doesn't always match the order we populate the engine, see: T51695. */ + /* The draw order doesn't always match the order we populate the engine, see: #51695. */ qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp); for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end; diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index c630a1a56536..4cc282a1cab4 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -329,7 +329,7 @@ void view3d_winmatrix_set(Depsgraph *depsgraph, clipend); #endif - /* Note the code here was tweaked to avoid an apparent compiler bug in clang 13 (see T91680). */ + /* Note the code here was tweaked to avoid an apparent compiler bug in clang 13 (see #91680). */ rctf viewplane; if (rect) { /* Smaller viewplane subset for selection picking. */ @@ -667,7 +667,7 @@ int view3d_opengl_select_ex(ViewContext *vc, G.f |= G_FLAG_PICKSEL; /* Important we use the 'viewmat' and don't re-calculate since - * the object & bone view locking takes 'rect' into account, see: T51629. */ + * the object & bone view locking takes 'rect' into account, see: #51629. */ ED_view3d_draw_setup_view( wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, &rect); @@ -702,7 +702,7 @@ int view3d_opengl_select_ex(ViewContext *vc, object_filter.user_data); hits = drw_select_loop_user_data.hits; /* FIX: This cleanup the state before doing another selection pass. - * (see T56695) */ + * (see #56695) */ GPU_select_cache_end(); } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 3c95d480b78b..398e82573294 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -343,7 +343,7 @@ void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV adr[1] = vec[1]; } else if (t->region->regiontype == RGN_TYPE_WINDOW) { - /* allow points behind the view T33643. */ + /* allow points behind the view #33643. */ if (ED_view3d_project_float_global(t->region, vec, adr, flag) != V3D_PROJ_RET_OK) { /* XXX, 2.64 and prior did this, weak! */ adr[0] = t->region->winx / 2.0f; @@ -989,7 +989,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) } } else if (transform_mode_is_changeable(t->mode)) { - /* Scale isn't normally very useful after extrude along normals, see T39756 */ + /* Scale isn't normally very useful after extrude along normals, see #39756 */ if ((t->con.mode & CON_APPLY) && (t->orient[t->orient_curr].type == V3D_ORIENT_NORMAL)) { stopConstraint(t); } @@ -1302,7 +1302,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) /* Per transform event, if present */ if (t->handleEvent && (!handled || - /* Needed for vertex slide, see T38756. */ + /* Needed for vertex slide, see #38756. */ (event->type == MOUSEMOVE))) { t->redraw |= t->handleEvent(t, event); } @@ -1377,7 +1377,7 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa static bool transinfo_show_overlay(const struct bContext *C, TransInfo *t, ARegion *region) { - /* Don't show overlays when not the active view and when overlay is disabled: T57139 */ + /* Don't show overlays when not the active view and when overlay is disabled: #57139 */ bool ok = false; if (region == t->region) { ok = true; @@ -1859,7 +1859,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve * * Do this only for translation/rotation/resize because only these * modes are available from gizmo and doing such check could - * lead to keymap conflicts for other modes (see T31584) + * lead to keymap conflicts for other modes (see #31584) */ if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { LISTBASE_FOREACH (const wmKeyMapItem *, kmi, &t->keymap->items) { diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index d548cf631f17..dede02b219ff 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -211,6 +211,12 @@ typedef enum { HLP_TRACKBALL = 6, } eTHelpline; +typedef enum { + O_DEFAULT = 0, + O_SCENE, + O_SET, +} eTOType; + /** \} */ /* -------------------------------------------------------------------- */ @@ -607,11 +613,7 @@ typedef struct TransInfo { float matrix[3][3]; } orient[3]; - enum { - O_DEFAULT = 0, - O_SCENE, - O_SET, - } orient_curr; + eTOType orient_curr; /** * All values from `TransInfo.orient[].type` converted into a flag diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 095c59f783b0..802851246c0c 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -421,7 +421,7 @@ static void applyAxisConstraintVec(const TransInfo *t, constraint_snap_plane_to_edge(t, plane, out); } else if (is_snap_to_face) { - /* Disabled, as it has not proven to be really useful. (See T82386). */ + /* Disabled, as it has not proven to be really useful. (See #82386). */ // constraint_snap_plane_to_face(t, plane, out); } else if (!isPlaneProjectionViewAligned(t, plane)) { @@ -1165,6 +1165,7 @@ void setNearestAxis(TransInfo *t) if (mode_prev != t->con.mode) { projection_matrix_calc(t, t->con.pmtx); + transform_gizmo_3d_model_from_constraint_and_mode_set(t); } } diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index a2161daa58c7..211b72c0e77d 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -566,7 +566,7 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) /* constraints that require this only under special conditions */ if (con->type == CONSTRAINT_TYPE_CHILDOF) { - /* ChildOf constraint only works when using all location components, see T42256. */ + /* ChildOf constraint only works when using all location components, see #42256. */ bChildOfConstraint *data = (bChildOfConstraint *)con->data; if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) && @@ -609,7 +609,7 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) } else if (con->type == CONSTRAINT_TYPE_TRANSFORM) { /* Transform constraint needs it for rotation at least (r.57309), - * but doing so when translating may also mess things up, see: T36203. */ + * but doing so when translating may also mess things up, see: #36203. */ bTransformConstraint *data = (bTransformConstraint *)con->data; if (data->to == TRANS_ROTATION) { @@ -709,7 +709,7 @@ static int countAndCleanTransDataContainer(TransInfo *t) static void init_proportional_edit(TransInfo *t) { - /* NOTE: Proportional editing is not usable in pose mode yet T32444. */ + /* NOTE: Proportional editing is not usable in pose mode yet #32444. */ if (!ELEM(t->data_type, &TransConvertType_Action, &TransConvertType_Curve, @@ -1021,7 +1021,7 @@ void createTransData(bContext *C, TransInfo *t) if (t->data_type == &TransConvertType_Object) { t->options |= CTX_OBJECT; - /* Needed for correct Object.obmat after duplication, see: T62135. */ + /* Needed for correct Object.obmat after duplication, see: #62135. */ BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); if ((t->settings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) { @@ -1196,7 +1196,7 @@ void animrecord_check_state(TransInfo *t, struct ID *id) /* copy current "action blending" settings from adt to the strip, * as it was keyframed with these settings, so omitting them will - * change the effect [T54766] + * change the effect [#54766] */ if (is_first == false) { strip->blendmode = adt->act_blendmode; diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 31d0dea3b96f..43fffdc634ac 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -338,7 +338,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) copy_v3_v3(data->grabtarget, pchan->pose_tail); /* watch-it! has to be 0 here, since we're still on the - * same bone for the first time through the loop T25885. */ + * same bone for the first time through the loop #25885. */ data->rootbone = 0; /* we only include bones that are part of a continual connected chain */ @@ -1051,9 +1051,9 @@ static void createTransArmatureVerts(bContext *UNUSED(C), TransInfo *t) copy_v3_v3(td->iloc, ebo->tail); /* Don't allow single selected tips to have a modified center, - * causes problem with snapping (see T45974). + * causes problem with snapping (see #45974). * However, in rotation mode, we want to keep that 'rotate bone around root with - * only its tip selected' behavior (see T46325). */ + * only its tip selected' behavior (see #46325). */ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) { copy_v3_v3(td->center, ebo->head); @@ -1271,7 +1271,7 @@ static void recalcData_edit_armature(TransInfo *t) rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec); mul_qt_v3(qrot, up_axis); - /* roll has a tendency to flip in certain orientations - T34283, T33974. */ + /* roll has a tendency to flip in certain orientations - #34283, #33974. */ roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false); ebo->roll = angle_compat_rad(roll, td->ival); } @@ -1612,7 +1612,7 @@ static short apply_targetless_ik(Object *ob) normalize_m3(rmat3); /* rotation */ - /* T22409 is partially caused by this, as slight numeric error introduced during + /* #22409 is partially caused by this, as slight numeric error introduced during * the solving process leads to locked-axis values changing. However, we cannot modify * the values here, or else there are huge discrepancies between IK-solver (interactive) * and applied poses. */ @@ -1712,7 +1712,7 @@ static void special_aftertrans_update__pose(bContext *C, TransInfo *t) if ((t->flag & T_AUTOIK) && (t->options & CTX_AUTOCONFIRM)) { /* when running transform non-interactively (operator exec), * we need to update the pose otherwise no updates get called during - * transform and the auto-ik is not applied. see T26164. */ + * transform and the auto-ik is not applied. see #26164. */ struct Object *pose_ob = tc->poseobj; BKE_pose_where_is(t->depsgraph, t->scene, pose_ob); } diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index b3ee49ef7ed1..8d1727e7ac7c 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -48,7 +48,7 @@ static int bezt_select_to_transform_triple_flag(const BezTriple *bezt, const boo * When a center point is being moved without the handles, * leaving the handles stationary makes no sense and only causes strange behavior, * where one handle is arbitrarily anchored, the other one is aligned and lengthened - * based on where the center point is moved. Also a bug when canceling, see: T52007. + * based on where the center point is moved. Also a bug when canceling, see: #52007. * * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'. * However that doesn't resolve odd behavior, so best transform the handles in this case. @@ -437,7 +437,7 @@ static void recalcData_curve(TransInfo *t) } } else { - /* Apply clipping after so we never project past the clip plane T25423. */ + /* Apply clipping after so we never project past the clip plane #25423. */ transform_convert_clip_mirror_modifier_apply(tc); /* Normal updating. */ diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index aeb7a223f641..902b995680fc 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -556,7 +556,7 @@ static void tc_mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tc * * Since we only need to check if the vertex is in this corner, * its not important _which_ loop - as long as its not overlapping - * 'sv->co_orig_3d', see: T45096. */ + * 'sv->co_orig_3d', see: #45096. */ project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis); while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) && ((l_prev = l_prev->prev) != l->next))) { @@ -1508,7 +1508,7 @@ static void createTransEditVerts(bContext *UNUSED(C), TransInfo *t) } /* Snap rotation along normal needs a common axis for whole islands, - * otherwise one get random crazy results, see T59104. + * otherwise one get random crazy results, see #59104. * However, we do not want to use the island center for the pivot/translation reference. */ const bool is_snap_rotate = ((t->mode == TFM_TRANSLATION) && /* There is not guarantee that snapping @@ -1517,7 +1517,7 @@ static void createTransEditVerts(bContext *UNUSED(C), TransInfo *t) (t->settings->snap_flag & SCE_SNAP_ROTATE) != 0) && (t->around != V3D_AROUND_LOCAL_ORIGINS)); - /* Even for translation this is needed because of island-orientation, see: T51651. */ + /* Even for translation this is needed because of island-orientation, see: #51651. */ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) || is_snap_rotate; if (is_island_center) { /* In this specific case, near-by vertices will need to know @@ -2046,7 +2046,7 @@ static void recalcData_mesh(TransInfo *t) bool do_mirror = !(t->flag & T_NO_MIRROR); FOREACH_TRANS_DATA_CONTAINER (t, tc) { - /* Apply clipping after so we never project past the clip plane T25423. */ + /* Apply clipping after so we never project past the clip plane #25423. */ transform_convert_clip_mirror_modifier_apply(tc); if (do_mirror) { diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c index f38d25b440bd..a9b1d07e7b46 100644 --- a/source/blender/editors/transform/transform_convert_nla.c +++ b/source/blender/editors/transform/transform_convert_nla.c @@ -67,7 +67,7 @@ typedef struct TransDataNla { static void applyTransformNLA_translation(PointerRNA *strip_rna_ptr, const TransDataNla *transdata) { /* NOTE: we write these twice to avoid truncation errors which can arise when - * moving the strips a large distance using numeric input T33852. + * moving the strips a large distance using numeric input #33852. */ RNA_float_set(strip_rna_ptr, "frame_start", transdata->h1[0]); RNA_float_set(strip_rna_ptr, "frame_end", transdata->h2[0]); @@ -457,7 +457,7 @@ static void recalcData_nla(TransInfo *t) if (BKE_nlatrack_has_space(track, strip->start, strip->end) && !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) { /* move strip to this track */ - BLI_remlink(&tdn->nlt->strips, strip); + BKE_nlatrack_remove_strip(tdn->nlt, strip); BKE_nlatrack_add_strip(track, strip, is_liboverride); tdn->nlt = track; @@ -477,7 +477,7 @@ static void recalcData_nla(TransInfo *t) if (BKE_nlatrack_has_space(track, strip->start, strip->end) && !BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) { /* move strip to this track */ - BLI_remlink(&tdn->nlt->strips, strip); + BKE_nlatrack_remove_strip(tdn->nlt, strip); BKE_nlatrack_add_strip(track, strip, is_liboverride); tdn->nlt = track; diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 045b737c4f7c..a0364642d1f4 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -211,7 +211,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) copy_m4_m4(ob->object_to_world, object_eval->object_to_world); /* Only copy negative scale flag, this is the only flag which is modified by * the BKE_object_where_is_calc(). The rest of the flags we need to keep, - * otherwise we might lose dupli flags (see T61787). */ + * otherwise we might lose dupli flags (see #61787). */ ob->transflag &= ~OB_NEG_SCALE; ob->transflag |= (object_eval->transflag & OB_NEG_SCALE); @@ -274,7 +274,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) copy_m3_m4(totmat, ob->object_to_world); /* If the object scale is zero on any axis, this might result in a zero matrix. - * In this case, the transformation would not do anything, see: T50103. */ + * In this case, the transformation would not do anything, see: #50103. */ orthogonalize_m3_zero_axes(obmtx, 1.0f); orthogonalize_m3_zero_axes(totmat, 1.0f); @@ -857,7 +857,7 @@ static bool motionpath_need_update_object(Scene *scene, Object *ob) { /* XXX: there's potential here for problems with unkeyed rotations/scale, * but for now (until proper data-locality for baking operations), - * this should be a better fix for T24451 and T37755 + * this should be a better fix for #24451 and #37755 */ if (autokeyframe_cfra_can_key(scene, &ob->id)) { diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index d1f210ca7722..48edf180a817 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -512,7 +512,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } } else { - /* Release confirms preference should not affect node editor (T69288, T70504). */ + /* Release confirms preference should not affect node editor (#69288, #70504). */ if (ISMOUSE_BUTTON(t->launch_event) && ((U.flag & USER_RELEASECONFIRM) || (t->spacetype == SPACE_NODE))) { /* Global "release confirm" on mouse bindings */ @@ -1422,7 +1422,7 @@ Object *transform_object_deform_pose_armature_get(const TransInfo *t, Object *ob if (!(ob->mode & OB_MODE_ALL_WEIGHT_PAINT)) { return NULL; } - /* Important that ob_armature can be set even when its not selected T23412. + /* Important that ob_armature can be set even when its not selected #23412. * Lines below just check is also visible. */ Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); if (ob_armature && ob_armature->mode & OB_MODE_POSE) { diff --git a/source/blender/editors/transform/transform_gizmo_3d.cc b/source/blender/editors/transform/transform_gizmo_3d.cc index dd4d9ef6a12b..811ff0e85bd9 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.cc +++ b/source/blender/editors/transform/transform_gizmo_3d.cc @@ -30,7 +30,9 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_context.h" +#include "BKE_crazyspace.hh" #include "BKE_curve.h" +#include "BKE_curves.hh" #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_gpencil.h" @@ -47,6 +49,7 @@ #include "WM_types.h" #include "ED_armature.h" +#include "ED_curves.h" #include "ED_gizmo_library.h" #include "ED_gizmo_utils.h" #include "ED_gpencil.h" @@ -623,6 +626,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, const TransformCalcParams *params, TransformBounds *tbounds) { + using namespace blender; ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); @@ -929,6 +933,28 @@ int ED_transform_calc_gizmo_stats(const bContext *C, } FOREACH_EDIT_OBJECT_END(); } + else if (obedit->type == OB_CURVES) { + FOREACH_EDIT_OBJECT_BEGIN (ob_iter, use_mat_local) { + const Curves &curves_id = *static_cast(ob_iter->data); + const bke::CurvesGeometry &curves = curves_id.geometry.wrap(); + const bke::crazyspace::GeometryDeformation deformation = + bke::crazyspace::get_evaluated_curves_deformation(*depsgraph, *ob); + + float4x4 mat_local; + if (use_mat_local) { + mat_local = float4x4(obedit->world_to_object) * float4x4(ob_iter->object_to_world); + } + + Vector indices; + const IndexMask selected_points = ed::curves::retrieve_selected_points(curves, indices); + const Span positions = deformation.positions; + totsel += selected_points.size(); + for (const int point_i : selected_points) { + calc_tw_center_with_matrix(tbounds, positions[point_i], use_mat_local, mat_local.ptr()); + } + } + FOREACH_EDIT_OBJECT_END(); + } #undef FOREACH_EDIT_OBJECT_BEGIN #undef FOREACH_EDIT_OBJECT_END @@ -1294,11 +1320,10 @@ static void gizmo_3d_dial_matrixbasis_calc(const ARegion *region, const float mval_init[2], float r_mat_basis[4][4]) { - copy_v3_v3(r_mat_basis[2], axis); + plane_from_point_normal_v3(r_mat_basis[2], center_global, axis); copy_v3_v3(r_mat_basis[3], center_global); - r_mat_basis[2][3] = -dot_v3v3(axis, center_global); - if (ED_view3d_win_to_3d_on_plane(region, axis, mval_init, false, r_mat_basis[1])) { + if (ED_view3d_win_to_3d_on_plane(region, r_mat_basis[2], mval_init, false, r_mat_basis[1])) { sub_v3_v3(r_mat_basis[1], center_global); normalize_v3(r_mat_basis[1]); cross_v3_v3v3(r_mat_basis[0], r_mat_basis[1], r_mat_basis[2]); @@ -1376,7 +1401,7 @@ static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx) WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_MODAL, true); WM_gizmo_set_scale(axis, 0.2f); - /* Prevent axis gizmos overlapping the center point, see: T63744. */ + /* Prevent axis gizmos overlapping the center point, see: #63744. */ axis->select_bias = 2.0f; break; case MAN_AXIS_SCALE_C: @@ -1386,7 +1411,7 @@ static void gizmo_3d_setup_draw_default(wmGizmo *axis, const int axis_idx) RNA_float_set(axis->ptr, "arc_inner_factor", 1.0 / 6.0); WM_gizmo_set_scale(axis, 1.2f); - /* Prevent axis gizmos overlapping the center point, see: T63744. */ + /* Prevent axis gizmos overlapping the center point, see: #63744. */ axis->select_bias = -2.0f; break; @@ -1577,7 +1602,7 @@ static int gizmo_modal(bContext *C, const wmEvent *event, eWM_GizmoFlagTweak /*tweak_flag*/) { - /* Avoid unnecessary updates, partially address: T55458. */ + /* Avoid unnecessary updates, partially address: #55458. */ if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) { return OPERATOR_RUNNING_MODAL; } @@ -2730,7 +2755,7 @@ void transform_gizmo_3d_model_from_constraint_and_mode_set(TransInfo *t) int axis_idx = -1; if (t->mode == TFM_TRACKBALL) { - axis_idx = MAN_AXIS_ROT_T; + /* Pass. Do not display gizmo. */ } else if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { const int axis_map[3][7] = { @@ -2776,15 +2801,17 @@ void transform_gizmo_3d_model_from_constraint_and_mode_set(TransInfo *t) wmGizmo *gizmo_modal_current = WM_gizmomap_get_modal(t->region->gizmo_map); if (axis_idx != -1) { RegionView3D *rv3d = static_cast(t->region->regiondata); - bool update_orientation = !(equals_v3v3(rv3d->twmat[0], t->spacemtx[0]) && - equals_v3v3(rv3d->twmat[1], t->spacemtx[1]) && - equals_v3v3(rv3d->twmat[2], t->spacemtx[2])); + float(*mat_cmp)[3] = t->orient[t->orient_curr != O_DEFAULT ? t->orient_curr : O_SCENE].matrix; + + bool update_orientation = !(equals_v3v3(rv3d->twmat[0], mat_cmp[0]) && + equals_v3v3(rv3d->twmat[1], mat_cmp[1]) && + equals_v3v3(rv3d->twmat[2], mat_cmp[2])); GizmoGroup *ggd = static_cast(gzgroup_xform->customdata); wmGizmo *gizmo_expected = ggd->gizmos[axis_idx]; if (update_orientation || gizmo_modal_current != gizmo_expected) { if (update_orientation) { - copy_m4_m3(rv3d->twmat, t->spacemtx); + copy_m4_m3(rv3d->twmat, mat_cmp); copy_v3_v3(rv3d->twmat[3], t->center_global); } diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 38dbe7422799..1295486550a8 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -55,7 +55,7 @@ static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], InputSpring(t, mi, mval, output); /* flip scale */ - /* values can become really big when zoomed in so use longs T26598. */ + /* values can become really big when zoomed in so use longs #26598. */ if (((int64_t)((int)mi->center[0] - mval[0]) * (int64_t)((int)mi->center[0] - mi->imval[0]) + (int64_t)((int)mi->center[1] - mval[1]) * (int64_t)((int)mi->center[1] - mi->imval[1])) < 0) { diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index d76dba63262f..4014fae07b37 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -884,7 +884,7 @@ void headerResize(TransInfo *t, const float vec[3], char *str, const int str_siz /** * \a smat is reference matrix only. * - * \note this is a tricky area, before making changes see: T29633, T42444 + * \note this is a tricky area, before making changes see: #29633, #42444 */ static void TransMat3ToSize(const float mat[3][3], const float smat[3][3], float size[3]) { @@ -1041,7 +1041,7 @@ void ElementResize(const TransInfo *t, if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { if (t->options & CTX_POSE_BONE) { /* Without this, the resulting location of scaled bones aren't correct, - * especially noticeable scaling root or disconnected bones around the cursor, see T92515. */ + * especially noticeable scaling root or disconnected bones around the cursor, see #92515. */ mul_mat3_m4_v3(tc->poseobj->object_to_world, vec); } mul_m3_v3(td->smtx, vec); diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index df8517563b5b..f54624c1a1b2 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -429,7 +429,7 @@ static void calcEdgeSlide_mval_range(TransInfo *t, continue; } - /* This test is only relevant if object is not wire-drawn! See T32068. */ + /* This test is only relevant if object is not wire-drawn! See #32068. */ bool is_visible = !use_occlude_geometry || BMBVH_EdgeVisible(bmbvh, e, t->depsgraph, region, v3d, tc->obedit); @@ -617,7 +617,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo * which calculates the direction to slide based on clever checks. * * otherwise we simply use 'e_dir' as an edge-rail. - * (which is better when the attached edge is a boundary, see: T40422) + * (which is better when the attached edge is a boundary, see: #40422) */ #define EDGESLIDE_VERT_IS_INNER(v, e_dir) \ ((BM_edge_is_boundary(e_dir) == false) && (BM_vert_edge_count_nonwire(v) == 2)) @@ -717,7 +717,7 @@ static EdgeSlideData *createEdgeSlideVerts_double_side(TransInfo *t, TransDataCo BMVert *v_prev; BMEdge *e_prev; - /* XXX, 'sv' will initialize multiple times, this is suspicious. see T34024. */ + /* XXX, 'sv' will initialize multiple times, this is suspicious. see #34024. */ BLI_assert(v != NULL); BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID); sv = SV_FROM_VERT(v); diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index bf9fba2b1e79..5a42edb9ad48 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -70,7 +70,7 @@ static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) /* Use 'invalid' dist when `center == p1` (after projecting), * in this case scale will _never_ move the point in relation to the center, - * so it makes no sense to take it into account when scaling. see: T46503 */ + * so it makes no sense to take it into account when scaling. see: #46503 */ return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID; } @@ -96,7 +96,7 @@ static void constrain_scale_to_boundary(const float numerator, float *scale) { /* It's possible the numerator or denominator can be very close to zero due to so-called - * "catastrophic cancellation". See T102923 for an example. We use epsilon tests here to + * "catastrophic cancellation". See #102923 for an example. We use epsilon tests here to * distinguish between genuine negative coordinates versus coordinates that should be rounded off * to zero. */ const float epsilon = 0.25f / 65536.0f; /* i.e. Quarter of a texel on a 65536 x 65536 texture. */ diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index b171b227aa6f..3ea18ef11524 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -500,7 +500,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) float pivot_local[3]; if (rotate_mode != TRANSLATE_ROTATE_OFF) { copy_v3_v3(pivot_local, t->tsnap.snap_source); - /* The pivot has to be in local-space (see T49494) */ + /* The pivot has to be in local-space (see #49494) */ if (tc->use_local_mat) { mul_m4_v3(tc->imat, pivot_local); } @@ -693,7 +693,7 @@ void initTranslation(TransInfo *t) copy_v3_fl(t->num.val_inc, t->snap[0]); t->num.unit_sys = t->scene->unit.system; if (t->spacetype == SPACE_VIEW3D) { - /* Handling units makes only sense in 3Dview... See T38877. */ + /* Handling units makes only sense in 3Dview... See #38877. */ t->num.unit_type[0] = B_UNIT_LENGTH; t->num.unit_type[1] = B_UNIT_LENGTH; t->num.unit_type[2] = B_UNIT_LENGTH; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 0da3bf4d85f5..cca191b99afb 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -420,10 +420,10 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) t->context = NULL; /* XXX, workaround: active needs to be calculated before transforming, - * since we're not reading from 'td->center' in this case. see: T40241 */ + * since we're not reading from 'td->center' in this case. see: #40241 */ if (t->tsnap.source_operation == SCE_SNAP_SOURCE_ACTIVE) { /* In camera view, tsnap callback is not set - * (see #initSnappingMode() in transform_snap.c, and T40348). */ + * (see #initSnappingMode() in transform_snap.c, and #40348). */ if (t->tsnap.snap_source_fn && ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0)) { t->tsnap.snap_source_fn(t); } diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 66fee01f864b..0cf9d5fa3091 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -526,7 +526,7 @@ short ED_transform_calc_orientation_from_type_ex(const Scene *scene, if (ob) { if (ob->mode & OB_MODE_POSE) { /* Each bone moves on its own local axis, but to avoid confusion, - * use the active pones axis for display T33575, this works as expected on a single + * use the active pones axis for display #33575, this works as expected on a single * bone and users who select many bones will understand what's going on and what local * means when they start transforming. */ ED_getTransformOrientationMatrix(scene, view_layer, v3d, ob, obedit, pivot_point, r_mat); @@ -889,7 +889,7 @@ int getTransformOrientation_ex(const Scene *scene, * - Point the Z axis outwards (the same direction as the normals). * * \note Z points outwards - along the normal. - * take care making changes here, see: T38592, T43708 + * take care making changes here, see: #38592, #43708 */ /* be deterministic where possible and ensure v_pair[0] is active */ @@ -1197,7 +1197,7 @@ int getTransformOrientation_ex(const Scene *scene, /* align normal to edge direction (so normal is perpendicular to the plane). * 'ORIENTATION_EDGE' will do the other way around. - * This has to be done **after** applying obmat, see T45775! */ + * This has to be done **after** applying obmat, see #45775! */ project_v3_v3v3(tvec, normal, plane); sub_v3_v3(normal, tvec); } diff --git a/source/blender/editors/transform/transform_snap.cc b/source/blender/editors/transform/transform_snap.cc index 425f97a23f44..50f6da7486db 100644 --- a/source/blender/editors/transform/transform_snap.cc +++ b/source/blender/editors/transform/transform_snap.cc @@ -699,10 +699,10 @@ static eSnapTargetOP snap_target_select_from_spacetype(TransInfo *t) if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) { /* In "Edit Strokes" mode, - * snap tool can perform snap to selected or active objects (see T49632) + * snap tool can perform snap to selected or active objects (see #49632) * TODO: perform self snap in gpencil_strokes. * - * When we're moving the origins, allow snapping onto our own geometry (see T69132). */ + * When we're moving the origins, allow snapping onto our own geometry (see #69132). */ return ret; } diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index a33f0bf6fca4..7fa13180f673 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -162,7 +162,7 @@ struct SnapObjectContext { * * - When the return value is null the `BKE_editmesh_from_object(ob_eval)` should be used. * - In rare cases there is no evaluated mesh available and a null result doesn't imply an - * edit-mesh, so callers need to account for a null edit-mesh too, see: T96536. + * edit-mesh, so callers need to account for a null edit-mesh too, see: #96536. */ static ID *data_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide) { @@ -726,7 +726,7 @@ static bool raycastMesh(SnapObjectContext *sctx, } /* 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 T50486, T38358. + * very far away ray_start values (as returned in case of ortho view3d), see #50486, #38358. */ if (len_diff > 400.0f) { /* Make temporary start point a bit away from bounding-box hit point. */ @@ -860,7 +860,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx, } /* 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 T50486, T38358. + * very far away ray_start values (as returned in case of ortho view3d), see #50486, #38358. */ if (len_diff > 400.0f) { len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ @@ -1375,7 +1375,7 @@ static bool snap_bound_box_check_dist(const float min[3], float dist_px_sq) { /* In vertex and edges you need to get the pixel distance from ray to BoundBox, - * see: T46099, T46816 */ + * see: #46099, #46816 */ DistProjectedAABBPrecalc data_precalc; dist_squared_to_projected_aabb_precalc(&data_precalc, lpmat, win_size, mval); diff --git a/source/blender/editors/undo/ed_undo.cc b/source/blender/editors/undo/ed_undo.cc index 1028867ce748..b4a42f9e1eac 100644 --- a/source/blender/editors/undo/ed_undo.cc +++ b/source/blender/editors/undo/ed_undo.cc @@ -121,7 +121,7 @@ void ED_undo_push(bContext *C, const char *str) } if (G.background) { /* Python developers may have explicitly created the undo stack in background mode, - * otherwise allow it to be nullptr, see: T60934. + * otherwise allow it to be nullptr, see: #60934. * Otherwise it must never be nullptr, even when undo is disabled. */ if (wm->undo_stack == nullptr) { return; @@ -428,7 +428,7 @@ bool ED_undo_is_valid(const bContext *C, const char *undoname) bool ED_undo_is_memfile_compatible(const bContext *C) { - /* Some modes don't co-exist with memfile undo, disable their use: T60593 + /* Some modes don't co-exist with memfile undo, disable their use: #60593 * (this matches 2.7x behavior). */ const Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -511,7 +511,7 @@ static int ed_undo_exec(bContext *C, wmOperator *op) static int ed_undo_push_exec(bContext *C, wmOperator *op) { if (G.background) { - /* Exception for background mode, see: T60934. + /* Exception for background mode, see: #60934. * NOTE: since the undo stack isn't initialized on startup, background mode behavior * won't match regular usage, this is just for scripts to do explicit undo pushes. */ wmWindowManager *wm = CTX_wm_manager(C); @@ -546,7 +546,7 @@ static int ed_undo_redo_exec(bContext *C, wmOperator * /*op*/) return ret; } -/* Disable in background mode, we could support if it's useful, T60934. */ +/* Disable in background mode, we could support if it's useful, #60934. */ static bool ed_undo_is_init_poll(bContext *C) { @@ -680,7 +680,7 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op) if (WM_operator_repeat_check(C, op) && WM_operator_poll(C, op->type) && /* NOTE: undo/redo can't run if there are jobs active, * check for screen jobs only so jobs like material/texture/world preview - * (which copy their data), won't stop redo, see T29579], + * (which copy their data), won't stop redo, see #29579. * * NOTE: WM_operator_check_ui_enabled() jobs test _must_ stay in sync with this. */ (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY) == 0)) { diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index 334516bfd6cf..e91242cb9e62 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -164,7 +164,7 @@ static void set_mapped_co(void *vuserdata, int index, const float co[3], const f tv = &tv[BM_elem_index_get(eve)]; /* Be clever, get the closest vertex to the original, - * behaves most logically when the mirror modifier is used for eg T33051. */ + * behaves most logically when the mirror modifier is used for eg #33051. */ if ((tv->flag & TX_VERT_USE_MAPLOC) == 0) { /* first time */ copy_v3_v3(tv->maploc, co); diff --git a/source/blender/editors/util/ed_util.cc b/source/blender/editors/util/ed_util.cc index eed46ea1c35e..77e5be4e0dd1 100644 --- a/source/blender/editors/util/ed_util.cc +++ b/source/blender/editors/util/ed_util.cc @@ -144,7 +144,7 @@ void ED_editors_init(bContext *C) /* Other edit/paint/etc. modes are only settable for objects visible in active scene currently. * Otherwise, they (and their obdata) may not be (fully) evaluated, which is mandatory for some * modes like Sculpt. - * Ref. T98225. */ + * Ref. #98225. */ if (!BKE_collection_has_object_recursive(scene->master_collection, ob) || !BKE_scene_has_object(scene, ob) || (ob->visibility_flag & OB_HIDE_VIEWPORT) != 0) { continue; @@ -193,7 +193,7 @@ void ED_editors_init(bContext *C) /* Enforce a full redraw for the first time areas/regions get drawn. Further region init/refresh * just triggers non-rebuild redraws (#RGN_DRAW_NO_REBUILD). Usually a full redraw would be * triggered by a `NC_WM | ND_FILEREAD` notifier, but if a startup script calls an operator that - * redraws the window, notifiers are not handled before the operator runs. See T98461. */ + * redraws the window, notifiers are not handled before the operator runs. See #98461. */ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { const bScreen *screen = WM_window_get_active_screen(win); @@ -235,7 +235,7 @@ void ED_editors_exit(Main *bmain, bool do_undo_system) * Python for example can do this, some callers to #ED_object_base_activate * don't handle modes either (doing so isn't always practical). * - * To reproduce the problem where stale data is used, see: T84920. */ + * To reproduce the problem where stale data is used, see: #84920. */ LISTBASE_FOREACH (Object *, ob, &bmain->objects) { if (ED_object_editmode_free_ex(bmain, ob)) { if (do_undo_system == false) { @@ -258,7 +258,7 @@ bool ED_editors_flush_edits_for_object_ex(Main *bmain, if (ob->mode & OB_MODE_SCULPT) { /* Don't allow flushing while in the middle of a stroke (frees data in use). * Auto-save prevents this from happening but scripts - * may cause a flush on saving: T53986. */ + * may cause a flush on saving: #53986. */ if (ob->sculpt != nullptr && ob->sculpt->cache == nullptr) { char *needs_flush_ptr = &ob->sculpt->needs_flush_to_id; if (check_needs_flush && (*needs_flush_ptr == 0)) { diff --git a/source/blender/editors/util/ed_util_ops.cc b/source/blender/editors/util/ed_util_ops.cc index 18d47af78543..0b3a8fe463bf 100644 --- a/source/blender/editors/util/ed_util_ops.cc +++ b/source/blender/editors/util/ed_util_ops.cc @@ -50,15 +50,15 @@ static bool lib_id_preview_editing_poll(bContext *C) return false; } if (ID_IS_LINKED(id)) { - CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit external library data")); + CTX_wm_operator_poll_msg_set(C, "Can't edit external library data"); return false; } if (ID_IS_OVERRIDE_LIBRARY(id)) { - CTX_wm_operator_poll_msg_set(C, TIP_("Can't edit previews of overridden library data")); + CTX_wm_operator_poll_msg_set(C, "Can't edit previews of overridden library data"); return false; } if (!BKE_previewimg_id_get_p(id)) { - CTX_wm_operator_poll_msg_set(C, TIP_("Data-block does not support previews")); + CTX_wm_operator_poll_msg_set(C, "Data-block does not support previews"); return false; } @@ -118,7 +118,7 @@ static bool lib_id_generate_preview_poll(bContext *C) const PointerRNA idptr = CTX_data_pointer_get(C, "id"); const ID *id = (ID *)idptr.data; if (GS(id->name) == ID_NT) { - CTX_wm_operator_poll_msg_set(C, TIP_("Can't generate automatic preview for node group")); + CTX_wm_operator_poll_msg_set(C, "Can't generate automatic preview for node group"); return false; } diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 60cbc2a2df65..0e9f6dce6b98 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -455,7 +455,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) return true; case EVT_PADPERIOD: case EVT_PERIODKEY: - /* Force number-pad "." since some OS's/countries generate a comma char, see: T37992 */ + /* Force number-pad "." since some OS's/countries generate a comma char, see: #37992 */ ascii[0] = '.'; utf8_buf = ascii; break; @@ -594,7 +594,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) if (n->val_flag[idx] & NUM_INVERSE) { val = n->val[idx]; /* If we invert on radians when user is in degrees, - * you get unexpected results... See T53463. */ + * you get unexpected results... See #53463. */ if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) { val = RAD2DEG(val); } diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index c090d8b95b71..32f6d03a4209 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -18,7 +18,7 @@ struct Scene; struct SpaceImage; struct wmOperatorType; -/* find nearest */ +/* UV Find Nearest */ typedef struct UvNearestHit { /** Only for `*_multi(..)` versions of functions. */ @@ -30,9 +30,9 @@ typedef struct UvNearestHit { * Needs to be set before calling nearest functions. * * \note When #UV_NEAREST_HIT_INIT_DIST_PX or #UV_NEAREST_HIT_INIT_MAX are used, - * this value is pixels squared. + * Units are pixels. */ - float dist_sq; + float dist; /** Scale the UVs to account for aspect ratio from the image view. */ float scale[2]; @@ -40,7 +40,7 @@ typedef struct UvNearestHit { #define UV_NEAREST_HIT_INIT_DIST_PX(v2d, dist_px) \ { \ - .dist_sq = square_f(U.pixelsize * dist_px), \ + .dist = U.pixelsize * dist_px, \ .scale = { \ UI_view2d_scale_get_x(v2d), \ UI_view2d_scale_get_y(v2d), \ @@ -49,7 +49,7 @@ typedef struct UvNearestHit { #define UV_NEAREST_HIT_INIT_MAX(v2d) \ { \ - .dist_sq = FLT_MAX, \ + .dist = FLT_MAX, \ .scale = { \ UI_view2d_scale_get_x(v2d), \ UI_view2d_scale_get_y(v2d), \ @@ -80,34 +80,11 @@ bool uv_find_nearest_edge_multi(struct Scene *scene, float penalty, struct UvNearestHit *hit); -/** - * \param only_in_face: when true, only hit faces which `co` is inside. - * This gives users a result they might expect, especially when zoomed in. - * - * \note Concave faces can cause odd behavior, although in practice this isn't often an issue. - * The center can be outside the face, in this case the distance to the center - * could cause the face to be considered too far away. - * If this becomes an issue we could track the distance to the faces closest edge. - */ -bool uv_find_nearest_face_ex(struct Scene *scene, - struct Object *obedit, - const float co[2], - struct UvNearestHit *hit, - bool only_in_face); -bool uv_find_nearest_face(struct Scene *scene, - struct Object *obedit, - const float co[2], - struct UvNearestHit *hit); -bool uv_find_nearest_face_multi_ex(struct Scene *scene, - struct Object **objects, - uint objects_len, - const float co[2], - struct UvNearestHit *hit, - bool only_in_face); bool uv_find_nearest_face_multi(struct Scene *scene, struct Object **objects, uint objects_len, const float co[2], + float penalty, struct UvNearestHit *hit); BMLoop *uv_find_nearest_loop_from_vert(struct Scene *scene, diff --git a/source/blender/editors/uvedit/uvedit_path.c b/source/blender/editors/uvedit/uvedit_path.c index 274196f79a4d..d4e217fb54bd 100644 --- a/source/blender/editors/uvedit/uvedit_path.c +++ b/source/blender/editors/uvedit/uvedit_path.c @@ -577,7 +577,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(®ion->v2d); bool hit_found = false; if (uv_selectmode == UV_SELECT_FACE) { - if (uv_find_nearest_face_multi(scene, objects, objects_len, co, &hit)) { + if (uv_find_nearest_face_multi(scene, objects, objects_len, co, 0.0f, &hit)) { hit_found = true; } } @@ -787,6 +787,156 @@ void UV_OT_shortest_path_pick(wmOperatorType *ot) /** \name Select Path Between Existing Selection * \{ */ +/* -------------------------------------------------------------------- */ +/** \name Selected Elements as Arrays (Vertex, Edge & Faces) + * + * These functions return single elements per connected vertex/edge. + * So an edge that has two connected edge loops only assigns one loop in the array. + * \{ */ + +static BMFace **ED_uvedit_selected_faces(const Scene *scene, + BMesh *bm, + int len_max, + int *r_faces_len) +{ + const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); + + int faces_len = 0; + BMFace **faces = MEM_mallocN(sizeof(*faces) * len_max, __func__); + + BMIter iter; + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (uvedit_face_visible_test(scene, f) && uvedit_face_select_test(scene, f, offsets)) { + faces[faces_len++] = f; + if (faces_len == len_max) { + break; + } + } + } + + *r_faces_len = faces_len; + return faces; +} + +static BMLoop **ED_uvedit_selected_edges(const Scene *scene, + BMesh *bm, + int len_max, + int *r_edges_len) +{ + const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); + BLI_assert(offsets.uv >= 0); + + CLAMP_MAX(len_max, bm->totloop); + int edges_len = 0; + BMLoop **edges = MEM_mallocN(sizeof(*edges) * len_max, __func__); + + BMIter iter; + BMFace *f; + + /* Clear tag. */ + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMIter liter; + BMLoop *l_iter; + BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { + BM_elem_flag_disable(l_iter, BM_ELEM_TAG); + } + } + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (uvedit_face_visible_test(scene, f)) { + BMIter liter; + BMLoop *l_iter; + BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { + if (!BM_elem_flag_test(l_iter, BM_ELEM_TAG)) { + if (uvedit_edge_select_test(scene, l_iter, offsets)) { + BM_elem_flag_enable(l_iter, BM_ELEM_TAG); + + edges[edges_len++] = l_iter; + if (edges_len == len_max) { + goto finally; + } + + /* Tag other connected loops so we don't consider them separate edges. */ + if (l_iter != l_iter->radial_next) { + BMLoop *l_radial_iter = l_iter->radial_next; + do { + if (BM_loop_uv_share_edge_check(l_iter, l_radial_iter, offsets.uv)) { + BM_elem_flag_enable(l_radial_iter, BM_ELEM_TAG); + } + } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter); + } + } + } + } + } + } + +finally: + *r_edges_len = edges_len; + return edges; +} + +static BMLoop **ED_uvedit_selected_verts(const Scene *scene, + BMesh *bm, + int len_max, + int *r_verts_len) +{ + const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); + BLI_assert(offsets.select_vert >= 0); + BLI_assert(offsets.uv >= 0); + + CLAMP_MAX(len_max, bm->totloop); + int verts_len = 0; + BMLoop **verts = MEM_mallocN(sizeof(*verts) * len_max, __func__); + + BMIter iter; + BMFace *f; + + /* Clear tag. */ + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMIter liter; + BMLoop *l_iter; + BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { + BM_elem_flag_disable(l_iter, BM_ELEM_TAG); + } + } + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (uvedit_face_visible_test(scene, f)) { + BMIter liter; + BMLoop *l_iter; + BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { + if (!BM_elem_flag_test(l_iter, BM_ELEM_TAG)) { + if (BM_ELEM_CD_GET_BOOL(l_iter, offsets.select_vert)) { + BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG); + + verts[verts_len++] = l_iter; + if (verts_len == len_max) { + goto finally; + } + + /* Tag other connected loops so we don't consider them separate vertices. */ + BMIter liter_disk; + BMLoop *l_disk_iter; + BM_ITER_ELEM (l_disk_iter, &liter_disk, l_iter->v, BM_LOOPS_OF_VERT) { + if (BM_loop_uv_share_vert_check(l_iter, l_disk_iter, offsets.uv)) { + BM_elem_flag_enable(l_disk_iter, BM_ELEM_TAG); + } + } + } + } + } + } + } + +finally: + *r_verts_len = verts_len; + return verts; +} + +/** \} */ + static int uv_shortest_path_select_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); diff --git a/source/blender/editors/uvedit/uvedit_rip.c b/source/blender/editors/uvedit/uvedit_rip.c index 6cb6e67cced7..7517a5267220 100644 --- a/source/blender/editors/uvedit/uvedit_rip.c +++ b/source/blender/editors/uvedit/uvedit_rip.c @@ -804,7 +804,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const * to detach the selection. * * We could also extract an edge loop from the boundary - * however in practice it's not that useful, see T78751. */ + * however in practice it's not that useful, see #78751. */ if (is_select_all_any) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 1796f6d34b63..ede1c4e083da 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -5,43 +5,22 @@ * \ingroup eduv */ -#include -#include -#include +#include "BKE_context.h" +#include "BKE_editmesh.h" +#include "BKE_layer.h" +#include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" +#include "BKE_report.h" -#include "MEM_guardedalloc.h" - -#include "DNA_image_types.h" -#include "DNA_material_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_space_types.h" - -#include "BLI_alloca.h" -#include "BLI_blenlib.h" #include "BLI_hash.h" #include "BLI_heap.h" #include "BLI_kdopbvh.h" #include "BLI_kdtree.h" #include "BLI_lasso_2d.h" -#include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_polyfill_2d.h" #include "BLI_polyfill_2d_beautify.h" -#include "BLI_utildefines.h" -#include "BKE_context.h" -#include "BKE_customdata.h" -#include "BKE_editmesh.h" -#include "BKE_layer.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_mesh_mapping.h" -#include "BKE_report.h" - -#include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" #include "ED_image.h" @@ -50,28 +29,19 @@ #include "ED_select_utils.h" #include "ED_uvedit.h" +#include "MEM_guardedalloc.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" -#include "WM_api.h" -#include "WM_types.h" - #include "UI_view2d.h" #include "uvedit_intern.h" -static void uv_select_all_perform(const Scene *scene, Object *obedit, int action); +#include "WM_api.h" -static void uv_select_all_perform_multi_ex(const Scene *scene, - Object **objects, - const uint objects_len, - int action, - const Object *ob_exclude); -static void uv_select_all_perform_multi(const Scene *scene, - Object **objects, - const uint objects_len, - int action); +static void uv_select_all_perform(const Scene *scene, Object *obedit, int action); static void uv_select_flush_from_tag_face(const Scene *scene, Object *obedit, const bool select); static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, const bool select); @@ -81,6 +51,30 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph, const ToolSettings *ts, Object *obedit); +/* Low level functions for sticky element selection (sticky mode independent). Type of sticky + * selection is specified explicitly (using sticky_flag, except for face selection). */ + +static void uvedit_face_select_shared_vert(const struct Scene *scene, + struct BMEditMesh *em, + struct BMFace *efa, + const bool select, + const bool do_history, + BMUVOffsets offsets); +static void uvedit_edge_select_shared_vert(const struct Scene *scene, + struct BMEditMesh *em, + struct BMLoop *l, + const bool select, + const int sticky_flag, + const bool do_history, + BMUVOffsets offsets); +static void uvedit_uv_select_shared_vert(const struct Scene *scene, + struct BMEditMesh *em, + struct BMLoop *l, + const bool select, + const int sticky_flag, + const bool do_history, + BMUVOffsets offsets); + typedef enum { UV_SSIM_AREA_UV = 1000, UV_SSIM_AREA_3D, @@ -153,32 +147,47 @@ BMLoop *ED_uvedit_active_edge_loop_get(BMesh *bm) char ED_uvedit_select_mode_get(const Scene *scene) { + /* Returns a single element selection mode (Vertex, Edge or Face) based on + * Sync Selection, and potentially multiple selected modes in the UI. */ const ToolSettings *ts = scene->toolsettings; - char uv_selectmode = UV_SELECT_VERTEX; + char uv_select_mode = ts->uv_selectmode; /* i.e. Default from UV Editor. */ if (ts->uv_flag & UV_SYNC_SELECTION) { + /* We're in Sync-Selection mode. + * Convert the selection mode options from the 3D Viewport + * into their closest UV Editor equivalents. */ + + uv_select_mode = 0; if (ts->selectmode & SCE_SELECT_VERTEX) { - uv_selectmode = UV_SELECT_VERTEX; + uv_select_mode |= UV_SELECT_VERTEX; } - else if (ts->selectmode & SCE_SELECT_EDGE) { - uv_selectmode = UV_SELECT_EDGE; + if (ts->selectmode & SCE_SELECT_EDGE) { + uv_select_mode |= UV_SELECT_EDGE; } - else if (ts->selectmode & SCE_SELECT_FACE) { - uv_selectmode = UV_SELECT_FACE; + if (ts->selectmode & SCE_SELECT_FACE) { + uv_select_mode |= UV_SELECT_FACE; } } - else { - if (ts->uv_selectmode & UV_SELECT_VERTEX) { - uv_selectmode = UV_SELECT_VERTEX; - } - else if (ts->uv_selectmode & UV_SELECT_EDGE) { - uv_selectmode = UV_SELECT_EDGE; - } - else if (ts->uv_selectmode & UV_SELECT_FACE) { - uv_selectmode = UV_SELECT_FACE; - } + + /* Order is important here, as more than one type of selection element could be enabled. */ + if (uv_select_mode & UV_SELECT_VERTEX) { + return UV_SELECT_VERTEX; /* Vertex selection is enabled, use Vertex mode. */ } - return uv_selectmode; + if (uv_select_mode & UV_SELECT_EDGE) { + return UV_SELECT_EDGE; /* Edge selection is enabled, use Edge mode. */ + } + if (uv_select_mode & UV_SELECT_FACE) { + return UV_SELECT_FACE; /* Face selection is enabled, use Face mode. */ + } + + if (uv_select_mode & UV_SELECT_ISLAND) { + /* Island selection is stored as Vertex selection internally. */ + return UV_SELECT_VERTEX; /* Not UV_SELECT_ISLAND ! */ + } + + BLI_assert_unreachable(); + + return UV_SELECT_VERTEX; /* Should never happen. */ } void ED_uvedit_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const bool select) @@ -202,7 +211,7 @@ void ED_uvedit_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const b static void uvedit_vertex_select_tagged(BMEditMesh *em, Scene *scene, - bool select, + const bool select, const BMUVOffsets offsets) { BMFace *efa; @@ -218,16 +227,18 @@ static void uvedit_vertex_select_tagged(BMEditMesh *em, } } -bool uvedit_face_visible_test_ex(const ToolSettings *ts, BMFace *efa) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0); - } - return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT)); -} bool uvedit_face_visible_test(const Scene *scene, BMFace *efa) { - return uvedit_face_visible_test_ex(scene->toolsettings, efa); + if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + /* Face Hidden flag always applies to both 3D viewport *and* UV Editor. */ + return false; + } + if (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) { + /* UV Sync Selection mode, ignore 3D Viewport selection for visibility in UV Editor. */ + return true; + } + /* No sync-selection, only *selected* faces in 3D Viewport are visible in UV Editor. */ + return BM_elem_flag_test(efa, BM_ELEM_SELECT); } bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const BMUVOffsets offsets) @@ -807,6 +818,33 @@ static BMLoop *uvedit_loop_find_other_boundary_loop_with_visible_face(const Scen /** \name Find Nearest Elements * \{ */ +static bool uv_nearest_was_updated(const UvNearestHit *hit) +{ + return hit->efa; +} + +static void uv_nearest_hit_update( + UvNearestHit *hit, Object *ob, BMFace *efa, BMLoop *l, const float dist) +{ + BLI_assert(ob != NULL); + BLI_assert(efa != NULL); + BLI_assert(dist >= 0.0f); + if (dist < hit->dist) { + hit->ob = ob; + hit->efa = efa; + hit->l = l; /* Can be NULL. */ + hit->dist = dist; + } +} + +static float uv_nearest_calc_dist(const UvNearestHit *hit, const float co[2], const float uv[2]) +{ + float delta[2]; + sub_v2_v2v2(delta, co, uv); + mul_v2_v2(delta, hit->scale); + return len_v2(delta); +} + bool uv_find_nearest_edge( Scene *scene, Object *obedit, const float co[2], const float penalty, UvNearestHit *hit) { @@ -817,7 +855,6 @@ bool uv_find_nearest_edge( BMIter iter, liter; float *luv, *luv_next; int i; - bool found = false; const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); BLI_assert(offsets.uv >= 0); @@ -834,29 +871,17 @@ bool uv_find_nearest_edge( float delta[2]; closest_to_line_segment_v2(delta, co, luv, luv_next); - - sub_v2_v2(delta, co); - mul_v2_v2(delta, hit->scale); - - float dist_test_sq = len_squared_v2(delta); + float dist_test = uv_nearest_calc_dist(hit, co, delta); /* Ensures that successive selection attempts will select other edges sharing the same * UV coordinates as the previous selection. */ if ((penalty != 0.0f) && uvedit_edge_select_test(scene, l, offsets)) { - dist_test_sq = square_f(sqrtf(dist_test_sq) + penalty); - } - if (dist_test_sq < hit->dist_sq) { - hit->ob = obedit; - hit->efa = efa; - - hit->l = l; - - hit->dist_sq = dist_test_sq; - found = true; + dist_test += penalty; } + uv_nearest_hit_update(hit, obedit, efa, l, dist_test); } } - return found; + return uv_nearest_was_updated(hit); } bool uv_find_nearest_edge_multi(Scene *scene, @@ -866,85 +891,64 @@ bool uv_find_nearest_edge_multi(Scene *scene, const float penalty, UvNearestHit *hit) { - bool found = false; for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_find_nearest_edge(scene, obedit, co, penalty, hit)) { - found = true; - } + uv_find_nearest_edge(scene, objects[ob_index], co, penalty, hit); } - return found; + return uv_nearest_was_updated(hit); } -bool uv_find_nearest_face_ex( - Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit, const bool only_in_face) +static bool uv_find_nearest_face( + Scene *scene, Object *obedit, const float co[2], const float penalty_dist, UvNearestHit *hit) { BLI_assert((hit->scale[0] > 0.0f) && (hit->scale[1] > 0.0f)); BMEditMesh *em = BKE_editmesh_from_object(obedit); - bool found = false; - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_PROP_FLOAT2); + const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); BMIter iter; BMFace *efa; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!uvedit_face_visible_test(scene, efa)) { continue; } - float cent[2]; - BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent); + /* Ensures that successive selection attempts will select other edges sharing the same + * UV coordinates as the previous selection. */ + const float face_penalty_dist = uvedit_face_select_test(scene, efa, offsets) ? penalty_dist : + 0.0f; - float delta[2]; - sub_v2_v2v2(delta, co, cent); - mul_v2_v2(delta, hit->scale); + if (BM_face_uv_point_inside_test(efa, co, offsets.uv)) { + uv_nearest_hit_update(hit, obedit, efa, NULL, face_penalty_dist); + continue; + } - const float dist_test_sq = len_squared_v2(delta); + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + float *luv = BM_ELEM_CD_GET_VOID_P(l, offsets.uv); + float *luv_next = BM_ELEM_CD_GET_VOID_P(l->next, offsets.uv); - if (dist_test_sq < hit->dist_sq) { - - if (only_in_face) { - if (!BM_face_uv_point_inside_test(efa, co, cd_loop_uv_offset)) { - continue; - } - } - - hit->ob = obedit; - hit->efa = efa; - hit->dist_sq = dist_test_sq; - found = true; + float delta[2]; + closest_to_line_segment_v2(delta, co, luv, luv_next); + sub_v2_v2(delta, co); + mul_v2_v2(delta, hit->scale); + uv_nearest_hit_update(hit, obedit, efa, NULL, len_v2(delta) + face_penalty_dist); } } - return found; + return uv_nearest_was_updated(hit); } -bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit) +bool uv_find_nearest_face_multi(Scene *scene, + Object **objects, + uint objects_len, + const float co[2], + const float penalty_dist, + UvNearestHit *hit) { - return uv_find_nearest_face_ex(scene, obedit, co, hit, false); -} - -bool uv_find_nearest_face_multi_ex(Scene *scene, - Object **objects, - const uint objects_len, - const float co[2], - UvNearestHit *hit, - const bool only_in_face) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_find_nearest_face_ex(scene, obedit, co, hit, only_in_face)) { - found = true; - } + for (int ob_index = 0; ob_index < objects_len; ob_index++) { + uv_find_nearest_face(scene, objects[ob_index], co, penalty_dist, hit); } - return found; -} - -bool uv_find_nearest_face_multi( - Scene *scene, Object **objects, const uint objects_len, const float co[2], UvNearestHit *hit) -{ - return uv_find_nearest_face_multi_ex(scene, objects, objects_len, co, hit, false); + return uv_nearest_was_updated(hit); } static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_loop_uv_offset) @@ -961,7 +965,6 @@ bool uv_find_nearest_vert( Scene *scene, Object *obedit, float const co[2], const float penalty_dist, UvNearestHit *hit) { BLI_assert((hit->scale[0] > 0.0f) && (hit->scale[1] > 0.0f)); - bool found = false; BMEditMesh *em = BKE_editmesh_from_object(obedit); BMFace *efa; @@ -981,39 +984,30 @@ bool uv_find_nearest_vert( BMLoop *l; int i; BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - - float delta[2]; - - sub_v2_v2v2(delta, co, luv); - mul_v2_v2(delta, hit->scale); - - float dist_test_sq = len_squared_v2(delta); + const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); + float dist_test = uv_nearest_calc_dist(hit, co, luv); /* Ensures that successive selection attempts will select other vertices sharing the same * UV coordinates */ if ((penalty_dist != 0.0f) && uvedit_uv_select_test(scene, l, offsets)) { - dist_test_sq = square_f(sqrtf(dist_test_sq) + penalty_dist); + dist_test += penalty_dist; } - if (dist_test_sq <= hit->dist_sq) { - if (dist_test_sq == hit->dist_sq) { - if (!uv_nearest_between(l, co, offsets.uv)) { - continue; - } + if (dist_test == hit->dist) { + /* Special case to break ties. */ + if (uv_nearest_between(l, co, offsets.uv)) { + hit->ob = obedit; + hit->efa = efa; + hit->l = l; } - - hit->dist_sq = dist_test_sq; - - hit->ob = obedit; - hit->efa = efa; - hit->l = l; - found = true; + continue; } + + uv_nearest_hit_update(hit, obedit, efa, l, dist_test); } } - return found; + return uv_nearest_was_updated(hit); } bool uv_find_nearest_vert_multi(Scene *scene, @@ -1800,9 +1794,9 @@ static void uv_select_linked_multi(Scene *scene, BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ - /* NOTE: we had 'use winding' so we don't consider overlapping islands as connected, see T44320 + /* NOTE: we had 'use winding' so we don't consider overlapping islands as connected, see #44320 * this made *every* projection split the island into front/back islands. - * Keep 'use_winding' to false, see: T50970. + * Keep 'use_winding' to false, see: #50970. * * Better solve this by having a delimit option for select-linked operator, * keeping island-select working as is. */ @@ -2433,8 +2427,8 @@ static bool uv_mouse_select_multi(bContext *C, Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; UvNearestHit hit = UV_NEAREST_HIT_INIT_DIST_PX(®ion->v2d, 75.0f); - int selectmode, sticky; - bool found_item = false; + int selectmode = ts->uv_selectmode; + int sticky = ts->uv_sticky; /* 0 == don't flush, 1 == sel, -1 == deselect; only use when selection sync is enabled. */ int flush = 0; @@ -2456,16 +2450,11 @@ static bool uv_mouse_select_multi(bContext *C, sticky = SI_STICKY_DISABLE; } - else { - selectmode = ts->uv_selectmode; - sticky = ts->uv_sticky; - } /* find nearest element */ if (selectmode == UV_SELECT_VERTEX) { /* find vertex */ - found_item = uv_find_nearest_vert_multi(scene, objects, objects_len, co, penalty_dist, &hit); - if (found_item) { + if (uv_find_nearest_vert_multi(scene, objects, objects_len, co, penalty_dist, &hit)) { if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) { BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm; ED_uvedit_active_vert_loop_set(bm, hit.l); @@ -2474,8 +2463,7 @@ static bool uv_mouse_select_multi(bContext *C, } else if (selectmode == UV_SELECT_EDGE) { /* find edge */ - found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, penalty_dist, &hit); - if (found_item) { + if (uv_find_nearest_edge_multi(scene, objects, objects_len, co, penalty_dist, &hit)) { if ((ts->uv_flag & UV_SYNC_SELECTION) == 0) { BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm; ED_uvedit_active_edge_loop_set(bm, hit.l); @@ -2484,33 +2472,18 @@ static bool uv_mouse_select_multi(bContext *C, } else if (selectmode == UV_SELECT_FACE) { /* find face */ - found_item = uv_find_nearest_face_multi(scene, objects, objects_len, co, &hit); - - if (!found_item) { - /* Fallback, perform a second pass without a limited threshold, - * which succeeds as long as the cursor is inside the UV face. - * Useful when zoomed in, to select faces with distant screen-space face centers. */ - hit.dist_sq = FLT_MAX; - found_item = uv_find_nearest_face_multi_ex(scene, objects, objects_len, co, &hit, true); - } - + const bool found_item = uv_find_nearest_face_multi( + scene, objects, objects_len, co, penalty_dist, &hit); if (found_item) { BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm; BM_mesh_active_face_set(bm, hit.efa); } } else if (selectmode == UV_SELECT_ISLAND) { - found_item = uv_find_nearest_edge_multi(scene, objects, objects_len, co, 0.0f, &hit); - - if (!found_item) { - /* Without this, we can be within the face of an island but too far from an edge, - * see face selection comment for details. */ - hit.dist_sq = FLT_MAX; - found_item = uv_find_nearest_face_multi_ex(scene, objects, objects_len, co, &hit, true); - } + uv_find_nearest_face_multi(scene, objects, objects_len, co, penalty_dist, &hit); } - bool found = found_item; + bool found = uv_nearest_was_updated(&hit); bool changed = false; bool is_selected = false; @@ -2528,9 +2501,8 @@ static bool uv_mouse_select_multi(bContext *C, is_selected = uvedit_edge_select_test(scene, hit.l, offsets); } else { - /* Vertex or island. For island (if we were using #uv_find_nearest_face_multi_ex, see above), - * `hit.l` is NULL, use `hit.efa` instead. */ - if (hit.l != NULL) { + /* Vertex or island. */ + if (hit.l) { is_selected = uvedit_uv_select_test(scene, hit.l, offsets); } else { @@ -3494,6 +3466,32 @@ static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMEditMesh * /** \name Box Select Operator * \{ */ +static bool uv_box_select_is_face_touching(Scene *scene, + BMFace *efa, + rctf rectf, + const int cd_loop_uv_offset) +{ + /* First, are we visible? */ + if (!uvedit_face_visible_test(scene, efa)) { + return false; + } + + /* Next, are any of the edges inside the rectangle? */ + BMLoop *l; + BMIter iter; + BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) { + float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); + float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset); + if (BLI_rctf_isect_segment(&rectf, luv_next, luv)) { + return true; + } + } + + /* Last, is an arbitrary point of the rectangle in the interior of the face? */ + float rectangle_corner[2] = {rectf.xmin, rectf.ymin}; + return BM_face_uv_point_inside_test(efa, rectangle_corner, cd_loop_uv_offset); +} + static int uv_box_select_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -3506,10 +3504,9 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) BMIter iter, liter; float *luv; rctf rectf; - bool pinned; - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_face_touch = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? (ts->selectmode == SCE_SELECT_EDGE) : (ts->uv_selectmode == UV_SELECT_EDGE)); @@ -3524,7 +3521,7 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) const bool select = (sel_op != SEL_OP_SUB); const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); - pinned = RNA_boolean_get(op->ptr, "pinned"); + const bool pinned = RNA_boolean_get(op->ptr, "pinned"); bool changed_multi = false; @@ -3536,7 +3533,6 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); } - /* don't indent to avoid diff noise! */ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); @@ -3549,22 +3545,13 @@ static int uv_box_select_exec(bContext *C, wmOperator *op) BM_uv_map_ensure_pin_attr(em->bm, active_uv_name); const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - /* do actual selection */ - if (use_face_center && !pinned) { - /* handle face selection mode */ - float cent[2]; - + /* Do actual selection. */ + if (use_face_touch && !pinned) { + /* Handle face selection mode. */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* assume not touched */ - BM_elem_flag_disable(efa, BM_ELEM_TAG); - - if (uvedit_face_visible_test(scene, efa)) { - BM_face_uv_calc_center_median(efa, offsets.uv, cent); - if (BLI_rctf_isect_pt_v(&rectf, cent)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } + const bool touched = uv_box_select_is_face_touching(scene, efa, rectf, offsets.uv); + BM_elem_flag_set(efa, BM_ELEM_TAG, touched); + changed |= touched; } /* (de)selects all tagged faces and deals with sticky modes */ @@ -3735,6 +3722,26 @@ static bool uv_circle_select_is_edge_inside(const float uv_a[2], return dist_squared_to_line_segment_v2((const float[2]){0.0f, 0.0f}, co_a, co_b) < 1.0f; } +static bool uv_circle_select_is_face_touching(BMFace *efa, + const float offset[2], + const float ellipse[2], + const int cd_loop_uv_offset) +{ + /* First, are any of the edges inside the solid ellipse? */ + BMLoop *l; + BMIter iter; + BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) { + float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); + float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset); + if (uv_circle_select_is_edge_inside(luv, luv_next, offset, ellipse)) { + return true; + } + } + + /* Also, is the center of the ellipse in the interior of the face? */ + return BM_face_uv_point_inside_test(efa, offset, cd_loop_uv_offset); +} + static int uv_circle_select_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -3751,9 +3758,6 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) float zoomx, zoomy; float offset[2], ellipse[2]; - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? (ts->selectmode == SCE_SELECT_EDGE) : (ts->uv_selectmode == UV_SELECT_EDGE)); @@ -3801,19 +3805,13 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) BM_uv_map_ensure_edge_select_attr(em->bm, active_uv_name); const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - /* do selection */ - if (use_face_center) { + /* Do selection. */ + if (ED_uvedit_select_mode_get(scene) == UV_SELECT_FACE) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_disable(efa, BM_ELEM_TAG); - /* assume not touched */ - if (select != uvedit_face_select_test(scene, efa, offsets)) { - float cent[2]; - BM_face_uv_calc_center_median(efa, offsets.uv, cent); - if (uv_circle_select_is_point_inside(cent, offset, ellipse)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } + const bool touched = select != uvedit_face_select_test(scene, efa, offsets) && + uv_circle_select_is_face_touching(efa, offset, ellipse, offsets.uv); + BM_elem_flag_set(efa, BM_ELEM_TAG, touched); + changed |= touched; } /* (de)selects all tagged faces and deals with sticky modes */ @@ -3944,14 +3942,35 @@ static bool do_lasso_select_mesh_uv_is_edge_inside(const ARegion *region, const float co_test_b[2]) { int co_screen_a[2], co_screen_b[2]; - if (UI_view2d_view_to_region_segment_clip( - ®ion->v2d, co_test_a, co_test_b, co_screen_a, co_screen_b) && - BLI_rcti_isect_segment(clip_rect, co_screen_a, co_screen_b) && - BLI_lasso_is_edge_inside( - mcoords, mcoords_len, UNPACK2(co_screen_a), UNPACK2(co_screen_b), V2D_IS_CLIPPED)) { - return true; + return UI_view2d_view_to_region_segment_clip( + ®ion->v2d, co_test_a, co_test_b, co_screen_a, co_screen_b) && + BLI_rcti_isect_segment(clip_rect, co_screen_a, co_screen_b) && + BLI_lasso_is_edge_inside( + mcoords, mcoords_len, UNPACK2(co_screen_a), UNPACK2(co_screen_b), V2D_IS_CLIPPED); +} + +static bool uv_lasso_select_is_face_touching(BMFace *efa, + const ARegion *region, + const rcti *clip_rect, + const int mcoords[][2], + const int mcoords_len, + const int cd_loop_uv_offset) +{ + /* First, are any of the face edges inside the lasso? */ + BMLoop *l; + BMIter iter; + BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) { + float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset); + float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset); + if (do_lasso_select_mesh_uv_is_edge_inside( + region, clip_rect, mcoords, mcoords_len, luv, luv_next)) { + return true; + } } - return false; + + /* Also, is an arbitrary point of the lasso in the interior of the face? */ + float lasso_corner[2] = {mcoords[0][0], mcoords[0][1]}; + return BM_face_uv_point_inside_test(efa, lasso_corner, cd_loop_uv_offset); } static bool do_lasso_select_mesh_uv(bContext *C, @@ -3964,9 +3983,6 @@ static bool do_lasso_select_mesh_uv(bContext *C, Scene *scene = CTX_data_scene(C); const ToolSettings *ts = scene->toolsettings; ViewLayer *view_layer = CTX_data_view_layer(C); - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? (ts->selectmode == SCE_SELECT_EDGE) : (ts->uv_selectmode == UV_SELECT_EDGE)); @@ -4005,18 +4021,13 @@ static bool do_lasso_select_mesh_uv(bContext *C, BM_uv_map_ensure_edge_select_attr(em->bm, active_uv_name); const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - if (use_face_center) { /* Face Center Select. */ + if (ED_uvedit_select_mode_get(scene) == UV_SELECT_FACE) { /* Face Touch Select. */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_disable(efa, BM_ELEM_TAG); - /* assume not touched */ - if (select != uvedit_face_select_test(scene, efa, offsets)) { - float cent[2]; - BM_face_uv_calc_center_median(efa, offsets.uv, cent); - if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcoords, mcoords_len, cent)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } + const bool touched = select != uvedit_face_select_test(scene, efa, offsets) && + uv_lasso_select_is_face_touching( + efa, region, &rect, mcoords, mcoords_len, offsets.uv); + BM_elem_flag_set(efa, BM_ELEM_TAG, touched); + changed |= touched; } /* (de)selects all tagged faces and deals with sticky modes */ @@ -4302,7 +4313,7 @@ static bool overlap_tri_tri_uv_test(const float t1[3][2], * However, the `endpoint_bias` on segment intersections causes _exact_ overlapping * triangles not to be detected. * - * Resolve this problem at the small cost of calculating the triangle center, see T85508. */ + * Resolve this problem at the small cost of calculating the triangle center, see #85508. */ mid_v2_v2v2v2(vi, UNPACK3(t1)); if (isect_point_tri_v2(vi, UNPACK3(t2)) != 0) { return true; @@ -4341,7 +4352,7 @@ static int uv_select_overlap(bContext *C, const bool extend) BMIter iter; BMFace *efa; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test_ex(scene->toolsettings, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } uv_tri_len += efa->len - 2; @@ -4375,7 +4386,7 @@ static int uv_select_overlap(bContext *C, const bool extend) int face_index; BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) { - if (!uvedit_face_visible_test_ex(scene->toolsettings, efa)) { + if (!uvedit_face_visible_test(scene, efa)) { continue; } @@ -4402,7 +4413,7 @@ static int uv_select_overlap(bContext *C, const bool extend) BLI_polyfill_calc_arena(uv_verts, face_len, coords_sign, indices, arena); /* A beauty fill is necessary to remove degenerate triangles that may be produced from the - * above poly-fill (see T103913), otherwise the overlap tests can fail. */ + * above poly-fill (see #103913), otherwise the overlap tests can fail. */ BLI_polyfill_beautify(uv_verts, face_len, indices, arena, heap); for (int t = 0; t < tri_len; t++) { @@ -5245,160 +5256,6 @@ void UV_OT_select_similar(wmOperatorType *ot) /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Selected Elements as Arrays (Vertex, Edge & Faces) - * - * These functions return single elements per connected vertex/edge. - * So an edge that has two connected edge loops only assigns one loop in the array. - * \{ */ - -BMFace **ED_uvedit_selected_faces(const Scene *scene, BMesh *bm, int len_max, int *r_faces_len) -{ - const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); - - CLAMP_MAX(len_max, bm->totface); - int faces_len = 0; - BMFace **faces = MEM_mallocN(sizeof(*faces) * len_max, __func__); - - BMIter iter; - BMFace *f; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, f)) { - if (uvedit_face_select_test(scene, f, offsets)) { - faces[faces_len++] = f; - if (faces_len == len_max) { - goto finally; - } - } - } - } - -finally: - *r_faces_len = faces_len; - if (faces_len != len_max) { - faces = MEM_reallocN(faces, sizeof(*faces) * faces_len); - } - return faces; -} - -BMLoop **ED_uvedit_selected_edges(const Scene *scene, BMesh *bm, int len_max, int *r_edges_len) -{ - const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); - BLI_assert(offsets.uv >= 0); - - CLAMP_MAX(len_max, bm->totloop); - int edges_len = 0; - BMLoop **edges = MEM_mallocN(sizeof(*edges) * len_max, __func__); - - BMIter iter; - BMFace *f; - - /* Clear tag. */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMIter liter; - BMLoop *l_iter; - BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { - BM_elem_flag_disable(l_iter, BM_ELEM_TAG); - } - } - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, f)) { - BMIter liter; - BMLoop *l_iter; - BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { - if (!BM_elem_flag_test(l_iter, BM_ELEM_TAG)) { - if (uvedit_edge_select_test(scene, l_iter, offsets)) { - BM_elem_flag_enable(l_iter, BM_ELEM_TAG); - - edges[edges_len++] = l_iter; - if (edges_len == len_max) { - goto finally; - } - - /* Tag other connected loops so we don't consider them separate edges. */ - if (l_iter != l_iter->radial_next) { - BMLoop *l_radial_iter = l_iter->radial_next; - do { - if (BM_loop_uv_share_edge_check(l_iter, l_radial_iter, offsets.uv)) { - BM_elem_flag_enable(l_radial_iter, BM_ELEM_TAG); - } - } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter); - } - } - } - } - } - } - -finally: - *r_edges_len = edges_len; - if (edges_len != len_max) { - edges = MEM_reallocN(edges, sizeof(*edges) * edges_len); - } - return edges; -} - -BMLoop **ED_uvedit_selected_verts(const Scene *scene, BMesh *bm, int len_max, int *r_verts_len) -{ - const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); - BLI_assert(offsets.select_vert >= 0); - BLI_assert(offsets.uv >= 0); - - CLAMP_MAX(len_max, bm->totloop); - int verts_len = 0; - BMLoop **verts = MEM_mallocN(sizeof(*verts) * len_max, __func__); - - BMIter iter; - BMFace *f; - - /* Clear tag. */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMIter liter; - BMLoop *l_iter; - BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { - BM_elem_flag_disable(l_iter, BM_ELEM_TAG); - } - } - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, f)) { - BMIter liter; - BMLoop *l_iter; - BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { - if (!BM_elem_flag_test(l_iter, BM_ELEM_TAG)) { - if (BM_ELEM_CD_GET_BOOL(l_iter, offsets.select_vert)) { - BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG); - - verts[verts_len++] = l_iter; - if (verts_len == len_max) { - goto finally; - } - - /* Tag other connected loops so we don't consider them separate vertices. */ - BMIter liter_disk; - BMLoop *l_disk_iter; - BM_ITER_ELEM (l_disk_iter, &liter_disk, l_iter->v, BM_LOOPS_OF_VERT) { - if (BM_loop_uv_share_vert_check(l_iter, l_disk_iter, offsets.uv)) { - BM_elem_flag_enable(l_disk_iter, BM_ELEM_TAG); - } - } - } - } - } - } - } - -finally: - *r_verts_len = verts_len; - if (verts_len != len_max) { - verts = MEM_reallocN(verts, sizeof(*verts) * verts_len); - } - return verts; -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Select Mode UV Vert/Edge/Face/Island Operator * \{ */ diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 356fbde0b72a..4c5da3a0d57b 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1839,7 +1839,7 @@ static StitchState *stitch_init(bContext *C, state->em = em; /* Workaround for sync-select & face-select mode which implies all selected faces are detached, - * for stitch this isn't useful behavior, see T86924. */ + * for stitch this isn't useful behavior, see #86924. */ const int selectmode_orig = scene->toolsettings->selectmode; scene->toolsettings->selectmode = SCE_SELECT_VERTEX; state->element_map = BM_uv_element_map_create(state->em->bm, scene, false, true, true, true); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 53e25fb4a622..dc6e13b3d3a1 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -50,7 +50,7 @@ NodeGroup *BlenderFileLoader::Load() // Adjust clipping start/end and set up a Z offset when the viewport preview // is used with the orthographic view. In this case, _re->clip_start is negative, // while Freestyle assumes that imported mesh data are in the camera coordinate - // system with the view point located at origin [bug T36009]. + // system with the view point located at origin [bug #36009]. _z_near = -0.001f; _z_offset = _re->clip_start + _z_near; _z_far = -_re->clip_end + _z_offset; diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp index 0701b1c4ef36..668f654159bb 100644 --- a/source/blender/freestyle/intern/python/BPy_Convert.cpp +++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp @@ -376,7 +376,7 @@ PyObject *BPy_CurvePoint_from_CurvePoint(CurvePoint &cp) // member whose value is mutable upon iteration over different CurvePoints. // It is likely that such a mutable reference is passed to this function, // so that a new allocated CurvePoint instance is created here to avoid - // nasty bugs (cf. T41464). + // nasty bugs (cf. #41464). ((BPy_CurvePoint *)py_cp)->cp = new CurvePoint(cp); ((BPy_CurvePoint *)py_cp)->py_if0D.if0D = ((BPy_CurvePoint *)py_cp)->cp; ((BPy_CurvePoint *)py_cp)->py_if0D.borrowed = false; diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp index 3082988bd362..677029feb4cc 100644 --- a/source/blender/freestyle/intern/winged_edge/WEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp @@ -644,7 +644,7 @@ WFace *WShape::MakeFace(vector &iVertexList, vector::iterator it; // compute the face normal (v1v2 ^ v1v3) - // Double precision numbers are used here to avoid truncation errors [T47705] + // Double precision numbers are used here to avoid truncation errors [#47705] Vec3r v1, v2, v3; it = iVertexList.begin(); v1 = (*it)->GetVertex(); diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index e3c0c0c898de..6e0dec8f4f6b 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -16,6 +16,7 @@ set(INC set(SRC intern/add_curves_on_mesh.cc + intern/curve_constraints.cc intern/fillet_curves.cc intern/mesh_merge_by_distance.cc intern/mesh_primitive_cuboid.cc @@ -32,6 +33,7 @@ set(SRC intern/uv_parametrizer.cc GEO_add_curves_on_mesh.hh + GEO_curve_constraints.hh GEO_fillet_curves.hh GEO_mesh_merge_by_distance.hh GEO_mesh_primitive_cuboid.hh diff --git a/source/blender/geometry/GEO_curve_constraints.hh b/source/blender/geometry/GEO_curve_constraints.hh new file mode 100644 index 000000000000..0cec5d3ebf2a --- /dev/null +++ b/source/blender/geometry/GEO_curve_constraints.hh @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "BKE_curves.hh" + +namespace blender::geometry::curve_constraints { + +void compute_segment_lengths(OffsetIndices points_by_curve, + Span positions, + IndexMask curve_selection, + MutableSpan r_segment_lengths); + +void solve_length_constraints(OffsetIndices points_by_curve, + IndexMask curve_selection, + Span segment_lenghts, + MutableSpan positions); + +void solve_length_and_collision_constraints(OffsetIndices points_by_curve, + IndexMask curve_selection, + Span segment_lengths, + Span start_positions, + const Mesh &surface, + const bke::CurvesSurfaceTransforms &transforms, + MutableSpan positions); + +} // namespace blender::geometry::curve_constraints diff --git a/source/blender/geometry/intern/curve_constraints.cc b/source/blender/geometry/intern/curve_constraints.cc new file mode 100644 index 000000000000..9775fd1443ed --- /dev/null +++ b/source/blender/geometry/intern/curve_constraints.cc @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_math_matrix.hh" +#include "BLI_task.hh" + +#include "GEO_curve_constraints.hh" + +#include "BKE_bvhutils.h" + +/** + * The code below uses a prefix naming convention to indicate the coordinate space: + * `cu`: Local space of the curves object that is being edited. + * `su`: Local space of the surface object. + * `wo`: World space. + */ + +namespace blender::geometry::curve_constraints { + +void compute_segment_lengths(const OffsetIndices points_by_curve, + const Span positions, + const IndexMask curve_selection, + MutableSpan r_segment_lengths) +{ + BLI_assert(r_segment_lengths.size() == points_by_curve.total_size()); + + threading::parallel_for(curve_selection.index_range(), 256, [&](const IndexRange range) { + for (const int curve_i : curve_selection.slice(range)) { + const IndexRange points = points_by_curve[curve_i].drop_back(1); + for (const int point_i : points) { + const float3 &p1 = positions[point_i]; + const float3 &p2 = positions[point_i + 1]; + const float length = math::distance(p1, p2); + r_segment_lengths[point_i] = length; + } + } + }); +} + +void solve_length_constraints(const OffsetIndices points_by_curve, + const IndexMask curve_selection, + const Span segment_lenghts, + MutableSpan positions) +{ + BLI_assert(segment_lenghts.size() == points_by_curve.total_size()); + + threading::parallel_for(curve_selection.index_range(), 256, [&](const IndexRange range) { + for (const int curve_i : curve_selection.slice(range)) { + const IndexRange points = points_by_curve[curve_i].drop_back(1); + for (const int point_i : points) { + const float3 &p1 = positions[point_i]; + float3 &p2 = positions[point_i + 1]; + const float3 direction = math::normalize(p2 - p1); + const float goal_length = segment_lenghts[point_i]; + p2 = p1 + direction * goal_length; + } + } + }); +} + +void solve_length_and_collision_constraints(const OffsetIndices points_by_curve, + const IndexMask curve_selection, + const Span segment_lengths_cu, + const Span start_positions_cu, + const Mesh &surface, + const bke::CurvesSurfaceTransforms &transforms, + MutableSpan positions_cu) +{ + solve_length_constraints(points_by_curve, curve_selection, segment_lengths_cu, positions_cu); + + BVHTreeFromMesh surface_bvh; + BKE_bvhtree_from_mesh_get(&surface_bvh, &surface, BVHTREE_FROM_LOOPTRI, 2); + BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); }); + + const float radius = 0.005f; + const int max_collisions = 5; + + threading::parallel_for(curve_selection.index_range(), 64, [&](const IndexRange range) { + for (const int curve_i : curve_selection.slice(range)) { + const IndexRange points = points_by_curve[curve_i]; + + /* Sometimes not all collisions can be handled. This happens relatively rarely, but if it + * happens it's better to just not to move the curve instead of going into the surface. */ + bool revert_curve = false; + for (const int point_i : points.drop_front(1)) { + const float goal_segment_length_cu = segment_lengths_cu[point_i - 1]; + const float3 &prev_pos_cu = positions_cu[point_i - 1]; + const float3 &start_pos_cu = start_positions_cu[point_i]; + + int used_iterations = 0; + for ([[maybe_unused]] const int iteration : IndexRange(max_collisions)) { + used_iterations++; + const float3 &old_pos_cu = positions_cu[point_i]; + if (start_pos_cu == old_pos_cu) { + /* The point did not move, done. */ + break; + } + + /* Check if the point moved through a surface. */ + const float3 start_pos_su = math::transform_point(transforms.curves_to_surface, + start_pos_cu); + const float3 old_pos_su = math::transform_point(transforms.curves_to_surface, + old_pos_cu); + const float3 pos_diff_su = old_pos_su - start_pos_su; + float max_ray_length_su; + const float3 ray_direction_su = math::normalize_and_get_length(pos_diff_su, + max_ray_length_su); + BVHTreeRayHit hit; + hit.index = -1; + hit.dist = max_ray_length_su + radius; + BLI_bvhtree_ray_cast(surface_bvh.tree, + start_pos_su, + ray_direction_su, + radius, + &hit, + surface_bvh.raycast_callback, + &surface_bvh); + if (hit.index == -1) { + break; + } + const float3 hit_pos_su = hit.co; + const float3 hit_normal_su = hit.no; + if (math::dot(hit_normal_su, ray_direction_su) > 0.0f) { + /* Moving from the inside to the outside is ok. */ + break; + } + + /* The point was moved through a surface. Now put it back on the correct side of the + * surface and slide it on the surface to keep the length the same. */ + + const float3 hit_pos_cu = math::transform_point(transforms.surface_to_curves, + hit_pos_su); + const float3 hit_normal_cu = math::normalize( + math::transform_direction(transforms.surface_to_curves_normal, hit_normal_su)); + + /* Slide on a plane that is slightly above the surface. */ + const float3 plane_pos_cu = hit_pos_cu + hit_normal_cu * radius; + const float3 plane_normal_cu = hit_normal_cu; + + /* Decompose the current segment into the part normal and tangent to the collision + * surface. */ + const float3 collided_segment_cu = plane_pos_cu - prev_pos_cu; + const float3 slide_normal_cu = plane_normal_cu * + math::dot(collided_segment_cu, plane_normal_cu); + const float3 slide_direction_cu = collided_segment_cu - slide_normal_cu; + + float slide_direction_length_cu; + const float3 normalized_slide_direction_cu = math::normalize_and_get_length( + slide_direction_cu, slide_direction_length_cu); + + /* Use pythagorian theorem to determine how far to slide. */ + const float slide_distance_cu = std::sqrt(pow2f(goal_segment_length_cu) - + math::length_squared(slide_normal_cu)) - + slide_direction_length_cu; + positions_cu[point_i] = plane_pos_cu + normalized_slide_direction_cu * slide_distance_cu; + } + if (used_iterations == max_collisions) { + revert_curve = true; + break; + } + } + if (revert_curve) { + positions_cu.slice(points).copy_from(start_positions_cu.slice(points)); + } + } + }); +} + +} // namespace blender::geometry::curve_constraints diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 6b12512aea07..609d6e52a3c2 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -839,7 +839,6 @@ static OrderedAttributes gather_generic_mesh_attributes_to_propagate( options.propagation_info, attributes_to_propagate); attributes_to_propagate.remove("position"); - attributes_to_propagate.remove("normal"); attributes_to_propagate.remove("shade_smooth"); r_create_id = attributes_to_propagate.pop_try("id").has_value(); r_create_material_index = attributes_to_propagate.pop_try("material_index").has_value(); diff --git a/source/blender/geometry/intern/uv_parametrizer.cc b/source/blender/geometry/intern/uv_parametrizer.cc index cd97001bab6f..61f37ca5fd78 100644 --- a/source/blender/geometry/intern/uv_parametrizer.cc +++ b/source/blender/geometry/intern/uv_parametrizer.cc @@ -353,7 +353,7 @@ static void p_triangle_angles( *r_a2 = angle_v3v3v3(v1, v2, v3); *r_a3 = angle_v3v3v3(v2, v3, v1); - /* Fix for degenerate geometry e.g. v1 = sum(v2 + v3). See T100874 */ + /* Fix for degenerate geometry e.g. v1 = sum(v2 + v3). See #100874 */ fix_large_angle(v1, v2, v3, r_a1, r_a2, r_a3); fix_large_angle(v2, v3, v1, r_a2, r_a3, r_a1); fix_large_angle(v3, v1, v2, r_a3, r_a1, r_a2); @@ -3259,7 +3259,7 @@ static float p_face_stretch(PFace *f) if (area <= 0.0f) { /* When a face is flipped, provide a large penalty. - * Add on a slight gradient to unflip the face, see also: T99781. */ + * Add on a slight gradient to unflip the face, see also: #99781. */ return 1e8f * (1.0f + p_edge_uv_length(e1) + p_edge_uv_length(e2) + p_edge_uv_length(e3)); } @@ -3871,7 +3871,7 @@ void GEO_uv_parametrizer_face_add(ParamHandle *phandle, if (nverts > 3) { /* Protect against (manifold) geometry which has a non-manifold triangulation. - * See T102543. */ + * See #102543. */ blender::Vector permute; permute.reserve(nverts); diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt index 8c85d9772636..cac836386ede 100644 --- a/source/blender/gpencil_modifiers/CMakeLists.txt +++ b/source/blender/gpencil_modifiers/CMakeLists.txt @@ -66,7 +66,6 @@ set(SRC # Lineart code intern/lineart/lineart_chain.c - intern/lineart/lineart_cpp_bridge.cc intern/lineart/lineart_cpu.cc intern/lineart/lineart_ops.c intern/lineart/lineart_shadow.c diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc deleted file mode 100644 index 85f158d42e63..000000000000 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cc +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup modifiers - */ - -#include "BLI_sort.hh" -#include "BLI_vector.hh" -#include "MOD_lineart.h" -#include "lineart_intern.h" - -void lineart_sort_adjacent_items(LineartAdjacentEdge *ai, int length) -{ - blender::parallel_sort( - ai, ai + length, [](const LineartAdjacentEdge &p1, const LineartAdjacentEdge &p2) { - int a = p1.v1 - p2.v1; - int b = p1.v2 - p2.v2; - /* parallel_sort() requires cmp() to return true when the first element needs to appear - * before the second element in the sorted array, false otherwise (strict weak ordering), - * see https://en.cppreference.com/w/cpp/named_req/Compare. */ - return a < 0 ? true : (a == 0 ? b < 0 : false); - }); -} diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc index fe8621bb9fe7..1624544a5ced 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.cc @@ -12,8 +12,10 @@ #include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_sort.hh" #include "BLI_task.h" #include "BLI_utildefines.h" +#include "BLI_vector.hh" #include "PIL_time.h" @@ -1887,6 +1889,25 @@ static void lineart_edge_neighbor_init_task(void *__restrict userdata, edge_nabr->flags = 0; } +static void lineart_sort_adjacent_items(LineartAdjacentEdge *ai, int length) +{ + blender::parallel_sort( + ai, ai + length, [](const LineartAdjacentEdge &p1, const LineartAdjacentEdge &p2) { + int a = p1.v1 - p2.v1; + int b = p1.v2 - p2.v2; + /* parallel_sort() requires cmp() to return true when the first element needs to appear + * before the second element in the sorted array, false otherwise (strict weak ordering), + * see https://en.cppreference.com/w/cpp/named_req/Compare. */ + if (a < 0) { + return true; + } + if (a > 0) { + return false; + } + return b < 0; + }); +} + static LineartEdgeNeighbor *lineart_build_edge_neighbor(Mesh *me, int total_edges) { /* Because the mesh is triangulated, so `me->totedge` should be reliable? */ @@ -2458,7 +2479,7 @@ static void lineart_object_load_single_instance(LineartData *ld, if ((!use_mesh) || use_mesh->edit_mesh) { /* If the object is being edited, then the mesh is not evaluated fully into the final * result, do not load them. This could be caused by incorrect evaluation order due to - * the way line art uses depsgraph.See T102612 for explanation of this workaround. */ + * the way line art uses depsgraph.See #102612 for explanation of this workaround. */ return; } } diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h index f33208ff9310..086428ff481f 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_intern.h @@ -173,8 +173,6 @@ void lineart_add_edge_to_array(struct LineartPendingEdges *pe, struct LineartEdg void lineart_finalize_object_edge_array_reserve(struct LineartPendingEdges *pe, int count); void lineart_destroy_render_data_keep_init(struct LineartData *ld); -void lineart_sort_adjacent_items(struct LineartAdjacentEdge *ai, int length); - #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 4967d8984c5f..4b378384a9dd 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -70,7 +70,7 @@ set(SRC intern/gpu_select_pick.c intern/gpu_select_sample_query.cc intern/gpu_shader.cc - intern/gpu_shader_builtin.c + intern/gpu_shader_builtin.cc intern/gpu_shader_create_info.cc intern/gpu_shader_dependency.cc intern/gpu_shader_interface.cc @@ -104,6 +104,7 @@ set(SRC GPU_primitive.h GPU_select.h GPU_shader.h + GPU_shader_builtin.h GPU_shader_shared.h GPU_state.h GPU_storage_buffer.h @@ -195,6 +196,7 @@ set(VULKAN_SRC vulkan/vk_fence.cc vulkan/vk_framebuffer.cc vulkan/vk_index_buffer.cc + vulkan/vk_memory.cc vulkan/vk_pixel_buffer.cc vulkan/vk_query.cc vulkan/vk_shader.cc @@ -211,6 +213,7 @@ set(VULKAN_SRC vulkan/vk_fence.hh vulkan/vk_framebuffer.hh vulkan/vk_index_buffer.hh + vulkan/vk_memory.hh vulkan/vk_pixel_buffer.hh vulkan/vk_query.hh vulkan/vk_shader.hh @@ -303,6 +306,10 @@ if(WITH_VULKAN_BACKEND) add_definitions(-DWITH_VULKAN_BACKEND) endif() +if(WITH_VULKAN_GUARDEDALLOC) + add_definitions(-DWITH_VULKAN_GUARDEDALLOC) +endif() + set(MSL_SRC shaders/metal/mtl_shader_defines.msl shaders/metal/mtl_shader_common.msl @@ -371,7 +378,6 @@ set(GLSL_SRC shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl shaders/gpu_shader_point_varying_color_frag.glsl - shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 1e5adab15d43..35d2d3f6e1a7 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -263,9 +263,9 @@ void GPU_batch_program_set_imm_shader(GPUBatch *batch); #define GPU_batch_uniform_mat4(batch, name, val) \ GPU_shader_uniform_mat4((batch)->shader, name, val); #define GPU_batch_uniformbuf_bind(batch, name, ubo) \ - GPU_uniformbuf_bind(ubo, GPU_shader_get_uniform_block_binding((batch)->shader, name)); + GPU_uniformbuf_bind(ubo, GPU_shader_get_ubo_binding((batch)->shader, name)); #define GPU_batch_texture_bind(batch, name, tex) \ - GPU_texture_bind(tex, GPU_shader_get_texture_binding((batch)->shader, name)); + GPU_texture_bind(tex, GPU_shader_get_sampler_binding((batch)->shader, name)); /** \} */ diff --git a/source/blender/gpu/GPU_index_buffer.h b/source/blender/gpu/GPU_index_buffer.h index e5fefda527db..9d152b01c8b0 100644 --- a/source/blender/gpu/GPU_index_buffer.h +++ b/source/blender/gpu/GPU_index_buffer.h @@ -89,13 +89,11 @@ void GPU_indexbuf_create_subrange_in_place(GPUIndexBuf *elem, uint length); /** - * (Download and) return a pointer containing the data of an index buffer. + * (Download and) fill data with the contents of the index buffer. * - * Note that the returned pointer is still owned by the driver. To get an - * local copy, use `GPU_indexbuf_unmap` after calling `GPU_indexbuf_read`. + * NOTE: caller is responsible to reserve enough memory. */ -const uint32_t *GPU_indexbuf_read(GPUIndexBuf *elem); -uint32_t *GPU_indexbuf_unmap(const GPUIndexBuf *elem, const uint32_t *mapped_buffer); +void GPU_indexbuf_read(GPUIndexBuf *elem, uint32_t *data); void GPU_indexbuf_discard(GPUIndexBuf *elem); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index f9bae39b0166..7e7905c3aeb9 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -254,9 +254,20 @@ void GPU_materials_free(struct Main *bmain); struct Scene *GPU_material_scene(GPUMaterial *material); struct GPUPass *GPU_material_get_pass(GPUMaterial *material); +/* Return the most optimal shader configuration for the given material .*/ struct GPUShader *GPU_material_get_shader(GPUMaterial *material); +/* Return the base un-optimized shader. */ +struct GPUShader *GPU_material_get_shader_base(GPUMaterial *material); const char *GPU_material_get_name(GPUMaterial *material); +/** + * Material Optimization. + * \note Compiles optimal version of shader graph, populating mat->optimized_pass. + * This operation should always be deferred until existing compilations have completed. + * Default un-optimized materials will still exist for interactive material editing performance. + */ +void GPU_material_optimize(GPUMaterial *mat); + /** * Return can be NULL if it's a world material. */ @@ -274,6 +285,24 @@ eGPUMaterialOptimizationStatus GPU_material_optimization_status(GPUMaterial *mat void GPU_material_optimization_status_set(GPUMaterial *mat, eGPUMaterialOptimizationStatus status); bool GPU_material_optimization_ready(GPUMaterial *mat); +/** + * Store reference to a similar default material for async PSO cache warming. + * + * This function expects `material` to have not yet been compiled and for `default_material` to be + * ready. When compiling `material` as part of an async shader compilation job, use existing PSO + * descriptors from `default_material`'s shader to also compile PSOs for this new material + * asynchronously, rather than at runtime. + * + * The default_material `options` should match this new materials options in order + * for PSO descriptors to match those needed by the new `material`. + * + * NOTE: `default_material` must exist when `GPU_material_compile(..)` is called for + * `material`. + * + * See `GPU_shader_warm_cache(..)` for more information. + */ +void GPU_material_set_default(GPUMaterial *material, GPUMaterial *default_material); + struct GPUUniformBuf *GPU_material_uniform_buffer_get(GPUMaterial *material); /** * Create dynamic UBO from parameters diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h index 2a9c4a89b2ad..ed95bf8185f4 100644 --- a/source/blender/gpu/GPU_matrix.h +++ b/source/blender/gpu/GPU_matrix.h @@ -95,7 +95,7 @@ struct GPUMatrixUnproject_Precalc { /** * Result of #projmat_dimensions_db. * Using double precision here is important as far clipping ranges - * can cause divide-by-zero when using float, see: T66937. + * can cause divide-by-zero when using float, see: #66937. */ struct { double xmin, xmax; diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 3cf64edaa6e8..8268dd78c106 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -3,10 +3,14 @@ /** \file * \ingroup gpu + * + * A #GPUShader is a container for backend specific shader program. */ #pragma once +#include "GPU_shader_builtin.h" + #ifdef __cplusplus extern "C" { #endif @@ -18,6 +22,161 @@ typedef struct GPUShaderCreateInfo GPUShaderCreateInfo; /** Opaque type hiding #blender::gpu::Shader */ typedef struct GPUShader GPUShader; +/* Hardware limit is 16. Position attribute is always needed so we reduce to 15. + * This makes sure the GPUVertexFormat name buffer does not overflow. */ +#define GPU_MAX_ATTR 15 + +/* Determined by the maximum uniform buffer size divided by chunk size. */ +#define GPU_MAX_UNIFORM_ATTR 8 + +/* -------------------------------------------------------------------- */ +/** \name Creation + * \{ */ + +/** + * Create a shader using the given #GPUShaderCreateInfo. + * Can return a NULL pointer if compilation fails. + */ +GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info); + +/** + * Create a shader using a named #GPUShaderCreateInfo registered at startup. + * These are declared inside `*_info.hh` files using the `GPU_SHADER_CREATE_INFO()` macro. + * They are also expected to have been flagged using `do_static_compilation`. + * Can return a NULL pointer if compilation fails. + */ +GPUShader *GPU_shader_create_from_info_name(const char *info_name); + +/** + * Fetch a named #GPUShaderCreateInfo registered at startup. + * These are declared inside `*_info.hh` files using the `GPU_SHADER_CREATE_INFO()` macro. + * Can return a NULL pointer if no match is found. + */ +const GPUShaderCreateInfo *GPU_shader_create_info_get(const char *info_name); + +/** + * Error checking for user created shaders. + * \return true is create info is valid. + */ +bool GPU_shader_create_info_check_error(const GPUShaderCreateInfo *_info, char r_error[128]); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Free + * \{ */ + +void GPU_shader_free(GPUShader *shader); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Binding + * \{ */ + +/** + * Set the given shader as active shader for the active GPU context. + * It replaces any already bound shader. + * All following draw-calls and dispatches will use this shader. + * Uniform functions need to have the shader bound in order to work. (TODO: until we use + * glProgramUniform) + */ +void GPU_shader_bind(GPUShader *shader); + +/** + * Unbind the active shader. + * \note this is a no-op in release builds. But it make sense to actually do it in user land code + * to detect incorrect API usage. + */ +void GPU_shader_unbind(void); + +/** + * Return the currently bound shader to the active GPU context. + * \return NULL pointer if no shader is bound of if no context is active. + */ +GPUShader *GPU_shader_get_bound(void); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Debugging introspection API. + * \{ */ + +const char *GPU_shader_get_name(GPUShader *shader); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Uniform API. + * \{ */ + +/** + * Returns binding point location. + * Binding location are given to be set at shader compile time and immutable. + */ +int GPU_shader_get_ubo_binding(GPUShader *shader, const char *name); +int GPU_shader_get_ssbo_binding(GPUShader *shader, const char *name); +int GPU_shader_get_sampler_binding(GPUShader *shader, const char *name); + +/** + * Returns uniform location. + * If cached, it is faster than querying the interface for each uniform assignment. + */ +int GPU_shader_get_uniform(GPUShader *shader, const char *name); + +/** + * Sets a generic push constant (a.k.a. uniform). + * \a length and \a array_size should match the create info push_constant declaration. + */ +void GPU_shader_uniform_float_ex( + GPUShader *shader, int location, int length, int array_size, const float *value); +void GPU_shader_uniform_int_ex( + GPUShader *shader, int location, int length, int array_size, const int *value); + +/** + * Sets a generic push constant (a.k.a. uniform). + * \a length and \a array_size should match the create info push_constant declaration. + * These functions need to have the shader bound in order to work. (TODO: until we use + * glProgramUniform) + */ +void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value); +void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value); +void GPU_shader_uniform_1f(GPUShader *sh, const char *name, float value); +void GPU_shader_uniform_2f(GPUShader *sh, const char *name, float x, float y); +void GPU_shader_uniform_3f(GPUShader *sh, const char *name, float x, float y, float z); +void GPU_shader_uniform_4f(GPUShader *sh, const char *name, float x, float y, float z, float w); +void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2]); +void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3]); +void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4]); +void GPU_shader_uniform_2iv(GPUShader *sh, const char *name, const int data[2]); +void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4]); +void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const float data[3][3]); +void GPU_shader_uniform_2fv_array(GPUShader *sh, const char *name, int len, const float (*val)[2]); +void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, const float (*val)[4]); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Attribute API. + * + * Used to create #GPUVertexFormat from the shader's vertex input layout. + * \{ */ + +unsigned int GPU_shader_get_attribute_len(const GPUShader *shader); +int GPU_shader_get_attribute(const GPUShader *shader, const char *name); +bool GPU_shader_get_attribute_info(const GPUShader *shader, + int attr_location, + char r_name[256], + int *r_type); + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Legacy API + * + * All of this section is deprecated and should be ported to use the API described above. + * \{ */ + typedef enum eGPUShaderTFBType { GPU_SHADER_TFB_NONE = 0, /* Transform feedback unsupported. */ GPU_SHADER_TFB_POINTS = 1, @@ -51,54 +210,6 @@ GPUShader *GPU_shader_create_ex(const char *vertcode, const char **tf_names, int tf_count, const char *shname); -GPUShader *GPU_shader_create_from_info(const GPUShaderCreateInfo *_info); -GPUShader *GPU_shader_create_from_info_name(const char *info_name); - -const GPUShaderCreateInfo *GPU_shader_create_info_get(const char *info_name); -bool GPU_shader_create_info_check_error(const GPUShaderCreateInfo *_info, char r_error[128]); - -struct GPU_ShaderCreateFromArray_Params { - const char **vert, **geom, **frag, **defs; -}; -/** - * Use via #GPU_shader_create_from_arrays macro (avoids passing in param). - * - * Similar to #DRW_shader_create_with_lib with the ability to include libraries for each type of - * shader. - * - * It has the advantage that each item can be conditionally included - * without having to build the string inline, then free it. - * - * \param params: NULL terminated arrays of strings. - * - * Example: - * \code{.c} - * sh = GPU_shader_create_from_arrays({ - * .vert = (const char *[]){shader_lib_glsl, shader_vert_glsl, NULL}, - * .geom = (const char *[]){shader_geom_glsl, NULL}, - * .frag = (const char *[]){shader_frag_glsl, NULL}, - * .defs = (const char *[]){"#define DEFINE\n", test ? "#define OTHER_DEFINE\n" : "", NULL}, - * }); - * \endcode - */ -struct GPUShader *GPU_shader_create_from_arrays_impl( - const struct GPU_ShaderCreateFromArray_Params *params, const char *func, int line); - -#define GPU_shader_create_from_arrays(...) \ - GPU_shader_create_from_arrays_impl( \ - &(const struct GPU_ShaderCreateFromArray_Params)__VA_ARGS__, __func__, __LINE__) - -#define GPU_shader_create_from_arrays_named(name, ...) \ - GPU_shader_create_from_arrays_impl( \ - &(const struct GPU_ShaderCreateFromArray_Params)__VA_ARGS__, name, 0) - -void GPU_shader_free(GPUShader *shader); - -void GPU_shader_bind(GPUShader *shader); -void GPU_shader_unbind(void); -GPUShader *GPU_shader_get_bound(void); - -const char *GPU_shader_get_name(GPUShader *shader); /** * Returns true if transform feedback was successfully enabled. @@ -106,9 +217,54 @@ const char *GPU_shader_get_name(GPUShader *shader); bool GPU_shader_transform_feedback_enable(GPUShader *shader, struct GPUVertBuf *vertbuf); void GPU_shader_transform_feedback_disable(GPUShader *shader); +/** + * Shader cache warming. + * For each shader, rendering APIs perform a two-step compilation: + * + * * The first stage is Front-End compilation which only needs to be performed once, and generates + * a portable intermediate representation. This happens during `gpu::Shader::finalize()`. + * + * * The second is Back-End compilation which compiles a device-specific executable shader + * program. This compilation requires some contextual pipeline state which is baked into the + * executable shader source, producing a Pipeline State Object (PSO). In OpenGL, backend + * compilation happens in the background, within the driver, but can still incur runtime stutters. + * In Metal/Vulkan, PSOs are compiled explicitly. These are currently resolved within the backend + * based on the current pipeline state and can incur runtime stalls when they occur. + * + * Shader Cache warming uses the specified parent shader set using `GPU_shader_set_parent(..)` as a + * template reference for pre-compiling Render Pipeline State Objects (PSOs) outside of the main + * render pipeline. + * + * PSOs require descriptors containing information on the render state for a given shader, which + * includes input vertex data layout and output pixel formats, along with some state such as + * blend mode and color output masks. As this state information is usually consistent between + * similar draws, we can assign a parent shader and use this shader's cached pipeline state's to + * prime compilations. + * + * Shaders do not necessarily have to be similar in functionality to be used as a parent, so long + * as the #GPUVertFormt and #GPUFrameBuffer which they are used with remain the same. + * Other bindings such as textures, uniforms and UBOs are all assigned independently as dynamic + * state. + * + * This function should be called asynchronously, mitigating the impact of run-time stuttering from + * dynamic compilation of PSOs during normal rendering. + * + * \param: shader: The shader whose cache to warm. + * \param limit: The maximum number of PSOs to compile within a call. Specifying + * a limit <= 0 will compile a PSO for all cached PSOs in the parent shader. */ +void GPU_shader_warm_cache(GPUShader *shader, int limit); + +/* We expect the parent shader to be compiled and already have some cached PSOs when being assigned + * as a reference. Ensure the parent shader still exists when `GPU_shader_cache_warm(..)` is + * called. */ +void GPU_shader_set_parent(GPUShader *shader, GPUShader *parent); + /** DEPRECATED: Kept only because of BGL API. */ int GPU_shader_get_program(GPUShader *shader); +/** + * Indexed commonly used uniform name for faster lookup into the uniform cache. + */ typedef enum { GPU_UNIFORM_MODEL = 0, /* mat4 ModelMatrix */ GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */ @@ -132,16 +288,21 @@ typedef enum { GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */ GPU_UNIFORM_RESOURCE_ID, /* int resourceId */ GPU_UNIFORM_SRGB_TRANSFORM, /* bool srgbTarget */ - - GPU_NUM_UNIFORMS, /* Special value, denotes number of builtin uniforms. */ } GPUUniformBuiltin; +#define GPU_NUM_UNIFORMS (GPU_UNIFORM_SRGB_TRANSFORM + 1) +/** + * TODO: To be moved as private API. Not really used outside of gpu_matrix.cc and doesn't really + * offer a noticeable performance boost. + */ +int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin); + +/** DEPRECATED: Use hardcoded buffer location instead. */ typedef enum { - /** Deprecated */ GPU_UNIFORM_BLOCK_VIEW = 0, /* viewBlock */ GPU_UNIFORM_BLOCK_MODEL, /* modelBlock */ GPU_UNIFORM_BLOCK_INFO, /* infoBlock */ - /** New ones */ + GPU_UNIFORM_BLOCK_DRW_VIEW, GPU_UNIFORM_BLOCK_DRW_MODEL, GPU_UNIFORM_BLOCK_DRW_INFOS, @@ -150,260 +311,13 @@ typedef enum { GPU_NUM_UNIFORM_BLOCKS, /* Special value, denotes number of builtin uniforms block. */ } GPUUniformBlockBuiltin; -typedef enum { - GPU_STORAGE_BUFFER_DEBUG_VERTS = 0, /* drw_debug_verts_buf */ - GPU_STORAGE_BUFFER_DEBUG_PRINT, /* drw_debug_print_buf */ - - GPU_NUM_STORAGE_BUFFERS, /* Special value, denotes number of builtin buffer blocks. */ -} GPUStorageBufferBuiltin; - -void GPU_shader_set_srgb_uniform(GPUShader *shader); - -int GPU_shader_get_uniform(GPUShader *shader, const char *name); -int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin); +/** DEPRECATED: Use hardcoded buffer location instead. */ int GPU_shader_get_builtin_block(GPUShader *shader, int builtin); -int GPU_shader_get_builtin_ssbo(GPUShader *shader, int builtin); + /** DEPRECATED: Kept only because of Python GPU API. */ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name); -int GPU_shader_get_ssbo(GPUShader *shader, const char *name); -int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name); -int GPU_shader_get_texture_binding(GPUShader *shader, const char *name); - -void GPU_shader_uniform_vector( - GPUShader *shader, int location, int length, int arraysize, const float *value); -void GPU_shader_uniform_vector_int( - GPUShader *shader, int location, int length, int arraysize, const int *value); - -void GPU_shader_uniform_float(GPUShader *shader, int location, float value); -void GPU_shader_uniform_int(GPUShader *shader, int location, int value); - -void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value); -void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value); -void GPU_shader_uniform_1f(GPUShader *sh, const char *name, float value); -void GPU_shader_uniform_2f(GPUShader *sh, const char *name, float x, float y); -void GPU_shader_uniform_3f(GPUShader *sh, const char *name, float x, float y, float z); -void GPU_shader_uniform_4f(GPUShader *sh, const char *name, float x, float y, float z, float w); -void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2]); -void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3]); -void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4]); -void GPU_shader_uniform_2iv(GPUShader *sh, const char *name, const int data[2]); -void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4]); -void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const float data[3][3]); -void GPU_shader_uniform_2fv_array(GPUShader *sh, const char *name, int len, const float (*val)[2]); -void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, const float (*val)[4]); - -unsigned int GPU_shader_get_attribute_len(const GPUShader *shader); -int GPU_shader_get_attribute(GPUShader *shader, const char *name); -bool GPU_shader_get_attribute_info(const GPUShader *shader, - int attr_location, - char r_name[256], - int *r_type); - -void GPU_shader_set_framebuffer_srgb_target(int use_srgb_to_linear); - -/* Builtin/Non-generated shaders */ -typedef enum eGPUBuiltinShader { - /* specialized drawing */ - GPU_SHADER_TEXT, - GPU_SHADER_KEYFRAME_SHAPE, - GPU_SHADER_SIMPLE_LIGHTING, - /** - * Draw an icon, leaving a semi-transparent rectangle on top of the icon. - */ - GPU_SHADER_ICON, - /** - * Take a 2D position and color for each vertex with linear interpolation in window space. - * - * \param color: in vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_IMAGE_DESATURATE_COLOR, - GPU_SHADER_2D_IMAGE_RECT_COLOR, - GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR, - GPU_SHADER_2D_CHECKER, - GPU_SHADER_2D_DIAG_STRIPES, - /* for simple 3D drawing */ - /** - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param color: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_UNIFORM_COLOR, - GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR, - /** - * Take a 3D position and color for each vertex without color interpolation. - * - * \param color: in vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_FLAT_COLOR, - /** - * Take a 3D position and color for each vertex with perspective correct interpolation. - * - * \param color: in vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_SMOOTH_COLOR, - /** - * Take a single color for all the vertices and a 3D position for each vertex. - * Used for drawing wide lines. - * - * \param color: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, - GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR, - /** - * Take a 3D position and color for each vertex without color interpolation. - * Used for drawing wide lines. - * - * \param color: in vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POLYLINE_FLAT_COLOR, - /** - * Take a 3D position and color for each vertex with perspective correct interpolation. - * Used for drawing wide lines. - * - * \param color: in vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR, - /** - * Take a 3D position for each vertex and output only depth. - * Used for drawing wide lines. - * - * \param pos: in vec3 - */ - GPU_SHADER_3D_DEPTH_ONLY, - /* basic image drawing */ - GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE, - GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE, - GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR, - /** - * Draw a texture in 3D. Take a 3D position and a 2D texture coordinate for each vertex. - * - * Exposed via Python-API for add-ons. - * - * \param image: uniform sampler2D - * \param texCoord: in vec2 - * \param pos: in vec3 - */ - GPU_SHADER_3D_IMAGE, - /** - * Take a 3D position and color for each vertex with linear interpolation in window space. - * - * \param color: uniform vec4 - * \param image: uniform sampler2D - * \param texCoord: in vec2 - * \param pos: in vec3 - */ - GPU_SHADER_3D_IMAGE_COLOR, - /* points */ - /** - * Draw round points with a constant size. - * Take a single color for all the vertices and a 2D position for each vertex. - * - * \param size: uniform float - * \param color: uniform vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, - /** - * Draw round points with a constant size and an outline. - * Take a single color for all the vertices and a 2D position for each vertex. - * - * \param size: uniform float - * \param outlineWidth: uniform float - * \param color: uniform vec4 - * \param outlineColor: uniform vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, - /** - * Draw round points with a hardcoded size. - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param color: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR, - /** - * Draw round points with a constant size. - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param size: uniform float - * \param color: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, - /** - * Draw round points with a constant size and an outline. - * Take a 3D position and a color for each vertex. - * - * \param size: in float - * \param color: in vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR, - /* lines */ - GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR, - /* grease pencil drawing */ - GPU_SHADER_GPENCIL_STROKE, - /* specialized for widget drawing */ - GPU_SHADER_2D_AREA_BORDERS, - GPU_SHADER_2D_WIDGET_BASE, - GPU_SHADER_2D_WIDGET_BASE_INST, - GPU_SHADER_2D_WIDGET_SHADOW, - GPU_SHADER_2D_NODELINK, - GPU_SHADER_2D_NODELINK_INST, -} eGPUBuiltinShader; -#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_2D_NODELINK_INST + 1) - -/** Support multiple configurations. */ -typedef enum eGPUShaderConfig { - GPU_SHADER_CFG_DEFAULT = 0, - GPU_SHADER_CFG_CLIPPED = 1, -} eGPUShaderConfig; -#define GPU_SHADER_CFG_LEN (GPU_SHADER_CFG_CLIPPED + 1) - -typedef struct GPUShaderConfigData { - const char *lib; - const char *def; -} GPUShaderConfigData; -/* gpu_shader.c */ - -extern const GPUShaderConfigData GPU_shader_cfg_data[GPU_SHADER_CFG_LEN]; - -GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, - eGPUShaderConfig sh_cfg); -GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader); - -void GPU_shader_free_builtin_shaders(void); - -/* Vertex attributes for shaders */ - -/* Hardware limit is 16. Position attribute is always needed so we reduce to 15. - * This makes sure the GPUVertexFormat name buffer does not overflow. */ -#define GPU_MAX_ATTR 15 - -/* Determined by the maximum uniform buffer size divided by chunk size. */ -#define GPU_MAX_UNIFORM_ATTR 8 - -typedef enum eGPUKeyframeShapes { - GPU_KEYFRAME_SHAPE_DIAMOND = (1 << 0), - GPU_KEYFRAME_SHAPE_CIRCLE = (1 << 1), - GPU_KEYFRAME_SHAPE_CLIPPED_VERTICAL = (1 << 2), - GPU_KEYFRAME_SHAPE_CLIPPED_HORIZONTAL = (1 << 3), - GPU_KEYFRAME_SHAPE_INNER_DOT = (1 << 4), - GPU_KEYFRAME_SHAPE_ARROW_END_MAX = (1 << 8), - GPU_KEYFRAME_SHAPE_ARROW_END_MIN = (1 << 9), - GPU_KEYFRAME_SHAPE_ARROW_END_MIXED = (1 << 10), -} eGPUKeyframeShapes; -#define GPU_KEYFRAME_SHAPE_SQUARE \ - (GPU_KEYFRAME_SHAPE_CLIPPED_VERTICAL | GPU_KEYFRAME_SHAPE_CLIPPED_HORIZONTAL) +/** \} */ #ifdef __cplusplus } diff --git a/source/blender/gpu/GPU_shader_builtin.h b/source/blender/gpu/GPU_shader_builtin.h new file mode 100644 index 000000000000..bd9fa9eb232f --- /dev/null +++ b/source/blender/gpu/GPU_shader_builtin.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2023 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + * + * Set of shaders used for interface drawing. + * + * 2D shaders are not expected to work in 3D. + * 3D shaders can work with 2D geometry and matrices. + * + * `INST` suffix means instance, which means the shader is build to leverage instancing + * capabilities to reduce the number of draw-calls. + * + * For full list of parameters, search for the the associated #ShaderCreateInfo. + * Example: `GPU_SHADER_ICON` is defined by `GPU_SHADER_CREATE_INFO(gpu_shader_icon)` + * Some parameters are builtins and are set automatically (ex: `ModelViewProjectionMatrix`). + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +struct GPUShader; + +typedef enum eGPUBuiltinShader { + /** Glyph drawing shader used by the BLF module. */ + GPU_SHADER_TEXT, + /** Draws keyframe markers. All markers shapes are supported through a single shader. */ + GPU_SHADER_KEYFRAME_SHAPE, + /** Draw solid mesh with a single distant light using a clamped simple dot product. */ + GPU_SHADER_SIMPLE_LIGHTING, + /** Draw an icon, leaving a semi-transparent rectangle on top of the icon. */ + GPU_SHADER_ICON, + /** Draw a texture with a uniform color multiplied. */ + GPU_SHADER_2D_IMAGE_RECT_COLOR, + /** Draw a texture with a desaturation factor. */ + GPU_SHADER_2D_IMAGE_DESATURATE_COLOR, + /** Draw a group of texture rectangle with an associated color multiplied. */ + GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR, + /** Draw a two color checker based on screen position (not UV coordinates). */ + GPU_SHADER_2D_CHECKER, + /** Draw diagonal stripes with two alternating colors. */ + GPU_SHADER_2D_DIAG_STRIPES, + /** Draw dashed lines with custom dash length and uniform color. */ + GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR, + /** Draw triangles / lines / points with only depth output. */ + GPU_SHADER_3D_DEPTH_ONLY, + /** Merge viewport overlay texture with the render output. */ + GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE, + GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE, + /** Merge viewport overlay texture with the render output. */ + GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR, + /** Used for drawing of annotations (former grease pencil). */ + GPU_SHADER_GPENCIL_STROKE, + /** Draw rounded area borders with silky smooth anti-aliasing without any over-draw. */ + GPU_SHADER_2D_AREA_BORDERS, + /** Multi usage widget shaders for drawing buttons and other UI elements. */ + GPU_SHADER_2D_WIDGET_BASE, + GPU_SHADER_2D_WIDGET_BASE_INST, + GPU_SHADER_2D_WIDGET_SHADOW, + /** Draw a node link given an input quadratic Bezier curve. */ + GPU_SHADER_2D_NODELINK, + GPU_SHADER_2D_NODELINK_INST, + + /** Draw round points with per vertex size and color. */ + GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR, + /** Draw round points with a uniform size. Disabling blending will disable AA. */ + GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, + /** Draw round points with a uniform size and an outline. Disabling blending will disable AA. */ + GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, + + /** Draw geometry with uniform color. Has an additional clip plane parameter. */ + GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR, + /** Draw wide lines with uniform color. Has an additional clip plane parameter. */ + GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR, + + /** + * ----------------------- Shaders exposed through pyGPU module ----------------------- + * + * Avoid breaking the interface of these shaders as they are used by addons. + * Polyline versions are used for drawing wide lines (> 1px width). + */ + + /** + * Take a 3D position and color for each vertex without color interpolation. + * + * \param color: in vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_FLAT_COLOR, + GPU_SHADER_3D_POLYLINE_FLAT_COLOR, + /** + * Take a 3D position and color for each vertex with perspective correct interpolation. + * + * \param color: in vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_SMOOTH_COLOR, + GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR, + /** + * Take a single color for all the vertices and a 3D position for each vertex. + * + * \param color: uniform vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_UNIFORM_COLOR, + GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, + /** + * Draw a texture in 3D. Take a 3D position and a 2D texture coordinate for each vertex. + * + * \param image: uniform sampler2D + * \param texCoord: in vec2 + * \param pos: in vec3 + */ + GPU_SHADER_3D_IMAGE, + /** + * Take a 3D position and color for each vertex with linear interpolation in window space. + * + * \param color: uniform vec4 + * \param image: uniform sampler2D + * \param texCoord: in vec2 + * \param pos: in vec3 + */ + GPU_SHADER_3D_IMAGE_COLOR, +} eGPUBuiltinShader; +#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_3D_IMAGE_COLOR + 1) + +/** Support multiple configurations. */ +typedef enum eGPUShaderConfig { + GPU_SHADER_CFG_DEFAULT = 0, + GPU_SHADER_CFG_CLIPPED = 1, +} eGPUShaderConfig; +#define GPU_SHADER_CFG_LEN (GPU_SHADER_CFG_CLIPPED + 1) + +struct GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, + eGPUShaderConfig sh_cfg); +struct GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader); + +void GPU_shader_free_builtin_shaders(void); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/gpu/GPU_shader_shared.h b/source/blender/gpu/GPU_shader_shared.h index 4fb321ce502b..66face85b07d 100644 --- a/source/blender/gpu/GPU_shader_shared.h +++ b/source/blender/gpu/GPU_shader_shared.h @@ -11,6 +11,24 @@ typedef struct TestOutputRawData TestOutputRawData; #endif +/* NOTE: float3 has differing stride and alignment rules across different GPU backends. If 12 byte + * stride and alignment is essential, use `packed_float3` to avoid data read issues. This is + * required in the common use-case where a float3 and an int/float are paired together for optimal + * data transfer. */ + +enum eGPUKeyframeShapes { + GPU_KEYFRAME_SHAPE_DIAMOND = (1u << 0u), + GPU_KEYFRAME_SHAPE_CIRCLE = (1u << 1u), + GPU_KEYFRAME_SHAPE_CLIPPED_VERTICAL = (1u << 2u), + GPU_KEYFRAME_SHAPE_CLIPPED_HORIZONTAL = (1u << 3u), + GPU_KEYFRAME_SHAPE_INNER_DOT = (1u << 4u), + GPU_KEYFRAME_SHAPE_ARROW_END_MAX = (1u << 8u), + GPU_KEYFRAME_SHAPE_ARROW_END_MIN = (1u << 9u), + GPU_KEYFRAME_SHAPE_ARROW_END_MIXED = (1u << 10u), + GPU_KEYFRAME_SHAPE_SQUARE = (GPU_KEYFRAME_SHAPE_CLIPPED_VERTICAL | + GPU_KEYFRAME_SHAPE_CLIPPED_HORIZONTAL), +}; + struct NodeLinkData { float4 colors[3]; /* bezierPts Is actually a float2, but due to std140 each element needs to be aligned to 16 @@ -57,7 +75,7 @@ BLI_STATIC_ASSERT_ALIGN(struct GPUClipPlanes, 16) struct SimpleLightingData { float4 l_color; - float3 light; + packed_float3 light; float _pad; }; BLI_STATIC_ASSERT_ALIGN(struct SimpleLightingData, 16) diff --git a/source/blender/gpu/GPU_shader_shared_utils.h b/source/blender/gpu/GPU_shader_shared_utils.h index 08fa8be22ef4..e1ad3b765f82 100644 --- a/source/blender/gpu/GPU_shader_shared_utils.h +++ b/source/blender/gpu/GPU_shader_shared_utils.h @@ -59,6 +59,7 @@ # define bool2 bvec2 # define bool3 bvec3 # define bool4 bvec4 +# define packed_float3 vec3 # endif #else /* C / C++ */ @@ -83,6 +84,7 @@ using bool1 = int; using bool2 = blender::int2; using bool3 = blender::int3; using bool4 = blender::int4; +using packed_float3 = blender::float3; # else /* C */ typedef float float2[2]; @@ -99,6 +101,7 @@ typedef int bool1; typedef int bool2[2]; typedef int bool3[2]; typedef int bool4[4]; +typedef float3 packed_float3; # endif #endif diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h index 979b7cc06cf0..5fcb97a2a6b6 100644 --- a/source/blender/gpu/GPU_vertex_buffer.h +++ b/source/blender/gpu/GPU_vertex_buffer.h @@ -64,13 +64,10 @@ GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *, GPUUsageTyp GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_STATIC) /** - * (Download and) return a pointer containing the data of a vertex buffer. - * - * Note that the returned pointer is still owned by the driver. To get an - * local copy, use `GPU_vertbuf_unmap` after calling `GPU_vertbuf_read`. + * (Download and) fill data with the data from the vertex buffer. + * NOTE: caller is responsible to reserve enough memory of the data parameter. */ -const void *GPU_vertbuf_read(GPUVertBuf *verts); -void *GPU_vertbuf_unmap(const GPUVertBuf *verts, const void *mapped_data); +void GPU_vertbuf_read(GPUVertBuf *verts, void *data); /** Same as discard but does not free. */ void GPU_vertbuf_clear(GPUVertBuf *verts); void GPU_vertbuf_discard(GPUVertBuf *); diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc index 38f80760d615..78cddc6d272a 100644 --- a/source/blender/gpu/intern/gpu_codegen.cc +++ b/source/blender/gpu/intern/gpu_codegen.cc @@ -25,6 +25,7 @@ #include "BKE_material.h" #include "GPU_capabilities.h" +#include "GPU_context.h" #include "GPU_material.h" #include "GPU_shader.h" #include "GPU_uniform_buffer.h" @@ -95,6 +96,9 @@ struct GPUPass { uint32_t hash; /** Did we already tried to compile the attached GPUShader. */ bool compiled; + /** Hint that an optimized variant of this pass should be created based on a complexity heuristic + * during pass code generation. */ + bool should_optimize; }; /* -------------------------------------------------------------------- */ @@ -252,6 +256,11 @@ class GPUCodegen { ListBase ubo_inputs_ = {nullptr, nullptr}; GPUInput *cryptomatte_input_ = nullptr; + /** Cache parameters for complexity heuristic. */ + uint nodes_total_ = 0; + uint textures_total_ = 0; + uint uniforms_total_ = 0; + public: GPUCodegen(GPUMaterial *mat_, GPUNodeGraph *graph_) : mat(*mat_), graph(*graph_) { @@ -292,6 +301,17 @@ class GPUCodegen { return hash_; } + /* Heuristic determined during pass codegen for whether a + * more optimal variant of this material should be compiled. */ + bool should_optimize_heuristic() const + { + /* If each of the maximal attributes are exceeded, we can optimize, but we should also ensure + * the baseline is met.*/ + bool do_optimize = (nodes_total_ >= 60 || textures_total_ >= 4 || uniforms_total_ >= 64) && + (textures_total_ >= 1 && uniforms_total_ >= 8 && nodes_total_ >= 4); + return do_optimize; + } + private: void set_unique_ids(); @@ -369,7 +389,7 @@ void GPUCodegen::generate_resources() { GPUCodegenCreateInfo &info = *create_info; - /* Ref. T98190: Defines are optimizations for old compilers. + /* Ref. #98190: Defines are optimizations for old compilers. * Might become unnecessary with EEVEE-Next. */ if (GPU_material_flag_get(&mat, GPU_MATFLAG_PRINCIPLED_CLEARCOAT)) { info.define("PRINCIPLED_CLEARCOAT"); @@ -413,6 +433,9 @@ void GPUCodegen::generate_resources() } } + /* Increment heuristic. */ + textures_total_ = slot; + if (!BLI_listbase_is_empty(&ubo_inputs_)) { /* NOTE: generate_uniform_buffer() should have sorted the inputs before this. */ ss << "struct NodeTree {\n"; @@ -454,11 +477,16 @@ void GPUCodegen::generate_library() GPUCodegenCreateInfo &info = *create_info; void *value; - GSetIterState pop_state = {}; - while (BLI_gset_pop(graph.used_libraries, &pop_state, &value)) { + /* Iterate over libraries. We need to keep this struct intact in case + * it is required for the optimization pass. */ + GHashIterator *ihash = BLI_ghashIterator_new((GHash *)graph.used_libraries); + while (!BLI_ghashIterator_done(ihash)) { + value = BLI_ghashIterator_getKey(ihash); auto deps = gpu_shader_dependency_get_resolved_source((const char *)value); info.dependencies_generated.extend_non_duplicates(deps); + BLI_ghashIterator_step(ihash); } + BLI_ghashIterator_free(ihash); } void GPUCodegen::node_serialize(std::stringstream &eval_ss, const GPUNode *node) @@ -526,6 +554,9 @@ void GPUCodegen::node_serialize(std::stringstream &eval_ss, const GPUNode *node) } } eval_ss << ");\n\n"; + + /* Increment heuristic. */ + nodes_total_++; } char *GPUCodegen::graph_serialize(eGPUNodeTag tree_tag, GPUNodeLink *output_link) @@ -589,6 +620,7 @@ void GPUCodegen::generate_uniform_buffer() if (input->source == GPU_SOURCE_UNIFORM && !input->link) { /* We handle the UBO uniforms separately. */ BLI_addtail(&ubo_inputs_, BLI_genericNodeN(input)); + uniforms_total_++; } } } @@ -661,10 +693,17 @@ void GPUCodegen::generate_graphs() GPUPass *GPU_generate_pass(GPUMaterial *material, GPUNodeGraph *graph, GPUCodegenCallbackFn finalize_source_cb, - void *thunk) + void *thunk, + bool optimize_graph) { gpu_node_graph_prune_unused(graph); + /* If Optimize flag is passed in, we are generating an optimized + * variant of the GPUMaterial's GPUPass. */ + if (optimize_graph) { + gpu_node_graph_optimize(graph); + } + /* Extract attributes before compiling so the generated VBOs are ready to accept the future * shader. */ gpu_node_graph_finalize_uniform_attrs(graph); @@ -672,23 +711,33 @@ GPUPass *GPU_generate_pass(GPUMaterial *material, GPUCodegen codegen(material, graph); codegen.generate_graphs(); codegen.generate_cryptomatte(); - codegen.generate_uniform_buffer(); - /* Cache lookup: Reuse shaders already compiled. */ - GPUPass *pass_hash = gpu_pass_cache_lookup(codegen.hash_get()); + GPUPass *pass_hash = nullptr; - /* FIXME(fclem): This is broken. Since we only check for the hash and not the full source - * there is no way to have a collision currently. Some advocated to only use a bigger hash. */ - if (pass_hash && (pass_hash->next == nullptr || pass_hash->next->hash != codegen.hash_get())) { - if (!gpu_pass_is_valid(pass_hash)) { - /* Shader has already been created but failed to compile. */ - return nullptr; + if (!optimize_graph) { + /* The optimized version of the shader should not re-generate a UBO. + * The UBO will not be used for this variant. */ + codegen.generate_uniform_buffer(); + + /** Cache lookup: Reuse shaders already compiled. + * NOTE: We only perform cache look-up for non-optimized shader + * graphs, as baked constant data among other optimizations will generate too many + * shader source permutations, with minimal re-usability. */ + pass_hash = gpu_pass_cache_lookup(codegen.hash_get()); + + /* FIXME(fclem): This is broken. Since we only check for the hash and not the full source + * there is no way to have a collision currently. Some advocated to only use a bigger hash. */ + if (pass_hash && (pass_hash->next == nullptr || pass_hash->next->hash != codegen.hash_get())) { + if (!gpu_pass_is_valid(pass_hash)) { + /* Shader has already been created but failed to compile. */ + return nullptr; + } + /* No collision, just return the pass. */ + BLI_spin_lock(&pass_cache_spin); + pass_hash->refcount += 1; + BLI_spin_unlock(&pass_cache_spin); + return pass_hash; } - /* No collision, just return the pass. */ - BLI_spin_lock(&pass_cache_spin); - pass_hash->refcount += 1; - BLI_spin_unlock(&pass_cache_spin); - return pass_hash; } /* Either the shader is not compiled or there is a hash collision... @@ -726,14 +775,33 @@ GPUPass *GPU_generate_pass(GPUMaterial *material, pass->create_info = codegen.create_info; pass->hash = codegen.hash_get(); pass->compiled = false; + /* Only flag pass optimization hint if this is the first generated pass for a material. + * Optimized passes cannot be optimized further, even if the heuristic is still not + * favorable. */ + pass->should_optimize = (!optimize_graph) && codegen.should_optimize_heuristic(); codegen.create_info = nullptr; - gpu_pass_cache_insert_after(pass_hash, pass); + /* Only insert non-optimized graphs into cache. + * Optimized graphs will continuously be recompiled with new unique source during material + * editing, and thus causing the cache to fill up quickly with materials offering minimal + * re-use. */ + if (!optimize_graph) { + gpu_pass_cache_insert_after(pass_hash, pass); + } } return pass; } +bool GPU_pass_should_optimize(GPUPass *pass) +{ + /* Returns optimization heuristic prepared during + * initial codegen. + * NOTE: Optimization currently limited to Metal backend as repeated compilations required for + * material specialization cause impactful CPU stalls on OpenGL platforms. */ + return (GPU_backend_get_type() == GPU_BACKEND_METAL) && pass->should_optimize; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -889,7 +957,6 @@ void gpu_codegen_init(void) void gpu_codegen_exit(void) { - // BKE_world_defaults_free_gpu(); BKE_material_defaults_free_gpu(); GPU_shader_free_builtin_shaders(); } diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 95a672c04005..aabdf1ac003d 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -25,10 +25,12 @@ typedef struct GPUPass GPUPass; GPUPass *GPU_generate_pass(GPUMaterial *material, struct GPUNodeGraph *graph, GPUCodegenCallbackFn finalize_source_cb, - void *thunk); + void *thunk, + bool optimize_graph); GPUShader *GPU_pass_shader_get(GPUPass *pass); bool GPU_pass_compile(GPUPass *pass, const char *shname); void GPU_pass_release(GPUPass *pass); +bool GPU_pass_should_optimize(GPUPass *pass); /* Module */ diff --git a/source/blender/gpu/intern/gpu_immediate.cc b/source/blender/gpu/intern/gpu_immediate.cc index 81c0a65bb7c9..645a920fc835 100644 --- a/source/blender/gpu/intern/gpu_immediate.cc +++ b/source/blender/gpu/intern/gpu_immediate.cc @@ -54,7 +54,7 @@ void immBindShader(GPUShader *shader) GPU_shader_bind(shader); GPU_matrix_bind(shader); - GPU_shader_set_srgb_uniform(shader); + Shader::set_srgb_uniform(shader); } void immBindBuiltinProgram(eGPUBuiltinShader shader_id) @@ -163,7 +163,7 @@ static void wide_line_workaround_start(GPUPrimType prim_type) immUniform1f("lineWidth", line_width); if (GPU_blend_get() == GPU_BLEND_NONE) { - /* Disable line smoothing when blending is disabled (see T81827). */ + /* Disable line smoothing when blending is disabled (see #81827). */ immUniform1i("lineSmooth", 0); } @@ -602,19 +602,19 @@ void immUniform1i(const char *name, int x) void immBindTexture(const char *name, GPUTexture *tex) { - int binding = GPU_shader_get_texture_binding(imm->shader, name); + int binding = GPU_shader_get_sampler_binding(imm->shader, name); GPU_texture_bind(tex, binding); } void immBindTextureSampler(const char *name, GPUTexture *tex, eGPUSamplerState state) { - int binding = GPU_shader_get_texture_binding(imm->shader, name); + int binding = GPU_shader_get_sampler_binding(imm->shader, name); GPU_texture_bind_ex(tex, state, binding, true); } void immBindUniformBuf(const char *name, GPUUniformBuf *ubo) { - int binding = GPU_shader_get_uniform_block_binding(imm->shader, name); + int binding = GPU_shader_get_ubo_binding(imm->shader, name); GPU_uniformbuf_bind(ubo, binding); } @@ -625,7 +625,7 @@ void immUniformColor4f(float r, float g, float b, float a) int32_t uniform_loc = GPU_shader_get_builtin_uniform(imm->shader, GPU_UNIFORM_COLOR); BLI_assert(uniform_loc != -1); float data[4] = {r, g, b, a}; - GPU_shader_uniform_vector(imm->shader, uniform_loc, 4, 1, data); + GPU_shader_uniform_float_ex(imm->shader, uniform_loc, 4, 1, data); /* For wide Line workaround. */ copy_v4_v4(imm->uniform_color, data); } diff --git a/source/blender/gpu/intern/gpu_index_buffer.cc b/source/blender/gpu/intern/gpu_index_buffer.cc index 99e47f5452ab..c5fd6ff22062 100644 --- a/source/blender/gpu/intern/gpu_index_buffer.cc +++ b/source/blender/gpu/intern/gpu_index_buffer.cc @@ -399,14 +399,6 @@ void IndexBuf::squeeze_indices_short(uint min_idx, } } -uint32_t *IndexBuf::unmap(const uint32_t *mapped_memory) const -{ - size_t size = size_get(); - uint32_t *result = static_cast(MEM_mallocN(size, __func__)); - memcpy(result, mapped_memory, size); - return result; -} - } // namespace blender::gpu /** \} */ @@ -456,14 +448,9 @@ void GPU_indexbuf_create_subrange_in_place(GPUIndexBuf *elem, unwrap(elem)->init_subrange(unwrap(elem_src), start, length); } -const uint32_t *GPU_indexbuf_read(GPUIndexBuf *elem) +void GPU_indexbuf_read(GPUIndexBuf *elem, uint32_t *data) { - return unwrap(elem)->read(); -} - -uint32_t *GPU_indexbuf_unmap(const GPUIndexBuf *elem, const uint32_t *mapped_buffer) -{ - return unwrap(elem)->unmap(mapped_buffer); + return unwrap(elem)->read(data); } void GPU_indexbuf_discard(GPUIndexBuf *elem) diff --git a/source/blender/gpu/intern/gpu_index_buffer_private.hh b/source/blender/gpu/intern/gpu_index_buffer_private.hh index 4099d6641a6d..8689d805f237 100644 --- a/source/blender/gpu/intern/gpu_index_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_index_buffer_private.hh @@ -72,7 +72,7 @@ class IndexBuf { uint32_t index_len_get() const { /* Return 0 to bypass drawing for index buffers full of restart indices. - * They can lead to graphical glitches on some systems. (See T96892) */ + * They can lead to graphical glitches on some systems. (See #96892) */ return is_empty_ ? 0 : index_len_; } uint32_t index_start_get() const @@ -98,8 +98,7 @@ class IndexBuf { virtual void bind_as_ssbo(uint binding) = 0; - virtual const uint32_t *read() const = 0; - uint32_t *unmap(const uint32_t *mapped_memory) const; + virtual void read(uint32_t *data) const = 0; virtual void update_sub(uint start, uint len, const void *data) = 0; diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 89db541a3653..a6d411a6ef01 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -34,6 +34,8 @@ #include "DRW_engine.h" +#include "PIL_time.h" + #include "gpu_codegen.h" #include "gpu_node_graph.h" @@ -43,6 +45,17 @@ #define MAX_COLOR_BAND 128 #define MAX_GPU_SKIES 8 +/** Whether the optimized variant of the GPUPass should be created asynchronously. + * Usage of this depends on whether there are possible threading challenges of doing so. + * Currently, the overhead of GPU_generate_pass is relatively small in comparison to shader + * compilation, though this option exists in case any potential scenarios for material graph + * optimization cause a slow down on the main thread. + * + * NOTE: The actual shader program for the optimized pass will always be compiled asynchronously, + * this flag controls whether shader node graph source serialization happens on the compilation + * worker thread as well. */ +#define ASYNC_OPTIMIZED_PASS_CREATION 0 + typedef struct GPUColorBandBuilder { float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4]; int current_layer; @@ -57,6 +70,27 @@ struct GPUMaterial { /* Contains #GPUShader and source code for deferred compilation. * Can be shared between similar material (i.e: sharing same node-tree topology). */ GPUPass *pass; + /* Optimized GPUPass, situationally compiled after initial pass for optimal realtime performance. + * This shader variant bakes dynamic uniform data as constant. This variant will not use + * the ubo, and instead bake constants directly into the shader source. */ + GPUPass *optimized_pass; + /* Optimization status. + * We also use this status to determine whether this material should be considered for + * optimization. Only sufficiently complex shaders benefit from constant-folding optimizations. + * `GPU_MAT_OPTIMIZATION_READY` -> shader should be optimized and is ready for optimization. + * `GPU_MAT_OPTIMIZATION_SKIP` -> Shader should not be optimized as it would not benefit + * performance to do so, based on the heuristic. + */ + eGPUMaterialOptimizationStatus optimization_status; + double creation_time; +#if ASYNC_OPTIMIZED_PASS_CREATION == 1 + struct DeferredOptimizePass { + GPUCodegenCallbackFn callback; + void *thunk; + } DeferredOptimizePass; + struct DeferredOptimizePass optimize_pass_info; +#endif + /** UBOs for this material parameters. */ GPUUniformBuf *ubo; /** Compilation status. Do not use if shader is not GPU_MAT_SUCCESS. */ @@ -86,6 +120,12 @@ struct GPUMaterial { /* Low level node graph(s). Also contains resources needed by the material. */ GPUNodeGraph graph; + /** Default material reference used for PSO cache warming. Default materials may perform + * different operations, but the permutation will frequently share the same input PSO + * descriptors. This enables asynchronous PSO compilation as part of the deferred compilation + * pass, reducing runtime stuttering and responsiveness while compiling materials. */ + GPUMaterial *default_mat; + /** DEPRECATED: To remove. */ bool has_surface_output; bool has_volume_output; @@ -214,6 +254,9 @@ void GPU_material_free_single(GPUMaterial *material) gpu_node_graph_free(&material->graph); + if (material->optimized_pass != NULL) { + GPU_pass_release(material->optimized_pass); + } if (material->pass != NULL) { GPU_pass_release(material->pass); } @@ -252,12 +295,29 @@ Scene *GPU_material_scene(GPUMaterial *material) GPUPass *GPU_material_get_pass(GPUMaterial *material) { - return material->pass; + /* If an optimized pass variant is available, and optimization is + * flagged as complete, we use this one instead. */ + return ((GPU_material_optimization_status(material) == GPU_MAT_OPTIMIZATION_SUCCESS) && + material->optimized_pass) ? + material->optimized_pass : + material->pass; } GPUShader *GPU_material_get_shader(GPUMaterial *material) { - return material->pass ? GPU_pass_shader_get(material->pass) : NULL; + /* If an optimized material shader variant is available, and optimization is + * flagged as complete, we use this one instead. */ + GPUShader *shader = ((GPU_material_optimization_status(material) == + GPU_MAT_OPTIMIZATION_SUCCESS) && + material->optimized_pass) ? + GPU_pass_shader_get(material->optimized_pass) : + NULL; + return (shader) ? shader : ((material->pass) ? GPU_pass_shader_get(material->pass) : NULL); +} + +GPUShader *GPU_material_get_shader_base(GPUMaterial *material) +{ + return (material->pass) ? GPU_pass_shader_get(material->pass) : NULL; } const char *GPU_material_get_name(GPUMaterial *material) @@ -665,6 +725,40 @@ void GPU_material_status_set(GPUMaterial *mat, eGPUMaterialStatus status) mat->status = status; } +eGPUMaterialOptimizationStatus GPU_material_optimization_status(GPUMaterial *mat) +{ + return mat->optimization_status; +} + +void GPU_material_optimization_status_set(GPUMaterial *mat, eGPUMaterialOptimizationStatus status) +{ + mat->optimization_status = status; + if (mat->optimization_status == GPU_MAT_OPTIMIZATION_READY) { + /* Reset creation timer to delay optimization pass. */ + mat->creation_time = PIL_check_seconds_timer(); + } +} + +bool GPU_material_optimization_ready(GPUMaterial *mat) +{ + /* Timer threshold before optimizations will be queued. + * When materials are frequently being modified, optimization + * can incur CPU overhead from excessive compilation. + * + * As the optimization is entirely asynchronous, it is still beneficial + * to do this quickly to avoid build-up and improve runtime performance. + * The threshold just prevents compilations being queued frame after frame. */ + const double optimization_time_threshold_s = 1.2; + return ((PIL_check_seconds_timer() - mat->creation_time) >= optimization_time_threshold_s); +} + +void GPU_material_set_default(GPUMaterial *material, GPUMaterial *default_material) +{ + if (material != default_material) { + material->default_mat = default_material; + } +} + /* Code generation */ bool GPU_material_has_surface_output(GPUMaterial *mat) @@ -730,6 +824,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, mat->uuid = shader_uuid; mat->flag = GPU_MATFLAG_UPDATED; mat->status = GPU_MAT_CREATED; + mat->default_mat = NULL; mat->is_volume_shader = is_volume_shader; mat->graph.used_libraries = BLI_gset_new( BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUNodeGraph.used_libraries"); @@ -748,7 +843,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, { /* Create source code and search pass cache for an already compiled version. */ - mat->pass = GPU_generate_pass(mat, &mat->graph, callback, thunk); + mat->pass = GPU_generate_pass(mat, &mat->graph, callback, thunk, false); if (mat->pass == NULL) { /* We had a cache hit and the shader has already failed to compile. */ @@ -756,11 +851,44 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, gpu_node_graph_free(&mat->graph); } else { + /* Determine whether we should generate an optimized variant of the graph. + * Heuristic is based on complexity of default material pass and shader node graph. */ + if (GPU_pass_should_optimize(mat->pass)) { + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_READY); + } + GPUShader *sh = GPU_pass_shader_get(mat->pass); if (sh != NULL) { /* We had a cache hit and the shader is already compiled. */ mat->status = GPU_MAT_SUCCESS; - gpu_node_graph_free_nodes(&mat->graph); + + if (mat->optimization_status == GPU_MAT_OPTIMIZATION_SKIP) { + gpu_node_graph_free_nodes(&mat->graph); + } + } + + /* Generate optimized pass. */ + if (mat->optimization_status == GPU_MAT_OPTIMIZATION_READY) { +#if ASYNC_OPTIMIZED_PASS_CREATION == 1 + mat->optimized_pass = NULL; + mat->optimize_pass_info.callback = callback; + mat->optimize_pass_info.thunk = thunk; +#else + mat->optimized_pass = GPU_generate_pass(mat, &mat->graph, callback, thunk, true); + if (mat->optimized_pass == NULL) { + /* Failed to create optimized pass. */ + gpu_node_graph_free_nodes(&mat->graph); + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SKIP); + } + else { + GPUShader *optimized_sh = GPU_pass_shader_get(mat->optimized_pass); + if (optimized_sh != NULL) { + /* Optimized shader already available. */ + gpu_node_graph_free_nodes(&mat->graph); + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SUCCESS); + } + } +#endif } } } @@ -810,8 +938,37 @@ void GPU_material_compile(GPUMaterial *mat) if (success) { GPUShader *sh = GPU_pass_shader_get(mat->pass); if (sh != NULL) { + + /** Perform async Render Pipeline State Object (PSO) compilation. + * + * Warm PSO cache within async compilation thread using default material as source. + * GPU_shader_warm_cache(..) performs the API-specific PSO compilation using the assigned + * parent shader's cached PSO descriptors as an input. + * + * This is only applied if the given material has a specified default reference + * material available, and the default material is already compiled. + * + * As PSOs do not always match for default shaders, we limit warming for PSO + * configurations to ensure compile time remains fast, as these first + * entries will be the most commonly used PSOs. As not all PSOs are necessarily + * required immediately, this limit should remain low (1-3 at most). + * */ + if (mat->default_mat != NULL && mat->default_mat != mat) { + if (mat->default_mat->pass != NULL) { + GPUShader *parent_sh = GPU_pass_shader_get(mat->default_mat->pass); + if (parent_sh) { + GPU_shader_set_parent(sh, parent_sh); + GPU_shader_warm_cache(sh, 1); + } + } + } + + /* Flag success. */ mat->status = GPU_MAT_SUCCESS; - gpu_node_graph_free_nodes(&mat->graph); + if (mat->optimization_status == GPU_MAT_OPTIMIZATION_SKIP) { + /* Only free node graph nodes if not required by secondary optimization pass. */ + gpu_node_graph_free_nodes(&mat->graph); + } } else { mat->status = GPU_MAT_FAILED; @@ -825,6 +982,89 @@ void GPU_material_compile(GPUMaterial *mat) } } +void GPU_material_optimize(GPUMaterial *mat) +{ + /* If shader is flagged for skipping optimization or has already been successfully + * optimized, skip. */ + if (ELEM(mat->optimization_status, GPU_MAT_OPTIMIZATION_SKIP, GPU_MAT_OPTIMIZATION_SUCCESS)) { + return; + } + + /* If original shader has not been fully compiled, we are not + * ready to perform optimization. */ + if (mat->status != GPU_MAT_SUCCESS) { + /* Reset optimization status. */ + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_READY); + return; + } + +#if ASYNC_OPTIMIZED_PASS_CREATION == 1 + /* If the optimized pass is not valid, first generate optimized pass. + * NOTE(Threading): Need to verify if GPU_generate_pass can cause side-effects, especially when + * used with "thunk". So far, this appears to work, and deferring optimized pass creation is more + * optimal, as these do not benefit from caching, due to baked constants. However, this could + * possibly be cause for concern for certain cases. */ + if (!mat->optimized_pass) { + mat->optimized_pass = GPU_generate_pass( + mat, &mat->graph, mat->optimize_pass_info.callback, mat->optimize_pass_info.thunk, true); + BLI_assert(mat->optimized_pass); + } +#else + if (!mat->optimized_pass) { + /* Optimized pass has not been created, skip future optimization attempts. */ + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SKIP); + return; + } +#endif + + bool success; + /* NOTE: The shader may have already been compiled here since we are + * sharing GPUShader across GPUMaterials. In this case it's a no-op. */ +#ifndef NDEBUG + success = GPU_pass_compile(mat->optimized_pass, mat->name); +#else + success = GPU_pass_compile(mat->optimized_pass, __func__); +#endif + + if (success) { + GPUShader *sh = GPU_pass_shader_get(mat->optimized_pass); + if (sh != NULL) { + /** Perform async Render Pipeline State Object (PSO) compilation. + * + * Warm PSO cache within async compilation thread for optimized materials. + * This setup assigns the original unoptimized shader as a "parent" shader + * for the optimized version. This then allows the associated GPU backend to + * compile PSOs within this asynchronous pass, using the identical PSO descriptors of the + * parent shader. + * + * This eliminates all run-time stuttering associated with material optimization and ensures + * realtime material editing and animation remains seamless, while retaining optimal realtime + * performance. */ + GPUShader *parent_sh = GPU_pass_shader_get(mat->pass); + if (parent_sh) { + GPU_shader_set_parent(sh, parent_sh); + GPU_shader_warm_cache(sh, -1); + } + + /* Mark as complete. */ + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SUCCESS); + } + else { + /* Optimized pass failed to compile. Disable any future optimization attempts. */ + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SKIP); + } + } + else { + /* Optimization pass generation failed. Disable future attempts to optimize. */ + GPU_pass_release(mat->optimized_pass); + mat->optimized_pass = NULL; + GPU_material_optimization_status_set(mat, GPU_MAT_OPTIMIZATION_SKIP); + } + + /* Release node graph as no longer needed. */ + gpu_node_graph_free_nodes(&mat->graph); +} + void GPU_materials_free(Main *bmain) { LISTBASE_FOREACH (Material *, ma, &bmain->materials) { @@ -835,7 +1075,6 @@ void GPU_materials_free(Main *bmain) GPU_material_free(&wo->gpumaterial); } - // BKE_world_defaults_free_gpu(); BKE_material_defaults_free_gpu(); } @@ -848,6 +1087,9 @@ GPUMaterial *GPU_material_from_callbacks(ConstructGPUMaterialFn construct_functi material->graph.used_libraries = BLI_gset_new( BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUNodeGraph.used_libraries"); material->refcount = 1; + material->optimization_status = GPU_MAT_OPTIMIZATION_SKIP; + material->optimized_pass = NULL; + material->default_mat = NULL; /* Construct the material graph by adding and linking the necessary GPU material nodes. */ construct_function_cb(thunk, material); @@ -856,7 +1098,9 @@ GPUMaterial *GPU_material_from_callbacks(ConstructGPUMaterialFn construct_functi gpu_material_ramp_texture_build(material); /* Lookup an existing pass in the cache or generate a new one. */ - material->pass = GPU_generate_pass(material, &material->graph, generate_code_function_cb, thunk); + material->pass = GPU_generate_pass( + material, &material->graph, generate_code_function_cb, thunk, false); + material->optimized_pass = NULL; /* The pass already exists in the pass cache but its shader already failed to compile. */ if (material->pass == NULL) { @@ -869,7 +1113,10 @@ GPUMaterial *GPU_material_from_callbacks(ConstructGPUMaterialFn construct_functi GPUShader *shader = GPU_pass_shader_get(material->pass); if (shader != NULL) { material->status = GPU_MAT_SUCCESS; - gpu_node_graph_free_nodes(&material->graph); + if (material->optimization_status == GPU_MAT_OPTIMIZATION_SKIP) { + /* Only free node graph if not required by secondary optimization pass. */ + gpu_node_graph_free_nodes(&material->graph); + } return material; } diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc index b46860cf0f48..d285ff5ef990 100644 --- a/source/blender/gpu/intern/gpu_matrix.cc +++ b/source/blender/gpu/intern/gpu_matrix.cc @@ -623,30 +623,31 @@ void GPU_matrix_bind(GPUShader *shader) int32_t P_inv = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV); if (MV != -1) { - GPU_shader_uniform_vector( + GPU_shader_uniform_float_ex( shader, MV, 16, 1, (const float *)GPU_matrix_model_view_get(nullptr)); } if (P != -1) { - GPU_shader_uniform_vector(shader, P, 16, 1, (const float *)GPU_matrix_projection_get(nullptr)); + GPU_shader_uniform_float_ex( + shader, P, 16, 1, (const float *)GPU_matrix_projection_get(nullptr)); } if (MVP != -1) { - GPU_shader_uniform_vector( + GPU_shader_uniform_float_ex( shader, MVP, 16, 1, (const float *)GPU_matrix_model_view_projection_get(nullptr)); } if (N != -1) { - GPU_shader_uniform_vector(shader, N, 9, 1, (const float *)GPU_matrix_normal_get(nullptr)); + GPU_shader_uniform_float_ex(shader, N, 9, 1, (const float *)GPU_matrix_normal_get(nullptr)); } if (MV_inv != -1) { Mat4 m; GPU_matrix_model_view_get(m); invert_m4(m); - GPU_shader_uniform_vector(shader, MV_inv, 16, 1, (const float *)m); + GPU_shader_uniform_float_ex(shader, MV_inv, 16, 1, (const float *)m); } if (P_inv != -1) { Mat4 m; GPU_matrix_projection_get(m); invert_m4(m); - GPU_shader_uniform_vector(shader, P_inv, 16, 1, (const float *)m); + GPU_shader_uniform_float_ex(shader, P_inv, 16, 1, (const float *)m); } gpu_matrix_state_active_set_dirty(false); diff --git a/source/blender/gpu/intern/gpu_node_graph.cc b/source/blender/gpu/intern/gpu_node_graph.cc index 8f51a6b91aa0..a00f621d106c 100644 --- a/source/blender/gpu/intern/gpu_node_graph.cc +++ b/source/blender/gpu/intern/gpu_node_graph.cc @@ -149,7 +149,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType case GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN: input->source = GPU_SOURCE_FUNCTION_CALL; /* NOTE(@fclem): End of function call is the return variable set during codegen. */ - SNPRINTF(input->function_call, "dF_branch(%s(), ", link->function_name); + SNPRINTF(input->function_call, "dF_branch_incomplete(%s(), ", link->function_name); break; default: break; @@ -983,3 +983,22 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph) } } } + +void gpu_node_graph_optimize(GPUNodeGraph *graph) +{ + /* Replace all uniform node links with constant. */ + LISTBASE_FOREACH (GPUNode *, node, &graph->nodes) { + LISTBASE_FOREACH (GPUInput *, input, &node->inputs) { + if (input->link) { + if (input->link->link_type == GPU_NODE_LINK_UNIFORM) { + input->link->link_type = GPU_NODE_LINK_CONSTANT; + } + } + if (input->source == GPU_SOURCE_UNIFORM) { + input->source = (input->type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT; + } + } + } + + /* TODO: Consider performing other node graph optimizations here. */ +} diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h index 6e3f71744e73..4ac1f4a7ec9c 100644 --- a/source/blender/gpu/intern/gpu_node_graph.h +++ b/source/blender/gpu/intern/gpu_node_graph.h @@ -190,6 +190,19 @@ void gpu_nodes_tag(GPUNodeLink *link, eGPUNodeTag tag); void gpu_node_graph_prune_unused(GPUNodeGraph *graph); void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph); +/** + * Optimize node graph for optimized material shader path. + * Once the base material has been generated, we can modify the shader + * node graph to create one which will produce an optimally performing shader. + * This currently involves baking uniform data into constant data to enable + * aggressive constant folding by the compiler in order to reduce complexity and + * shader core memory pressure. + * + * NOTE: Graph optimizations will produce a shader which needs to be re-compiled + * more frequently, however, the default material pass will always exist to fall + * back on. */ +void gpu_node_graph_optimize(GPUNodeGraph *graph); + /** * Free intermediate node graph. */ diff --git a/source/blender/gpu/intern/gpu_select_sample_query.cc b/source/blender/gpu/intern/gpu_select_sample_query.cc index 7393dfd0d816..0912e0a3b20d 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.cc +++ b/source/blender/gpu/intern/gpu_select_sample_query.cc @@ -79,7 +79,7 @@ void gpu_select_query_begin(GPUSelectResult *buffer, GPU_scissor_get(g_query_state.scissor); GPU_viewport_size_get_i(g_query_state.viewport); - /* Write to color buffer. Seems to fix issues with selecting alpha blended geom (see T7997). */ + /* Write to color buffer. Seems to fix issues with selecting alpha blended geom (see #7997). */ GPU_color_mask(true, true, true, true); /* In order to save some fill rate we minimize the viewport using rect. @@ -98,7 +98,7 @@ void gpu_select_query_begin(GPUSelectResult *buffer, * objects in the view frustum independently of their order, we need to disable the depth test */ if (mode == GPU_SELECT_ALL) { /* #glQueries on Windows+Intel drivers only works with depth testing turned on. - * See T62947 for details */ + * See #62947 for details */ GPU_depth_test(GPU_DEPTH_ALWAYS); GPU_depth_mask(true); } diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index 0653ae11a0ae..eac38adaed90 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -46,8 +46,6 @@ std::string Shader::defines_declare(const shader::ShaderCreateInfo &info) const using namespace blender; using namespace blender::gpu; -static bool gpu_shader_srgb_uniform_dirty_get(); - /* -------------------------------------------------------------------- */ /** \name Creation / Destruction * \{ */ @@ -443,58 +441,6 @@ GPUShader *GPU_shader_create_from_python(const char *vertcode, return sh; } -static const char *string_join_array_maybe_alloc(const char **str_arr, bool *r_is_alloc) -{ - bool is_alloc = false; - if (str_arr == nullptr) { - *r_is_alloc = false; - return nullptr; - } - /* Skip empty strings (avoid alloc if we can). */ - while (str_arr[0] && str_arr[0][0] == '\0') { - str_arr++; - } - int i; - for (i = 0; str_arr[i]; i++) { - if (i != 0 && str_arr[i][0] != '\0') { - is_alloc = true; - } - } - *r_is_alloc = is_alloc; - if (is_alloc) { - return BLI_string_join_arrayN(str_arr, i); - } - - return str_arr[0]; -} - -struct GPUShader *GPU_shader_create_from_arrays_impl( - const struct GPU_ShaderCreateFromArray_Params *params, const char *func, int line) -{ - struct { - const char *str; - bool is_alloc; - } str_dst[4] = {{nullptr}}; - const char **str_src[4] = {params->vert, params->frag, params->geom, params->defs}; - - for (int i = 0; i < ARRAY_SIZE(str_src); i++) { - str_dst[i].str = string_join_array_maybe_alloc(str_src[i], &str_dst[i].is_alloc); - } - - char name[64]; - BLI_snprintf(name, sizeof(name), "%s_%d", func, line); - - GPUShader *sh = GPU_shader_create( - str_dst[0].str, str_dst[1].str, str_dst[2].str, nullptr, str_dst[3].str, name); - - for (auto &i : str_dst) { - if (i.is_alloc) { - MEM_freeN((void *)i.str); - } - } - return sh; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -511,11 +457,11 @@ void GPU_shader_bind(GPUShader *gpu_shader) ctx->shader = shader; shader->bind(); GPU_matrix_bind(gpu_shader); - GPU_shader_set_srgb_uniform(gpu_shader); + Shader::set_srgb_uniform(gpu_shader); } else { - if (gpu_shader_srgb_uniform_dirty_get()) { - GPU_shader_set_srgb_uniform(gpu_shader); + if (Shader::srgb_uniform_dirty_get()) { + Shader::set_srgb_uniform(gpu_shader); } if (GPU_matrix_dirty_get()) { GPU_matrix_bind(gpu_shader); @@ -554,6 +500,26 @@ const char *GPU_shader_get_name(GPUShader *shader) return unwrap(shader)->name_get(); } +/* -------------------------------------------------------------------- */ +/** \name Shader cache warming + * \{ */ + +void GPU_shader_set_parent(GPUShader *shader, GPUShader *parent) +{ + BLI_assert(shader != nullptr); + BLI_assert(shader != parent); + if (shader != parent) { + Shader *shd_child = unwrap(shader); + Shader *shd_parent = unwrap(parent); + shd_child->parent_set(shd_parent); + } +} + +void GPU_shader_warm_cache(GPUShader *shader, int limit) +{ + unwrap(shader)->warm_cache(limit); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -580,66 +546,60 @@ void GPU_shader_transform_feedback_disable(GPUShader *shader) int GPU_shader_get_uniform(GPUShader *shader, const char *name) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; const ShaderInput *uniform = interface->uniform_get(name); return uniform ? uniform->location : -1; } int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; return interface->uniform_builtin((GPUUniformBuiltin)builtin); } int GPU_shader_get_builtin_block(GPUShader *shader, int builtin) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; return interface->ubo_builtin((GPUUniformBlockBuiltin)builtin); } -int GPU_shader_get_builtin_ssbo(GPUShader *shader, int builtin) +int GPU_shader_get_ssbo_binding(GPUShader *shader, const char *name) { - ShaderInterface *interface = unwrap(shader)->interface; - return interface->ssbo_builtin((GPUStorageBufferBuiltin)builtin); -} - -int GPU_shader_get_ssbo(GPUShader *shader, const char *name) -{ - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; const ShaderInput *ssbo = interface->ssbo_get(name); return ssbo ? ssbo->location : -1; } int GPU_shader_get_uniform_block(GPUShader *shader, const char *name) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; const ShaderInput *ubo = interface->ubo_get(name); return ubo ? ubo->location : -1; } -int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name) +int GPU_shader_get_ubo_binding(GPUShader *shader, const char *name) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; const ShaderInput *ubo = interface->ubo_get(name); return ubo ? ubo->binding : -1; } -int GPU_shader_get_texture_binding(GPUShader *shader, const char *name) +int GPU_shader_get_sampler_binding(GPUShader *shader, const char *name) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; const ShaderInput *tex = interface->uniform_get(name); return tex ? tex->binding : -1; } uint GPU_shader_get_attribute_len(const GPUShader *shader) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; return interface->attr_len_; } -int GPU_shader_get_attribute(GPUShader *shader, const char *name) +int GPU_shader_get_attribute(const GPUShader *shader, const char *name) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; const ShaderInput *attr = interface->attr_get(name); return attr ? attr->location : -1; } @@ -649,7 +609,7 @@ bool GPU_shader_get_attribute_info(const GPUShader *shader, char r_name[256], int *r_type) { - ShaderInterface *interface = unwrap(shader)->interface; + const ShaderInterface *interface = unwrap(shader)->interface; const ShaderInput *attr = interface->attr_get(attr_location); if (!attr) { @@ -678,32 +638,22 @@ int GPU_shader_get_program(GPUShader *shader) /** \name Uniforms setters * \{ */ -void GPU_shader_uniform_vector( - GPUShader *shader, int loc, int len, int arraysize, const float *value) +void GPU_shader_uniform_float_ex( + GPUShader *shader, int loc, int len, int array_size, const float *value) { - unwrap(shader)->uniform_float(loc, len, arraysize, value); + unwrap(shader)->uniform_float(loc, len, array_size, value); } -void GPU_shader_uniform_vector_int( - GPUShader *shader, int loc, int len, int arraysize, const int *value) +void GPU_shader_uniform_int_ex( + GPUShader *shader, int loc, int len, int array_size, const int *value) { - unwrap(shader)->uniform_int(loc, len, arraysize, value); -} - -void GPU_shader_uniform_int(GPUShader *shader, int location, int value) -{ - GPU_shader_uniform_vector_int(shader, location, 1, 1, &value); -} - -void GPU_shader_uniform_float(GPUShader *shader, int location, float value) -{ - GPU_shader_uniform_vector(shader, location, 1, 1, &value); + unwrap(shader)->uniform_int(loc, len, array_size, value); } void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_int(sh, loc, value); + GPU_shader_uniform_int_ex(sh, loc, 1, 1, &value); } void GPU_shader_uniform_1b(GPUShader *sh, const char *name, bool value) @@ -732,37 +682,37 @@ void GPU_shader_uniform_4f(GPUShader *sh, const char *name, float x, float y, fl void GPU_shader_uniform_1f(GPUShader *sh, const char *name, float value) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_float(sh, loc, value); + GPU_shader_uniform_float_ex(sh, loc, 1, 1, &value); } void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2]) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_vector(sh, loc, 2, 1, data); + GPU_shader_uniform_float_ex(sh, loc, 2, 1, data); } void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3]) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_vector(sh, loc, 3, 1, data); + GPU_shader_uniform_float_ex(sh, loc, 3, 1, data); } void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4]) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_vector(sh, loc, 4, 1, data); + GPU_shader_uniform_float_ex(sh, loc, 4, 1, data); } void GPU_shader_uniform_2iv(GPUShader *sh, const char *name, const int data[2]) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_vector_int(sh, loc, 2, 1, data); + GPU_shader_uniform_int_ex(sh, loc, 2, 1, data); } void GPU_shader_uniform_mat4(GPUShader *sh, const char *name, const float data[4][4]) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_vector(sh, loc, 16, 1, (const float *)data); + GPU_shader_uniform_float_ex(sh, loc, 16, 1, (const float *)data); } void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const float data[3][3]) @@ -775,13 +725,13 @@ void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const floa void GPU_shader_uniform_2fv_array(GPUShader *sh, const char *name, int len, const float (*val)[2]) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_vector(sh, loc, 2, len, (const float *)val); + GPU_shader_uniform_float_ex(sh, loc, 2, len, (const float *)val); } void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, const float (*val)[4]) { const int loc = GPU_shader_get_uniform(sh, name); - GPU_shader_uniform_vector(sh, loc, 4, len, (const float *)val); + GPU_shader_uniform_float_ex(sh, loc, 4, len, (const float *)val); } /** \} */ @@ -797,24 +747,26 @@ void GPU_shader_uniform_4fv_array(GPUShader *sh, const char *name, int len, cons * frame-buffer color-space. * \{ */ +namespace blender::gpu { + static int g_shader_builtin_srgb_transform = 0; static bool g_shader_builtin_srgb_is_dirty = false; -static bool gpu_shader_srgb_uniform_dirty_get() +bool Shader::srgb_uniform_dirty_get() { return g_shader_builtin_srgb_is_dirty; } -void GPU_shader_set_srgb_uniform(GPUShader *shader) +void Shader::set_srgb_uniform(GPUShader *shader) { int32_t loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_SRGB_TRANSFORM); if (loc != -1) { - GPU_shader_uniform_vector_int(shader, loc, 1, 1, &g_shader_builtin_srgb_transform); + GPU_shader_uniform_int_ex(shader, loc, 1, 1, &g_shader_builtin_srgb_transform); } g_shader_builtin_srgb_is_dirty = false; } -void GPU_shader_set_framebuffer_srgb_target(int use_srgb_to_linear) +void Shader::set_framebuffer_srgb_target(int use_srgb_to_linear) { if (g_shader_builtin_srgb_transform != use_srgb_to_linear) { g_shader_builtin_srgb_transform = use_srgb_to_linear; @@ -822,4 +774,6 @@ void GPU_shader_set_framebuffer_srgb_target(int use_srgb_to_linear) } } +} // namespace blender::gpu + /** \} */ diff --git a/source/blender/gpu/intern/gpu_shader_builtin.c b/source/blender/gpu/intern/gpu_shader_builtin.c deleted file mode 100644 index 470643ba8638..000000000000 --- a/source/blender/gpu/intern/gpu_shader_builtin.c +++ /dev/null @@ -1,404 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later - * Copyright 2005 Blender Foundation. All rights reserved. */ - -/** \file - * \ingroup gpu - */ - -#include "BLI_utildefines.h" - -#include "GPU_shader.h" - -/* Adjust these constants as needed. */ -#define MAX_DEFINE_LENGTH 256 -#define MAX_EXT_DEFINE_LENGTH 512 - -/* Non-generated shaders */ -extern char datatoc_gpu_shader_depth_only_frag_glsl[]; -extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; -extern char datatoc_gpu_shader_checker_frag_glsl[]; -extern char datatoc_gpu_shader_diag_stripes_frag_glsl[]; -extern char datatoc_gpu_shader_simple_lighting_frag_glsl[]; -extern char datatoc_gpu_shader_flat_color_frag_glsl[]; -extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[]; -extern char datatoc_gpu_shader_flat_id_frag_glsl[]; -extern char datatoc_gpu_shader_2D_area_borders_vert_glsl[]; -extern char datatoc_gpu_shader_2D_area_borders_frag_glsl[]; -extern char datatoc_gpu_shader_2D_vert_glsl[]; -extern char datatoc_gpu_shader_2D_smooth_color_uniform_alpha_vert_glsl[]; -extern char datatoc_gpu_shader_2D_image_vert_glsl[]; -extern char datatoc_gpu_shader_2D_image_rect_vert_glsl[]; -extern char datatoc_gpu_shader_2D_image_multi_rect_vert_glsl[]; -extern char datatoc_gpu_shader_2D_widget_base_vert_glsl[]; -extern char datatoc_gpu_shader_2D_widget_base_frag_glsl[]; -extern char datatoc_gpu_shader_2D_widget_shadow_vert_glsl[]; -extern char datatoc_gpu_shader_2D_widget_shadow_frag_glsl[]; -extern char datatoc_gpu_shader_2D_nodelink_frag_glsl[]; -extern char datatoc_gpu_shader_2D_nodelink_vert_glsl[]; - -extern char datatoc_gpu_shader_3D_image_vert_glsl[]; -extern char datatoc_gpu_shader_image_frag_glsl[]; -extern char datatoc_gpu_shader_image_overlays_merge_frag_glsl[]; -extern char datatoc_gpu_shader_image_overlays_stereo_merge_frag_glsl[]; -extern char datatoc_gpu_shader_image_color_frag_glsl[]; -extern char datatoc_gpu_shader_image_desaturate_frag_glsl[]; -extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[]; -extern char datatoc_gpu_shader_image_varying_color_frag_glsl[]; -extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[]; -extern char datatoc_gpu_shader_3D_vert_glsl[]; -extern char datatoc_gpu_shader_3D_normal_vert_glsl[]; -extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[]; -extern char datatoc_gpu_shader_3D_polyline_frag_glsl[]; -extern char datatoc_gpu_shader_3D_polyline_geom_glsl[]; -extern char datatoc_gpu_shader_3D_polyline_vert_glsl[]; -extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[]; -extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; -extern char datatoc_gpu_shader_3D_passthrough_vert_glsl[]; -extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[]; - -extern char datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl[]; - -extern char datatoc_gpu_shader_point_uniform_color_aa_frag_glsl[]; -extern char datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl[]; -extern char datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl[]; -extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; -extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[]; -extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[]; -extern char datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl[]; -extern char datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl[]; -extern char datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl[]; - -extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[]; -extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[]; -extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl[]; - -extern char datatoc_gpu_shader_text_vert_glsl[]; -extern char datatoc_gpu_shader_text_frag_glsl[]; -extern char datatoc_gpu_shader_keyframe_shape_vert_glsl[]; -extern char datatoc_gpu_shader_keyframe_shape_frag_glsl[]; - -extern char datatoc_gpu_shader_gpencil_stroke_vert_glsl[]; -extern char datatoc_gpu_shader_gpencil_stroke_frag_glsl[]; -extern char datatoc_gpu_shader_gpencil_stroke_geom_glsl[]; - -extern char datatoc_gpu_shader_cfg_world_clip_lib_glsl[]; - -extern char datatoc_gpu_shader_colorspace_lib_glsl[]; - -const struct GPUShaderConfigData GPU_shader_cfg_data[GPU_SHADER_CFG_LEN] = { - [GPU_SHADER_CFG_DEFAULT] = - { - .lib = "", - .def = "#define blender_srgb_to_framebuffer_space(a) a\n", - }, - [GPU_SHADER_CFG_CLIPPED] = - { - .lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl, - .def = "#define USE_WORLD_CLIP_PLANES\n" - "#define blender_srgb_to_framebuffer_space(a) a\n", - }, -}; - -/* cache of built-in shaders (each is created on first use) */ -static GPUShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = {{NULL}}; - -typedef struct { - const char *name; - const char *vert; - /** Optional. */ - const char *geom; - const char *frag; - /** Optional. */ - const char *defs; - - const char *create_info; - const char *clipped_create_info; -} GPUShaderStages; - -static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { - [GPU_SHADER_TEXT] = - { - .name = "GPU_SHADER_TEXT", - .create_info = "gpu_shader_text", - }, - [GPU_SHADER_KEYFRAME_SHAPE] = - { - .name = "GPU_SHADER_KEYFRAME_SHAPE", - .create_info = "gpu_shader_keyframe_shape", - }, - [GPU_SHADER_SIMPLE_LIGHTING] = - { - .name = "GPU_SHADER_SIMPLE_LIGHTING", - .create_info = "gpu_shader_simple_lighting", - }, - [GPU_SHADER_3D_IMAGE] = - { - .name = "GPU_SHADER_3D_IMAGE", - .create_info = "gpu_shader_3D_image", - }, - [GPU_SHADER_3D_IMAGE_COLOR] = - { - .name = "GPU_SHADER_3D_IMAGE_COLOR", - .create_info = "gpu_shader_3D_image_color", - }, - [GPU_SHADER_2D_CHECKER] = - { - .name = "GPU_SHADER_2D_CHECKER", - .create_info = "gpu_shader_2D_checker", - }, - - [GPU_SHADER_2D_DIAG_STRIPES] = - { - .name = "GPU_SHADER_2D_DIAG_STRIPES", - .create_info = "gpu_shader_2D_diag_stripes", - }, - - [GPU_SHADER_ICON] = - { - .name = "GPU_SHADER_ICON", - .create_info = "gpu_shader_icon", - }, - [GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] = - { - .name = "GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE", - .create_info = "gpu_shader_2D_image_overlays_merge", - }, - [GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE] = - { - .name = "GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE", - .create_info = "gpu_shader_2D_image_overlays_stereo_merge", - }, - [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] = - { - .name = "GPU_SHADER_2D_IMAGE_DESATURATE_COLOR", - .create_info = "gpu_shader_2D_image_desaturate_color", - }, - [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = - { - .name = "GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR", - .create_info = "gpu_shader_2D_image_shuffle_color", - }, - [GPU_SHADER_2D_IMAGE_RECT_COLOR] = - { - .name = "GPU_SHADER_2D_IMAGE_RECT_COLOR", - .create_info = "gpu_shader_2D_image_rect_color", - }, - [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = - { - .name = "GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR", - .create_info = "gpu_shader_2D_image_multi_rect_color", - }, - - [GPU_SHADER_3D_UNIFORM_COLOR] = - { - .name = "GPU_SHADER_3D_UNIFORM_COLOR", - .create_info = "gpu_shader_3D_uniform_color", - .clipped_create_info = "gpu_shader_3D_uniform_color_clipped", - }, - [GPU_SHADER_3D_FLAT_COLOR] = - { - .name = "GPU_SHADER_3D_FLAT_COLOR", - .create_info = "gpu_shader_3D_flat_color", - .clipped_create_info = "gpu_shader_3D_flat_color_clipped", - }, - [GPU_SHADER_3D_SMOOTH_COLOR] = - { - .name = "GPU_SHADER_3D_SMOOTH_COLOR", - .create_info = "gpu_shader_3D_smooth_color", - .clipped_create_info = "gpu_shader_3D_smooth_color_clipped", - }, - [GPU_SHADER_3D_DEPTH_ONLY] = - { - .name = "GPU_SHADER_3D_DEPTH_ONLY", - .create_info = "gpu_shader_3D_depth_only", - .clipped_create_info = "gpu_shader_3D_depth_only_clipped", - }, - [GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = - { - .name = "GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR", - .create_info = "gpu_shader_3D_clipped_uniform_color", - }, - - [GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR] = - { - .name = "GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR", - .create_info = "gpu_shader_3D_polyline_uniform_color", - }, - [GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR] = - { - .name = "GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR", - .create_info = "gpu_shader_3D_polyline_uniform_color_clipped", - }, - [GPU_SHADER_3D_POLYLINE_FLAT_COLOR] = - { - .name = "GPU_SHADER_3D_POLYLINE_FLAT_COLOR", - .create_info = "gpu_shader_3D_polyline_flat_color", - }, - [GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR] = - { - .name = "GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR", - .create_info = "gpu_shader_3D_polyline_smooth_color", - }, - - [GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR] = - { - .name = "GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR", - .create_info = "gpu_shader_3D_line_dashed_uniform_color", - .clipped_create_info = "gpu_shader_3D_line_dashed_uniform_color_clipped", - }, - - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = - { - .name = "GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA", - .create_info = "gpu_shader_2D_point_uniform_size_uniform_color_aa", - }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = - { - .name = "GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA", - .create_info = "gpu_shader_2D_point_uniform_size_uniform_color_outline_aa", - }, - [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = - { - .name = "GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR", - .create_info = "gpu_shader_3D_point_fixed_size_varying_color", - }, - [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] = - { - .name = "GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR", - .create_info = "gpu_shader_3D_point_varying_size_varying_color", - }, - [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = - { - .name = "GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA", - .create_info = "gpu_shader_3D_point_uniform_size_uniform_color_aa", - .clipped_create_info = "gpu_shader_3D_point_uniform_size_uniform_color_aa_clipped", - }, - - [GPU_SHADER_2D_AREA_BORDERS] = - { - .name = "GPU_SHADER_2D_AREA_BORDERS", - .create_info = "gpu_shader_2D_area_borders", - }, - [GPU_SHADER_2D_WIDGET_BASE] = - { - .name = "GPU_SHADER_2D_WIDGET_BASE", - .create_info = "gpu_shader_2D_widget_base", - }, - [GPU_SHADER_2D_WIDGET_BASE_INST] = - { - .name = "GPU_SHADER_2D_WIDGET_BASE_INST", - .defs = "#define USE_INSTANCE\n", - .create_info = "gpu_shader_2D_widget_base_inst", - }, - [GPU_SHADER_2D_WIDGET_SHADOW] = - { - .name = "GPU_SHADER_2D_WIDGET_SHADOW", - .create_info = "gpu_shader_2D_widget_shadow", - }, - [GPU_SHADER_2D_NODELINK] = - { - .name = "GPU_SHADER_2D_NODELINK", - .create_info = "gpu_shader_2D_nodelink", - }, - - [GPU_SHADER_2D_NODELINK_INST] = - { - .name = "GPU_SHADER_2D_NODELINK_INST", - .create_info = "gpu_shader_2D_nodelink_inst", - }, - - [GPU_SHADER_GPENCIL_STROKE] = - { - .name = "GPU_SHADER_GPENCIL_STROKE", - .create_info = "gpu_shader_gpencil_stroke", - }, -}; - -GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, - eGPUShaderConfig sh_cfg) -{ - BLI_assert(shader < GPU_SHADER_BUILTIN_LEN); - BLI_assert(sh_cfg < GPU_SHADER_CFG_LEN); - GPUShader **sh_p = &builtin_shaders[sh_cfg][shader]; - - if (*sh_p == NULL) { - const GPUShaderStages *stages = &builtin_shader_stages[shader]; - - /* common case */ - if (sh_cfg == GPU_SHADER_CFG_DEFAULT) { - if (stages->create_info != NULL) { - *sh_p = GPU_shader_create_from_info_name(stages->create_info); - if (ELEM(shader, - GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR, - GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, - GPU_SHADER_3D_POLYLINE_FLAT_COLOR, - GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR)) { - /* Set a default value for `lineSmooth`. - * Ideally this value should be set by the caller. */ - GPU_shader_bind(*sh_p); - GPU_shader_uniform_1i(*sh_p, "lineSmooth", 1); - } - } - else { - *sh_p = GPU_shader_create_from_arrays_named( - stages->name, - { - .vert = (const char *[]){stages->vert, NULL}, - .geom = (const char *[]){stages->geom, NULL}, - .frag = - (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL}, - .defs = (const char *[]){stages->defs, NULL}, - }); - } - } - else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - /* Remove eventually, for now ensure support for each shader has been added. */ - BLI_assert(ELEM(shader, - GPU_SHADER_3D_UNIFORM_COLOR, - GPU_SHADER_3D_SMOOTH_COLOR, - GPU_SHADER_3D_DEPTH_ONLY, - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, - GPU_SHADER_3D_FLAT_COLOR, - GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR)); - /* In rare cases geometry shaders calculate clipping themselves. */ - if (stages->clipped_create_info != NULL) { - *sh_p = GPU_shader_create_from_info_name(stages->clipped_create_info); - } - else { - const char *world_clip_lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl; - const char *world_clip_def = "#define USE_WORLD_CLIP_PLANES\n"; - *sh_p = GPU_shader_create_from_arrays_named( - stages->name, - { - .vert = (const char *[]){world_clip_lib, stages->vert, NULL}, - .geom = (const char *[]){stages->geom ? world_clip_lib : NULL, stages->geom, NULL}, - .frag = - (const char *[]){datatoc_gpu_shader_colorspace_lib_glsl, stages->frag, NULL}, - .defs = (const char *[]){world_clip_def, stages->defs, NULL}, - }); - } - } - else { - BLI_assert(0); - } - } - - return *sh_p; -} - -GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader) -{ - return GPU_shader_get_builtin_shader_with_config(shader, GPU_SHADER_CFG_DEFAULT); -} - -void GPU_shader_free_builtin_shaders(void) -{ - for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) { - for (int j = 0; j < GPU_SHADER_BUILTIN_LEN; j++) { - if (builtin_shaders[i][j]) { - GPU_shader_free(builtin_shaders[i][j]); - builtin_shaders[i][j] = NULL; - } - } - } -} diff --git a/source/blender/gpu/intern/gpu_shader_builtin.cc b/source/blender/gpu/intern/gpu_shader_builtin.cc new file mode 100644 index 000000000000..2a15e6d823d8 --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_builtin.cc @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2005 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "BLI_utildefines.h" + +#include "GPU_shader.h" + +/* Cache of built-in shaders (each is created on first use). */ +static GPUShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = {{nullptr}}; + +static const char *builtin_shader_create_info_name(eGPUBuiltinShader shader) +{ + switch (shader) { + case GPU_SHADER_TEXT: + return "gpu_shader_text"; + case GPU_SHADER_KEYFRAME_SHAPE: + return "gpu_shader_keyframe_shape"; + case GPU_SHADER_SIMPLE_LIGHTING: + return "gpu_shader_simple_lighting"; + case GPU_SHADER_3D_IMAGE: + return "gpu_shader_3D_image"; + case GPU_SHADER_3D_IMAGE_COLOR: + return "gpu_shader_3D_image_color"; + case GPU_SHADER_2D_CHECKER: + return "gpu_shader_2D_checker"; + case GPU_SHADER_2D_DIAG_STRIPES: + return "gpu_shader_2D_diag_stripes"; + case GPU_SHADER_ICON: + return "gpu_shader_icon"; + case GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE: + return "gpu_shader_2D_image_overlays_merge"; + case GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE: + return "gpu_shader_2D_image_overlays_stereo_merge"; + case GPU_SHADER_2D_IMAGE_DESATURATE_COLOR: + return "gpu_shader_2D_image_desaturate_color"; + case GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR: + return "gpu_shader_2D_image_shuffle_color"; + case GPU_SHADER_2D_IMAGE_RECT_COLOR: + return "gpu_shader_2D_image_rect_color"; + case GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR: + return "gpu_shader_2D_image_multi_rect_color"; + case GPU_SHADER_3D_UNIFORM_COLOR: + return "gpu_shader_3D_uniform_color"; + case GPU_SHADER_3D_FLAT_COLOR: + return "gpu_shader_3D_flat_color"; + case GPU_SHADER_3D_SMOOTH_COLOR: + return "gpu_shader_3D_smooth_color"; + case GPU_SHADER_3D_DEPTH_ONLY: + return "gpu_shader_3D_depth_only"; + case GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR: + return "gpu_shader_3D_clipped_uniform_color"; + case GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR: + return "gpu_shader_3D_polyline_uniform_color"; + case GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR: + return "gpu_shader_3D_polyline_uniform_color_clipped"; + case GPU_SHADER_3D_POLYLINE_FLAT_COLOR: + return "gpu_shader_3D_polyline_flat_color"; + case GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR: + return "gpu_shader_3D_polyline_smooth_color"; + case GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR: + return "gpu_shader_3D_line_dashed_uniform_color"; + case GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA: + return "gpu_shader_2D_point_uniform_size_uniform_color_aa"; + case GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA: + return "gpu_shader_2D_point_uniform_size_uniform_color_outline_aa"; + case GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR: + return "gpu_shader_3D_point_varying_size_varying_color"; + case GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA: + return "gpu_shader_3D_point_uniform_size_uniform_color_aa"; + case GPU_SHADER_2D_AREA_BORDERS: + return "gpu_shader_2D_area_borders"; + case GPU_SHADER_2D_WIDGET_BASE: + return "gpu_shader_2D_widget_base"; + case GPU_SHADER_2D_WIDGET_BASE_INST: + return "gpu_shader_2D_widget_base_inst"; + case GPU_SHADER_2D_WIDGET_SHADOW: + return "gpu_shader_2D_widget_shadow"; + case GPU_SHADER_2D_NODELINK: + return "gpu_shader_2D_nodelink"; + case GPU_SHADER_2D_NODELINK_INST: + return "gpu_shader_2D_nodelink_inst"; + case GPU_SHADER_GPENCIL_STROKE: + return "gpu_shader_gpencil_stroke"; + default: + BLI_assert_unreachable(); + return ""; + } +} + +static const char *builtin_shader_create_info_name_clipped(eGPUBuiltinShader shader) +{ + switch (shader) { + case GPU_SHADER_3D_UNIFORM_COLOR: + return "gpu_shader_3D_uniform_color_clipped"; + case GPU_SHADER_3D_FLAT_COLOR: + return "gpu_shader_3D_flat_color_clipped"; + case GPU_SHADER_3D_SMOOTH_COLOR: + return "gpu_shader_3D_smooth_color_clipped"; + case GPU_SHADER_3D_DEPTH_ONLY: + return "gpu_shader_3D_depth_only_clipped"; + case GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR: + return "gpu_shader_3D_line_dashed_uniform_color_clipped"; + case GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA: + return "gpu_shader_3D_point_uniform_size_uniform_color_aa_clipped"; + default: + BLI_assert_unreachable(); + return ""; + } +} + +GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, + eGPUShaderConfig sh_cfg) +{ + BLI_assert(shader < GPU_SHADER_BUILTIN_LEN); + BLI_assert(sh_cfg < GPU_SHADER_CFG_LEN); + GPUShader **sh_p = &builtin_shaders[sh_cfg][shader]; + + if (*sh_p == nullptr) { + if (sh_cfg == GPU_SHADER_CFG_DEFAULT) { + /* Common case. */ + *sh_p = GPU_shader_create_from_info_name(builtin_shader_create_info_name(shader)); + if (ELEM(shader, + GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR, + GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, + GPU_SHADER_3D_POLYLINE_FLAT_COLOR, + GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR)) { + /* Set a default value for `lineSmooth`. + * Ideally this value should be set by the caller. */ + GPU_shader_bind(*sh_p); + GPU_shader_uniform_1i(*sh_p, "lineSmooth", 1); + } + } + else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { + /* In rare cases geometry shaders calculate clipping themselves. */ + *sh_p = GPU_shader_create_from_info_name(builtin_shader_create_info_name_clipped(shader)); + } + else { + BLI_assert(0); + } + } + + return *sh_p; +} + +GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader) +{ + return GPU_shader_get_builtin_shader_with_config(shader, GPU_SHADER_CFG_DEFAULT); +} + +void GPU_shader_free_builtin_shaders(void) +{ + for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) { + for (int j = 0; j < GPU_SHADER_BUILTIN_LEN; j++) { + if (builtin_shaders[i][j]) { + GPU_shader_free(builtin_shaders[i][j]); + builtin_shaders[i][j] = nullptr; + } + } + } +} diff --git a/source/blender/gpu/intern/gpu_shader_dependency.cc b/source/blender/gpu/intern/gpu_shader_dependency.cc index 605ff585ff86..bfb8a22104e5 100644 --- a/source/blender/gpu/intern/gpu_shader_dependency.cc +++ b/source/blender/gpu/intern/gpu_shader_dependency.cc @@ -194,7 +194,7 @@ struct GPUSource { /** * Some drivers completely forbid quote characters even in unused preprocessor directives. * We fix the cases where we can't manually patch in `enum_preprocess()`. - * This check ensure none are present in non-patched sources. (see T97545) + * This check ensure none are present in non-patched sources. (see #97545) */ void check_no_quotes() { @@ -214,7 +214,7 @@ struct GPUSource { /** * Some drivers completely forbid string characters even in unused preprocessor directives. - * This fixes the cases we cannot manually patch: Shared headers #includes. (see T97545) + * This fixes the cases we cannot manually patch: Shared headers #includes. (see #97545) * TODO(fclem): This could be done during the datatoc step. */ void quote_preprocess() @@ -810,6 +810,8 @@ struct GPUSource { } dependencies.append_non_duplicates(dependency_source); } + /* Precedes an eternal loop (quiet CLANG's `unreachable-code` warning). */ + BLI_assert_unreachable(); return 0; } diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh index c27b5cc1a37b..fc9eafca3a5d 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.hh +++ b/source/blender/gpu/intern/gpu_shader_interface.hh @@ -57,7 +57,6 @@ class ShaderInterface { /** Location of builtin uniforms. Fast access, no lookup needed. */ int32_t builtins_[GPU_NUM_UNIFORMS]; int32_t builtin_blocks_[GPU_NUM_UNIFORM_BLOCKS]; - int32_t builtin_buffers_[GPU_NUM_STORAGE_BUFFERS]; /** * Currently only used for `GPU_shader_get_attribute_info`. @@ -128,17 +127,9 @@ class ShaderInterface { return builtin_blocks_[builtin]; } - /* Returns binding position. */ - inline int32_t ssbo_builtin(const GPUStorageBufferBuiltin builtin) const - { - BLI_assert(builtin >= 0 && builtin < GPU_NUM_STORAGE_BUFFERS); - return builtin_buffers_[builtin]; - } - protected: static inline const char *builtin_uniform_name(GPUUniformBuiltin u); static inline const char *builtin_uniform_block_name(GPUUniformBlockBuiltin u); - static inline const char *builtin_storage_block_name(GPUStorageBufferBuiltin u); inline uint32_t set_input_name(ShaderInput *input, char *name, uint32_t name_len) const; inline void copy_input_name(ShaderInput *input, @@ -234,18 +225,6 @@ inline const char *ShaderInterface::builtin_uniform_block_name(GPUUniformBlockBu } } -inline const char *ShaderInterface::builtin_storage_block_name(GPUStorageBufferBuiltin u) -{ - switch (u) { - case GPU_STORAGE_BUFFER_DEBUG_VERTS: - return "drw_debug_verts_buf"; - case GPU_STORAGE_BUFFER_DEBUG_PRINT: - return "drw_debug_print_buf"; - default: - return nullptr; - } -} - /* Returns string length including '\0' terminator. */ inline uint32_t ShaderInterface::set_input_name(ShaderInput *input, char *name, diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh index a822cd8aa38d..59c4d2b0ea96 100644 --- a/source/blender/gpu/intern/gpu_shader_private.hh +++ b/source/blender/gpu/intern/gpu_shader_private.hh @@ -34,6 +34,12 @@ class Shader { /** For debugging purpose. */ char name[64]; + /* Parent shader can be used for shaders which are derived from the same source material. + * The child shader can pull information from its parent to prepare additional resources + * such as PSOs upfront. This enables asynchronous PSO compilation which mitigates stuttering + * when updating new materials. */ + Shader *parent_shader_ = nullptr; + public: Shader(const char *name); virtual ~Shader(); @@ -43,6 +49,11 @@ class Shader { virtual void fragment_shader_from_glsl(MutableSpan sources) = 0; virtual void compute_shader_from_glsl(MutableSpan sources) = 0; virtual bool finalize(const shader::ShaderCreateInfo *info = nullptr) = 0; + /* Pre-warms PSOs using parent shader's cached PSO descriptors. Limit specifies maximum PSOs to + * warm. If -1, compiles all PSO permutations in parent shader. + * + * See `GPU_shader_warm_cache(..)` in `GPU_shader.h` for more information. */ + virtual void warm_cache(int limit) = 0; virtual void transform_feedback_names_set(Span name_list, eGPUShaderTFBType geom_type) = 0; @@ -69,7 +80,21 @@ class Shader { inline const char *const name_get() const { return name; - }; + } + + inline void parent_set(Shader *parent) + { + parent_shader_ = parent; + } + + inline Shader *parent_get() const + { + return parent_shader_; + } + + static bool srgb_uniform_dirty_get(); + static void set_srgb_uniform(GPUShader *shader); + static void set_framebuffer_srgb_target(int use_srgb_to_linear); protected: void print_log( diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc index 09a5b0ac6e95..6027aaec6b38 100644 --- a/source/blender/gpu/intern/gpu_state.cc +++ b/source/blender/gpu/intern/gpu_state.cc @@ -322,7 +322,7 @@ void GPU_bgl_start() } StateManager &state_manager = *(Context::get()->state_manager); if (state_manager.use_bgl == false) { - /* Expected by many addons (see T80169, T81289). + /* Expected by many addons (see #80169, #81289). * This will reset the blend function. */ GPU_blend(GPU_BLEND_NONE); diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc index abf5d2dc4c02..d24dd6af95b6 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.cc +++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc @@ -153,14 +153,9 @@ GPUVertBuf *GPU_vertbuf_duplicate(GPUVertBuf *verts_) return wrap(unwrap(verts_)->duplicate()); } -const void *GPU_vertbuf_read(GPUVertBuf *verts) +void GPU_vertbuf_read(GPUVertBuf *verts, void *data) { - return unwrap(verts)->read(); -} - -void *GPU_vertbuf_unmap(const GPUVertBuf *verts, const void *mapped_data) -{ - return unwrap(verts)->unmap(mapped_data); + unwrap(verts)->read(data); } void GPU_vertbuf_clear(GPUVertBuf *verts) diff --git a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh index f20f6caf6de5..be8e4f0c1859 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh @@ -94,8 +94,7 @@ class VertBuf { } virtual void update_sub(uint start, uint len, const void *data) = 0; - virtual const void *read() const = 0; - virtual void *unmap(const void *mapped_data) const = 0; + virtual void read(void *data) const = 0; protected: virtual void acquire_data() = 0; diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index eb5dedf2d4ec..2ba478d616b1 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -236,7 +236,7 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport, { /** * HACK(fclem): We copy the settings here to avoid use after free if an update frees the scene - * and the viewport stays cached (see T75443). But this means the OCIO curve-mapping caching + * and the viewport stays cached (see #75443). But this means the OCIO curve-mapping caching * (which is based on #CurveMap pointer address) cannot operate correctly and it will create * a different OCIO processor for each viewport. We try to only reallocate the curve-map copy * if needed to avoid unneeded cache invalidation. diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm index 13496e8ad6f3..07aaa5cfe62c 100644 --- a/source/blender/gpu/metal/mtl_batch.mm +++ b/source/blender/gpu/metal/mtl_batch.mm @@ -530,16 +530,16 @@ id MTLBatch::bind(uint v_first, uint v_count, uint i_fi /* Set SSBO-fetch-mode status uniforms. */ BLI_assert(active_shader_->uni_ssbo_input_prim_type_loc != -1); BLI_assert(active_shader_->uni_ssbo_input_vert_count_loc != -1); - GPU_shader_uniform_vector_int(reinterpret_cast(wrap(active_shader_)), - active_shader_->uni_ssbo_input_prim_type_loc, - 1, - 1, - (const int *)(&final_prim_type)); - GPU_shader_uniform_vector_int(reinterpret_cast(wrap(active_shader_)), - active_shader_->uni_ssbo_input_vert_count_loc, - 1, - 1, - (const int *)(&v_count)); + GPU_shader_uniform_int_ex(reinterpret_cast(wrap(active_shader_)), + active_shader_->uni_ssbo_input_prim_type_loc, + 1, + 1, + (const int *)(&final_prim_type)); + GPU_shader_uniform_int_ex(reinterpret_cast(wrap(active_shader_)), + active_shader_->uni_ssbo_input_vert_count_loc, + 1, + 1, + (const int *)(&v_count)); } /* Ensure Context Render Pipeline State is fully setup and ready to execute the draw. diff --git a/source/blender/gpu/metal/mtl_framebuffer.mm b/source/blender/gpu/metal/mtl_framebuffer.mm index dc8741e377bc..9b334dd71664 100644 --- a/source/blender/gpu/metal/mtl_framebuffer.mm +++ b/source/blender/gpu/metal/mtl_framebuffer.mm @@ -109,7 +109,7 @@ void MTLFrameBuffer::bind(bool enabled_srgb) this->mark_dirty(); } enabled_srgb_ = enabled_srgb; - GPU_shader_set_framebuffer_srgb_target(enabled_srgb && srgb_); + Shader::set_framebuffer_srgb_target(enabled_srgb && srgb_); } /* Reset clear state on bind -- Clears and load/store ops are set after binding. */ diff --git a/source/blender/gpu/metal/mtl_immediate.mm b/source/blender/gpu/metal/mtl_immediate.mm index f0809e6e9d37..985b962cc99d 100644 --- a/source/blender/gpu/metal/mtl_immediate.mm +++ b/source/blender/gpu/metal/mtl_immediate.mm @@ -248,16 +248,16 @@ void MTLImmediate::end() "ssbo_input_prim_type uniform location invalid!"); BLI_assert_msg(active_mtl_shader->uni_ssbo_input_vert_count_loc != -1, "ssbo_input_vert_count uniform location invalid!"); - GPU_shader_uniform_vector_int(reinterpret_cast(wrap(active_mtl_shader)), - active_mtl_shader->uni_ssbo_input_prim_type_loc, - 1, - 1, - (const int *)(&this->prim_type)); - GPU_shader_uniform_vector_int(reinterpret_cast(wrap(active_mtl_shader)), - active_mtl_shader->uni_ssbo_input_vert_count_loc, - 1, - 1, - (const int *)(&this->vertex_idx)); + GPU_shader_uniform_int_ex(reinterpret_cast(wrap(active_mtl_shader)), + active_mtl_shader->uni_ssbo_input_prim_type_loc, + 1, + 1, + (const int *)(&this->prim_type)); + GPU_shader_uniform_int_ex(reinterpret_cast(wrap(active_mtl_shader)), + active_mtl_shader->uni_ssbo_input_vert_count_loc, + 1, + 1, + (const int *)(&this->vertex_idx)); } MTLPrimitiveType mtl_prim_type = gpu_prim_type_to_metal(this->prim_type); diff --git a/source/blender/gpu/metal/mtl_index_buffer.hh b/source/blender/gpu/metal/mtl_index_buffer.hh index 702aa7f27d61..dd828598110a 100644 --- a/source/blender/gpu/metal/mtl_index_buffer.hh +++ b/source/blender/gpu/metal/mtl_index_buffer.hh @@ -48,7 +48,7 @@ class MTLIndexBuf : public IndexBuf { ~MTLIndexBuf(); void bind_as_ssbo(uint32_t binding) override; - const uint32_t *read() const override; + void read(uint32_t *data) const override; void upload_data() override; void update_sub(uint32_t start, uint32_t len, const void *data) override; diff --git a/source/blender/gpu/metal/mtl_index_buffer.mm b/source/blender/gpu/metal/mtl_index_buffer.mm index cf921e43a4b7..6a912983492c 100644 --- a/source/blender/gpu/metal/mtl_index_buffer.mm +++ b/source/blender/gpu/metal/mtl_index_buffer.mm @@ -46,16 +46,13 @@ void MTLIndexBuf::bind_as_ssbo(uint32_t binding) MTL_LOG_WARNING("MTLIndexBuf::bind_as_ssbo not yet implemented!\n"); } -const uint32_t *MTLIndexBuf::read() const +void MTLIndexBuf::read(uint32_t *data) const { if (ibo_ != nullptr) { - - /* Return host pointer. */ - void *data = ibo_->get_host_ptr(); - return static_cast(data); + void *host_ptr = ibo_->get_host_ptr(); + memcpy(data, host_ptr, size_get()); } BLI_assert(false && "Index buffer not ready to be read."); - return nullptr; } void MTLIndexBuf::upload_data() diff --git a/source/blender/gpu/metal/mtl_pso_descriptor_state.hh b/source/blender/gpu/metal/mtl_pso_descriptor_state.hh index 1890f6e8ccda..a3d2ded72a2a 100644 --- a/source/blender/gpu/metal/mtl_pso_descriptor_state.hh +++ b/source/blender/gpu/metal/mtl_pso_descriptor_state.hh @@ -31,6 +31,14 @@ struct MTLVertexAttributeDescriptorPSO { return uint64_t((uint64_t(this->format) ^ (this->offset << 4) ^ (this->buffer_index << 8) ^ (this->format_conversion_mode << 12))); } + + void reset() + { + format = MTLVertexFormatInvalid; + offset = 0; + buffer_index = 0; + format_conversion_mode = GPU_FETCH_FLOAT; + } }; struct MTLVertexBufferLayoutDescriptorPSO { @@ -48,6 +56,13 @@ struct MTLVertexBufferLayoutDescriptorPSO { { return uint64_t(uint64_t(this->step_function) ^ (this->step_rate << 4) ^ (this->stride << 8)); } + + void reset() + { + step_function = MTLVertexStepFunctionPerVertex; + step_rate = 1; + stride = 0; + } }; /* SSBO attribute state caching. */ @@ -76,6 +91,16 @@ struct MTLSSBOAttribute { { return (memcmp(this, &other, sizeof(MTLSSBOAttribute)) == 0); } + + void reset() + { + mtl_attribute_index = 0; + vbo_id = 0; + attribute_offset = 0; + per_vertex_stride = 0; + attribute_format = 0; + is_instance = false; + } }; struct MTLVertexDescriptor { @@ -241,10 +266,10 @@ struct MTLRenderPipelineStateDescriptor { hash ^= uint64_t(this->dest_rgb_blend_factor) << 37; /* Up to 18 (5 bits). */ hash ^= uint64_t(this->src_alpha_blend_factor) << 42; /* Up to 18 (5 bits). */ hash ^= uint64_t(this->src_rgb_blend_factor) << 47; /* Up to 18 (5 bits). */ - } - for (const uint c : IndexRange(GPU_FB_MAX_COLOR_ATTACHMENT)) { - hash ^= uint64_t(this->color_attachment_format[c]) << (c + 52); /* Up to 555 (9 bits). */ + for (const uint c : IndexRange(GPU_FB_MAX_COLOR_ATTACHMENT)) { + hash ^= uint64_t(this->color_attachment_format[c]) << (c + 52); /* Up to 555 (9 bits). */ + } } hash |= uint64_t((this->blending_enabled && (this->num_color_attachments > 0)) ? 1 : 0) << 62; @@ -262,9 +287,9 @@ struct MTLRenderPipelineStateDescriptor { vertex_descriptor.total_attributes = 0; vertex_descriptor.max_attribute_value = 0; vertex_descriptor.num_vert_buffers = 0; + vertex_descriptor.prim_topology_class = MTLPrimitiveTopologyClassUnspecified; for (int i = 0; i < GPU_VERT_ATTR_MAX_LEN; i++) { - vertex_descriptor.attributes[i].format = MTLVertexFormatInvalid; - vertex_descriptor.attributes[i].offset = 0; + vertex_descriptor.attributes[i].reset(); } vertex_descriptor.uses_ssbo_vertex_fetch = false; vertex_descriptor.num_ssbo_attributes = 0; diff --git a/source/blender/gpu/metal/mtl_shader.hh b/source/blender/gpu/metal/mtl_shader.hh index 59c5a810e5e0..095ca94cc411 100644 --- a/source/blender/gpu/metal/mtl_shader.hh +++ b/source/blender/gpu/metal/mtl_shader.hh @@ -76,6 +76,8 @@ struct MTLRenderPipelineStateInstance { int null_attribute_buffer_index; /* buffer bind used for transform feedback output buffer. */ int transform_feedback_buffer_index; + /* Topology class. */ + MTLPrimitiveTopologyClass prim_type; /** Reflection Data. * Currently used to verify whether uniform buffers of incorrect sizes being bound, due to left @@ -188,6 +190,7 @@ class MTLShader : public Shader { MTLRenderPipelineStateDescriptor current_pipeline_state_; /* Cache of compiled PipelineStateObjects. */ blender::Map pso_cache_; + std::mutex pso_cache_lock_; /** Compute pipeline state and Compute PSO caching. */ MTLComputePipelineStateInstance compute_pso_instance_; @@ -256,6 +259,7 @@ class MTLShader : public Shader { /* Compile and build - Return true if successful. */ bool finalize(const shader::ShaderCreateInfo *info = nullptr) override; bool finalize_compute(const shader::ShaderCreateInfo *info); + void warm_cache(int limit) override; /* Utility. */ bool is_valid() @@ -331,8 +335,14 @@ class MTLShader : public Shader { void shader_source_from_msl(NSString *input_vertex_source, NSString *input_fragment_source); void shader_compute_source_from_msl(NSString *input_compute_source); void set_interface(MTLShaderInterface *interface); + MTLRenderPipelineStateInstance *bake_current_pipeline_state(MTLContext *ctx, MTLPrimitiveTopologyClass prim_type); + MTLRenderPipelineStateInstance *bake_pipeline_state( + MTLContext *ctx, + MTLPrimitiveTopologyClass prim_type, + const MTLRenderPipelineStateDescriptor &pipeline_descriptor); + bool bake_compute_pipeline_state(MTLContext *ctx); const MTLComputePipelineStateInstance &get_compute_pipeline_state(); diff --git a/source/blender/gpu/metal/mtl_shader.mm b/source/blender/gpu/metal/mtl_shader.mm index 610079a644f8..3f0bcaea8756 100644 --- a/source/blender/gpu/metal/mtl_shader.mm +++ b/source/blender/gpu/metal/mtl_shader.mm @@ -6,6 +6,8 @@ #include "BKE_global.h" +#include "PIL_time.h" + #include "BLI_string.h" #include #include @@ -110,6 +112,7 @@ MTLShader::~MTLShader() } /* Free Pipeline Cache. */ + pso_cache_lock_.lock(); for (const MTLRenderPipelineStateInstance *pso_inst : pso_cache_.values()) { if (pso_inst->vert) { [pso_inst->vert release]; @@ -123,6 +126,7 @@ MTLShader::~MTLShader() delete pso_inst; } pso_cache_.clear(); + pso_cache_lock_.unlock(); /* Free Compute pipeline state object. */ if (compute_pso_instance_.compute) { @@ -616,6 +620,36 @@ void MTLShader::push_constant_bindstate_mark_dirty(bool is_dirty) push_constant_modified_ = is_dirty; } +void MTLShader::warm_cache(int limit) +{ + if (parent_shader_ != nullptr) { + MTLContext *ctx = MTLContext::get(); + MTLShader *parent_mtl = reinterpret_cast(parent_shader_); + + /* Extract PSO descriptors from parent shader. */ + blender::Vector descriptors; + blender::Vector prim_classes; + + parent_mtl->pso_cache_lock_.lock(); + for (const auto &pso_entry : parent_mtl->pso_cache_.items()) { + const MTLRenderPipelineStateDescriptor &pso_descriptor = pso_entry.key; + const MTLRenderPipelineStateInstance *pso_inst = pso_entry.value; + descriptors.append(pso_descriptor); + prim_classes.append(pso_inst->prim_type); + } + parent_mtl->pso_cache_lock_.unlock(); + + /* Warm shader cache with applied limit. + * If limit is <= 0, compile all PSO permutations. */ + limit = (limit > 0) ? limit : descriptors.size(); + for (int i : IndexRange(min_ii(descriptors.size(), limit))) { + const MTLRenderPipelineStateDescriptor &pso_descriptor = descriptors[i]; + const MTLPrimitiveTopologyClass &prim_class = prim_classes[i]; + bake_pipeline_state(ctx, prim_class, pso_descriptor); + } + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -681,12 +715,10 @@ void MTLShader::set_interface(MTLShaderInterface *interface) MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( MTLContext *ctx, MTLPrimitiveTopologyClass prim_type) { + /** Populate global pipeline descriptor and use this to prepare new PSO. */ /* NOTE(Metal): PSO cache can be accessed from multiple threads, though these operations should * be thread-safe due to organization of high-level renderer. If there are any issues, then * access can be guarded as appropriate. */ - BLI_assert(this); - MTLShaderInterface *mtl_interface = this->get_interface(); - BLI_assert(mtl_interface); BLI_assert(this->is_valid()); /* NOTE(Metal): Vertex input assembly description will have been populated externally @@ -756,15 +788,32 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( pipeline_descriptor.vertex_descriptor.prim_topology_class = (requires_specific_topology_class) ? prim_type : MTLPrimitiveTopologyClassUnspecified; + /* Bake pipeline state using global descriptor. */ + return bake_pipeline_state(ctx, prim_type, pipeline_descriptor); +} + +/* Variant which bakes a pipeline state based on an an existing MTLRenderPipelineStateDescriptor. + * This function should be callable from a secondary compilation thread. */ +MTLRenderPipelineStateInstance *MTLShader::bake_pipeline_state( + MTLContext *ctx, + MTLPrimitiveTopologyClass prim_type, + const MTLRenderPipelineStateDescriptor &pipeline_descriptor) +{ + /* Fetch shader interface. */ + MTLShaderInterface *mtl_interface = this->get_interface(); + BLI_assert(mtl_interface); + BLI_assert(this->is_valid()); + /* Check if current PSO exists in the cache. */ + pso_cache_lock_.lock(); MTLRenderPipelineStateInstance **pso_lookup = pso_cache_.lookup_ptr(pipeline_descriptor); MTLRenderPipelineStateInstance *pipeline_state = (pso_lookup) ? *pso_lookup : nullptr; + pso_cache_lock_.unlock(); + if (pipeline_state != nullptr) { return pipeline_state; } - shader_debug_printf("Baking new pipeline variant for shader: %s\n", this->name); - /* Generate new Render Pipeline State Object (PSO). */ @autoreleasepool { /* Prepare Render Pipeline Descriptor. */ @@ -774,7 +823,6 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( MTLFunctionConstantValues *values = [[MTLFunctionConstantValues new] autorelease]; /* Prepare Vertex descriptor based on current pipeline vertex binding state. */ - MTLRenderPipelineStateDescriptor ¤t_state = pipeline_descriptor; MTLRenderPipelineDescriptor *desc = pso_descriptor_; [desc reset]; pso_descriptor_.label = [NSString stringWithUTF8String:this->name]; @@ -784,7 +832,7 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( * specialization constant, customized per unique pipeline state permutation. * * NOTE: For binding point compaction, we could use the number of VBOs present - * in the current PSO configuration `current_state.vertex_descriptor.num_vert_buffers`). + * in the current PSO configuration `pipeline_descriptors.vertex_descriptor.num_vert_buffers`). * However, it is more efficient to simply offset the uniform buffer base index to the * maximal number of VBO bind-points, as then UBO bind-points for similar draw calls * will align and avoid the requirement for additional binding. */ @@ -792,7 +840,7 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( /* Null buffer index is used if an attribute is not found in the * bound VBOs #VertexFormat. */ - int null_buffer_index = current_state.vertex_descriptor.num_vert_buffers; + int null_buffer_index = pipeline_descriptor.vertex_descriptor.num_vert_buffers; bool using_null_buffer = false; if (this->get_uses_ssbo_vertex_fetch()) { @@ -806,11 +854,12 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( MTL_uniform_buffer_base_index = MTL_SSBO_VERTEX_FETCH_IBO_INDEX + 1; } else { - for (const uint i : IndexRange(current_state.vertex_descriptor.max_attribute_value + 1)) { + for (const uint i : + IndexRange(pipeline_descriptor.vertex_descriptor.max_attribute_value + 1)) { /* Metal back-end attribute descriptor state. */ - MTLVertexAttributeDescriptorPSO &attribute_desc = - current_state.vertex_descriptor.attributes[i]; + const MTLVertexAttributeDescriptorPSO &attribute_desc = + pipeline_descriptor.vertex_descriptor.attributes[i]; /* Flag format conversion */ /* In some cases, Metal cannot implicitly convert between data types. @@ -860,10 +909,10 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( mtl_attribute.bufferIndex = attribute_desc.buffer_index; } - for (const uint i : IndexRange(current_state.vertex_descriptor.num_vert_buffers)) { + for (const uint i : IndexRange(pipeline_descriptor.vertex_descriptor.num_vert_buffers)) { /* Metal back-end state buffer layout. */ const MTLVertexBufferLayoutDescriptorPSO &buf_layout = - current_state.vertex_descriptor.buffer_layouts[i]; + pipeline_descriptor.vertex_descriptor.buffer_layouts[i]; /* Copy metal back-end buffer layout state into PSO descriptor. * NOTE: need to copy each element due to copying from internal * back-end descriptor to Metal API descriptor. */ @@ -875,7 +924,7 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( } /* Mark empty attribute conversion. */ - for (int i = current_state.vertex_descriptor.max_attribute_value + 1; + for (int i = pipeline_descriptor.vertex_descriptor.max_attribute_value + 1; i < GPU_VERT_ATTR_MAX_LEN; i++) { int MTL_attribute_conversion_mode = 0; @@ -1039,7 +1088,7 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( for (int color_attachment = 0; color_attachment < GPU_FB_MAX_COLOR_ATTACHMENT; color_attachment++) { /* Fetch color attachment pixel format in back-end pipeline state. */ - MTLPixelFormat pixel_format = current_state.color_attachment_format[color_attachment]; + MTLPixelFormat pixel_format = pipeline_descriptor.color_attachment_format[color_attachment]; /* Populate MTL API PSO attachment descriptor. */ MTLRenderPipelineColorAttachmentDescriptor *col_attachment = desc.colorAttachments[color_attachment]; @@ -1048,19 +1097,19 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( if (pixel_format != MTLPixelFormatInvalid) { bool format_supports_blending = mtl_format_supports_blending(pixel_format); - col_attachment.writeMask = current_state.color_write_mask; - col_attachment.blendingEnabled = current_state.blending_enabled && + col_attachment.writeMask = pipeline_descriptor.color_write_mask; + col_attachment.blendingEnabled = pipeline_descriptor.blending_enabled && format_supports_blending; - if (format_supports_blending && current_state.blending_enabled) { - col_attachment.alphaBlendOperation = current_state.alpha_blend_op; - col_attachment.rgbBlendOperation = current_state.rgb_blend_op; - col_attachment.destinationAlphaBlendFactor = current_state.dest_alpha_blend_factor; - col_attachment.destinationRGBBlendFactor = current_state.dest_rgb_blend_factor; - col_attachment.sourceAlphaBlendFactor = current_state.src_alpha_blend_factor; - col_attachment.sourceRGBBlendFactor = current_state.src_rgb_blend_factor; + if (format_supports_blending && pipeline_descriptor.blending_enabled) { + col_attachment.alphaBlendOperation = pipeline_descriptor.alpha_blend_op; + col_attachment.rgbBlendOperation = pipeline_descriptor.rgb_blend_op; + col_attachment.destinationAlphaBlendFactor = pipeline_descriptor.dest_alpha_blend_factor; + col_attachment.destinationRGBBlendFactor = pipeline_descriptor.dest_rgb_blend_factor; + col_attachment.sourceAlphaBlendFactor = pipeline_descriptor.src_alpha_blend_factor; + col_attachment.sourceRGBBlendFactor = pipeline_descriptor.src_rgb_blend_factor; } else { - if (current_state.blending_enabled && !format_supports_blending) { + if (pipeline_descriptor.blending_enabled && !format_supports_blending) { shader_debug_printf( "[Warning] Attempting to Bake PSO, but MTLPixelFormat %d does not support " "blending\n", @@ -1069,8 +1118,8 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( } } } - desc.depthAttachmentPixelFormat = current_state.depth_attachment_format; - desc.stencilAttachmentPixelFormat = current_state.stencil_attachment_format; + desc.depthAttachmentPixelFormat = pipeline_descriptor.depth_attachment_format; + desc.stencilAttachmentPixelFormat = pipeline_descriptor.stencil_attachment_format; /* Compile PSO */ MTLAutoreleasedRenderPipelineReflection reflection_data; @@ -1090,7 +1139,7 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( return nullptr; } else { -#ifndef NDEBUG +#if 0 NSLog(@"Successfully compiled PSO for shader: %s (Metal Context: %p)\n", this->name, ctx); #endif } @@ -1103,7 +1152,7 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( pso_inst->base_uniform_buffer_index = MTL_uniform_buffer_base_index; pso_inst->null_attribute_buffer_index = (using_null_buffer) ? null_buffer_index : -1; pso_inst->transform_feedback_buffer_index = MTL_transform_feedback_buffer_index; - pso_inst->shader_pso_index = pso_cache_.size(); + pso_inst->prim_type = prim_type; pso_inst->reflection_data_available = (reflection_data != nil); if (reflection_data != nil) { @@ -1189,9 +1238,14 @@ MTLRenderPipelineStateInstance *MTLShader::bake_current_pipeline_state( [pso_inst->pso retain]; /* Insert into pso cache. */ + pso_cache_lock_.lock(); + pso_inst->shader_pso_index = pso_cache_.size(); pso_cache_.add(pipeline_descriptor, pso_inst); - shader_debug_printf("PSO CACHE: Stored new variant in PSO cache for shader '%s'\n", - this->name); + pso_cache_lock_.unlock(); + shader_debug_printf( + "PSO CACHE: Stored new variant in PSO cache for shader '%s' Hash: '%llu'\n", + this->name, + pipeline_descriptor.hash()); return pso_inst; } } @@ -1256,7 +1310,7 @@ bool MTLShader::bake_compute_pipeline_state(MTLContext *ctx) return false; } else { -#ifndef NDEBUG +#if 0 NSLog(@"Successfully compiled compute PSO for shader: %s (Metal Context: %p)\n", this->name, ctx); diff --git a/source/blender/gpu/metal/mtl_shader_generator.mm b/source/blender/gpu/metal/mtl_shader_generator.mm index 40ee7d5ac142..0b866456ffc0 100644 --- a/source/blender/gpu/metal/mtl_shader_generator.mm +++ b/source/blender/gpu/metal/mtl_shader_generator.mm @@ -869,7 +869,7 @@ bool MTLShader::generate_msl_from_glsl(const shader::ShaderCreateInfo *info) #define GPU_ARB_shader_draw_parameters 1\n"; /* NOTE(Metal): textureGather appears to not function correctly on non-Apple-silicon GPUs. - * Manifests as selection outlines not showing up (T103412). Disable texture gather if + * Manifests as selection outlines not showing up (#103412). Disable texture gather if * not suitable for use. */ if (MTLBackend::get_capabilities().supports_texture_gather) { msl_defines_string += "#define GPU_ARB_texture_gather 1\n"; diff --git a/source/blender/gpu/metal/mtl_vertex_buffer.hh b/source/blender/gpu/metal/mtl_vertex_buffer.hh index 54d2b7a86a3b..056e2062ab16 100644 --- a/source/blender/gpu/metal/mtl_vertex_buffer.hh +++ b/source/blender/gpu/metal/mtl_vertex_buffer.hh @@ -56,8 +56,7 @@ class MTLVertBuf : public VertBuf { void update_sub(uint start, uint len, const void *data) override; - const void *read() const override; - void *unmap(const void *mapped_data) const override; + void read(void *data) const override; void wrap_handle(uint64_t handle) override; diff --git a/source/blender/gpu/metal/mtl_vertex_buffer.mm b/source/blender/gpu/metal/mtl_vertex_buffer.mm index 919eb1e3267c..6114e1057c84 100644 --- a/source/blender/gpu/metal/mtl_vertex_buffer.mm +++ b/source/blender/gpu/metal/mtl_vertex_buffer.mm @@ -328,21 +328,12 @@ void MTLVertBuf::bind_as_texture(uint binding) GPU_texture_bind(buffer_texture_, binding); } -const void *MTLVertBuf::read() const +void MTLVertBuf::read(void *data) const { BLI_assert(vbo_ != nullptr); BLI_assert(usage_ != GPU_USAGE_DEVICE_ONLY); - void *return_ptr = vbo_->get_host_ptr(); - BLI_assert(return_ptr != nullptr); - - return return_ptr; -} - -void *MTLVertBuf::unmap(const void *mapped_data) const -{ - void *result = MEM_mallocN(alloc_size_, __func__); - memcpy(result, mapped_data, alloc_size_); - return result; + void *host_ptr = vbo_->get_host_ptr(); + memcpy(data, host_ptr, alloc_size_); } void MTLVertBuf::wrap_handle(uint64_t handle) diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index cba53188c05b..21af443401fb 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -255,7 +255,7 @@ static void detect_workarounds() * requirements. * * We use it as a target for glMapBuffer(Range) what is part of the OpenGL 4 API. So better - * disable it when we don't have an OpenGL4 context (See T77657) */ + * disable it when we don't have an OpenGL4 context (See #77657) */ if (!(epoxy_gl_version() >= 40)) { GLContext::base_instance_support = false; } @@ -275,12 +275,12 @@ static void detect_workarounds() GCaps.shader_draw_parameters_support = false; GCaps.broken_amd_driver = true; } - /* Compute shaders have some issues with those versions (see T94936). */ + /* Compute shaders have some issues with those versions (see #94936). */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL) && (strstr(version, "4.5.14831") || strstr(version, "4.5.14760"))) { GCaps.compute_shader_support = false; } - /* We have issues with this specific renderer. (see T74024) */ + /* We have issues with this specific renderer. (see #74024) */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && (strstr(renderer, "AMD VERDE") || strstr(renderer, "AMD KAVERI") || strstr(renderer, "AMD TAHITI"))) { @@ -289,14 +289,14 @@ static void detect_workarounds() GCaps.shader_draw_parameters_support = false; GCaps.broken_amd_driver = true; } - /* Fix slowdown on this particular driver. (see T77641) */ + /* Fix slowdown on this particular driver. (see #77641) */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && strstr(version, "Mesa 19.3.4")) { GCaps.shader_image_load_store_support = false; GCaps.shader_draw_parameters_support = false; GCaps.broken_amd_driver = true; } - /* See T82856: AMD drivers since 20.11 running on a polaris architecture doesn't support the + /* See #82856: AMD drivers since 20.11 running on a polaris architecture doesn't support the * `GL_INT_2_10_10_10_REV` data type correctly. This data type is used to pack normals and flags. * The work around uses `GPU_RGBA16I`. In 22.?.? drivers this has been fixed for * polaris platform. Keeping legacy platforms around just in case. @@ -321,18 +321,18 @@ static void detect_workarounds() } /* Limit this fix to older hardware with GL < 4.5. This means Broadwell GPUs are * covered since they only support GL 4.4 on windows. - * This fixes some issues with workbench anti-aliasing on Win + Intel GPU. (see T76273) */ + * This fixes some issues with workbench anti-aliasing on Win + Intel GPU. (see #76273) */ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && !(epoxy_gl_version() >= 45)) { GLContext::copy_image_support = false; } /* Special fix for these specific GPUs. - * Without this workaround, blender crashes on startup. (see T72098) */ + * Without this workaround, blender crashes on startup. (see #72098) */ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && (strstr(renderer, "HD Graphics 620") || strstr(renderer, "HD Graphics 630"))) { GCaps.mip_render_workaround = true; } - /* Intel Ivy Bridge GPU's seems to have buggy cube-map array support. (see T75943) */ + /* Intel Ivy Bridge GPU's seems to have buggy cube-map array support. (see #75943) */ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && (strstr(renderer, "HD Graphics 4000") || strstr(renderer, "HD Graphics 4400") || strstr(renderer, "HD Graphics 2500"))) { @@ -349,12 +349,12 @@ static void detect_workarounds() GLContext::base_instance_support = false; GCaps.use_main_context_workaround = true; } - /* Somehow fixes armature display issues (see T69743). */ + /* Somehow fixes armature display issues (see #69743). */ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY) && strstr(version, "Build 20.19.15.4285")) { GCaps.use_main_context_workaround = true; } - /* See T70187: merging vertices fail. This has been tested from `18.2.2` till `19.3.0~dev` + /* See #70187: merging vertices fail. This has been tested from `18.2.2` till `19.3.0~dev` * of the Mesa driver */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && (strstr(version, "Mesa 18.") || strstr(version, "Mesa 19.0") || @@ -362,7 +362,7 @@ static void detect_workarounds() GLContext::unused_fb_slot_workaround = true; } /* There is a bug on older Nvidia GPU where GL_ARB_texture_gather - * is reported to be supported but yield a compile error (see T55802). */ + * is reported to be supported but yield a compile error (see #55802). */ if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) && !(epoxy_gl_version() >= 40)) { GLContext::texture_gather_support = false; @@ -413,7 +413,7 @@ static void detect_workarounds() GLContext::generate_mipmap_workaround = true; } - /* Buggy interface query functions cause crashes when handling SSBOs (T93680) */ + /* Buggy interface query functions cause crashes when handling SSBOs (#93680) */ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY) && (strstr(renderer, "HD Graphics 4400") || strstr(renderer, "HD Graphics 4600"))) { GCaps.shader_storage_buffer_objects_support = false; diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc index 28105e326eea..57db98094273 100644 --- a/source/blender/gpu/opengl/gl_batch.cc +++ b/source/blender/gpu/opengl/gl_batch.cc @@ -214,7 +214,7 @@ GLuint GLVaoCache::base_instance_vao_get(GPUBatch *batch, int i_first) base_instance_ = 0; } /** - * There seems to be a nasty bug when drawing using the same VAO reconfiguring (T71147). + * There seems to be a nasty bug when drawing using the same VAO reconfiguring (#71147). * We just use a throwaway VAO for that. Note that this is likely to degrade performance. */ #ifdef __APPLE__ diff --git a/source/blender/gpu/opengl/gl_framebuffer.cc b/source/blender/gpu/opengl/gl_framebuffer.cc index e94f5b66b97b..cc7ecae5c559 100644 --- a/source/blender/gpu/opengl/gl_framebuffer.cc +++ b/source/blender/gpu/opengl/gl_framebuffer.cc @@ -280,7 +280,7 @@ void GLFrameBuffer::bind(bool enabled_srgb) else { glDisable(GL_FRAMEBUFFER_SRGB); } - GPU_shader_set_framebuffer_srgb_target(enabled_srgb && srgb_); + Shader::set_framebuffer_srgb_target(enabled_srgb && srgb_); } if (context_->active_fb != this) { diff --git a/source/blender/gpu/opengl/gl_immediate.cc b/source/blender/gpu/opengl/gl_immediate.cc index a332a2fbc7ce..b0840e0bc227 100644 --- a/source/blender/gpu/opengl/gl_immediate.cc +++ b/source/blender/gpu/opengl/gl_immediate.cc @@ -153,7 +153,7 @@ void GLImmediate::end() glEnable(GL_PRIMITIVE_RESTART); #endif /* These lines are causing crash on startup on some old GPU + drivers. - * They are not required so just comment them. (T55722) */ + * They are not required so just comment them. (#55722) */ // glBindBuffer(GL_ARRAY_BUFFER, 0); // glBindVertexArray(0); } diff --git a/source/blender/gpu/opengl/gl_immediate.hh b/source/blender/gpu/opengl/gl_immediate.hh index 5c6ff510cef2..91eda10551a4 100644 --- a/source/blender/gpu/opengl/gl_immediate.hh +++ b/source/blender/gpu/opengl/gl_immediate.hh @@ -21,7 +21,7 @@ namespace blender::gpu { class GLImmediate : public Immediate { private: /* Use two buffers for strict and non-strict vertex count to - * avoid some huge driver slowdown (see T70922). + * avoid some huge driver slowdown (see #70922). * Use accessor functions to get / modify. */ struct { /** Opengl Handle for this buffer. */ diff --git a/source/blender/gpu/opengl/gl_index_buffer.cc b/source/blender/gpu/opengl/gl_index_buffer.cc index 566169182e30..2125583cd6b7 100644 --- a/source/blender/gpu/opengl/gl_index_buffer.cc +++ b/source/blender/gpu/opengl/gl_index_buffer.cc @@ -46,12 +46,12 @@ void GLIndexBuf::bind_as_ssbo(uint binding) glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, ibo_id_); } -const uint32_t *GLIndexBuf::read() const +void GLIndexBuf::read(uint32_t *data) const { BLI_assert(is_active()); - void *data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); - uint32_t *result = static_cast(data); - return result; + void *buffer = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY); + memcpy(data, buffer, size_get()); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); } bool GLIndexBuf::is_active() const diff --git a/source/blender/gpu/opengl/gl_index_buffer.hh b/source/blender/gpu/opengl/gl_index_buffer.hh index 78159db764c3..eeb7aeeca884 100644 --- a/source/blender/gpu/opengl/gl_index_buffer.hh +++ b/source/blender/gpu/opengl/gl_index_buffer.hh @@ -29,7 +29,7 @@ class GLIndexBuf : public IndexBuf { void bind(); void bind_as_ssbo(uint binding) override; - const uint32_t *read() const override; + void read(uint32_t *data) const override; void *offset_ptr(uint additional_vertex_offset) const { diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index 58407db015d6..7fe0d8787980 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -486,9 +486,9 @@ std::string GLShader::resources_declare(const ShaderCreateInfo &info) const } ss << ";\n"; } -#if 0 /* T95278: This is not be enough to prevent some compilers think it is recursive. */ +#if 0 /* #95278: This is not be enough to prevent some compilers think it is recursive. */ for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) { - /* T95278: Double macro to avoid some compilers think it is recursive. */ + /* #95278: Double macro to avoid some compilers think it is recursive. */ ss << "#define " << uniform.name << "_ " << uniform.name << "\n"; ss << "#define " << uniform.name << " (" << uniform.name << "_)\n"; } @@ -817,7 +817,7 @@ static char *glsl_patch_default_get() if (GLContext::texture_gather_support) { STR_CONCAT(patch, slen, "#extension GL_ARB_texture_gather: enable\n"); /* Some drivers don't agree on epoxy_has_gl_extension("GL_ARB_texture_gather") and the actual - * support in the shader so double check the preprocessor define (see T56544). */ + * support in the shader so double check the preprocessor define (see #56544). */ STR_CONCAT(patch, slen, "#ifdef GL_ARB_texture_gather\n"); STR_CONCAT(patch, slen, "# define GPU_ARB_texture_gather\n"); STR_CONCAT(patch, slen, "#endif\n"); diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh index bebbb2fa82e6..17e4339e130e 100644 --- a/source/blender/gpu/opengl/gl_shader.hh +++ b/source/blender/gpu/opengl/gl_shader.hh @@ -47,6 +47,7 @@ class GLShader : public Shader { void fragment_shader_from_glsl(MutableSpan sources) override; void compute_shader_from_glsl(MutableSpan sources) override; bool finalize(const shader::ShaderCreateInfo *info = nullptr) override; + void warm_cache(int /*limit*/) override{}; std::string resources_declare(const shader::ShaderCreateInfo &info) const override; std::string vertex_interface_declare(const shader::ShaderCreateInfo &info) const override; diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index ef97d74bf81b..4b10780e551e 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -371,13 +371,6 @@ GLShaderInterface::GLShaderInterface(GLuint program) builtin_blocks_[u] = (block != nullptr) ? block->binding : -1; } - /* Builtin Storage Buffers */ - for (int32_t u_int = 0; u_int < GPU_NUM_STORAGE_BUFFERS; u_int++) { - GPUStorageBufferBuiltin u = static_cast(u_int); - const ShaderInput *block = this->ssbo_get(builtin_storage_block_name(u)); - builtin_buffers_[u] = (block != nullptr) ? block->binding : -1; - } - MEM_freeN(uniforms_from_blocks); /* Resize name buffer to save some memory. */ @@ -550,13 +543,6 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI builtin_blocks_[u] = (block != nullptr) ? block->binding : -1; } - /* Builtin Storage Buffers */ - for (int32_t u_int = 0; u_int < GPU_NUM_STORAGE_BUFFERS; u_int++) { - GPUStorageBufferBuiltin u = static_cast(u_int); - const ShaderInput *block = this->ssbo_get(builtin_storage_block_name(u)); - builtin_buffers_[u] = (block != nullptr) ? block->binding : -1; - } - this->sort_inputs(); // this->debug_print(); diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc index 1410dad8a2ff..424fbf702ea9 100644 --- a/source/blender/gpu/opengl/gl_texture.cc +++ b/source/blender/gpu/opengl/gl_texture.cc @@ -353,7 +353,7 @@ void GLTexture::generate_mipmap() return; } - /* Some drivers have bugs when using #glGenerateMipmap with depth textures (see T56789). + /* Some drivers have bugs when using #glGenerateMipmap with depth textures (see #56789). * In this case we just create a complete texture with mipmaps manually without * down-sampling. You must initialize the texture levels using other methods like * #GPU_framebuffer_recursive_downsample(). */ @@ -448,7 +448,7 @@ void *GLTexture::read(int mip, eGPUDataFormat type) size_t texture_size = sample_len * sample_size; /* AMD Pro driver have a bug that write 8 bytes past buffer size - * if the texture is big. (see T66573) */ + * if the texture is big. (see #66573) */ void *data = MEM_mallocN(texture_size + 8, "GPU_texture_read"); GLenum gl_format = to_gl_data_format(format_); @@ -677,17 +677,17 @@ bool GLTexture::proxy_check(int mip) GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_MAC, GPU_DRIVER_OFFICIAL) || GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OFFICIAL)) { /* Some AMD drivers have a faulty `GL_PROXY_TEXTURE_..` check. - * (see T55888, T56185, T59351). + * (see #55888, #56185, #59351). * Checking with `GL_PROXY_TEXTURE_..` doesn't prevent `Out Of Memory` issue, * it just states that the OGL implementation can support the texture. * So we already manually check the maximum size and maximum number of layers. - * Same thing happens on Nvidia/macOS 10.15 (T78175). */ + * Same thing happens on Nvidia/macOS 10.15 (#78175). */ return true; } if ((type_ == GPU_TEXTURE_CUBE_ARRAY) && GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY)) { - /* Special fix for T79703. */ + /* Special fix for #79703. */ return true; } diff --git a/source/blender/gpu/opengl/gl_vertex_array.cc b/source/blender/gpu/opengl/gl_vertex_array.cc index 9a6df38cb058..d5aa1141521b 100644 --- a/source/blender/gpu/opengl/gl_vertex_array.cc +++ b/source/blender/gpu/opengl/gl_vertex_array.cc @@ -136,7 +136,7 @@ void GLVertArray::update_bindings(const GLuint vao, if (attr_mask & mask) { GLContext *ctx = GLContext::get(); /* This replaces glVertexAttrib4f(a, 0.0f, 0.0f, 0.0f, 1.0f); with a more modern style. - * Fix issues for some drivers (see T75069). */ + * Fix issues for some drivers (see #75069). */ glBindVertexBuffer(a, ctx->default_attr_vbo_, intptr_t(0), intptr_t(0)); glEnableVertexAttribArray(a); glVertexAttribFormat(a, 4, GL_FLOAT, GL_FALSE, 0); diff --git a/source/blender/gpu/opengl/gl_vertex_buffer.cc b/source/blender/gpu/opengl/gl_vertex_buffer.cc index d186c2025b3f..3a22480e190d 100644 --- a/source/blender/gpu/opengl/gl_vertex_buffer.cc +++ b/source/blender/gpu/opengl/gl_vertex_buffer.cc @@ -125,18 +125,12 @@ void GLVertBuf::bind_as_texture(uint binding) GPU_texture_bind(buffer_texture_, binding); } -const void *GLVertBuf::read() const +void GLVertBuf::read(void *data) const { BLI_assert(is_active()); void *result = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); - return result; -} - -void *GLVertBuf::unmap(const void *mapped_data) const -{ - void *result = MEM_mallocN(vbo_size_, __func__); - memcpy(result, mapped_data, vbo_size_); - return result; + memcpy(data, result, size_used_get()); + glUnmapBuffer(GL_ARRAY_BUFFER); } void GLVertBuf::wrap_handle(uint64_t handle) diff --git a/source/blender/gpu/opengl/gl_vertex_buffer.hh b/source/blender/gpu/opengl/gl_vertex_buffer.hh index deb966961f26..5137781309ef 100644 --- a/source/blender/gpu/opengl/gl_vertex_buffer.hh +++ b/source/blender/gpu/opengl/gl_vertex_buffer.hh @@ -37,8 +37,7 @@ class GLVertBuf : public VertBuf { void update_sub(uint start, uint len, const void *data) override; - const void *read() const override; - void *unmap(const void *mapped_data) const override; + void read(void *data) const override; void wrap_handle(uint64_t handle) override; diff --git a/source/blender/gpu/shaders/common/gpu_shader_math_matrix_lib.glsl b/source/blender/gpu/shaders/common/gpu_shader_math_matrix_lib.glsl index 407469ab8a26..0b764b954c86 100644 --- a/source/blender/gpu/shaders/common/gpu_shader_math_matrix_lib.glsl +++ b/source/blender/gpu/shaders/common/gpu_shader_math_matrix_lib.glsl @@ -169,7 +169,7 @@ mat4x4 scale(mat4x4 mat, vec3 scale); * * \note This code is about five times faster than the polar decomposition. * However, it gives un-expected results even with non-uniformly scaled matrices, - * see T46418 for an example. + * see #46418 for an example. * * \param A: Input matrix which is totally effective with `t = 0.0`. * \param B: Input matrix which is totally effective with `t = 1.0`. @@ -1059,7 +1059,7 @@ EulerXYZ to_euler(mat4x4 mat, const bool normalized) Quaternion normalized_to_quat_fast(mat3 mat) { - /* Caller must ensure matrices aren't negative for valid results, see: T24291, T94231. */ + /* Caller must ensure matrices aren't negative for valid results, see: #24291, #94231. */ Quaternion q; /* Method outlined by Mike Day, ref: https://math.stackexchange.com/a/3183435/220949 @@ -1122,7 +1122,7 @@ Quaternion normalized_to_quat_fast(mat3 mat) } else { /* NOTE(@ideasman42): A zero matrix will fall through to this block, - * needed so a zero scaled matrices to return a quaternion without rotation, see: T101848. */ + * needed so a zero scaled matrices to return a quaternion without rotation, see: #101848. */ float trace = 1.0f + mat[0][0] + mat[1][1] + mat[2][2]; float s = 2.0f * sqrt(trace); q.x = 0.25f * s; diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl deleted file mode 100644 index a43c1aa40cf9..000000000000 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl +++ /dev/null @@ -1,6 +0,0 @@ - -void main() -{ - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - finalColor = color; -} diff --git a/source/blender/gpu/shaders/gpu_shader_codegen_lib.glsl b/source/blender/gpu/shaders/gpu_shader_codegen_lib.glsl index 3775f7f7ee38..1f7482a1b517 100644 --- a/source/blender/gpu/shaders/gpu_shader_codegen_lib.glsl +++ b/source/blender/gpu/shaders/gpu_shader_codegen_lib.glsl @@ -228,6 +228,11 @@ void dF_branch(float fn, out vec2 result) result = vec2(0.0); } +void dF_branch_incomplete(float fn, out vec2 result) +{ + result = vec2(0.0); +} + #elif 0 /* TODO(@fclem): User Option? */ /* Fast derivatives */ vec3 dF_impl(vec3 v) @@ -257,6 +262,17 @@ vec3 dF_impl(vec3 v) } # define dF_branch(fn, result) \ + if (true) { \ + g_derivative_flag = 1; \ + result.x = (fn); \ + g_derivative_flag = -1; \ + result.y = (fn); \ + g_derivative_flag = 0; \ + result -= vec2((fn)); \ + } + +/* Used when the non-offset value is already computed elsewhere */ +# define dF_branch_incomplete(fn, result) \ if (true) { \ g_derivative_flag = 1; \ result.x = (fn); \ diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_shape_frag.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_shape_frag.glsl index 3690dd8d1d2a..3b1dad241824 100644 --- a/source/blender/gpu/shaders/gpu_shader_keyframe_shape_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_shape_frag.glsl @@ -1,16 +1,4 @@ -/* Values in GPU_shader.h. */ -#define GPU_KEYFRAME_SHAPE_DIAMOND (1u << 0) -#define GPU_KEYFRAME_SHAPE_CIRCLE (1u << 1) -#define GPU_KEYFRAME_SHAPE_CLIPPED_VERTICAL (1u << 2) -#define GPU_KEYFRAME_SHAPE_CLIPPED_HORIZONTAL (1u << 3) -#define GPU_KEYFRAME_SHAPE_INNER_DOT (1u << 4) -#define GPU_KEYFRAME_SHAPE_ARROW_END_MAX (1u << 8) -#define GPU_KEYFRAME_SHAPE_ARROW_END_MIN (1u << 9) -#define GPU_KEYFRAME_SHAPE_ARROW_END_MIXED (1u << 10) -#define GPU_KEYFRAME_SHAPE_SQUARE \ - (GPU_KEYFRAME_SHAPE_CLIPPED_VERTICAL | GPU_KEYFRAME_SHAPE_CLIPPED_HORIZONTAL) - const float diagonal_scale = sqrt(0.5); const float minmax_bias = 0.7; diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_shape_vert.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_shape_vert.glsl index 78e8f40b25ee..22599ca9fe5d 100644 --- a/source/blender/gpu/shaders/gpu_shader_keyframe_shape_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_shape_vert.glsl @@ -1,16 +1,4 @@ -/* Values in GPU_shader.h. */ -#define GPU_KEYFRAME_SHAPE_DIAMOND (1u << 0) -#define GPU_KEYFRAME_SHAPE_CIRCLE (1u << 1) -#define GPU_KEYFRAME_SHAPE_CLIPPED_VERTICAL (1u << 2) -#define GPU_KEYFRAME_SHAPE_CLIPPED_HORIZONTAL (1u << 3) -#define GPU_KEYFRAME_SHAPE_INNER_DOT (1u << 4) -#define GPU_KEYFRAME_SHAPE_ARROW_END_MAX (1u << 8) -#define GPU_KEYFRAME_SHAPE_ARROW_END_MIN (1u << 9) -#define GPU_KEYFRAME_SHAPE_ARROW_END_MIXED (1u << 10) -#define GPU_KEYFRAME_SHAPE_SQUARE \ - (GPU_KEYFRAME_SHAPE_CLIPPED_VERTICAL | GPU_KEYFRAME_SHAPE_CLIPPED_HORIZONTAL) - const float line_falloff = 1.0; const float circle_scale = sqrt(2.0 / 3.1416); const float square_scale = sqrt(0.5); diff --git a/source/blender/gpu/shaders/infos/gpu_shader_2D_widget_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_2D_widget_info.hh index 7a430717f852..4432c879be98 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_2D_widget_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_2D_widget_info.hh @@ -37,7 +37,7 @@ GPU_SHADER_CREATE_INFO(gpu_shader_2D_widget_base) .do_static_compilation(true) /* gl_InstanceID is supposed to be 0 if not drawing instances, but this seems * to be violated in some drivers. For example, macOS 10.15.4 and Intel Iris - * causes T78307 when using gl_InstanceID outside of instance. */ + * causes #78307 when using gl_InstanceID outside of instance. */ .define("widgetID", "0") .push_constant(Type::VEC4, "parameters", MAX_PARAM) .additional_info("gpu_shader_2D_widget_shared"); diff --git a/source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh index c71d7cf632a6..e7a4705761f4 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_3D_point_info.hh @@ -7,16 +7,6 @@ #include "gpu_shader_create_info.hh" -GPU_SHADER_CREATE_INFO(gpu_shader_3D_point_fixed_size_varying_color) - .vertex_in(0, Type::VEC3, "pos") - .vertex_in(1, Type::VEC4, "color") - .vertex_out(smooth_color_iface) - .fragment_out(0, Type::VEC4, "fragColor") - .push_constant(Type::MAT4, "ModelViewProjectionMatrix") - .vertex_source("gpu_shader_3D_point_fixed_size_varying_color_vert.glsl") - .fragment_source("gpu_shader_point_varying_color_frag.glsl") - .do_static_compilation(true); - GPU_SHADER_CREATE_INFO(gpu_shader_3D_point_varying_size_varying_color) .vertex_in(0, Type::VEC3, "pos") .vertex_in(1, Type::VEC4, "color") diff --git a/source/blender/gpu/shaders/infos/gpu_shader_keyframe_shape_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_keyframe_shape_info.hh index f203a08eea55..eccbd50bf21e 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_keyframe_shape_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_keyframe_shape_info.hh @@ -15,6 +15,7 @@ GPU_SHADER_INTERFACE_INFO(keyframe_shape_iface, "") .flat(Type::UINT, "finalFlags"); GPU_SHADER_CREATE_INFO(gpu_shader_keyframe_shape) + .typedef_source("GPU_shader_shared.h") .vertex_in(0, Type::VEC4, "color") .vertex_in(1, Type::VEC4, "outlineColor") .vertex_in(2, Type::VEC2, "pos") diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 0833809cc42a..d5175f786dbe 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -149,7 +149,7 @@ void node_bsdf_principled(vec4 base_color, max(roughness, transmission_roughness); refraction_data.ior = ior; - /* Ref. T98190: Defines are optimizations for old compilers. + /* Ref. #98190: Defines are optimizations for old compilers. * Might become unnecessary with EEVEE-Next. */ if (do_diffuse == 0.0 && do_refraction == 0.0 && do_clearcoat != 0.0) { #ifdef PRINCIPLED_CLEARCOAT diff --git a/source/blender/gpu/tests/gpu_shader_builtin_test.cc b/source/blender/gpu/tests/gpu_shader_builtin_test.cc index 567f1370f009..bb3f9f1a2ae9 100644 --- a/source/blender/gpu/tests/gpu_shader_builtin_test.cc +++ b/source/blender/gpu/tests/gpu_shader_builtin_test.cc @@ -52,8 +52,6 @@ static void test_shader_builtin() GPU_SHADER_CFG_DEFAULT); test_compile_builtin_shader(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, GPU_SHADER_CFG_DEFAULT); - test_compile_builtin_shader(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR, - GPU_SHADER_CFG_DEFAULT); test_compile_builtin_shader(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR, GPU_SHADER_CFG_DEFAULT); test_compile_builtin_shader(GPU_SHADER_GPENCIL_STROKE, GPU_SHADER_CFG_DEFAULT); diff --git a/source/blender/gpu/tests/gpu_shader_test.cc b/source/blender/gpu/tests/gpu_shader_test.cc index 2125c67108e9..ce1397f33277 100644 --- a/source/blender/gpu/tests/gpu_shader_test.cc +++ b/source/blender/gpu/tests/gpu_shader_test.cc @@ -47,7 +47,7 @@ static void test_gpu_shader_compute_2d() EXPECT_NE(texture, nullptr); GPU_shader_bind(shader); - GPU_texture_image_bind(texture, GPU_shader_get_texture_binding(shader, "img_output")); + GPU_texture_image_bind(texture, GPU_shader_get_sampler_binding(shader, "img_output")); /* Dispatch compute task. */ GPU_compute_dispatch(shader, SIZE, SIZE, 1); @@ -93,7 +93,7 @@ static void test_gpu_shader_compute_1d() EXPECT_NE(texture, nullptr); GPU_shader_bind(shader); - GPU_texture_image_bind(texture, GPU_shader_get_texture_binding(shader, "img_output")); + GPU_texture_image_bind(texture, GPU_shader_get_sampler_binding(shader, "img_output")); /* Dispatch compute task. */ GPU_compute_dispatch(shader, SIZE, 1, 1); @@ -142,7 +142,7 @@ static void test_gpu_shader_compute_vbo() GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); GPUVertBuf *vbo = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_DEVICE_ONLY); GPU_vertbuf_data_alloc(vbo, SIZE); - GPU_vertbuf_bind_as_ssbo(vbo, GPU_shader_get_ssbo(shader, "out_positions")); + GPU_vertbuf_bind_as_ssbo(vbo, GPU_shader_get_ssbo_binding(shader, "out_positions")); /* Dispatch compute task. */ GPU_compute_dispatch(shader, SIZE, 1, 1); @@ -151,8 +151,8 @@ static void test_gpu_shader_compute_vbo() GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE); /* Download the vertex buffer. */ - const float *data = static_cast(GPU_vertbuf_read(vbo)); - ASSERT_NE(data, nullptr); + float data[SIZE * 4]; + GPU_vertbuf_read(vbo, data); for (int index = 0; index < SIZE; index++) { float expected_value = index; EXPECT_FLOAT_EQ(data[index * 4 + 0], expected_value); @@ -186,7 +186,7 @@ static void test_gpu_shader_compute_ibo() /* Construct IBO. */ GPUIndexBuf *ibo = GPU_indexbuf_build_on_device(SIZE); - GPU_indexbuf_bind_as_ssbo(ibo, GPU_shader_get_ssbo(shader, "out_indices")); + GPU_indexbuf_bind_as_ssbo(ibo, GPU_shader_get_ssbo_binding(shader, "out_indices")); /* Dispatch compute task. */ GPU_compute_dispatch(shader, SIZE, 1, 1); @@ -195,8 +195,8 @@ static void test_gpu_shader_compute_ibo() GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE); /* Download the index buffer. */ - const uint32_t *data = GPU_indexbuf_read(ibo); - ASSERT_NE(data, nullptr); + uint32_t data[SIZE]; + GPU_indexbuf_read(ibo, data); for (int index = 0; index < SIZE; index++) { uint32_t expected = index; EXPECT_EQ(data[index], expected); @@ -228,7 +228,7 @@ static void test_gpu_shader_compute_ssbo() /* Construct IBO. */ GPUStorageBuf *ssbo = GPU_storagebuf_create_ex( SIZE * sizeof(uint32_t), nullptr, GPU_USAGE_DEVICE_ONLY, __func__); - GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo(shader, "out_indices")); + GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo_binding(shader, "out_indices")); /* Dispatch compute task. */ GPU_compute_dispatch(shader, SIZE, 1, 1); @@ -264,8 +264,8 @@ static void test_gpu_shader_ssbo_binding() EXPECT_NE(shader, nullptr); GPU_shader_bind(shader); - EXPECT_EQ(0, GPU_shader_get_ssbo(shader, "data0")); - EXPECT_EQ(1, GPU_shader_get_ssbo(shader, "data1")); + EXPECT_EQ(0, GPU_shader_get_ssbo_binding(shader, "data0")); + EXPECT_EQ(1, GPU_shader_get_ssbo_binding(shader, "data1")); /* Cleanup. */ GPU_shader_unbind(); diff --git a/source/blender/gpu/vulkan/vk_index_buffer.cc b/source/blender/gpu/vulkan/vk_index_buffer.cc index ca3ce48dc64e..70387bd0fceb 100644 --- a/source/blender/gpu/vulkan/vk_index_buffer.cc +++ b/source/blender/gpu/vulkan/vk_index_buffer.cc @@ -17,9 +17,8 @@ void VKIndexBuffer::bind_as_ssbo(uint /*binding*/) { } -const uint32_t *VKIndexBuffer::read() const +void VKIndexBuffer::read(uint32_t * /*data*/) const { - return 0; } void VKIndexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*data*/) diff --git a/source/blender/gpu/vulkan/vk_index_buffer.hh b/source/blender/gpu/vulkan/vk_index_buffer.hh index 94a584086e01..7586b49ff212 100644 --- a/source/blender/gpu/vulkan/vk_index_buffer.hh +++ b/source/blender/gpu/vulkan/vk_index_buffer.hh @@ -17,7 +17,7 @@ class VKIndexBuffer : public IndexBuf { void bind_as_ssbo(uint binding) override; - const uint32_t *read() const override; + void read(uint32_t *data) const override; void update_sub(uint start, uint len, const void *data) override; diff --git a/source/blender/gpu/vulkan/vk_memory.cc b/source/blender/gpu/vulkan/vk_memory.cc new file mode 100644 index 000000000000..e02ca0b014ff --- /dev/null +++ b/source/blender/gpu/vulkan/vk_memory.cc @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2023 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#include "vk_memory.hh" + +#include "MEM_guardedalloc.h" + +namespace blender::gpu { + +#ifdef WITH_VULKAN_GUARDEDALLOC + +void *vk_memory_allocation(void *user_data, + size_t size, + size_t alignment, + VkSystemAllocationScope /*scope*/) +{ + const char *name = static_cast(const_cast(user_data)); + if (alignment) { + return MEM_mallocN_aligned(size, alignment, name); + } + return MEM_mallocN(size, name); +} + +void *vk_memory_reallocation(void *user_data, + void *original, + size_t size, + size_t /*alignment*/, + VkSystemAllocationScope /*scope*/) +{ + const char *name = static_cast(const_cast(user_data)); + return MEM_reallocN_id(original, size, name); +} + +void vk_memory_free(void * /*user_data*/, void *memory) +{ + MEM_freeN(memory); +} + +#endif + +} // namespace blender::gpu diff --git a/source/blender/gpu/vulkan/vk_memory.hh b/source/blender/gpu/vulkan/vk_memory.hh new file mode 100644 index 000000000000..991801de7b4b --- /dev/null +++ b/source/blender/gpu/vulkan/vk_memory.hh @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2023 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#ifdef __APPLE__ +# include +#else +# include +#endif + +namespace blender::gpu { + +/** + * `VK_ALLOCATION_CALLBACKS` initializes allocation callbacks for host allocations. + * The macro creates a local static variable with the name `vk_allocation_callbacks` + * that can be passed to VULKAN API functions that expect + * `const VkAllocationCallbacks *pAllocator`. + * + * When Blender is compiled with `WITH_VULKAN_GUARDEDALLOC` this will use + * `MEM_guardedalloc` for host allocations that the driver does on behalf + * of blender. More internal allocations are still being allocated via the + * implementation inside the VULKAN device driver. + * + * When `WITH_VULKAN_GUARDEDALLOC=Off` the memory allocation implemented + * in the vulkan device driver is used for both internal and application + * focused memory operations. + */ + +#ifdef WITH_VULKAN_GUARDEDALLOC +void *vk_memory_allocation(void *user_data, + size_t size, + size_t alignment, + VkSystemAllocationScope scope); +void *vk_memory_reallocation( + void *user_data, void *original, size_t size, size_t alignment, VkSystemAllocationScope scope); +void vk_memory_free(void *user_data, void *memory); + +constexpr VkAllocationCallbacks vk_allocation_callbacks_init(const char *name) +{ + VkAllocationCallbacks callbacks = {}; + callbacks.pUserData = const_cast(name); + callbacks.pfnAllocation = vk_memory_allocation; + callbacks.pfnReallocation = vk_memory_reallocation; + callbacks.pfnFree = vk_memory_free; + callbacks.pfnInternalAllocation = nullptr; + callbacks.pfnInternalFree = nullptr; + return callbacks; +} + +# define VK_ALLOCATION_CALLBACKS \ + static constexpr const VkAllocationCallbacks vk_allocation_callbacks_ = \ + vk_allocation_callbacks_init(__func__); \ + static constexpr const VkAllocationCallbacks *vk_allocation_callbacks = \ + &vk_allocation_callbacks_; +#else +# define VK_ALLOCATION_CALLBACKS \ + static constexpr const VkAllocationCallbacks *vk_allocation_callbacks = nullptr; +#endif + +} // namespace blender::gpu diff --git a/source/blender/gpu/vulkan/vk_shader.cc b/source/blender/gpu/vulkan/vk_shader.cc index 17c06fb42e69..3f145bd47632 100644 --- a/source/blender/gpu/vulkan/vk_shader.cc +++ b/source/blender/gpu/vulkan/vk_shader.cc @@ -8,6 +8,7 @@ #include "vk_shader.hh" #include "vk_backend.hh" +#include "vk_memory.hh" #include "vk_shader_log.hh" #include "BLI_string_utils.h" @@ -559,6 +560,8 @@ Vector VKShader::compile_glsl_to_spirv(Span sources, void VKShader::build_shader_module(Span spirv_module, VkShaderModule *r_shader_module) { + VK_ALLOCATION_CALLBACKS; + VkShaderModuleCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; create_info.codeSize = spirv_module.size() * sizeof(uint32_t); @@ -567,7 +570,7 @@ void VKShader::build_shader_module(Span spirv_module, VkShaderModule * VKContext &context = *static_cast(VKContext::get()); VkResult result = vkCreateShaderModule( - context.device_get(), &create_info, nullptr, r_shader_module); + context.device_get(), &create_info, vk_allocation_callbacks, r_shader_module); if (result != VK_SUCCESS) { compilation_failed_ = true; *r_shader_module = VK_NULL_HANDLE; @@ -581,21 +584,23 @@ VKShader::VKShader(const char *name) : Shader(name) VKShader::~VKShader() { + VK_ALLOCATION_CALLBACKS + VkDevice device = context_->device_get(); if (vertex_module_ != VK_NULL_HANDLE) { - vkDestroyShaderModule(device, vertex_module_, nullptr); + vkDestroyShaderModule(device, vertex_module_, vk_allocation_callbacks); vertex_module_ = VK_NULL_HANDLE; } if (geometry_module_ != VK_NULL_HANDLE) { - vkDestroyShaderModule(device, geometry_module_, nullptr); + vkDestroyShaderModule(device, geometry_module_, vk_allocation_callbacks); geometry_module_ = VK_NULL_HANDLE; } if (fragment_module_ != VK_NULL_HANDLE) { - vkDestroyShaderModule(device, fragment_module_, nullptr); + vkDestroyShaderModule(device, fragment_module_, vk_allocation_callbacks); fragment_module_ = VK_NULL_HANDLE; } if (compute_module_ != VK_NULL_HANDLE) { - vkDestroyShaderModule(device, compute_module_, nullptr); + vkDestroyShaderModule(device, compute_module_, vk_allocation_callbacks); compute_module_ = VK_NULL_HANDLE; } } diff --git a/source/blender/gpu/vulkan/vk_shader.hh b/source/blender/gpu/vulkan/vk_shader.hh index 2fca185ea939..6cc0e0c77e54 100644 --- a/source/blender/gpu/vulkan/vk_shader.hh +++ b/source/blender/gpu/vulkan/vk_shader.hh @@ -35,6 +35,7 @@ class VKShader : public Shader { void fragment_shader_from_glsl(MutableSpan sources) override; void compute_shader_from_glsl(MutableSpan sources) override; bool finalize(const shader::ShaderCreateInfo *info = nullptr) override; + void warm_cache(int limit) override{}; void transform_feedback_names_set(Span name_list, eGPUShaderTFBType geom_type) override; diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.cc b/source/blender/gpu/vulkan/vk_vertex_buffer.cc index 3931c9274992..f2326ddb1347 100644 --- a/source/blender/gpu/vulkan/vk_vertex_buffer.cc +++ b/source/blender/gpu/vulkan/vk_vertex_buffer.cc @@ -32,14 +32,8 @@ void VKVertexBuffer::update_sub(uint /*start*/, uint /*len*/, const void * /*dat { } -const void *VKVertexBuffer::read() const +void VKVertexBuffer::read(void * /*data*/) const { - return nullptr; -} - -void *VKVertexBuffer::unmap(const void * /*mapped_data*/) const -{ - return nullptr; } void VKVertexBuffer::acquire_data() diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.hh b/source/blender/gpu/vulkan/vk_vertex_buffer.hh index e42407871383..ebc3e105553a 100644 --- a/source/blender/gpu/vulkan/vk_vertex_buffer.hh +++ b/source/blender/gpu/vulkan/vk_vertex_buffer.hh @@ -20,8 +20,7 @@ class VKVertexBuffer : public VertBuf { void wrap_handle(uint64_t handle) override; void update_sub(uint start, uint len, const void *data) override; - const void *read() const override; - void *unmap(const void *mapped_data) const override; + void read(void *data) const override; protected: void acquire_data() override; diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index c467e48d21e6..1560567ba8dd 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -398,7 +398,7 @@ static void execute_posetree(struct Depsgraph *depsgraph, * local transform of the segment itself. */ copy_m4_m4(rootmat, pchan->parent->pose_mat); /* However, we do not want to get (i.e. reverse) parent's scale, - * as it generates T31008 kind of nasty bugs. */ + * as it generates #31008 kind of nasty bugs. */ normalize_m4(rootmat); } else { diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 06f7770d2672..129b265f8543 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -49,7 +49,7 @@ typedef struct DDSData { /* WARNING: Keep explicit value assignments here, * this file is included in areas where not all format defines are set * (e.g. intern/dds only get WITH_DDS, even if TIFF, HDR etc are also defined). - * See T46524. */ + * See #46524. */ /** #ImBuf.ftype flag, main image types. */ enum eImbFileType { diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 94c0555dcf0e..a6edcc5977e7 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -593,7 +593,7 @@ static int startffmpeg(struct anim *anim) anim->duration_in_frames = video_stream->nb_frames; /* Sanity check on the detected duration. This is to work around corruption like reported in - * T68091. */ + * #68091. */ if (frame_rate.den != 0 && pFormatCtx->duration > 0) { double stream_sec = anim->duration_in_frames * av_q2d(frame_rate); double container_sec = pFormatCtx->duration / (double)AV_TIME_BASE; @@ -927,7 +927,7 @@ static bool ffmpeg_pts_isect(int64_t pts_start, int64_t pts_end, int64_t pts_to_ static AVFrame *ffmpeg_frame_by_pts_get(struct anim *anim, int64_t pts_to_search) { /* NOTE: `frame->pts + frame->pkt_duration` does not always match pts of next frame. - * See footage from T86361. Here it is OK to use, because PTS must match current or backup frame. + * See footage from #86361. Here it is OK to use, because PTS must match current or backup frame. * If there is no current frame, return NULL. */ if (!anim->pFrame_complete) { @@ -986,7 +986,7 @@ static int ffmpeg_decode_video_frame(struct anim *anim) av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n"); /* Sometimes, decoder returns more than one frame per sent packet. Check if frames are available. - * This frames must be read, otherwise decoding will fail. See T91405. */ + * This frames must be read, otherwise decoding will fail. See #91405. */ anim->pFrame_complete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0; if (anim->pFrame_complete) { av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE FROM CODEC BUFFER\n"); @@ -1175,8 +1175,7 @@ static void ffmpeg_decode_video_frame_scan(struct anim *anim, int64_t pts_to_sea /* Wrapper over av_seek_frame(), for formats that doesn't have its own read_seek() or * read_seek2() functions defined. When seeking in these formats, rule to seek to last * necessary I-frame is not honored. It is not even guaranteed that I-frame, that must be - * decoded will be read. See https://trac.ffmpeg.org/ticket/1607 and - * https://developer.blender.org/T86944. */ + * decoded will be read. See https://trac.ffmpeg.org/ticket/1607 & #86944. */ static int ffmpeg_generic_seek_workaround(struct anim *anim, int64_t *requested_pts, int64_t pts_to_search) @@ -1413,7 +1412,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ ffmpeg_decode_video_frame_scan(anim, pts_to_search); - /* Update resolution as it can change per-frame with WebM. See T100741 & T100081. */ + /* Update resolution as it can change per-frame with WebM. See #100741 & #100081. */ anim->x = anim->pCodecCtx->width; anim->y = anim->pCodecCtx->height; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 9f14ca0d5968..344dccfe9192 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -2054,7 +2054,7 @@ void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, if (STREQ(from_colorspace, to_colorspace)) { /* Because this function always takes a byte buffer and returns a float buffer, it must * always do byte-to-float conversion of some kind. To avoid threading overhead - * IMB_buffer_float_from_byte is used when color spaces are identical. See T51002. + * IMB_buffer_float_from_byte is used when color spaces are identical. See #51002. */ IMB_buffer_float_from_byte(float_buffer, byte_buffer, diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index c17931827f74..e7d7ae973e4a 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1493,7 +1493,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa * like, MX or NZ, which is basically has structure of * * - * This is a bit silly, but see file from T35658. + * This is a bit silly, but see file from #35658. * * Here we do some magic to distinguish such cases. */ diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 42c19ce1a7e4..6332310f43ce 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -846,7 +846,7 @@ static void q_scale_float( * Should be comparable in speed to the ImBuf ..._fast functions at least * for byte-buffers. * - * NOTE: disabled, due to unacceptable inaccuracy and quality loss, see bug T18609 (ton) + * NOTE: disabled, due to unacceptable inaccuracy and quality loss, see bug #18609 (ton) */ static bool q_scale_linear_interpolation(struct ImBuf *ibuf, int newx, int newy) { @@ -998,14 +998,14 @@ static ImBuf *scaledownx(struct ImBuf *ibuf, int newx) if (do_rect) { // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); - BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug T26502. */ + BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug #26502. */ imb_freerectImBuf(ibuf); ibuf->mall |= IB_rect; ibuf->rect = (uint *)_newrect; } if (do_float) { // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size); - BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug T26502. */ + BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug #26502. */ imb_freerectfloatImBuf(ibuf); ibuf->mall |= IB_rectfloat; ibuf->rect_float = _newrectf; @@ -1140,14 +1140,14 @@ static ImBuf *scaledowny(struct ImBuf *ibuf, int newy) if (do_rect) { // printf("%ld %ld\n", (uchar *)rect - ((uchar *)ibuf->rect), rect_size); - BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug T26502. */ + BLI_assert((uchar *)rect - ((uchar *)ibuf->rect) == rect_size); /* see bug #26502. */ imb_freerectImBuf(ibuf); ibuf->mall |= IB_rect; ibuf->rect = (uint *)_newrect; } if (do_float) { // printf("%ld %ld\n", rectf - ibuf->rect_float, rect_size); - BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug T26502. */ + BLI_assert((rectf - ibuf->rect_float) == rect_size); /* see bug #26502. */ imb_freerectfloatImBuf(ibuf); ibuf->mall |= IB_rectfloat; ibuf->rect_float = (float *)_newrectf; @@ -1196,7 +1196,7 @@ static ImBuf *scaleupx(struct ImBuf *ibuf, int newx) newrectf = _newrectf; /* Special case, copy all columns, needed since the scaling logic assumes there is at least - * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */ + * two rows to interpolate between causing out of bounds read for 1px images, see #70356. */ if (UNLIKELY(ibuf->x == 1)) { if (do_rect) { for (y = ibuf->y; y > 0; y--) { @@ -1400,7 +1400,7 @@ static ImBuf *scaleupy(struct ImBuf *ibuf, int newy) skipx = 4 * ibuf->x; /* Special case, copy all rows, needed since the scaling logic assumes there is at least - * two rows to interpolate between causing out of bounds read for 1px images, see T70356. */ + * two rows to interpolate between causing out of bounds read for 1px images, see #70356. */ if (UNLIKELY(ibuf->y == 1)) { if (do_rect) { for (y = newy; y > 0; y--) { @@ -1648,7 +1648,7 @@ bool IMB_scaleImBuf(struct ImBuf *ibuf, uint newx, uint newy) scalefast_Z_ImBuf(ibuf, newx, newy); /* try to scale common cases in a fast way */ - /* disabled, quality loss is unacceptable, see report T18609 (ton) */ + /* disabled, quality loss is unacceptable, see report #18609 (ton) */ if (0 && q_scale_linear_interpolation(ibuf, newx, newy)) { return true; } diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index d535bd005019..29bac03654f4 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -397,7 +397,7 @@ static ImBuf *thumb_create_ex(const char *file_path, if (img->x > tsize || img->y > tsize) { float scale = MIN2((float)tsize / (float)img->x, (float)tsize / (float)img->y); - /* Scaling down must never assign zero width/height, see: T89868. */ + /* Scaling down must never assign zero width/height, see: #89868. */ short ex = MAX2(1, (short)(img->x * scale)); short ey = MAX2(1, (short)(img->y * scale)); /* Save some time by only scaling byte buf */ diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 77d42d905c7e..e7eee7a43be7 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -530,7 +530,7 @@ static void get_loop_normals(struct Mesh *mesh, normals.clear(); /* If all polygons are smooth shaded, and there are no custom normals, we don't need to export - * normals at all. This is also done by other software, see T71246. */ + * normals at all. This is also done by other software, see #71246. */ if (!has_flat_shaded_poly && !CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL) && (mesh->flag & ME_AUTOSMOOTH) == 0) { return; diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index 9e5182c53d4d..baa03ca915b4 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -420,7 +420,7 @@ static void read_custom_data_mcols(const std::string &iobject_full_name, /* The colors can go through two layers of indexing. Often the 'indices' * array doesn't do anything (i.e. indices[n] = n), but when it does, it's - * important. Blender 2.79 writes indices incorrectly (see T53745), which + * important. Blender 2.79 writes indices incorrectly (see #53745), which * is why we have to check for indices->size() > 0 */ bool use_dual_indexing = is_facevarying && indices->size() > 0; diff --git a/source/blender/io/alembic/intern/abc_reader_archive.h b/source/blender/io/alembic/intern/abc_reader_archive.h index 18f36922a1ba..685da5af5dc5 100644 --- a/source/blender/io/alembic/intern/abc_reader_archive.h +++ b/source/blender/io/alembic/intern/abc_reader_archive.h @@ -16,7 +16,7 @@ struct Main; namespace blender::io::alembic { /* Wrappers around input and output archives. The goal is to be able to use - * streams so that unicode paths work on Windows (T49112), and to make sure that + * streams so that unicode paths work on Windows (#49112), and to make sure that * the stream objects remain valid as long as the archives are open. */ diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 11fb191b31cf..e52b30cf5eaf 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -202,7 +202,7 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) poly.totloop = face_size; /* Polygons are always assumed to be smooth-shaded. If the Alembic mesh should be flat-shaded, - * this is encoded in custom loop normals. See T71246. */ + * this is encoded in custom loop normals. See #71246. */ poly.flag |= ME_SMOOTH; /* NOTE: Alembic data is stored in the reverse order. */ @@ -215,7 +215,7 @@ static void read_mpolys(CDStreamConfig &config, const AbcMeshData &mesh_data) if (f > 0 && loop.v == last_vertex_index) { /* This face is invalid, as it has consecutive loops from the same vertex. This is caused - * by invalid geometry in the Alembic file, such as in T76514. */ + * by invalid geometry in the Alembic file, such as in #76514. */ seen_invalid_geometry = true; } last_vertex_index = loop.v; @@ -732,7 +732,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, } else { /* If the face count changed (e.g. by triangulation), only read points. - * This prevents crash from T49813. + * This prevents crash from #49813. * TODO(kevin): perhaps find a better way to do this? */ if (face_counts->size() != existing_mesh->totpoly || face_indices->size() != existing_mesh->totloop) { @@ -1065,7 +1065,7 @@ Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh, } else { /* If the face count changed (e.g. by triangulation), only read points. - * This prevents crash from T49813. + * This prevents crash from #49813. * TODO(kevin): perhaps find a better way to do this? */ if (face_counts->size() != existing_mesh->totpoly || face_indices->size() != existing_mesh->totloop) { diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index 826d7864067e..3d12abe3cda5 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -1189,7 +1189,7 @@ void AnimationImporter::translate_Animations( for (uint j = 0; j < matBinds.getCount(); j++) { const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial(); const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]); - if (ef != nullptr) { /* can be NULL T28909. */ + if (ef != nullptr) { /* can be NULL #28909. */ Material *ma = uid_material_map[matuid]; if (!ma) { fprintf(stderr, @@ -1445,7 +1445,7 @@ AnimationImporter::AnimMix *AnimationImporter::get_animation_type( for (uint j = 0; j < matBinds.getCount(); j++) { const COLLADAFW::UniqueId &matuid = matBinds[j].getReferencedMaterial(); const COLLADAFW::Effect *ef = (COLLADAFW::Effect *)(FW_object_map[matuid]); - if (ef != nullptr) { /* can be NULL T28909. */ + if (ef != nullptr) { /* can be NULL #28909. */ const COLLADAFW::CommonEffectPointerArray &commonEffects = ef->getCommonEffects(); if (!commonEffects.empty()) { COLLADAFW::EffectCommon *efc = commonEffects[0]; diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 5c1b9a1a2947..49ed37ba9768 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -265,7 +265,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = nullptr, Object *parob = nullptr) { - /* The split in T29246, root_map must point at actual root when + /* The split in #29246, root_map must point at actual root when * calculating bones in apply_curves_as_matrix. - actual root is the root node. * This has to do with inverse bind poses being world space * (the sources for skinned bones' rest-poses) and the way diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index 51fc8377c0cf..b95c6110a0ec 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -101,7 +101,7 @@ void GeometryExporter::operator()(Object *ob) createLooseEdgeList(ob, me, geom_id); - /* Only create Polylists if number of faces > 0 */ + /* Only create poly-lists if number of faces > 0. */ if (me->totface > 0) { /* XXX slow */ if (ob->totcol) { diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt index b123eb251abd..e7a884087b10 100644 --- a/source/blender/io/usd/CMakeLists.txt +++ b/source/blender/io/usd/CMakeLists.txt @@ -83,6 +83,7 @@ set(SRC intern/usd_reader_mesh.cc intern/usd_reader_nurbs.cc intern/usd_reader_prim.cc + intern/usd_reader_shape.cc intern/usd_reader_stage.cc intern/usd_reader_volume.cc intern/usd_reader_xform.cc @@ -111,6 +112,7 @@ set(SRC intern/usd_reader_mesh.h intern/usd_reader_nurbs.h intern/usd_reader_prim.h + intern/usd_reader_shape.h intern/usd_reader_stage.h intern/usd_reader_volume.h intern/usd_reader_xform.h @@ -127,6 +129,8 @@ list(APPEND LIB ${BOOST_LIBRARIES} ${BOOST_PYTHON_LIBRARIES} ${PYTHON_LIBRARIES} + ${USD_LIBRARIES} + ${TBB_LIBRARIES} ) if(WITH_OPENVDB) @@ -141,31 +145,10 @@ endif() blender_add_lib(bf_usd "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") -if(WIN32) - set_property(TARGET bf_usd APPEND_STRING PROPERTY INTERFACE_LINK_OPTIONS "$<$:/WHOLEARCHIVE:${USD_DEBUG_LIB}>") - set_property(TARGET bf_usd APPEND_STRING PROPERTY INTERFACE_LINK_OPTIONS "$<$:/WHOLEARCHIVE:${USD_RELEASE_LIB}>") - set_property(TARGET bf_usd APPEND_STRING PROPERTY INTERFACE_LINK_OPTIONS "$<$:/WHOLEARCHIVE:${USD_RELEASE_LIB}>") - set_property(TARGET bf_usd APPEND_STRING PROPERTY INTERFACE_LINK_OPTIONS "$<$:/WHOLEARCHIVE:${USD_RELEASE_LIB}>") -endif() - -# Source: -# https://github.com/PixarAnimationStudios/USD/blob/master/BUILDING.md#linking-whole-archives -if(WIN32) - target_link_libraries(bf_usd INTERFACE ${USD_LIBRARIES}) -elseif(APPLE) - target_link_libraries(bf_usd INTERFACE -Wl,-force_load ${USD_LIBRARIES}) -elseif(UNIX) - target_link_libraries(bf_usd INTERFACE "-Wl,--whole-archive ${USD_LIBRARIES} -Wl,--no-whole-archive ${TBB_LIBRARIES}") -else() - message(FATAL_ERROR "Unknown how to link USD with your compiler ${CMAKE_CXX_COMPILER_ID}") -endif() - -target_link_libraries(bf_usd INTERFACE ${TBB_LIBRARIES}) - if(WITH_GTESTS) set(TEST_SRC - tests/usd_stage_creation_test.cc tests/usd_export_test.cc + tests/usd_stage_creation_test.cc tests/usd_tests_common.cc tests/usd_tests_common.h diff --git a/source/blender/io/usd/intern/usd_reader_shape.cc b/source/blender/io/usd/intern/usd_reader_shape.cc new file mode 100644 index 000000000000..a1082e8d734e --- /dev/null +++ b/source/blender/io/usd/intern/usd_reader_shape.cc @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2023 Nvidia. All rights reserved. */ + +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_object.h" + +#include "DNA_cachefile_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_windowmanager_types.h" + +#include "WM_api.h" + +#include "usd_reader_shape.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace blender::io::usd { + +USDShapeReader::USDShapeReader(const pxr::UsdPrim &prim, + const USDImportParams &import_params, + const ImportSettings &settings) + : USDGeomReader(prim, import_params, settings) +{ +} + +void USDShapeReader::create_object(Main *bmain, double /*motionSampleTime*/) +{ + Mesh *mesh = BKE_mesh_add(bmain, name_.c_str()); + object_ = BKE_object_add_only_object(bmain, OB_MESH, name_.c_str()); + object_->data = mesh; +} + +void USDShapeReader::read_object_data(Main *bmain, double motionSampleTime) +{ + Mesh *mesh = (Mesh *)object_->data; + Mesh *read_mesh = this->read_mesh( + mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr); + + if (read_mesh != mesh) { + BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_); + if (is_time_varying()) { + USDGeomReader::add_cache_modifier(); + } + } + + USDXformReader::read_object_data(bmain, motionSampleTime); +} + +template +void USDShapeReader::read_values(const double motionSampleTime, + pxr::VtVec3fArray &positions, + pxr::VtIntArray &face_indices, + pxr::VtIntArray &face_counts) const +{ + Adapter adapter; + pxr::VtValue points_val = adapter.GetPoints(prim_, motionSampleTime); + + if (points_val.IsHolding()) { + positions = points_val.Get(); + } + + pxr::VtValue topology_val = adapter.GetTopology(prim_, pxr::SdfPath(), motionSampleTime); + + if (topology_val.IsHolding()) { + const pxr::HdMeshTopology &topology = topology_val.Get(); + face_counts = topology.GetFaceVertexCounts(); + face_indices = topology.GetFaceVertexIndices(); + } +} + +bool USDShapeReader::read_mesh_values(double motionSampleTime, + pxr::VtVec3fArray &positions, + pxr::VtIntArray &face_indices, + pxr::VtIntArray &face_counts) const +{ + if (prim_.IsA()) { + read_values( + motionSampleTime, positions, face_indices, face_counts); + return true; + } + + if (prim_.IsA()) { + read_values( + motionSampleTime, positions, face_indices, face_counts); + return true; + } + + if (prim_.IsA()) { + read_values( + motionSampleTime, positions, face_indices, face_counts); + return true; + } + + if (prim_.IsA()) { + read_values( + motionSampleTime, positions, face_indices, face_counts); + return true; + } + + if (prim_.IsA()) { + read_values( + motionSampleTime, positions, face_indices, face_counts); + return true; + } + + WM_reportf(RPT_ERROR, + "Unhandled Gprim type: %s (%s)", + prim_.GetTypeName().GetText(), + prim_.GetPath().GetText()); + return false; +} + +Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh, + double motionSampleTime, + int /*read_flag*/, + const char ** /*err_str*/) +{ + pxr::VtIntArray face_indices; + pxr::VtIntArray face_counts; + + if (!prim_) { + return existing_mesh; + } + + /* Should have a good set of data by this point-- copy over. */ + Mesh *active_mesh = mesh_from_prim(existing_mesh, motionSampleTime, face_indices, face_counts); + if (active_mesh == existing_mesh) { + return existing_mesh; + } + + MutableSpan polys = active_mesh->polys_for_write(); + MutableSpan loops = active_mesh->loops_for_write(); + + const char should_smooth = prim_.IsA() ? 0 : ME_SMOOTH; + + int loop_index = 0; + for (int i = 0; i < face_counts.size(); i++) { + const int face_size = face_counts[i]; + + MPoly &poly = polys[i]; + poly.loopstart = loop_index; + poly.totloop = face_size; + + /* Don't smooth-shade cubes; we're not worrying about sharpness for Gprims. */ + poly.flag |= should_smooth; + + for (int f = 0; f < face_size; ++f, ++loop_index) { + loops[loop_index].v = face_indices[loop_index]; + } + } + + BKE_mesh_calc_edges(active_mesh, false, false); + return active_mesh; +} + +Mesh *USDShapeReader::mesh_from_prim(Mesh *existing_mesh, + double motionSampleTime, + pxr::VtIntArray &face_indices, + pxr::VtIntArray &face_counts) const +{ + pxr::VtVec3fArray positions; + + if (!read_mesh_values(motionSampleTime, positions, face_indices, face_counts)) { + return existing_mesh; + } + + const bool poly_counts_match = existing_mesh ? face_counts.size() == existing_mesh->totpoly : + false; + const bool position_counts_match = existing_mesh ? positions.size() == existing_mesh->totvert : + false; + + Mesh *active_mesh = nullptr; + if (!position_counts_match || !poly_counts_match) { + active_mesh = BKE_mesh_new_nomain_from_template( + existing_mesh, positions.size(), 0, 0, face_indices.size(), face_counts.size()); + } + else { + active_mesh = existing_mesh; + } + + MutableSpan vert_positions = active_mesh->vert_positions_for_write(); + + for (int i = 0; i < positions.size(); i++) { + vert_positions[i][0] = positions[i][0]; + vert_positions[i][1] = positions[i][1]; + vert_positions[i][2] = positions[i][2]; + } + + return active_mesh; +} + +bool USDShapeReader::is_time_varying() +{ + if (prim_.IsA()) { + pxr::UsdGeomCapsule geom(prim_); + return (geom.GetAxisAttr().ValueMightBeTimeVarying() || + geom.GetHeightAttr().ValueMightBeTimeVarying() || + geom.GetRadiusAttr().ValueMightBeTimeVarying()); + } + + if (prim_.IsA()) { + pxr::UsdGeomCylinder geom(prim_); + return (geom.GetAxisAttr().ValueMightBeTimeVarying() || + geom.GetHeightAttr().ValueMightBeTimeVarying() || + geom.GetRadiusAttr().ValueMightBeTimeVarying()); + } + + if (prim_.IsA()) { + pxr::UsdGeomCone geom(prim_); + return (geom.GetAxisAttr().ValueMightBeTimeVarying() || + geom.GetHeightAttr().ValueMightBeTimeVarying() || + geom.GetRadiusAttr().ValueMightBeTimeVarying()); + } + + if (prim_.IsA()) { + pxr::UsdGeomCube geom(prim_); + return geom.GetSizeAttr().ValueMightBeTimeVarying(); + } + + if (prim_.IsA()) { + pxr::UsdGeomSphere geom(prim_); + return geom.GetRadiusAttr().ValueMightBeTimeVarying(); + } + + WM_reportf(RPT_ERROR, + "Unhandled Gprim type: %s (%s)", + prim_.GetTypeName().GetText(), + prim_.GetPath().GetText()); + return false; +} + +} // namespace blender::io::usd diff --git a/source/blender/io/usd/intern/usd_reader_shape.h b/source/blender/io/usd/intern/usd_reader_shape.h new file mode 100644 index 000000000000..b6135f31b2f4 --- /dev/null +++ b/source/blender/io/usd/intern/usd_reader_shape.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2023 Nvidia. All rights reserved. */ + +#pragma once + +#include "usd.h" +#include "usd_reader_geom.h" +#include "usd_reader_xform.h" +#include + +struct Mesh; + +namespace blender::io::usd { + +/* + * Read USDGeom primitive shapes as Blender Meshes. This class uses the same adapter functions + * as the GL viewport to generate geometry for each of the supported types. + */ +class USDShapeReader : public USDGeomReader { + private: + /* Template required to read mesh information out of Shape prims, + * as each prim type has a separate subclass. */ + template + void read_values(double motionSampleTime, + pxr::VtVec3fArray &positions, + pxr::VtIntArray &face_indices, + pxr::VtIntArray &face_counts) const; + + /* Wrapper for the templated method read_values, calling the correct template + * instantiation based on the introspected prim type. */ + bool read_mesh_values(double motionSampleTime, + pxr::VtVec3fArray &positions, + pxr::VtIntArray &face_indices, + pxr::VtIntArray &face_counts) const; + + /* Read the pxr:UsdGeomMesh values and convert them to a Blender Mesh, + * also returning face_indices and counts for further loop processing. */ + Mesh *mesh_from_prim(Mesh *existing_mesh, + double motionSampleTime, + pxr::VtIntArray &face_indices, + pxr::VtIntArray &face_counts) const; + + public: + USDShapeReader(const pxr::UsdPrim &prim, + const USDImportParams &import_params, + const ImportSettings &settings); + + void create_object(Main *bmain, double /*motionSampleTime*/) override; + void read_object_data(Main *bmain, double motionSampleTime) override; + Mesh *read_mesh(Mesh *existing_mesh, + double motionSampleTime, + int /*read_flag*/, + const char ** /*err_str*/) override; + bool is_time_varying(); + + virtual bool topology_changed(const Mesh * /*existing_mesh*/, double /*motionSampleTime*/) + { + return false; + }; +}; + +} // namespace blender::io::usd diff --git a/source/blender/io/usd/intern/usd_reader_stage.cc b/source/blender/io/usd/intern/usd_reader_stage.cc index 393d8acba4a3..ef3608ea9364 100644 --- a/source/blender/io/usd/intern/usd_reader_stage.cc +++ b/source/blender/io/usd/intern/usd_reader_stage.cc @@ -9,16 +9,22 @@ #include "usd_reader_mesh.h" #include "usd_reader_nurbs.h" #include "usd_reader_prim.h" +#include "usd_reader_shape.h" #include "usd_reader_volume.h" #include "usd_reader_xform.h" #include #include #include +#include +#include +#include #include +#include #include #include #include +#include #include #include @@ -57,8 +63,18 @@ bool USDStageReader::valid() const return stage_; } +bool USDStageReader::is_primitive_prim(const pxr::UsdPrim &prim) const +{ + return (prim.IsA() || prim.IsA() || + prim.IsA() || prim.IsA() || + prim.IsA()); +} + USDPrimReader *USDStageReader::create_reader_if_allowed(const pxr::UsdPrim &prim) { + if (params_.import_shapes && is_primitive_prim(prim)) { + return new USDShapeReader(prim, params_, settings_); + } if (params_.import_cameras && prim.IsA()) { return new USDCameraReader(prim, params_, settings_); } @@ -91,6 +107,9 @@ USDPrimReader *USDStageReader::create_reader_if_allowed(const pxr::UsdPrim &prim USDPrimReader *USDStageReader::create_reader(const pxr::UsdPrim &prim) { + if (is_primitive_prim(prim)) { + return new USDShapeReader(prim, params_, settings_); + } if (prim.IsA()) { return new USDCameraReader(prim, params_, settings_); } diff --git a/source/blender/io/usd/intern/usd_reader_stage.h b/source/blender/io/usd/intern/usd_reader_stage.h index 9b2c37132bcc..028c9987060a 100644 --- a/source/blender/io/usd/intern/usd_reader_stage.h +++ b/source/blender/io/usd/intern/usd_reader_stage.h @@ -100,6 +100,12 @@ class USDStageReader { * toggled off. */ bool include_by_purpose(const pxr::UsdGeomImageable &imageable) const; + + /* + * Returns true if the specified UsdPrim is a UsdGeom primitive, + * procedural shape, such as UsdGeomCube. + */ + bool is_primitive_prim(const pxr::UsdPrim &prim) const; }; }; // namespace blender::io::usd diff --git a/source/blender/io/usd/intern/usd_writer_abstract.cc b/source/blender/io/usd/intern/usd_writer_abstract.cc index f4ae9d20e527..79cb521aacd3 100644 --- a/source/blender/io/usd/intern/usd_writer_abstract.cc +++ b/source/blender/io/usd/intern/usd_writer_abstract.cc @@ -5,12 +5,15 @@ #include "usd_writer_material.h" #include +#include #include "BKE_customdata.h" #include "BLI_assert.h" #include "DNA_mesh_types.h" +#include "WM_api.h" + /* TfToken objects are not cheap to construct, so we do it once. */ namespace usdtokens { /* Materials */ @@ -149,4 +152,25 @@ bool USDAbstractWriter::mark_as_instance(const HierarchyContext &context, const return true; } +void USDAbstractWriter::author_extent(const pxr::UsdTimeCode timecode, pxr::UsdGeomBoundable &prim) +{ + /* Do not use any existing `extentsHint` that may be authored, instead recompute the extent when + * authoring it. */ + const bool useExtentsHint = false; + const pxr::TfTokenVector includedPurposes{pxr::UsdGeomTokens->default_}; + pxr::UsdGeomBBoxCache bboxCache(timecode, includedPurposes, useExtentsHint); + pxr::GfBBox3d bounds = bboxCache.ComputeLocalBound(prim.GetPrim()); + if (pxr::GfBBox3d() == bounds) { + /* This will occur, for example, if a mesh does not have any vertices. */ + WM_reportf(RPT_WARNING, + "USD Export: no bounds could be computed for %s", + prim.GetPrim().GetName().GetText()); + return; + } + + pxr::VtArray extent{(pxr::GfVec3f)bounds.GetRange().GetMin(), + (pxr::GfVec3f)bounds.GetRange().GetMax()}; + prim.CreateExtentAttr().Set(extent); +} + } // namespace blender::io::usd diff --git a/source/blender/io/usd/intern/usd_writer_abstract.h b/source/blender/io/usd/intern/usd_writer_abstract.h index 8adc054c2c2f..e6ac6a8ba215 100644 --- a/source/blender/io/usd/intern/usd_writer_abstract.h +++ b/source/blender/io/usd/intern/usd_writer_abstract.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -67,6 +68,24 @@ class USDAbstractWriter : public AbstractHierarchyWriter { * Reference the original data instead of writing a copy. */ virtual bool mark_as_instance(const HierarchyContext &context, const pxr::UsdPrim &prim); + + /** + * Compute the bounds for a boundable prim, and author the result as the `extent` attribute. + * + * Although this method works for any boundable prim, it is preferred to use Blender's own + * cached bounds when possible. + * + * This method does not author the `extentsHint` attribute, which is also important to provide. + * Whereas the `extent` attribute can only be authored on prims inheriting from + * `UsdGeomBoundable`, an `extentsHint` can be provided on any prim, including scopes. This + * `extentsHint` should be authored on every prim in a hierarchy being exported. + * + * Note that this hint is only useful when importing or inspecting layers, and should not be + * taken into account when computing extents during export. + * + * TODO: also provide method for authoring extentsHint on every prim in a hierarchy. + */ + virtual void author_extent(const pxr::UsdTimeCode timecode, pxr::UsdGeomBoundable &prim); }; } // namespace blender::io::usd diff --git a/source/blender/io/usd/intern/usd_writer_hair.cc b/source/blender/io/usd/intern/usd_writer_hair.cc index 8ec1447b5054..31c419094806 100644 --- a/source/blender/io/usd/intern/usd_writer_hair.cc +++ b/source/blender/io/usd/intern/usd_writer_hair.cc @@ -62,6 +62,8 @@ void USDHairWriter::do_write(HierarchyContext &context) colors.push_back(pxr::GfVec3f(cache[0]->col)); curves.CreateDisplayColorAttr(pxr::VtValue(colors)); } + + this->author_extent(timecode, curves); } bool USDHairWriter::check_is_animated(const HierarchyContext & /*context*/) const diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 62656c902d0a..8363f9f8b353 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -3,6 +3,7 @@ #include "usd_writer_mesh.h" #include "usd_hierarchy_iterator.h" +#include #include #include #include @@ -247,6 +248,15 @@ void USDGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) if (usd_export_context_.export_params.export_materials) { assign_materials(context, usd_mesh, usd_mesh_data.face_groups); } + + /* Blender grows its bounds cache to cover animated meshes, so only author once. */ + float bound_min[3]; + float bound_max[3]; + INIT_MINMAX(bound_min, bound_max); + BKE_mesh_minmax(mesh, bound_min, bound_max); + pxr::VtArray extent{pxr::GfVec3f{bound_min[0], bound_min[1], bound_min[2]}, + pxr::GfVec3f{bound_max[0], bound_max[1], bound_max[2]}}; + usd_mesh.CreateExtentAttr().Set(extent); } static void get_vertices(const Mesh *mesh, USDMeshData &usd_mesh_data) diff --git a/source/blender/io/usd/usd.h b/source/blender/io/usd/usd.h index 36ad857c57eb..dc172fd72db5 100644 --- a/source/blender/io/usd/usd.h +++ b/source/blender/io/usd/usd.h @@ -66,6 +66,7 @@ struct USDImportParams { bool import_materials; bool import_meshes; bool import_volumes; + bool import_shapes; char prim_path_mask[1024]; bool import_subdiv; bool import_instance_proxies; diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index e2ad7de7291b..3f8a21cc5ab8 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -186,7 +186,7 @@ int OBJMesh::ith_smooth_group(const int poly_index) const void OBJMesh::ensure_mesh_normals() const { - /* Const cast can be removed when calculating face corner normals lazily is possible. */ + /* Constant cast can be removed when calculating face corner normals lazily is possible. */ BKE_mesh_calc_normals_split(const_cast(export_mesh_)); } diff --git a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc index b90a0c994243..edd46ccd6907 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_file_reader.cc @@ -152,21 +152,67 @@ static void geom_add_uv_vertex(const char *p, const char *end, GlobalVertices &r r_global_vertices.uv_vertices.append(uv); } -static void geom_add_edge(Geometry *geom, - const char *p, - const char *end, - GlobalVertices &r_global_vertices) +/** + * Parse vertex index and transform to non-negative, zero-based. + * Sets r_index to the index or INT32_MAX on error. + * Index is transformed and bounds-checked using n_vertices, + * which specifies the number of vertices that have been read before. + * Returns updated p. + */ +static const char *parse_vertex_index(const char *p, const char *end, size_t n_elems, int &r_index) { - int edge_v1, edge_v2; - p = parse_int(p, end, -1, edge_v1); - p = parse_int(p, end, -1, edge_v2); - /* Always keep stored indices non-negative and zero-based. */ - edge_v1 += edge_v1 < 0 ? r_global_vertices.vertices.size() : -1; - edge_v2 += edge_v2 < 0 ? r_global_vertices.vertices.size() : -1; - BLI_assert(edge_v1 >= 0 && edge_v2 >= 0); - geom->edges_.append({uint(edge_v1), uint(edge_v2)}); - geom->track_vertex_index(edge_v1); - geom->track_vertex_index(edge_v2); + p = parse_int(p, end, INT32_MAX, r_index, false); + if (r_index != INT32_MAX) { + r_index += r_index < 0 ? n_elems : -1; + if (r_index < 0 || r_index >= n_elems) { + fprintf(stderr, "Invalid vertex index %i (valid range [0, %zu))\n", r_index, n_elems); + r_index = INT32_MAX; + } + } + return p; +} + +/** + * Parse a polyline and add its line segments as loose edges. + * We support the following polyline specifications: + * - "l v1/vt1 v2/vt2 ..." + * - "l v1 v2 ..." + * If a line only has one vertex (technically not allowed by the spec), + * no line is created, but the vertex will be added to + * the mesh even if it is unconnected. + */ +static void geom_add_polyline(Geometry *geom, + const char *p, + const char *end, + GlobalVertices &r_global_vertices) +{ + int last_vertex_index; + p = drop_whitespace(p, end); + p = parse_vertex_index(p, end, r_global_vertices.vertices.size(), last_vertex_index); + + if (last_vertex_index == INT32_MAX) { + fprintf(stderr, "Skipping invalid OBJ polyline.\n"); + return; + } + geom->track_vertex_index(last_vertex_index); + + while (p < end) { + int vertex_index; + + /* Lines can contain texture coordinate indices, just ignore them. */ + p = drop_non_whitespace(p, end); + /* Skip whitespace to get to the next vertex. */ + p = drop_whitespace(p, end); + + p = parse_vertex_index(p, end, r_global_vertices.vertices.size(), vertex_index); + if (vertex_index == INT32_MAX) { + break; + } + + geom->edges_.append({uint(last_vertex_index), uint(vertex_index)}); + geom->track_vertex_index(vertex_index); + last_vertex_index = vertex_index; + } } static void geom_add_polygon(Geometry *geom, @@ -222,7 +268,7 @@ static void geom_add_polygon(Geometry *geom, else { geom->track_vertex_index(corner.vert_index); } - /* Ignore UV index, if the geometry does not have any UVs (T103212). */ + /* Ignore UV index, if the geometry does not have any UVs (#103212). */ if (got_uv && !global_vertices.uv_vertices.is_empty()) { corner.uv_vert_index += corner.uv_vert_index < 0 ? global_vertices.uv_vertices.size() : -1; if (corner.uv_vert_index < 0 || corner.uv_vert_index >= global_vertices.uv_vertices.size()) { @@ -235,7 +281,7 @@ static void geom_add_polygon(Geometry *geom, } /* Ignore corner normal index, if the geometry does not have any normals. * Some obj files out there do have face definitions that refer to normal indices, - * without any normals being present (T98782). */ + * without any normals being present (#98782). */ if (got_normal && !global_vertices.vertex_normals.is_empty()) { corner.vertex_normal_index += corner.vertex_normal_index < 0 ? global_vertices.vertex_normals.size() : @@ -252,7 +298,7 @@ static void geom_add_polygon(Geometry *geom, geom->face_corners_.append(corner); curr_face.corner_count_++; - /* Some files contain extra stuff per face (e.g. 4 indices); skip any remainder (T103441). */ + /* Some files contain extra stuff per face (e.g. 4 indices); skip any remainder (#103441). */ p = drop_non_whitespace(p, end); /* Skip whitespace to get to the next face corner. */ p = drop_whitespace(p, end); @@ -548,7 +594,7 @@ void OBJParser::parse(Vector> &r_all_geometries, } /* Faces. */ else if (parse_keyword(p, end, "l")) { - geom_add_edge(curr_geom, p, end, r_global_vertices); + geom_add_polyline(curr_geom, p, end, r_global_vertices); } /* Objects. */ else if (parse_keyword(p, end, "o")) { @@ -767,7 +813,7 @@ Span OBJParser::mtl_libraries() const void OBJParser::add_mtl_library(StringRef path) { - /* Remove any quotes from start and end (T67266, T97794). */ + /* Remove any quotes from start and end (#67266, #97794). */ if (path.size() > 2 && path.startswith("\"") && path.endswith("\"")) { path = path.drop_prefix(1).drop_suffix(1); } @@ -783,7 +829,7 @@ void OBJParser::add_default_mtl_library() * into candidate .mtl files to search through. This is not technically following the * spec, but the old python importer was doing it, and there are user files out there * that contain "mtllib bar.mtl" for a foo.obj, and depend on finding materials - * from foo.mtl (see T97757). */ + * from foo.mtl (see #97757). */ char mtl_file_path[FILE_MAX]; BLI_strncpy(mtl_file_path, import_params_.filepath, sizeof(mtl_file_path)); BLI_path_extension_replace(mtl_file_path, sizeof(mtl_file_path), ".mtl"); @@ -855,7 +901,7 @@ void MTLParser::parse_and_store(Map> &r_mat parse_float(p, end, 1.0f, material->alpha); } else if (parse_keyword(p, end, "illum")) { - /* Some files incorrectly use a float (T60135). */ + /* Some files incorrectly use a float (#60135). */ float val; parse_float(p, end, 1.0f, val); material->illum_mode = val; diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index 3c9d5663a431..aa89be9780c6 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -86,6 +86,7 @@ void MeshFromGeometry::fixup_invalid_faces() /* Skip and remove faces that have fewer than 3 corners. */ mesh_geometry_.total_loops_ -= curr_face.corner_count_; mesh_geometry_.face_elements_.remove_and_reorder(face_idx); + --face_idx; continue; } @@ -128,6 +129,7 @@ void MeshFromGeometry::fixup_invalid_faces() /* Remove the invalid face. */ mesh_geometry_.total_loops_ -= curr_face.corner_count_; mesh_geometry_.face_elements_.remove_and_reorder(face_idx); + --face_idx; Vector> new_faces = fixup_invalid_polygon(global_vertices_.vertices, face_verts); diff --git a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc index f15687e7bef7..62998a51d766 100644 --- a/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc +++ b/source/blender/io/wavefront_obj/tests/obj_importer_tests.cc @@ -486,6 +486,15 @@ TEST_F(obj_importer_test, import_faces_invalid_or_with_holes) import_and_check("faces_invalid_or_with_holes.obj", expect, std::size(expect), 0); } +TEST_F(obj_importer_test, import_invalid_faces) +{ + Expectation expect[] = { + {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)}, + {"OBTheMesh", OB_MESH, 5, 3, 1, 3, float3(-2, 0, -2), float3(0, 2, 0)}, + }; + import_and_check("invalid_faces.obj", expect, std::size(expect), 0); +} + TEST_F(obj_importer_test, import_invalid_indices) { Expectation expect[] = { @@ -869,4 +878,13 @@ TEST_F(obj_importer_test, import_split_options_none) import_and_check("split_options.obj", expect, std::size(expect), 0); } +TEST_F(obj_importer_test, import_polylines) +{ + Expectation expect[] = { + {"OBCube", OB_MESH, 8, 12, 6, 24, float3(1, 1, -1), float3(-1, 1, 1)}, + {"OBpolylines", OB_MESH, 13, 8, 0, 0, float3(1, 0, 0), float3(.7, .7, 2)}, + }; + import_and_check("polylines.obj", expect, std::size(expect), 0); +} + } // namespace blender::io::obj diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index a0f5448a0032..a5fea870a9b0 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -818,7 +818,7 @@ enum { * RESET_NEVER * * \warning This should not be cleared on existing data. - * If support for this is needed, see T88026 as this flag controls memory ownership + * If support for this is needed, see #88026 as this flag controls memory ownership * of physics *shared* pointers. */ LIB_TAG_COPIED_ON_WRITE = 1 << 12, diff --git a/source/blender/makesdna/DNA_ID_enums.h b/source/blender/makesdna/DNA_ID_enums.h index 5999af8bf5c5..94ab24511d84 100644 --- a/source/blender/makesdna/DNA_ID_enums.h +++ b/source/blender/makesdna/DNA_ID_enums.h @@ -46,7 +46,7 @@ typedef enum ID_Type { ID_LI = MAKE_ID2('L', 'I'), /* Library */ ID_OB = MAKE_ID2('O', 'B'), /* Object */ ID_ME = MAKE_ID2('M', 'E'), /* Mesh */ - ID_CU_LEGACY = MAKE_ID2('C', 'U'), /* Curve. ID_CV should be used in the future (see T95355). */ + ID_CU_LEGACY = MAKE_ID2('C', 'U'), /* Curve. ID_CV should be used in the future (see #95355). */ ID_MB = MAKE_ID2('M', 'B'), /* MetaBall */ ID_MA = MAKE_ID2('M', 'A'), /* Material */ ID_TE = MAKE_ID2('T', 'E'), /* Tex (Texture) */ diff --git a/source/blender/makesdna/DNA_asset_types.h b/source/blender/makesdna/DNA_asset_types.h index 195cc059f188..5ab24b2db4ac 100644 --- a/source/blender/makesdna/DNA_asset_types.h +++ b/source/blender/makesdna/DNA_asset_types.h @@ -85,11 +85,11 @@ typedef struct AssetMetaData { } AssetMetaData; typedef enum eAssetLibraryType { - /* For the future. Display assets bundled with Blender by default. */ - // ASSET_LIBRARY_BUNDLED = 0, /** Display assets from the current session (current "Main"). */ ASSET_LIBRARY_LOCAL = 1, ASSET_LIBRARY_ALL = 2, + /** Display assets bundled with Blender by default. */ + ASSET_LIBRARY_ESSENTIALS = 3, /** Display assets from custom asset libraries, as defined in the preferences * (#bUserAssetLibrary). The name will be taken from #FileSelectParams.asset_library_ref.idname @@ -99,6 +99,17 @@ typedef enum eAssetLibraryType { ASSET_LIBRARY_CUSTOM = 100, } eAssetLibraryType; +typedef enum eAssetImportMethod { + /** Regular data-block linking. */ + ASSET_IMPORT_LINK = 0, + /** Regular data-block appending (basically linking + "Make Local"). */ + ASSET_IMPORT_APPEND = 1, + /** Append data-block with the #BLO_LIBLINK_APPEND_LOCAL_ID_REUSE flag enabled. Some typically + * heavy data dependencies (e.g. the image data-blocks of a material, the mesh of an object) may + * be reused from an earlier append. */ + ASSET_IMPORT_APPEND_REUSE = 2, +} eAssetImportMethod; + /** * Information to identify an asset library. May be either one of the predefined types (current * 'Main', builtin library, project library), or a custom type as defined in the Preferences. diff --git a/source/blender/makesdna/DNA_brush_defaults.h b/source/blender/makesdna/DNA_brush_defaults.h index 6e88275672aa..562632e05cd5 100644 --- a/source/blender/makesdna/DNA_brush_defaults.h +++ b/source/blender/makesdna/DNA_brush_defaults.h @@ -94,7 +94,7 @@ .automasking_cavity_blur_steps = 0,\ .automasking_cavity_factor = 1.0f,\ \ - /* A kernel radius of 1 has almost no effect (T63233). */ \ + /* A kernel radius of 1 has almost no effect (#63233). */ \ .blur_kernel_radius = 2, \ \ .mtex = _DNA_DEFAULT_MTex, \ diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h index 72357ea67343..3ea2c3d70b7e 100644 --- a/source/blender/makesdna/DNA_brush_enums.h +++ b/source/blender/makesdna/DNA_brush_enums.h @@ -412,6 +412,7 @@ typedef enum eBrushFlags2 { BRUSH_CLOTH_USE_COLLISION = (1 << 6), BRUSH_AREA_RADIUS_PRESSURE = (1 << 7), BRUSH_GRAB_SILHOUETTE = (1 << 8), + BRUSH_USE_COLOR_AS_DISPLACEMENT = (1 << 9), } eBrushFlags2; typedef enum { diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index fd72a58fe14b..dd335335b903 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -162,7 +162,8 @@ typedef struct BrushCurvesSculptSettings { int density_add_attempts; /** #eBrushCurvesSculptDensityMode. */ uint8_t density_mode; - char _pad[7]; + char _pad[3]; + struct CurveMapping *curve_parameter_falloff; } BrushCurvesSculptSettings; typedef struct Brush { diff --git a/source/blender/makesdna/DNA_curves_types.h b/source/blender/makesdna/DNA_curves_types.h index 3ee2ba2797d7..cef5f70b7327 100644 --- a/source/blender/makesdna/DNA_curves_types.h +++ b/source/blender/makesdna/DNA_curves_types.h @@ -197,6 +197,7 @@ typedef struct Curves { /** #Curves.flag */ enum { HA_DS_EXPAND = (1 << 0), + CV_SCULPT_COLLISION_ENABLED = (1 << 1), }; /** #Curves.symmetry */ diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 8f9ae28b441d..9e4505ca5295 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -282,6 +282,10 @@ typedef enum eNodeSocketFlag { * type is obvious and the name takes up too much space. */ SOCK_HIDE_LABEL = (1 << 12), + /** + * Only used for geometry nodes. Don't show the socket value in the modifier interface. + */ + SOCK_HIDE_IN_MODIFIER = (1 << 13), } eNodeSocketFlag; typedef struct bNode { @@ -961,7 +965,7 @@ typedef struct NodeScriptDict { typedef struct NodeGlare { char quality, type, iter; /* XXX angle is only kept for backward/forward compatibility, - * was used for two different things, see T50736. */ + * was used for two different things, see #50736. */ char angle DNA_DEPRECATED, _pad0, size, star_45, streaks; float colmod, mix, threshold, fade; float angle_ofs; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 889f154c1b82..e217ff3ad9cb 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -497,7 +497,7 @@ typedef struct ObHook { enum { OB_EMPTY = 0, OB_MESH = 1, - /** Curve object is still used but replaced by "Curves" for the future (see T95355). */ + /** Curve object is still used but replaced by "Curves" for the future (see #95355). */ OB_CURVES_LEGACY = 2, OB_SURF = 3, OB_FONT = 4, @@ -556,8 +556,7 @@ enum { /** Matches #OB_TYPE_SUPPORT_EDITMODE. */ #define OB_DATA_SUPPORT_EDITMODE(_type) \ - (ELEM(_type, ID_ME, ID_CU_LEGACY, ID_MB, ID_LT, ID_AR) || \ - (U.experimental.use_new_curves_tools && (_type) == ID_CV)) + (ELEM(_type, ID_ME, ID_CU_LEGACY, ID_MB, ID_LT, ID_AR, ID_CV)) /* is this ID type used as object data */ #define OB_DATA_SUPPORT_ID(_id_type) \ diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 75410716e22e..445d75406f18 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -113,7 +113,7 @@ typedef struct ParticleData { * Particles can die unnaturally (collision). * * \note Particles die on this frame, be sure to add 1 when clamping the lifetime of particles - * to inclusive ranges such as the scenes end frame. See: T68290. + * to inclusive ranges such as the scenes end frame. See: #68290. */ float dietime; diff --git a/source/blender/makesdna/DNA_pointcache_types.h b/source/blender/makesdna/DNA_pointcache_types.h index 1133237199b5..2a63482c6b9e 100644 --- a/source/blender/makesdna/DNA_pointcache_types.h +++ b/source/blender/makesdna/DNA_pointcache_types.h @@ -126,7 +126,7 @@ enum { // PTCACHE_BAKE_EDIT = 1 << 4, // PTCACHE_BAKE_EDIT_ACTIVE = 1 << 5, PTCACHE_DISK_CACHE = 1 << 6, - /* removed since 2.64 - T30974, could be added back in a more useful way */ + /* removed since 2.64 - #30974, could be added back in a more useful way */ // PTCACHE_QUICK_CACHE = 1 << 7, PTCACHE_FRAMES_SKIPPED = 1 << 8, PTCACHE_EXTERNAL = 1 << 9, diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 608bf6b3bf7c..ca1d878110f8 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -14,7 +14,7 @@ /** * Check for cyclic set-scene. - * Libraries can cause this case which is normally prevented, see (T42009). + * Libraries can cause this case which is normally prevented, see (#42009). */ #define USE_SETSCENE_CHECK @@ -2161,7 +2161,7 @@ extern const char *RE_engine_id_CYCLES; /** \name Scene Defines * \{ */ -/* Note that much higher max-frames give imprecise sub-frames, see: T46859. */ +/* Note that much higher max-frames give imprecise sub-frames, see: #46859. */ /* Current precision is 16 for the sub-frames closer to MAXFRAME. */ /* For general use. */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 54edf795e6c7..2330d7dec7b3 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -95,12 +95,13 @@ enum { /** * The space is not a regular one opened through the editor menu (for example) but spawned by an * operator to fulfill some task and then disappear again. - * Can typically be cancelled using Escape, but that is handled on the editor level. */ + * Can typically be canceled using Escape, but that is handled on the editor level. + */ SPACE_FLAG_TYPE_TEMPORARY = (1 << 0), /** * Used to mark a space as active but "overlapped" by temporary full-screen spaces. Without this * we wouldn't be able to restore the correct active space after closing temp full-screens - * reliably if the same space type is opened twice in a full-screen stack (see T19296). We don't + * reliably if the same space type is opened twice in a full-screen stack (see #19296). We don't * actually open the same space twice, we have to pretend it is by managing area order carefully. */ SPACE_FLAG_TYPE_WAS_ACTIVE = (1 << 1), @@ -605,10 +606,13 @@ typedef struct SequencerTimelineOverlay { typedef enum eSpaceSeq_SequencerTimelineOverlay_Flag { SEQ_TIMELINE_SHOW_STRIP_OFFSETS = (1 << 1), SEQ_TIMELINE_SHOW_THUMBNAILS = (1 << 2), - SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG = (1 << 3), /* use Sequence->color_tag */ + /** Use #Sequence::color_tag */ + SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG = (1 << 3), SEQ_TIMELINE_SHOW_FCURVES = (1 << 5), - SEQ_TIMELINE_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */ - SEQ_TIMELINE_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */ + /** Draw all wave-forms. */ + SEQ_TIMELINE_ALL_WAVEFORMS = (1 << 7), + /** Draw no wave-forms. */ + SEQ_TIMELINE_NO_WAVEFORMS = (1 << 8), SEQ_TIMELINE_SHOW_STRIP_NAME = (1 << 14), SEQ_TIMELINE_SHOW_STRIP_SOURCE = (1 << 15), SEQ_TIMELINE_SHOW_STRIP_DURATION = (1 << 16), @@ -846,6 +850,8 @@ typedef enum eFileAssetImportType { * heavy data dependencies (e.g. the image data-blocks of a material, the mesh of an object) may * be reused from an earlier append. */ FILE_ASSET_IMPORT_APPEND_REUSE = 2, + /** Default: Follow the preference setting for this asset library. */ + FILE_ASSET_IMPORT_FOLLOW_PREFS = 3, } eFileAssetImportType; /** @@ -978,7 +984,7 @@ enum eFileDetails { FILE_DETAILS_DATETIME = (1 << 1), }; -/* these values need to be hardcoded in structs, dna does not recognize defines */ +/* These values need to be hard-coded in structs, DNA does not recognize defines. */ /* also defined in BKE */ #define FILE_MAXDIR 768 #define FILE_MAXFILE 256 @@ -1091,13 +1097,14 @@ typedef enum eFileSel_File_Types { } eFileSel_File_Types; ENUM_OPERATORS(eFileSel_File_Types, FILE_TYPE_BLENDERLIB); -/** Selection Flags in filesel: struct direntry, unsigned char selflag. */ +/** Selection Flags #FileList::selection_state. */ typedef enum eDirEntry_SelectFlag { /* FILE_SEL_ACTIVE = (1 << 1), */ /* UNUSED */ FILE_SEL_HIGHLIGHTED = (1 << 2), FILE_SEL_SELECTED = (1 << 3), FILE_SEL_EDITING = (1 << 4), } eDirEntry_SelectFlag; +ENUM_OPERATORS(eDirEntry_SelectFlag, FILE_SEL_EDITING); /* ***** Related to file browser, but never saved in DNA, only here to help with RNA. ***** */ @@ -1209,7 +1216,7 @@ typedef struct SpaceImage { struct Image *image; struct ImageUser iuser; - /** Histogram waveform and vectorscope. */ + /** Histogram waveform and vector-scope. */ struct Scopes scopes; /** Sample line histogram. */ struct Histogram sample_line_hist; @@ -1588,12 +1595,12 @@ typedef struct SpaceNode { /* tree type for the current node tree */ char tree_idname[64]; - /** Treetype: as same nodetree->type. */ + /** Same as #bNodeTree::type (deprecated). */ int treetype DNA_DEPRECATED; - /** Texfrom object, world or brush. */ + /** Texture-from object, world or brush (#eSpaceNode_TexFrom). */ short texfrom; - /** Shader from object or world. */ + /** Shader from object or world (#eSpaceNode_ShaderFrom). */ short shaderfrom; /** Grease-pencil data. */ @@ -1657,7 +1664,7 @@ typedef struct ConsoleLine { /* Keep these 3 vars so as to share free, realloc functions. */ /** Allocated length. */ int len_alloc; - /** Real len - strlen(). */ + /** Real length: `strlen()`. */ int len; char *line; @@ -1670,7 +1677,8 @@ typedef struct ConsoleLine { typedef enum eConsoleLine_Type { CONSOLE_LINE_OUTPUT = 0, CONSOLE_LINE_INPUT = 1, - CONSOLE_LINE_INFO = 2, /* autocomp feedback */ + /** Auto-completion feedback. */ + CONSOLE_LINE_INFO = 2, CONSOLE_LINE_ERROR = 3, } eConsoleLine_Type; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index b48c58ee7527..519510cd18ac 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -354,7 +354,8 @@ typedef struct ThemeSpace { unsigned char path_before[4], path_after[4]; unsigned char path_keyframe_before[4], path_keyframe_after[4]; unsigned char camera_path[4]; - unsigned char _pad1[6]; + unsigned char camera_passepartout[4]; + unsigned char _pad1[2]; unsigned char gp_vertex_size; unsigned char gp_vertex[4], gp_vertex_select[4]; @@ -576,6 +577,9 @@ typedef struct bUserAssetLibrary { char name[64]; /* MAX_NAME */ char path[1024]; /* FILE_MAX */ + + short import_method; /* eAssetImportMethod */ + char _pad0[6]; } bUserAssetLibrary; typedef struct SolidLight { @@ -779,8 +783,10 @@ typedef struct UserDef { char keyconfigstr[64]; + /** Index of the asset library being edited in the Preferences UI. */ + short active_asset_library; + short undosteps; - char _pad1[2]; int undomemory; float gpu_viewport_quality DNA_DEPRECATED; short gp_manhattandist, gp_euclideandist, gp_eraser; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 4c5ba4c43f81..fb70fe982ba0 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -232,6 +232,10 @@ typedef struct View3DOverlay { float gpencil_vertex_paint_opacity; /** Handles display type for curves. */ int handle_display; + + /** Curves sculpt mode settings. */ + float sculpt_curves_cage_opacity; + char _pad[4]; } View3DOverlay; /** #View3DOverlay.handle_display */ @@ -400,7 +404,7 @@ enum { /*#define RV3D_IS_GAME_ENGINE (1 << 5) */ /* UNUSED */ /** * Disable Z-buffer offset, skip calls to #ED_view3d_polygon_offset. - * Use when precise surface depth is needed and picking bias isn't, see T45434). + * Use when precise surface depth is needed and picking bias isn't, see #45434). */ #define RV3D_ZOFFSET_DISABLED 64 @@ -547,6 +551,7 @@ enum { V3D_OVERLAY_VIEWER_ATTRIBUTE = (1 << 13), V3D_OVERLAY_SCULPT_SHOW_MASK = (1 << 14), V3D_OVERLAY_SCULPT_SHOW_FACE_SETS = (1 << 15), + V3D_OVERLAY_SCULPT_CURVES_CAGE = (1 << 16), }; /** #View3DOverlay.edit_flag */ diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 49099d921c47..e6f48c2da46d 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -292,7 +292,7 @@ typedef struct wmWindow { /** * Enable when the drag was handled, * to avoid mouse-motion continually triggering drag events which are not handled - * but add overhead to gizmo handling (for example), see T87511. + * but add overhead to gizmo handling (for example), see #87511. */ char event_queue_check_drag_handled; @@ -620,7 +620,7 @@ enum { * This difference can be important because previous settings may be used, * even with #PROP_SKIP_SAVE the repeat last operator will use the previous settings. * Unlike #OP_IS_REPEAT the selection (and context generally) may be different each time. - * See T60777 for an example of when this is needed. + * See #60777 for an example of when this is needed. */ OP_IS_REPEAT_LAST = (1 << 1), diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index b9556a411cfc..a28c159722fb 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -86,7 +86,7 @@ typedef enum PropertyUnit { * Use values besides #PROP_SCALE_LINEAR * so the movement of the mouse doesn't map linearly to the value of the slider. * - * For some settings it's useful to space motion in a non-linear way, see T77868. + * For some settings it's useful to space motion in a non-linear way, see #77868. * * NOTE: The scale types are available for all float sliders. * For integer sliders they are only available if they use the visible value bar. @@ -234,7 +234,7 @@ typedef enum PropertyFlag { * Use for... * - pointers: in the UI and python so unsetting or setting to None won't work. * - strings: so our internal generated get/length/set - * functions know to do NULL checks before access T30865. + * functions know to do NULL checks before access #30865. */ PROP_NEVER_NULL = (1 << 18), /** diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 49c388a6cbf7..c4509fb44dca 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -577,7 +577,7 @@ IDProperty **rna_ID_idprops(PointerRNA *ptr) int rna_ID_is_runtime_editable(PointerRNA *ptr, const char **r_info) { ID *id = (ID *)ptr->data; - /* TODO: This should be abstracted in a BKE function or define, somewhat related to T88555. */ + /* TODO: This should be abstracted in a BKE function or define, somewhat related to #88555. */ if (id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_TEMP_MAIN | LIB_TAG_LOCALIZED | LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT | LIB_TAG_COPIED_ON_WRITE)) { *r_info = @@ -592,7 +592,7 @@ int rna_ID_is_runtime_editable(PointerRNA *ptr, const char **r_info) bool rna_ID_is_runtime_get(PointerRNA *ptr) { ID *id = (ID *)ptr->data; - /* TODO: This should be abstracted in a BKE function or define, somewhat related to T88555. */ + /* TODO: This should be abstracted in a BKE function or define, somewhat related to #88555. */ if (id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_TEMP_MAIN | LIB_TAG_LOCALIZED | LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT | LIB_TAG_COPIED_ON_WRITE)) { return true; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 217973d9479a..ca919224b257 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -2130,7 +2130,7 @@ static void rna_property_update( * * So editing custom properties only causes updates in the UI, * keep this exception because it happens to be useful for driving settings. - * Python developers on the other hand will need to manually 'update_tag', see: T74000. */ + * Python developers on the other hand will need to manually 'update_tag', see: #74000. */ DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_PARAMETERS); @@ -5942,7 +5942,7 @@ ParameterList *RNA_parameter_list_create(ParameterList *parms, case PROP_STRING: { const char *defvalue = ((StringPropertyRNA *)parm)->defaultvalue; if (defvalue && defvalue[0]) { - /* causes bug T29988, possibly this is only correct for thick wrapped + /* Causes bug #29988, possibly this is only correct for thick wrapped * need to look further into it - campbell */ #if 0 BLI_strncpy(data, defvalue, size); diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 14f4a82c62ba..79d6ba0e442f 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -876,7 +876,7 @@ static void rna_def_action(BlenderRNA *brna) RNA_def_property_collection_sdna(prop, NULL, "markers", NULL); RNA_def_property_struct_type(prop, "TimelineMarker"); /* Use lib exception so the list isn't grayed out; - * adding/removing is still banned though, see T45689. */ + * adding/removing is still banned though, see #45689. */ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); RNA_def_property_ui_text( prop, "Pose Markers", "Markers specific to this action, for labeling poses"); diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index fa2ef98d3df4..43560c5ecba2 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -593,7 +593,7 @@ static void rna_NlaTrack_remove( return; } - BKE_nlatrack_free(&adt->nla_tracks, track, true); + BKE_nlatrack_remove_and_free(&adt->nla_tracks, track, true); RNA_POINTER_INVALIDATE(track_ptr); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL); diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 8e6908841a6a..319531d68214 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -2106,6 +2106,12 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna) RNA_def_property_enum_items(prop, density_mode_items); RNA_def_property_ui_text( prop, "Density Mode", "Determines whether the brush adds or removes curves"); + + prop = RNA_def_property(srna, "curve_parameter_falloff", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, + "Curve Parameter Falloff", + "Falloff that is applied from the tip to the root of each curve"); } static void rna_def_brush(BlenderRNA *brna) @@ -2899,6 +2905,14 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Texture Sample Bias", "Value added to texture samples"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "use_color_as_displacement", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_USE_COLOR_AS_DISPLACEMENT); + RNA_def_property_ui_text(prop, + "Vector Displacement", + "Handles each pixel color as individual vector for displacement. Works " + "only with area plane mapping"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "normal_weight", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "normal_weight"); RNA_def_property_float_default(prop, 0); diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 72cf9d57c7bc..e9068010c48b 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -332,7 +332,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA * WM_main_add_notifier(NC_LINESTYLE, linestyle); break; } - /* ColorRamp for particle display is owned by the object (see T54422) */ + /* ColorRamp for particle display is owned by the object (see #54422) */ case ID_OB: case ID_PA: { ParticleSettings *part = (ParticleSettings *)ptr->owner_id; diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 671286be0521..53e13c29852d 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1621,8 +1621,9 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna) prop, "Mode", "The way the constraint treats original non-free axis scaling"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - prop = RNA_def_property(srna, "volume", PROP_FLOAT, PROP_DISTANCE); - RNA_def_property_range(prop, 0.001f, 100.0f); + prop = RNA_def_property(srna, "volume", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.001f, 100.0f, 1, 3); RNA_def_property_ui_text(prop, "Volume", "Volume of the bone at rest"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); diff --git a/source/blender/makesrna/intern/rna_curves.c b/source/blender/makesrna/intern/rna_curves.c index 7560e1a60cb9..24b3de95123f 100644 --- a/source/blender/makesrna/intern/rna_curves.c +++ b/source/blender/makesrna/intern/rna_curves.c @@ -275,7 +275,7 @@ static void rna_def_curves_point(BlenderRNA *brna) prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_int_funcs(prop, "rna_CurvePoint_index_get", NULL, NULL); - RNA_def_property_ui_text(prop, "Index", "Index of this points"); + RNA_def_property_ui_text(prop, "Index", "Index of this point"); } /* Defines a read-only vector type since normals can not be modified manually. */ @@ -453,6 +453,13 @@ static void rna_def_curves(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_Curves_update_data"); + prop = RNA_def_property(srna, "use_sculpt_collision", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CV_SCULPT_COLLISION_ENABLED); + RNA_def_property_ui_text( + prop, "Use Sculpt Collision", "Enable collision with the surface while sculpting"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, 0, "rna_Curves_update_draw"); + /* attributes */ rna_def_attributes_common(srna); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index b7856794da21..58acc49aefe5 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -4439,7 +4439,7 @@ void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropert if (tot == 0) { *items = MEM_callocN(sizeof(EnumPropertyItem[8]), __func__); - /* Ensure we get crashes on missing calls to 'RNA_enum_item_end', see T74227. */ + /* Ensure we get crashes on missing calls to 'RNA_enum_item_end', see #74227. */ #ifdef DEBUG memset(*items, 0xff, sizeof(EnumPropertyItem[8])); #endif diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c index 9af76de2a2b5..1ff41e3637b6 100644 --- a/source/blender/makesrna/intern/rna_depsgraph.c +++ b/source/blender/makesrna/intern/rna_depsgraph.c @@ -48,7 +48,7 @@ typedef struct RNA_DepsgraphIterator { # ifdef WITH_PYTHON /** * Store the Python instance so the #BPy_StructRNA can be set as invalid iteration is completed. - * Otherwise accessing from Python (console auto-complete for e.g.) crashes, see: T100286. */ + * Otherwise accessing from Python (console auto-complete for e.g.) crashes, see: #100286. */ void *py_instance; # endif } RNA_DepsgraphIterator; @@ -348,7 +348,7 @@ static PointerRNA rna_Depsgraph_objects_get(CollectionPropertyIterator *iter) * Contains extra information about duplicator and persistent ID. */ -/* XXX Ugly python seems to query next item of an iterator before using current one (see T57558). +/* XXX Ugly python seems to query next item of an iterator before using current one (see #57558). * This forces us to use that nasty ping-pong game between two sets of iterator data, * so that previous one remains valid memory for python to access to. Yuck. */ diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index e19c569bca0f..f92b137d3aef 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -714,7 +714,7 @@ static void rna_FModifier_start_frame_range(PointerRNA *UNUSED(ptr), // FModifier *fcm = (FModifier *)ptr->data; /* Technically, "sfra <= efra" must hold; however, we can't strictly enforce that, - * or else it becomes tricky to adjust the range, see: T36844. + * or else it becomes tricky to adjust the range, see: #36844. * * NOTE: we do not set soft-limits on lower bounds, as it's too confusing when you * can't easily use the slider to set things here @@ -729,7 +729,7 @@ static void rna_FModifier_end_frame_range( FModifier *fcm = (FModifier *)ptr->data; /* Technically, "sfra <= efra" must hold; however, we can't strictly enforce that, - * or else it becomes tricky to adjust the range, see: T36844. */ + * or else it becomes tricky to adjust the range, see: #36844. */ *min = MINAFRAMEF; *softmin = (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) ? fcm->sfra : MINAFRAMEF; @@ -951,7 +951,7 @@ static void rna_FModifierStepped_frame_start_set(PointerRNA *ptr, float value) value = CLAMPIS(value, prop_clamp_min, prop_clamp_max); /* Need to set both step-data's start/end and the start/end on the base-data, - * or else Restrict-Range doesn't work due to RNA-property shadowing (T52009) + * or else Restrict-Range doesn't work due to RNA-property shadowing (#52009) */ data->start_frame = value; fcm->sfra = value; @@ -968,7 +968,7 @@ static void rna_FModifierStepped_frame_end_set(PointerRNA *ptr, float value) value = CLAMPIS(value, prop_clamp_min, prop_clamp_max); /* Need to set both step-data's start/end and the start/end on the base-data, - * or else Restrict-Range doesn't work due to RNA-property shadowing (T52009) + * or else Restrict-Range doesn't work due to RNA-property shadowing (#52009) */ data->end_frame = value; fcm->efra = value; diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 97233f39d862..c8736b57863e 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -203,7 +203,7 @@ static void rna_Image_alpha_mode_update(Main *bmain, Scene *scene, PointerRNA *p { Image *ima = (Image *)ptr->owner_id; /* When operating on a generated image, avoid re-generating when changing the alpha-mode - * as it doesn't impact generated images, causing them to reload pixel data, see T82785. */ + * as it doesn't impact generated images, causing them to reload pixel data, see #82785. */ if (ima->source == IMA_SRC_GENERATED) { return; } diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c index f429fd73cdb8..0ff0787de502 100644 --- a/source/blender/makesrna/intern/rna_light.c +++ b/source/blender/makesrna/intern/rna_light.c @@ -341,7 +341,7 @@ static void rna_def_light_shadow(StructRNA *srna, bool sun) RNA_def_property_ui_range(prop, 0, 100, 0.1, 3); RNA_def_property_ui_text( prop, "Shadow Soft Size", "Light size for ray shadow sampling (Raytraced shadows)"); - RNA_def_property_update(prop, 0, "rna_Light_update"); + RNA_def_property_update(prop, 0, "rna_Light_draw_update"); /* Eevee */ prop = RNA_def_property(srna, "use_contact_shadow", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 0f9b11905fa6..e660513a2439 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2385,8 +2385,9 @@ static PointerRNA rna_Mesh_uv_layers_new(struct Mesh *me, static void rna_Mesh_uv_layers_remove(struct Mesh *me, ReportList *reports, CustomDataLayer *layer) { - if (!BKE_id_attribute_find(&me->id, layer->name, CD_PROP_FLOAT, ATTR_DOMAIN_CORNER)) { + if (!BKE_id_attribute_find(&me->id, layer->name, CD_PROP_FLOAT2, ATTR_DOMAIN_CORNER)) { BKE_reportf(reports, RPT_ERROR, "UV map '%s' not found", layer->name); + return; } BKE_id_attribute_remove(&me->id, layer->name, reports); } diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h index 495c58d7b307..2b01c98b35b8 100644 --- a/source/blender/makesrna/intern/rna_mesh_utils.h +++ b/source/blender/makesrna/intern/rna_mesh_utils.h @@ -8,13 +8,13 @@ /* Macros to help reduce code clutter in rna_mesh.c */ -/* Define the accessors for a basic CustomDataLayer collection */ +/* Define the accessors for a basic CustomDataLayer collection, skipping anonymous layers */ #define DEFINE_CUSTOMDATA_LAYER_COLLECTION(collection_name, customdata_type, layer_type) \ /* check */ \ static int rna_##collection_name##_check(CollectionPropertyIterator *UNUSED(iter), void *data) \ { \ CustomDataLayer *layer = (CustomDataLayer *)data; \ - return (layer->type != layer_type); \ + return (layer->anonymous_id != NULL || layer->type != layer_type); \ } \ /* begin */ \ static void rna_Mesh_##collection_name##s_begin(CollectionPropertyIterator *iter, \ @@ -37,7 +37,9 @@ static int rna_Mesh_##collection_name##s_length(PointerRNA *ptr) \ { \ CustomData *data = rna_mesh_##customdata_type(ptr); \ - return data ? CustomData_number_of_layers(data, layer_type) : 0; \ + return data ? CustomData_number_of_layers(data, layer_type) - \ + CustomData_number_of_anonymous_layers(data, layer_type) : \ + 0; \ } \ /* index range */ \ static void rna_Mesh_##collection_name##_index_range( \ @@ -45,7 +47,9 @@ { \ CustomData *data = rna_mesh_##customdata_type(ptr); \ *min = 0; \ - *max = data ? CustomData_number_of_layers(data, layer_type) - 1 : 0; \ + *max = data ? CustomData_number_of_layers(data, layer_type) - \ + CustomData_number_of_anonymous_layers(data, layer_type) - 1 : \ + 0; \ *max = MAX2(0, *max); \ } diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index b86e202a791d..c8c1801876b0 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -3313,12 +3313,12 @@ static void rna_def_modifier_correctivesmooth(BlenderRNA *brna) "ORCO", 0, "Original Coords", - "Use base mesh vertex coords as the rest position"}, + "Use base mesh vertex coordinates as the rest position"}, {MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND, "BIND", 0, "Bind Coords", - "Use bind vertex coords for rest position"}, + "Use bind vertex coordinates for rest position"}, {0, NULL, 0, NULL, NULL}, }; @@ -5967,13 +5967,13 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna) "OVERWRITE", 0, "Overwrite", - "Replace vertex coords with cached values"}, + "Replace vertex coordinates with cached values"}, {MOD_MESHCACHE_DEFORM_INTEGRATE, "INTEGRATE", 0, "Integrate", - "Integrate deformation from this modifiers input with the mesh-cache coords (useful for " - "shape keys)"}, + "Integrate deformation from this modifier's input with the mesh-cache coordinates " + "(useful for shape keys)"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 2027f6b2249a..4d284695ade0 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -544,7 +544,7 @@ static NlaStrip *rna_NlaStrip_new(ID *id, reports, RPT_ERROR, "Unable to add strip (the track does not have any space to accommodate this new strip)"); - BKE_nlastrip_free(NULL, strip, true); + BKE_nlastrip_free(strip, true); return NULL; } @@ -595,7 +595,7 @@ static void rna_NlaStrip_remove( return; } - BKE_nlastrip_free(&track->strips, strip, true); + BKE_nlastrip_remove_and_free(&track->strips, strip, true); RNA_POINTER_INVALIDATE(strip_ptr); WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index ed7ca84bda33..71d6c72c05d6 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -9645,6 +9645,14 @@ static void def_geo_distribute_points_on_faces(StructRNA *srna) RNA_def_property_enum_default(prop, GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_RANDOM); RNA_def_property_ui_text(prop, "Distribution Method", "Method to use for scattering points"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "use_legacy_normal", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom2", 1); + RNA_def_property_ui_text(prop, + "Legacy Normal", + "Output the normal and rotation values that have been output " + "before the node started taking smooth normals into account"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } static void def_geo_curve_spline_type(StructRNA *srna) @@ -11211,6 +11219,14 @@ static void rna_def_node_socket_interface(BlenderRNA *brna) prop, "Hide Value", "Hide the socket input value even when the socket is not connected"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); + prop = RNA_def_property(srna, "hide_in_modifier", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDE_IN_MODIFIER); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, + "Hide in Modifier", + "Don't show the input value in the geometry nodes modifier interface"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); + prop = RNA_def_property(srna, "attribute_domain", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_attribute_domain_items); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 71ad8dda859b..56c66ddca3e6 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -770,7 +770,7 @@ static void rna_Object_dup_collection_set(PointerRNA *ptr, Collection *grp = (Collection *)value.data; /* Must not let this be set if the object belongs in this group already, - * thus causing a cycle/infinite-recursion leading to crashes on load T25298. */ + * thus causing a cycle/infinite-recursion leading to crashes on load #25298. */ if (BKE_collection_has_object_recursive(grp, ob) == 0) { if (ob->type == OB_EMPTY) { id_us_min(&ob->instance_collection->id); @@ -2373,14 +2373,14 @@ static void rna_def_vertex_group(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name", "Vertex group name"); RNA_def_struct_name_property(srna, prop); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_VertexGroup_name_set"); - /* update data because modifiers may use T24761. */ + /* update data because modifiers may use #24761. */ RNA_def_property_update( prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data_dependency"); prop = RNA_def_property(srna, "lock_weight", PROP_BOOLEAN, PROP_NONE); RNA_def_property_ui_text(prop, "", "Maintain the relative weights for the group"); RNA_def_property_boolean_sdna(prop, NULL, "flag", 0); - /* update data because modifiers may use T24761. */ + /* update data because modifiers may use #24761. */ RNA_def_property_update(prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data"); prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED); @@ -2433,7 +2433,7 @@ static void rna_def_face_map(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name", "Face map name"); RNA_def_struct_name_property(srna, prop); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_FaceMap_name_set"); - /* update data because modifiers may use T24761. */ + /* update data because modifiers may use #24761. */ RNA_def_property_update(prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_path.cc b/source/blender/makesrna/intern/rna_path.cc index 420c89071072..a878acd5b778 100644 --- a/source/blender/makesrna/intern/rna_path.cc +++ b/source/blender/makesrna/intern/rna_path.cc @@ -832,7 +832,7 @@ static char *rna_idp_path(PointerRNA *ptr, * That case must be ignored here, we only want to deal with runtime RNA properties stored in * IDProps. * - * See T84091. */ + * See #84091. */ PropertyRNA *prop = RNA_struct_find_property(ptr, iter->name); if (prop == nullptr || (prop->flag & PROP_IDPROPERTY) == 0) { continue; @@ -906,7 +906,7 @@ static char *rna_path_from_ID_to_idpgroup(const PointerRNA *ptr) BLI_assert(ptr->owner_id != nullptr); /* TODO: Support Bones/PoseBones. no pointers stored to the bones from here, only the ID. - * See example in T25746. + * See example in #25746. * Unless this is added only way to find this is to also search * all bones and pose bones of an armature or object. */ @@ -1227,7 +1227,7 @@ char *RNA_path_full_struct_py(const PointerRNA *ptr) data_path = RNA_path_from_ID_to_struct(ptr); - /* XXX data_path may be NULL (see T36788), + /* XXX data_path may be NULL (see #36788), * do we want to get the 'bpy.data.foo["bar"].(null)' stuff? */ ret = BLI_sprintfN("%s.%s", id_path, data_path); diff --git a/source/blender/makesrna/intern/rna_pointcloud.c b/source/blender/makesrna/intern/rna_pointcloud.c index 493178574411..99ce90deaf4f 100644 --- a/source/blender/makesrna/intern/rna_pointcloud.c +++ b/source/blender/makesrna/intern/rna_pointcloud.c @@ -162,7 +162,7 @@ static void rna_def_point(BlenderRNA *brna) prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_int_funcs(prop, "rna_Point_index_get", NULL, NULL); - RNA_def_property_ui_text(prop, "Index", "Index of this points"); + RNA_def_property_ui_text(prop, "Index", "Index of this point"); } static void rna_def_pointcloud(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 6a66445ee4cb..5eb00175c33b 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -120,10 +120,7 @@ static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene { GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_IMAGE); GPU_shader_bind(shader); - - int img_loc = GPU_shader_get_uniform(shader, "image"); - - GPU_shader_uniform_int(shader, img_loc, 0); + /** \note "image" binding slot is 0. */ } static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine)) diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 3953fc66fc8a..f586507427df 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -74,7 +74,7 @@ static void rna_Scene_frame_set(Scene *scene, Main *bmain, int frame, float subf * redrawing while the data is being modified for render */ if (!G.is_rendering) { /* can't use NC_SCENE|ND_FRAME because this causes wm_event_do_notifiers to call - * BKE_scene_graph_update_for_newframe which will lose any un-keyed changes T24690. */ + * BKE_scene_graph_update_for_newframe which will lose any un-keyed changes #24690. */ // WM_main_add_notifier(NC_SCENE|ND_FRAME, scene); /* instead just redraw the views */ diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index a65bd613ecfc..4d837a374d10 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -76,7 +76,7 @@ static void rna_Screen_redraw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), static bool rna_Screen_is_animation_playing_get(PointerRNA *UNUSED(ptr)) { - /* can be NULL on file load, T42619 */ + /* can be NULL on file load, #42619 */ wmWindowManager *wm = G_MAIN->wm.first; return wm ? (ED_screen_animation_playing(wm) != NULL) : 0; } @@ -103,7 +103,7 @@ static int rna_Area_type_get(PointerRNA *ptr) { ScrArea *area = (ScrArea *)ptr->data; /* Usually 'spacetype' is used. It lags behind a bit while switching area - * type though, then we use 'butspacetype' instead (T41435). */ + * type though, then we use 'butspacetype' instead (#41435). */ return (area->butspacetype == SPACE_EMPTY) ? area->spacetype : area->butspacetype; } @@ -130,7 +130,7 @@ static void rna_Area_type_update(bContext *C, PointerRNA *ptr) bScreen *screen = (bScreen *)ptr->owner_id; ScrArea *area = (ScrArea *)ptr->data; - /* Running update without having called 'set', see: T64049 */ + /* Running update without having called 'set', see: #64049 */ if (area->butspacetype == SPACE_EMPTY) { return; } @@ -377,7 +377,7 @@ static void rna_def_area(BlenderRNA *brna) * and needs to be read back by script authors. * * This happens when an area is full-screen (when #ScrArea.full is set). - * in this case reading the empty value is needed, but it should never be set, see: T87187. */ + * in this case reading the empty value is needed, but it should never be set, see: #87187. */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "spacetype"); RNA_def_property_enum_items(prop, rna_enum_space_type_items); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 7c1cae1c44db..aa60339b7b83 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -228,7 +228,7 @@ static const EnumPropertyItem *rna_ParticleEdit_tool_itemf(bContext *C, # else /* use this rather than PE_get_current() - because the editing cache is * dependent on the cache being updated which can happen after this UI - * draws causing a glitch T28883. */ + * draws causing a glitch #28883. */ ParticleSystem *psys = psys_get_current(ob); # endif diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 21843a5c2238..55a71ceb14e9 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -3128,7 +3128,7 @@ static void rna_def_gaussian_blur(StructRNA *srna) static void rna_def_text(StructRNA *srna) { - /* Avoid text icons because they imply this aligns within a frame, see: T71082 */ + /* Avoid text icons because they imply this aligns within a frame, see: #71082 */ static const EnumPropertyItem text_align_x_items[] = { {SEQ_TEXT_ALIGN_X_LEFT, "LEFT", ICON_ANCHOR_LEFT, "Left", ""}, {SEQ_TEXT_ALIGN_X_CENTER, "CENTER", ICON_ANCHOR_CENTER, "Center", ""}, diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7bdbfe756840..53e5f3a21aa9 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2064,7 +2064,7 @@ static void rna_SpaceProperties_context_update(Main *UNUSED(bmain), PointerRNA *ptr) { SpaceProperties *sbuts = (SpaceProperties *)(ptr->data); - /* XXX BCONTEXT_DATA is ugly, but required for lights... See T51318. */ + /* XXX BCONTEXT_DATA is ugly, but required for lights... See #51318. */ if (ELEM(sbuts->mainb, BCONTEXT_WORLD, BCONTEXT_MATERIAL, BCONTEXT_TEXTURE, BCONTEXT_DATA)) { sbuts->preview = 1; } @@ -4714,18 +4714,31 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_sculpt_curves_cage", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_SCULPT_CURVES_CAGE); + RNA_def_property_ui_text( + prop, "Sculpt Curves Cage", "Show original curves that are currently being edited"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "sculpt_curves_cage_opacity", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "overlay.sculpt_curves_cage_opacity"); + RNA_def_property_ui_text( + prop, "Curves Sculpt Cage Opacity", "Opacity of the cage overlay in curves sculpt mode"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "sculpt_mode_face_sets_opacity", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "overlay.sculpt_mode_face_sets_opacity"); RNA_def_property_ui_text(prop, "Sculpt Face Sets Opacity", ""); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "sculpt_show_mask", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "show_sculpt_mask", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_SCULPT_SHOW_MASK); RNA_def_property_ui_text(prop, "Sculpt Show Mask", ""); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "sculpt_show_face_sets", PROP_BOOLEAN, PROP_NONE); + prop = RNA_def_property(srna, "show_sculpt_face_sets", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_SCULPT_SHOW_FACE_SETS); RNA_def_property_ui_text(prop, "Sculpt Show Face Sets", ""); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); @@ -6899,6 +6912,12 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna) PropertyRNA *prop; static const EnumPropertyItem asset_import_type_items[] = { + {FILE_ASSET_IMPORT_FOLLOW_PREFS, + "FOLLOW_PREFS", + 0, + "Follow Preferences", + "Use the import method set in the Preferences for this asset library, don't override it " + "for this Asset Browser"}, {FILE_ASSET_IMPORT_LINK, "LINK", 0, "Link", "Import the assets as linked data-block"}, {FILE_ASSET_IMPORT_APPEND, "APPEND", @@ -6945,9 +6964,9 @@ static void rna_def_fileselect_asset_params(BlenderRNA *brna) prop = RNA_def_property(srna, "import_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, asset_import_type_items); - RNA_def_property_ui_text(prop, "Import Type", "Determine how the asset will be imported"); - /* Asset drag info saved by buttons stores the import type, so the space must redraw when import - * type changes. */ + RNA_def_property_ui_text(prop, "Import Method", "Determine how the asset will be imported"); + /* Asset drag info saved by buttons stores the import method, so the space must redraw when + * import type changes. */ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 9de32c24702f..b768c7074b79 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -562,7 +562,7 @@ static void uilist_filter_items(uiList *ui_list, RNA_parameter_dynamic_length_get(&list, parm), "filter_flags", len); - /* NOTE: we cannot return here, we would let flt_data in inconsistent state... see T38356. */ + /* NOTE: we cannot return here, we would let flt_data in inconsistent state... see #38356. */ filter_flags = NULL; } else { @@ -578,7 +578,7 @@ static void uilist_filter_items(uiList *ui_list, RNA_parameter_dynamic_length_get(&list, parm), "filter_neworder", len); - /* NOTE: we cannot return here, we would let flt_data in inconsistent state... see T38356. */ + /* NOTE: we cannot return here, we would let flt_data in inconsistent state... see #38356. */ filter_neworder = NULL; } else { diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 347211f52460..f9e10a4eaf13 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -373,7 +373,7 @@ static void rna_userdef_undo_steps_set(PointerRNA *ptr, int value) { UserDef *userdef = (UserDef *)ptr->data; - /* Do not allow 1 undo steps, useless and breaks undo/redo process (see T42531). */ + /* Do not allow 1 undo steps, useless and breaks undo/redo process (see #42531). */ userdef->undosteps = (value == 1) ? 2 : value; } @@ -605,7 +605,7 @@ static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRN static void rna_UserDef_viewport_lights_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - /* If all lights are off gpu_draw resets them all, see: T27627, + /* If all lights are off gpu_draw resets them all, see: #27627, * so disallow them all to be disabled. */ if (U.light_param[0].flag == 0 && U.light_param[1].flag == 0 && U.light_param[2].flag == 0 && U.light_param[3].flag == 0) { @@ -2345,6 +2345,11 @@ static void rna_def_userdef_theme_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Camera Path", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "camera_passepartout", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Camera Passepartout", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "skin_root", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Skin Root", ""); @@ -6129,6 +6134,31 @@ static void rna_def_userdef_filepaths_asset_library(BlenderRNA *brna) prop, "Path", "Path to a directory with .blend files to use as an asset library"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_userdef_asset_library_path_set"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + static const EnumPropertyItem import_method_items[] = { + {ASSET_IMPORT_LINK, "LINK", 0, "Link", "Import the assets as linked data-block"}, + {ASSET_IMPORT_APPEND, + "APPEND", + 0, + "Append", + "Import the assets as copied data-block, with no link to the original asset data-block"}, + {ASSET_IMPORT_APPEND_REUSE, + "APPEND_REUSE", + 0, + "Append (Reuse Data)", + "Import the assets as copied data-block while avoiding multiple copies of nested, " + "typically heavy data. For example the textures of a material asset, or the mesh of an " + "object asset, don't have to be copied every time this asset is imported. The instances of " + "the asset share the data instead"}, + {0, NULL, 0, NULL, NULL}, + }; + prop = RNA_def_property(srna, "import_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, import_method_items); + RNA_def_property_ui_text( + prop, + "Default Import Method", + "Determine how the asset will be imported, unless overridden by the Asset Browser"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_filepaths(BlenderRNA *brna) @@ -6316,6 +6346,13 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna) prop = RNA_def_property(srna, "asset_libraries", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "UserAssetLibrary"); RNA_def_property_ui_text(prop, "Asset Libraries", ""); + + prop = RNA_def_property(srna, "active_asset_library", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, + "Active Asset Library", + "Index of the asset library being edited in the Preferences UI"); + /* Tag for UI-only update, meaning preferences will not be tagged as changed. */ + RNA_def_property_update(prop, 0, "rna_userdef_ui_update"); } static void rna_def_userdef_apps(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 20ff4c2efab2..e646258fb92d 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1548,7 +1548,7 @@ static StructRNA *rna_Operator_register(Main *bmain, BLI_assert(ARRAY_SIZE(strings) == 5); } - /* XXX, this doubles up with the operator name T29666. + /* XXX, this doubles up with the operator name #29666. * for now just remove from dir(bpy.types) */ /* create a new operator type */ @@ -1702,7 +1702,7 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, BLI_assert(ARRAY_SIZE(strings) == 5); } - /* XXX, this doubles up with the operator name T29666. + /* XXX, this doubles up with the operator name #29666. * for now just remove from dir(bpy.types) */ /* create a new operator type */ diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index b82458c44429..5d8bb533d7eb 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -291,7 +291,7 @@ static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, kmi->flag |= KMI_REPEAT_IGNORE; } - /* T32437 allow scripts to define hotkeys that get added to start of keymap + /* #32437 allow scripts to define hotkeys that get added to start of keymap * so that they stand a chance against catch-all defines later on */ if (head) { diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c index a4630415ccd5..23fd22b47b2d 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo.c @@ -517,7 +517,7 @@ static void rna_Gizmo_unregister(struct Main *bmain, StructRNA *type) WM_gizmotype_remove_ptr(NULL, bmain, gzt); - /* Free extension after removing instances so `__del__` doesn't crash, see: T85567. */ + /* Free extension after removing instances so `__del__` doesn't crash, see: #85567. */ RNA_struct_free_extension(type, &gzt->rna_ext); RNA_struct_free(&BLENDER_RNA, type); @@ -916,7 +916,7 @@ static void rna_GizmoGroup_unregister(struct Main *bmain, StructRNA *type) WM_gizmo_group_type_remove_ptr(bmain, gzgt); - /* Free extension after removing instances so `__del__` doesn't crash, see: T85567. */ + /* Free extension after removing instances so `__del__` doesn't crash, see: #85567. */ RNA_struct_free_extension(type, &gzgt->rna_ext); RNA_struct_free(&BLENDER_RNA, type); diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc index 453c66c26a6a..bc657717e380 100644 --- a/source/blender/modifiers/intern/MOD_boolean.cc +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -237,7 +237,7 @@ static BMesh *BMD_mesh_bm_create( BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params); /* Keep `mesh` first, needed so active layers are set based on `mesh` not `mesh_operand_ob`, - * otherwise the wrong active render layer is used, see T92384. + * otherwise the wrong active render layer is used, see #92384. * * NOTE: while initializing customer data layers the is not essential, * it avoids the overhead of having to re-allocate #BMHeader.data when the 2nd mesh is added diff --git a/source/blender/modifiers/intern/MOD_datatransfer.cc b/source/blender/modifiers/intern/MOD_datatransfer.cc index 7ac834c804ad..80c78955d146 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.cc +++ b/source/blender/modifiers/intern/MOD_datatransfer.cc @@ -183,7 +183,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if (((result == me) || (me_positions == result_positions) || (me_edges == result_edges)) && (dtmd->data_types & DT_TYPES_AFFECT_MESH)) { /* We need to duplicate data here, otherwise setting custom normals, edges' sharpness, etc., - * could modify org mesh, see T43671. */ + * could modify org mesh, see #43671. */ result = (Mesh *)BKE_id_copy_ex(nullptr, &me_mod->id, nullptr, LIB_ID_COPY_LOCALIZE); } diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.cc b/source/blender/modifiers/intern/MOD_meshsequencecache.cc index c8628a7693ee..16b54bd49bd8 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.cc +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.cc @@ -213,7 +213,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * XXX(Hans): This probably isn't true anymore with various CoW improvements, etc. */ if ((me_positions.data() == mesh_positions.data()) || (me_edges.data() == mesh_edges.data()) || (me_polys.data() == mesh_polys.data())) { - /* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */ + /* We need to duplicate data here, otherwise we'll modify org mesh, see #51701. */ mesh = reinterpret_cast( BKE_id_copy_ex(nullptr, &mesh->id, diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 6ecd2c74462c..15aab38bed7d 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -1736,7 +1736,9 @@ static void panel_draw(const bContext *C, Panel *panel) int socket_index; LISTBASE_FOREACH_INDEX (bNodeSocket *, socket, &nmd->node_group->inputs, socket_index) { - draw_property_for_socket(*C, layout, nmd, &bmain_ptr, ptr, *socket, socket_index); + if (!(socket->flag & SOCK_HIDE_IN_MODIFIER)) { + draw_property_for_socket(*C, layout, nmd, &bmain_ptr, ptr, *socket, socket_index); + } } } diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc index d6089372da6d..aecbff5c7be0 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.cc +++ b/source/blender/modifiers/intern/MOD_normal_edit.cc @@ -95,7 +95,7 @@ static void generate_vert_coordinates(Mesh *mesh, /* Translate our coordinates so that center of ob_center is at (0, 0, 0). */ /* Get ob_center (world) coordinates in ob local coordinates. - * No need to take into account ob_center's space here, see T44027. */ + * No need to take into account ob_center's space here, see #44027. */ invert_m4_m4(inv_obmat, ob->object_to_world); mul_v3_m4v3(diff, inv_obmat, ob_center->object_to_world[3]); negate_v3(diff); @@ -532,7 +532,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, if (BKE_mesh_edges(mesh) == BKE_mesh_edges((Mesh *)ob->data)) { /* We need to duplicate data here, otherwise setting custom normals * (which may also affect sharp edges) could - * modify original mesh, see T43671. */ + * modify original mesh, see #43671. */ result = (Mesh *)BKE_id_copy_ex(nullptr, &mesh->id, nullptr, LIB_ID_COPY_LOCALIZE); } else { diff --git a/source/blender/modifiers/intern/MOD_remesh.cc b/source/blender/modifiers/intern/MOD_remesh.cc index d35f4095acf5..e57778841e20 100644 --- a/source/blender/modifiers/intern/MOD_remesh.cc +++ b/source/blender/modifiers/intern/MOD_remesh.cc @@ -178,7 +178,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext * /*ctx*/, M } /* TODO(jbakker): Dualcon crashes when run in parallel. Could be related to incorrect * input data or that the library isn't thread safe. - * This was identified when changing the task isolation's during T76553. */ + * This was identified when changing the task isolation's during #76553. */ static ThreadMutex dualcon_mutex = BLI_MUTEX_INITIALIZER; BLI_mutex_lock(&dualcon_mutex); output = static_cast(dualcon(&input, diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 64d272c33e35..27f5d5f2f326 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -168,7 +168,7 @@ static void simpleDeform_bend(const float factor, cost = cosf(theta); /* NOTE: the operations below a susceptible to float precision errors - * regarding the order of operations, take care when changing, see: T85470 */ + * regarding the order of operations, take care when changing, see: #85470 */ switch (axis) { case 0: r_co[0] = x; diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index e3fbd072f36d..cdb7559a099a 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -143,7 +143,7 @@ typedef struct Frame { struct Frame *frame; int corner; /* checked to avoid chaining. - * (merging when we're already been referenced), see T39775 */ + * (merging when we're already been referenced), see #39775 */ uint is_target : 1; } merge[4]; @@ -834,7 +834,7 @@ static int calc_edge_subdivisions(const float (*vert_positions)[3], const MEdge *e, const int *degree) { - /* prevent memory errors T38003. */ + /* prevent memory errors #38003. */ #define NUM_SUBDIVISIONS_MAX 128 const MVertSkin *evs[2] = {&nodes[e->v1], &nodes[e->v2]}; diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.cc b/source/blender/modifiers/intern/MOD_solidify_extrude.cc index eb5cacc88865..9375a3eb59f7 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.cc +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.cc @@ -32,7 +32,7 @@ /** \name High Quality Normal Calculation Function * \{ */ -/* skip shell thickness for non-manifold edges, see T35710. */ +/* skip shell thickness for non-manifold edges, see #35710. */ #define USE_NONMANIFOLD_WORKAROUND /* *** derived mesh high quality normal calculation function *** */ @@ -974,7 +974,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex MEM_freeN(vert_nors); } - /* must recalculate normals with vgroups since they can displace unevenly T26888. */ + /* must recalculate normals with vgroups since they can displace unevenly #26888. */ if (BKE_mesh_vertex_normals_are_dirty(mesh) || do_rim || dvert) { BKE_mesh_normals_tag_dirty(result); } diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.cc b/source/blender/modifiers/intern/MOD_surfacedeform.cc index 8f144990e55b..bbcbb80a7717 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.cc +++ b/source/blender/modifiers/intern/MOD_surfacedeform.cc @@ -811,7 +811,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, const float edge_angle_a = bpoly->point_edgemid_angles[bpoly->dominant_edge]; const float edge_angle_b = bpoly->point_edgemid_angles[!bpoly->dominant_edge]; /* Clamp so skinny faces with near zero `edgemid_angle` - * won't cause numeric problems. see T81988. */ + * won't cause numeric problems. see #81988. */ scale_weight = edge_angle_a / max_ff(edge_angle_a, bpoly->edgemid_angle); scale_weight /= scale_weight + (edge_angle_b / max_ff(edge_angle_b, bpoly->edgemid_angle)); } @@ -888,7 +888,7 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, /* Apply after other kinds of scaling so the faces corner angle is always * scaled in a uniform way, preventing heavily sub-divided triangle fans - * from having a lop-sided influence on the weighting, see T81988. */ + * from having a lop-sided influence on the weighting, see #81988. */ bpoly->weight *= bpoly->edgemid_angle / M_PI; tot_weight += bpoly->weight; diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c index 0f6c40610a0d..f88fb971b9ca 100644 --- a/source/blender/modifiers/intern/MOD_ui_common.c +++ b/source/blender/modifiers/intern/MOD_ui_common.c @@ -274,6 +274,17 @@ static void modifier_ops_extra_draw(bContext *C, uiLayout *layout, void *md_v) if (!md->next) { uiLayoutSetEnabled(row, false); } + + if (md->type == eModifierType_Nodes) { + uiItemFullO(layout, + "OBJECT_OT_geometry_nodes_move_to_nodes", + NULL, + ICON_NONE, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &op_ptr); + } } static void modifier_panel_header(const bContext *C, Panel *panel) diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.cc b/source/blender/nodes/composite/nodes/node_composite_composite.cc index 70e4c2b5d3b1..dafa87f93f0f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_composite.cc +++ b/source/blender/nodes/composite/nodes/node_composite_composite.cc @@ -94,7 +94,7 @@ class CompositeOperation : public NodeOperation { image.bind_as_texture(shader, "input_tx"); GPUTexture *output_texture = context().get_output_texture(); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(output_texture, image_unit); const int2 compositing_region_size = context().get_compositing_region_size(); @@ -122,7 +122,7 @@ class CompositeOperation : public NodeOperation { image.bind_as_texture(shader, "input_tx"); GPUTexture *output_texture = context().get_output_texture(); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(output_texture, image_unit); const int2 compositing_region_size = context().get_compositing_region_size(); @@ -152,7 +152,7 @@ class CompositeOperation : public NodeOperation { alpha.bind_as_texture(shader, "alpha_tx"); GPUTexture *output_texture = context().get_output_texture(); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(output_texture, image_unit); const int2 compositing_region_size = context().get_compositing_region_size(); diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.cc b/source/blender/nodes/composite/nodes/node_composite_dilate.cc index 07063c1a06b9..b34a7bd6646b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_dilate.cc +++ b/source/blender/nodes/composite/nodes/node_composite_dilate.cc @@ -122,7 +122,7 @@ class DilateErodeOperation : public NodeOperation { const int2 transposed_domain = int2(domain.size.y, domain.size.x); GPUTexture *horizontal_pass_result = texture_pool().acquire_color(transposed_domain); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(horizontal_pass_result, image_unit); compute_dispatch_threads_at_least(shader, domain.size); @@ -143,7 +143,7 @@ class DilateErodeOperation : public NodeOperation { GPU_shader_uniform_1i(shader, "radius", math::abs(get_distance())); GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH); - const int texture_image_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(horizontal_pass_result, texture_image_unit); const Domain domain = compute_domain(); @@ -273,7 +273,7 @@ class DilateErodeOperation : public NodeOperation { const int2 transposed_domain = int2(domain.size.y, domain.size.x); GPUTexture *horizontal_pass_result = texture_pool().acquire_color(transposed_domain); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(horizontal_pass_result, image_unit); compute_dispatch_threads_at_least(shader, domain.size); @@ -293,7 +293,7 @@ class DilateErodeOperation : public NodeOperation { GPU_shader_bind(shader); GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH); - const int texture_image_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + const int texture_image_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(horizontal_pass_result, texture_image_unit); const MorphologicalDistanceFeatherWeights &weights = diff --git a/source/blender/nodes/composite/nodes/node_composite_image.cc b/source/blender/nodes/composite/nodes/node_composite_image.cc index ad49d687220a..27b864f9856d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.cc +++ b/source/blender/nodes/composite/nodes/node_composite_image.cc @@ -525,7 +525,7 @@ class ImageOperation : public NodeOperation { GPUShader *shader = shader_manager().get(get_shader_name(identifier)); GPU_shader_bind(shader); - const int input_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + const int input_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(image_texture, input_unit); result.bind_as_image(shader, "output_img"); @@ -859,7 +859,7 @@ class RenderLayerOperation : public NodeOperation { const int2 lower_bound = int2(compositing_region.xmin, compositing_region.ymin); GPU_shader_uniform_2iv(shader, "compositing_region_lower_bound", lower_bound); - const int input_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + const int input_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(pass_texture, input_unit); const int2 compositing_region_size = context().get_compositing_region_size(); @@ -889,7 +889,7 @@ class RenderLayerOperation : public NodeOperation { const int2 lower_bound = int2(compositing_region.xmin, compositing_region.ymin); GPU_shader_uniform_2iv(shader, "compositing_region_lower_bound", lower_bound); - const int input_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + const int input_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(pass_texture, input_unit); const int2 compositing_region_size = context().get_compositing_region_size(); diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.cc b/source/blender/nodes/composite/nodes/node_composite_movieclip.cc index c55df061873d..a3fa99d83565 100644 --- a/source/blender/nodes/composite/nodes/node_composite_movieclip.cc +++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.cc @@ -128,7 +128,7 @@ class MovieClipOperation : public NodeOperation { GPUShader *shader = shader_manager().get("compositor_convert_color_to_half_color"); GPU_shader_bind(shader); - const int input_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + const int input_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(movie_clip_texture, input_unit); result.bind_as_image(shader, "output_img"); @@ -162,7 +162,7 @@ class MovieClipOperation : public NodeOperation { GPUShader *shader = shader_manager().get("compositor_extract_alpha_from_color"); GPU_shader_bind(shader); - const int input_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + const int input_unit = GPU_shader_get_sampler_binding(shader, "input_tx"); GPU_texture_bind(movie_clip_texture, input_unit); result.bind_as_image(shader, "output_img"); diff --git a/source/blender/nodes/composite/nodes/node_composite_output_file.cc b/source/blender/nodes/composite/nodes/node_composite_output_file.cc index 8939405cc075..512977944090 100644 --- a/source/blender/nodes/composite/nodes/node_composite_output_file.cc +++ b/source/blender/nodes/composite/nodes/node_composite_output_file.cc @@ -258,7 +258,7 @@ static void update_output_file(bNodeTree *ntree, bNode *node) { PointerRNA ptr; - /* XXX fix for T36706: remove invalid sockets added with bpy API. + /* XXX fix for #36706: remove invalid sockets added with bpy API. * This is not ideal, but prevents crashes from missing storage. * FileOutput node needs a redesign to support this properly. */ diff --git a/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc b/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc index 73dcf42904c8..c03a3a42dc99 100644 --- a/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc +++ b/source/blender/nodes/composite/nodes/node_composite_split_viewer.cc @@ -77,7 +77,7 @@ class ViewerOperation : public NodeOperation { second_image.bind_as_texture(shader, "second_image_tx"); GPUTexture *output_texture = context().get_output_texture(); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(output_texture, image_unit); compute_dispatch_threads_at_least(shader, compositing_region_size); diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.cc b/source/blender/nodes/composite/nodes/node_composite_viewer.cc index 66a16905d674..0beee8621acf 100644 --- a/source/blender/nodes/composite/nodes/node_composite_viewer.cc +++ b/source/blender/nodes/composite/nodes/node_composite_viewer.cc @@ -123,7 +123,7 @@ class ViewerOperation : public NodeOperation { image.bind_as_texture(shader, "input_tx"); GPUTexture *output_texture = context().get_output_texture(); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(output_texture, image_unit); const int2 compositing_region_size = context().get_compositing_region_size(); @@ -151,7 +151,7 @@ class ViewerOperation : public NodeOperation { image.bind_as_texture(shader, "input_tx"); GPUTexture *output_texture = context().get_output_texture(); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(output_texture, image_unit); const int2 compositing_region_size = context().get_compositing_region_size(); @@ -181,7 +181,7 @@ class ViewerOperation : public NodeOperation { alpha.bind_as_texture(shader, "alpha_tx"); GPUTexture *output_texture = context().get_output_texture(); - const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img"); GPU_texture_image_bind(output_texture, image_unit); const int2 compositing_region_size = context().get_compositing_region_size(); diff --git a/source/blender/nodes/function/nodes/node_fn_compare.cc b/source/blender/nodes/function/nodes/node_fn_compare.cc index 62cfaf369a00..67b2c15d08e9 100644 --- a/source/blender/nodes/function/nodes/node_fn_compare.cc +++ b/source/blender/nodes/function/nodes/node_fn_compare.cc @@ -93,7 +93,7 @@ static void node_init(bNodeTree * /*tree*/, bNode *node) class SocketSearchOp { public: - std::string socket_name; + const StringRef socket_name; eNodeSocketDatatype data_type; NodeCompareOperation operation; NodeCompareMode mode = NODE_COMPARE_MODE_ELEMENT; @@ -107,40 +107,62 @@ class SocketSearchOp { } }; +static std::optional get_compare_type_for_operation( + const eNodeSocketDatatype type, const NodeCompareOperation operation) +{ + switch (type) { + case SOCK_BOOLEAN: + if (ELEM(operation, NODE_COMPARE_COLOR_BRIGHTER, NODE_COMPARE_COLOR_DARKER)) { + return SOCK_RGBA; + } + return SOCK_INT; + case SOCK_INT: + case SOCK_FLOAT: + case SOCK_VECTOR: + if (ELEM(operation, NODE_COMPARE_COLOR_BRIGHTER, NODE_COMPARE_COLOR_DARKER)) { + return SOCK_RGBA; + } + return type; + case SOCK_RGBA: + if (!ELEM(operation, + NODE_COMPARE_COLOR_BRIGHTER, + NODE_COMPARE_COLOR_DARKER, + NODE_COMPARE_EQUAL, + NODE_COMPARE_NOT_EQUAL)) { + return SOCK_VECTOR; + } + return type; + case SOCK_STRING: + if (!ELEM(operation, NODE_COMPARE_EQUAL, NODE_COMPARE_NOT_EQUAL)) { + return std::nullopt; + } + return type; + default: + BLI_assert_unreachable(); + return std::nullopt; + } +} + static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) { - const eNodeSocketDatatype type = static_cast(params.other_socket().type); - if (!ELEM(type, SOCK_BOOLEAN, SOCK_FLOAT, SOCK_RGBA, SOCK_VECTOR, SOCK_INT, SOCK_STRING)) { + const eNodeSocketDatatype type = eNodeSocketDatatype(params.other_socket().type); + if (!ELEM(type, SOCK_INT, SOCK_BOOLEAN, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_STRING)) { return; } - - const eNodeSocketDatatype mode_type = (type == SOCK_BOOLEAN) ? SOCK_INT : type; - const bool string_type = (type == SOCK_STRING); - - const std::string socket_name = params.in_out() == SOCK_IN ? "A" : "Result"; - + const StringRef socket_name = params.in_out() == SOCK_IN ? "A" : "Result"; for (const EnumPropertyItem *item = rna_enum_node_compare_operation_items; item->identifier != nullptr; item++) { if (item->name != nullptr && item->identifier[0] != '\0') { - if (!string_type && - ELEM(item->value, NODE_COMPARE_COLOR_BRIGHTER, NODE_COMPARE_COLOR_DARKER)) { - params.add_item(IFACE_(item->name), - SocketSearchOp{socket_name, - SOCK_RGBA, - static_cast(item->value)}); - } - else if ((!string_type) || - (string_type && ELEM(item->value, NODE_COMPARE_EQUAL, NODE_COMPARE_NOT_EQUAL))) { - params.add_item(IFACE_(item->name), - SocketSearchOp{socket_name, - mode_type, - static_cast(item->value)}); + const NodeCompareOperation operation = NodeCompareOperation(item->value); + if (const std::optional fixed_type = get_compare_type_for_operation( + type, operation)) { + params.add_item(IFACE_(item->name), SocketSearchOp{socket_name, *fixed_type, operation}); } } } - /* Add Angle socket. */ - if (!string_type && params.in_out() == SOCK_IN) { + + if (params.in_out() != SOCK_IN && type != SOCK_STRING) { params.add_item( IFACE_("Angle"), SocketSearchOp{ diff --git a/source/blender/nodes/function/nodes/node_fn_random_value.cc b/source/blender/nodes/function/nodes/node_fn_random_value.cc index df90c2103cc7..416d0e754eb8 100644 --- a/source/blender/nodes/function/nodes/node_fn_random_value.cc +++ b/source/blender/nodes/function/nodes/node_fn_random_value.cc @@ -170,7 +170,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder) [](int min_value, int max_value, int id, int seed) -> int { const float value = noise::hash_to_float(id, seed); /* Add one to the maximum and use floor to produce an even - * distribution for the first and last values (See T93591). */ + * distribution for the first and last values (See #93591). */ return floor(value * (max_value + 1 - min_value) + min_value); }, mf::build::exec_presets::SomeSpanOrSingle<2>()); diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 448a5e69de44..f1cccf756e62 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -75,17 +75,17 @@ set(SRC nodes/node_geo_extrude_mesh.cc nodes/node_geo_flip_faces.cc nodes/node_geo_geometry_to_instance.cc + nodes/node_geo_image.cc nodes/node_geo_image_info.cc nodes/node_geo_image_texture.cc - nodes/node_geo_image.cc nodes/node_geo_input_curve_handles.cc nodes/node_geo_input_curve_tilt.cc nodes/node_geo_input_id.cc nodes/node_geo_input_index.cc nodes/node_geo_input_instance_rotation.cc nodes/node_geo_input_instance_scale.cc - nodes/node_geo_input_material_index.cc nodes/node_geo_input_material.cc + nodes/node_geo_input_material_index.cc nodes/node_geo_input_mesh_edge_angle.cc nodes/node_geo_input_mesh_edge_neighbors.cc nodes/node_geo_input_mesh_edge_vertices.cc @@ -135,17 +135,17 @@ set(SRC nodes/node_geo_mesh_topology_vertex_of_corner.cc nodes/node_geo_object_info.cc nodes/node_geo_offset_point_in_curve.cc + nodes/node_geo_points.cc nodes/node_geo_points_to_vertices.cc nodes/node_geo_points_to_volume.cc - nodes/node_geo_points.cc nodes/node_geo_proximity.cc nodes/node_geo_raycast.cc nodes/node_geo_realize_instances.cc nodes/node_geo_remove_attribute.cc nodes/node_geo_rotate_instances.cc nodes/node_geo_sample_index.cc - nodes/node_geo_sample_nearest_surface.cc nodes/node_geo_sample_nearest.cc + nodes/node_geo_sample_nearest_surface.cc nodes/node_geo_sample_uv_surface.cc nodes/node_geo_scale_elements.cc nodes/node_geo_scale_instances.cc @@ -157,8 +157,8 @@ set(SRC nodes/node_geo_set_curve_radius.cc nodes/node_geo_set_curve_tilt.cc nodes/node_geo_set_id.cc - nodes/node_geo_set_material_index.cc nodes/node_geo_set_material.cc + nodes/node_geo_set_material_index.cc nodes/node_geo_set_point_radius.cc nodes/node_geo_set_position.cc nodes/node_geo_set_shade_smooth.cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_topology_points_of_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_topology_points_of_curve.cc index 086a68401ed0..b8138ef67693 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_topology_points_of_curve.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_topology_points_of_curve.cc @@ -219,7 +219,7 @@ class CurveStartPointInput final : public bke::CurvesFieldInput { return false; } - std::optional preferred_domain(const bke::CurvesGeometry & /*curves*/) + std::optional preferred_domain(const bke::CurvesGeometry & /*curves*/) const final { return ATTR_DOMAIN_CURVE; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index d37f36e17a5f..0e459566d479 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -67,6 +67,11 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) uiItemR(layout, ptr, "distribute_method", 0, "", ICON_NONE); } +static void node_layout_ex(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) +{ + uiItemR(layout, ptr, "use_legacy_normal", 0, nullptr, ICON_NONE); +} + static void node_point_distribute_points_on_faces_update(bNodeTree *ntree, bNode *node) { bNodeSocket *sock_distance_min = static_cast(BLI_findlink(&node->inputs, 2)); @@ -325,11 +330,73 @@ struct AttributeOutputs { }; } // namespace +static void compute_normal_outputs(const Mesh &mesh, + const Span bary_coords, + const Span looptri_indices, + MutableSpan r_normals) +{ + Array corner_normals(mesh.totloop); + BKE_mesh_calc_normals_split_ex( + const_cast(&mesh), nullptr, reinterpret_cast(corner_normals.data())); + + const Span looptris = mesh.looptris(); + + threading::parallel_for(bary_coords.index_range(), 512, [&](const IndexRange range) { + for (const int i : range) { + const int looptri_index = looptri_indices[i]; + const MLoopTri &looptri = looptris[looptri_index]; + const float3 &bary_coord = bary_coords[i]; + + const float3 normal = math::normalize( + bke::mesh_surface_sample::sample_corner_attrribute_with_bary_coords( + bary_coord, looptri, corner_normals.as_span())); + + r_normals[i] = normal; + } + }); +} + +static void compute_legacy_normal_outputs(const Mesh &mesh, + const Span bary_coords, + const Span looptri_indices, + MutableSpan r_normals) +{ + const Span positions = mesh.vert_positions(); + const Span loops = mesh.loops(); + const Span looptris = mesh.looptris(); + + for (const int i : bary_coords.index_range()) { + const int looptri_index = looptri_indices[i]; + const MLoopTri &looptri = looptris[looptri_index]; + + const int v0_index = loops[looptri.tri[0]].v; + const int v1_index = loops[looptri.tri[1]].v; + const int v2_index = loops[looptri.tri[2]].v; + const float3 v0_pos = positions[v0_index]; + const float3 v1_pos = positions[v1_index]; + const float3 v2_pos = positions[v2_index]; + + float3 normal; + normal_tri_v3(normal, v0_pos, v1_pos, v2_pos); + r_normals[i] = normal; + } +} + +static void compute_rotation_output(const Span normals, MutableSpan r_rotations) +{ + threading::parallel_for(normals.index_range(), 256, [&](const IndexRange range) { + for (const int i : range) { + r_rotations[i] = normal_to_euler_rotation(normals[i]); + } + }); +} + BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh, PointCloud &points, const Span bary_coords, const Span looptri_indices, - const AttributeOutputs &attribute_outputs) + const AttributeOutputs &attribute_outputs, + const bool use_legacy_normal) { MutableAttributeAccessor point_attributes = points.attributes_for_write(); @@ -348,33 +415,24 @@ BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh, attribute_outputs.rotation_id.get(), ATTR_DOMAIN_POINT); } - const Span positions = mesh.vert_positions(); - const Span loops = mesh.loops(); - const Span looptris = mesh.looptris(); - - for (const int i : bary_coords.index_range()) { - const int looptri_index = looptri_indices[i]; - const MLoopTri &looptri = looptris[looptri_index]; - const float3 &bary_coord = bary_coords[i]; - - const int v0_index = loops[looptri.tri[0]].v; - const int v1_index = loops[looptri.tri[1]].v; - const int v2_index = loops[looptri.tri[2]].v; - const float3 v0_pos = positions[v0_index]; - const float3 v1_pos = positions[v1_index]; - const float3 v2_pos = positions[v2_index]; - - ids.span[i] = noise::hash(noise::hash_float(bary_coord), looptri_index); - - float3 normal; - if (!normals.span.is_empty() || !rotations.span.is_empty()) { - normal_tri_v3(normal, v0_pos, v1_pos, v2_pos); + threading::parallel_for(bary_coords.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + const int looptri_index = looptri_indices[i]; + const float3 &bary_coord = bary_coords[i]; + ids.span[i] = noise::hash(noise::hash_float(bary_coord), looptri_index); } - if (!normals.span.is_empty()) { - normals.span[i] = normal; + }); + + if (normals) { + if (use_legacy_normal) { + compute_legacy_normal_outputs(mesh, bary_coords, looptri_indices, normals.span); } - if (!rotations.span.is_empty()) { - rotations.span[i] = normal_to_euler_rotation(normal); + else { + compute_normal_outputs(mesh, bary_coords, looptri_indices, normals.span); + } + + if (rotations) { + compute_rotation_output(normals.span, rotations.span); } } @@ -507,7 +565,9 @@ static void point_distribution_calculate(GeometrySet &geometry_set, propagate_existing_attributes(mesh, attributes, *pointcloud, bary_coords, looptri_indices); - compute_attribute_outputs(mesh, *pointcloud, bary_coords, looptri_indices, attribute_outputs); + const bool use_legacy_normal = params.node().custom2 != 0; + compute_attribute_outputs( + mesh, *pointcloud, bary_coords, looptri_indices, attribute_outputs, use_legacy_normal); } static void node_geo_exec(GeoNodeExecParams params) @@ -521,8 +581,9 @@ static void node_geo_exec(GeoNodeExecParams params) const Field selection_field = params.extract_input>("Selection"); AttributeOutputs attribute_outputs; - attribute_outputs.normal_id = params.get_output_anonymous_attribute_id_if_needed("Normal"); attribute_outputs.rotation_id = params.get_output_anonymous_attribute_id_if_needed("Rotation"); + attribute_outputs.normal_id = params.get_output_anonymous_attribute_id_if_needed( + "Normal", bool(attribute_outputs.rotation_id)); lazy_threading::send_hint(); @@ -567,5 +628,6 @@ void register_node_type_geo_distribute_points_on_faces() ntype.declare = file_ns::node_declare; ntype.geometry_node_execute = file_ns::node_geo_exec; ntype.draw_buttons = file_ns::node_layout; + ntype.draw_buttons_ex = file_ns::node_layout_ex; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index 8e51e8ac2b52..c4f88b8ac75f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -540,7 +540,7 @@ static bool vertex_needs_dissolving(const int vertex, * used in the data-structures derived from the mesh. For each pair of polygons which has such a * vertex, an edge is created for the dual mesh between the centers of those two polygons. All * edges in the input mesh which contain such a vertex are marked as 'done' to prevent duplicate - * edges being created. (See T94144) + * edges being created. (See #94144) */ static void dissolve_redundant_verts(const Span edges, const Span polys, diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index da4d3c7e6415..c61bb8b4d8a7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -64,18 +64,6 @@ struct IndexAttributes { /** \name Utility Functions * \{ */ -static Map gather_attributes_without_id( - const GeometrySet &geometry_set, - const GeometryComponentType component_type, - const AnonymousAttributePropagationInfo &propagation_info) -{ - Map attributes; - geometry_set.gather_attributes_for_propagation( - {component_type}, component_type, false, propagation_info, attributes); - attributes.remove("id"); - return attributes; -}; - static OffsetIndices accumulate_counts_to_offsets(const IndexMask selection, const VArray &counts, Array &r_offset_data) @@ -183,39 +171,25 @@ static void copy_stable_id_point(const OffsetIndices offsets, dst_attribute.finish(); } -static void copy_attributes_without_id(GeometrySet &geometry_set, - const GeometryComponentType component_type, - const eAttrDomain domain, - const OffsetIndices offsets, +static void copy_attributes_without_id(const OffsetIndices offsets, const IndexMask selection, const AnonymousAttributePropagationInfo &propagation_info, + const eAttrDomain domain, const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes) { - const Map attributes = gather_attributes_without_id( - geometry_set, component_type, propagation_info); - - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_attributes.lookup(attribute_id); - if (!src_attribute || src_attribute.domain != domain) { - continue; - } - eAttrDomain out_domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( - attribute_id, out_domain, data_type); - if (!dst_attribute) { - continue; - } - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + for (auto &attribute : bke::retrieve_attributes_for_transfer(src_attributes, + dst_attributes, + ATTR_DOMAIN_AS_MASK(domain), + propagation_info, + {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src = src_attribute.varray.typed(); - MutableSpan dst = dst_attribute.span.typed(); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); threaded_slice_fill(offsets, selection, src, dst); }); - dst_attribute.finish(); + attribute.dst.finish(); } } @@ -230,42 +204,26 @@ static void copy_attributes_without_id(GeometrySet &geometry_set, * copied with an offset fill, otherwise a mapping is used. */ static void copy_curve_attributes_without_id( - const GeometrySet &geometry_set, const bke::CurvesGeometry &src_curves, const IndexMask selection, const OffsetIndices curve_offsets, const AnonymousAttributePropagationInfo &propagation_info, bke::CurvesGeometry &dst_curves) { - Map attributes = gather_attributes_without_id( - geometry_set, GEO_COMPONENT_TYPE_CURVE, propagation_info); - const OffsetIndices src_points_by_curve = src_curves.points_by_curve(); const OffsetIndices dst_points_by_curve = dst_curves.points_by_curve(); - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_curves.attributes().lookup(attribute_id); - if (!src_attribute) { - continue; - } - - eAttrDomain out_domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - GSpanAttributeWriter dst_attribute = - dst_curves.attributes_for_write().lookup_or_add_for_write_only_span( - attribute_id, out_domain, data_type); - if (!dst_attribute) { - continue; - } - - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(), + dst_curves.attributes_for_write(), + ATTR_DOMAIN_MASK_ALL, + propagation_info, + {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src{src_attribute.varray.typed()}; - MutableSpan dst = dst_attribute.span.typed(); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); - switch (out_domain) { + switch (attribute.meta_data.domain) { case ATTR_DOMAIN_CURVE: threaded_slice_fill(curve_offsets, selection, src, dst); break; @@ -281,10 +239,11 @@ static void copy_curve_attributes_without_id( }); break; default: + BLI_assert_unreachable(); break; } }); - dst_attribute.finish(); + attribute.dst.finish(); } } @@ -394,8 +353,7 @@ static void duplicate_curves(GeometrySet &geometry_set, }); all_dst_offsets.last() = dst_points_num; - copy_curve_attributes_without_id( - geometry_set, curves, selection, curve_offsets, propagation_info, new_curves); + copy_curve_attributes_without_id(curves, selection, curve_offsets, propagation_info, new_curves); copy_stable_id_curves(curves, selection, curve_offsets, new_curves); @@ -407,6 +365,7 @@ static void duplicate_curves(GeometrySet &geometry_set, curve_offsets); } + new_curves.update_curve_types(); geometry_set.replace_curves(new_curves_id); } @@ -421,7 +380,6 @@ static void duplicate_curves(GeometrySet &geometry_set, * copied with an offset fill, otherwise a mapping is used. */ static void copy_face_attributes_without_id( - GeometrySet &geometry_set, const Span edge_mapping, const Span vert_mapping, const Span loop_mapping, @@ -431,31 +389,14 @@ static void copy_face_attributes_without_id( const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes) { - Map attributes = gather_attributes_without_id( - geometry_set, GEO_COMPONENT_TYPE_MESH, propagation_info); - - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_attributes.lookup(attribute_id); - if (!src_attribute) { - continue; - } - - eAttrDomain out_domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( - attribute_id, out_domain, data_type); - if (!dst_attribute) { - continue; - } - - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + for (auto &attribute : bke::retrieve_attributes_for_transfer( + src_attributes, dst_attributes, ATTR_DOMAIN_MASK_ALL, propagation_info, {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src{src_attribute.varray.typed()}; - MutableSpan dst = dst_attribute.span.typed(); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); - switch (out_domain) { + switch (attribute.meta_data.domain) { case ATTR_DOMAIN_POINT: array_utils::gather(src, vert_mapping, dst); break; @@ -469,10 +410,11 @@ static void copy_face_attributes_without_id( array_utils::gather(src, loop_mapping, dst); break; default: + BLI_assert_unreachable(); break; } }); - dst_attribute.finish(); + attribute.dst.finish(); } } @@ -606,8 +548,7 @@ static void duplicate_faces(GeometrySet &geometry_set, new_mesh->loose_edges_tag_none(); - copy_face_attributes_without_id(geometry_set, - edge_mapping, + copy_face_attributes_without_id(edge_mapping, vert_mapping, loop_mapping, duplicates, @@ -645,7 +586,6 @@ static void duplicate_faces(GeometrySet &geometry_set, * copied with an offset fill, for point domain a mapping is used. */ static void copy_edge_attributes_without_id( - GeometrySet &geometry_set, const Span point_mapping, const OffsetIndices offsets, const IndexMask selection, @@ -653,30 +593,18 @@ static void copy_edge_attributes_without_id( const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes) { - Map attributes = gather_attributes_without_id( - geometry_set, GEO_COMPONENT_TYPE_MESH, propagation_info); - - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_attributes.lookup(attribute_id); - if (!src_attribute) { - continue; - } - - const eAttrDomain out_domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - GSpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( - attribute_id, out_domain, data_type); - if (!dst_attribute) { - continue; - } - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + for (auto &attribute : + bke::retrieve_attributes_for_transfer(src_attributes, + dst_attributes, + ATTR_DOMAIN_MASK_POINT | ATTR_DOMAIN_MASK_EDGE, + propagation_info, + {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src{src_attribute.varray.typed()}; - MutableSpan dst = dst_attribute.span.typed(); + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); - switch (out_domain) { + switch (attribute.meta_data.domain) { case ATTR_DOMAIN_EDGE: threaded_slice_fill(offsets, selection, src, dst); break; @@ -684,10 +612,11 @@ static void copy_edge_attributes_without_id( array_utils::gather(src, point_mapping, dst); break; default: + BLI_assert_unreachable(); break; } }); - dst_attribute.finish(); + attribute.dst.finish(); } } @@ -790,8 +719,7 @@ static void duplicate_edges(GeometrySet &geometry_set, } }); - copy_edge_attributes_without_id(geometry_set, - vert_orig_indices, + copy_edge_attributes_without_id(vert_orig_indices, duplicates, selection, propagation_info, @@ -854,32 +782,16 @@ static void duplicate_points_curve(GeometrySet &geometry_set, } new_curve_offsets.last() = dst_num; - Map attributes = gather_attributes_without_id( - geometry_set, GEO_COMPONENT_TYPE_CURVE, propagation_info); - - for (const Map::Item entry : attributes.items()) { - const AttributeIDRef attribute_id = entry.key; - GAttributeReader src_attribute = src_curves.attributes().lookup(attribute_id); - if (!src_attribute) { - continue; - } - - eAttrDomain domain = src_attribute.domain; - const eCustomDataType data_type = bke::cpp_type_to_custom_data_type( - src_attribute.varray.type()); - GSpanAttributeWriter dst_attribute = - new_curves.attributes_for_write().lookup_or_add_for_write_only_span( - attribute_id, domain, data_type); - if (!dst_attribute) { - continue; - } - - attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + for (auto &attribute : bke::retrieve_attributes_for_transfer(src_curves.attributes(), + new_curves.attributes_for_write(), + ATTR_DOMAIN_MASK_ALL, + propagation_info, + {"id"})) { + attribute_math::convert_to_static_type(attribute.src.type(), [&](auto dummy) { using T = decltype(dummy); - VArraySpan src{src_attribute.varray.typed()}; - MutableSpan dst = dst_attribute.span.typed(); - - switch (domain) { + const Span src = attribute.src.typed(); + MutableSpan dst = attribute.dst.span.typed(); + switch (attribute.meta_data.domain) { case ATTR_DOMAIN_CURVE: threading::parallel_for(selection.index_range(), 512, [&](IndexRange range) { for (const int i_selection : range) { @@ -892,10 +804,11 @@ static void duplicate_points_curve(GeometrySet &geometry_set, threaded_slice_fill(duplicates, selection, src, dst); break; default: + BLI_assert_unreachable(); break; } }); - dst_attribute.finish(); + attribute.dst.finish(); } copy_stable_id_point(duplicates, src_curves.attributes(), new_curves.attributes_for_write()); @@ -939,12 +852,10 @@ static void duplicate_points_mesh(GeometrySet &geometry_set, Mesh *new_mesh = BKE_mesh_new_nomain(duplicates.total_size(), 0, 0, 0, 0); - copy_attributes_without_id(geometry_set, - GEO_COMPONENT_TYPE_MESH, - ATTR_DOMAIN_POINT, - duplicates, + copy_attributes_without_id(duplicates, selection, propagation_info, + ATTR_DOMAIN_POINT, mesh.attributes(), new_mesh->attributes_for_write()); @@ -989,12 +900,10 @@ static void duplicate_points_pointcloud(GeometrySet &geometry_set, PointCloud *pointcloud = BKE_pointcloud_new_nomain(duplicates.total_size()); - copy_attributes_without_id(geometry_set, - GEO_COMPONENT_TYPE_POINT_CLOUD, - ATTR_DOMAIN_POINT, - duplicates, + copy_attributes_without_id(duplicates, selection, propagation_info, + ATTR_DOMAIN_POINT, src_points.attributes(), pointcloud->attributes_for_write()); @@ -1102,12 +1011,10 @@ static void duplicate_instances(GeometrySet &geometry_set, dst_instances->reference_handles().slice(range).fill(new_handle); } - copy_attributes_without_id(geometry_set, - GEO_COMPONENT_TYPE_INSTANCES, - ATTR_DOMAIN_INSTANCE, - duplicates, + copy_attributes_without_id(duplicates, selection, propagation_info, + ATTR_DOMAIN_INSTANCE, src_instances.attributes(), dst_instances->attributes_for_write()); diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 63d84076654c..c5d2bbe1b65e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -471,9 +471,6 @@ static void extrude_mesh_edges(Mesh &mesh, } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); - if (!attribute) { - return true; /* Impossible to write the "normal" attribute. */ - } attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); @@ -867,9 +864,6 @@ static void extrude_mesh_face_regions(Mesh &mesh, } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); - if (!attribute) { - return true; /* Impossible to write the "normal" attribute. */ - } attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); @@ -1158,9 +1152,6 @@ static void extrude_individual_mesh_faces(Mesh &mesh, } GSpanAttributeWriter attribute = attributes.lookup_or_add_for_write_span( id, meta_data.domain, meta_data.data_type); - if (!attribute) { - return true; /* Impossible to write the "normal" attribute. */ - } attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc index fb895aaf7dc8..741bd2932253 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_resolution.cc @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BKE_curves.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_input_spline_resolution_cc { @@ -9,10 +11,39 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output(N_("Resolution")).field_source(); } +class ResolutionFieldInput final : public bke::CurvesFieldInput { + public: + ResolutionFieldInput() : bke::CurvesFieldInput(CPPType::get(), "resolution") + { + category_ = Category::NamedAttribute; + } + + GVArray get_varray_for_context(const bke::CurvesGeometry &curves, + const eAttrDomain domain, + const IndexMask /*mask*/) const final + { + return curves.adapt_domain(curves.resolution(), ATTR_DOMAIN_CURVE, domain); + } + + uint64_t hash() const final + { + return 82713465872345682; + } + + bool is_equal_to(const fn::FieldNode &other) const final + { + return dynamic_cast(&other) != nullptr; + } + + std::optional preferred_domain(const bke::CurvesGeometry & /*curves*/) const final + { + return ATTR_DOMAIN_CURVE; + } +}; + static void node_geo_exec(GeoNodeExecParams params) { - Field resolution_field = AttributeFieldInput::Create("resolution"); - params.set_output("Resolution", std::move(resolution_field)); + params.set_output("Resolution", Field(std::make_shared())); } } // namespace blender::nodes::node_geo_input_spline_resolution_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc b/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc index 6c05234f1e8c..b17c41f8189a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_uv_unwrap.cc @@ -114,7 +114,7 @@ static VArray construct_uv_gvarray(const Mesh &mesh, ParamKey vkeys[2]{edge.v1, edge.v2}; GEO_uv_parametrizer_edge_set_seam(handle, vkeys); } - /* TODO: once field input nodes are able to emit warnings (T94039), emit a + /* TODO: once field input nodes are able to emit warnings (#94039), emit a * warning if we fail to solve an island. */ GEO_uv_parametrizer_construct_end(handle, fill_holes, false, nullptr); diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index a57bfad7a79a..c1d8a8f81b31 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -330,7 +330,7 @@ void GeoTreeLog::ensure_used_named_attributes() GeoTreeLog &child_log = modifier_log_->get_tree_log(child_hash); child_log.ensure_used_named_attributes(); if (const std::optional &group_node_id = child_log.tree_loggers_[0]->group_node_id) { - for (const auto &item : child_log.used_named_attributes.items()) { + for (const auto item : child_log.used_named_attributes.items()) { add_attribute(*group_node_id, item.key, item.value); } } diff --git a/source/blender/nodes/intern/node_common.cc b/source/blender/nodes/intern/node_common.cc index 8652493b49bf..97a6a925aee8 100644 --- a/source/blender/nodes/intern/node_common.cc +++ b/source/blender/nodes/intern/node_common.cc @@ -78,16 +78,14 @@ bool node_group_poll_instance(const bNode *node, const bNodeTree *nodetree, const char **disabled_hint) { - if (node->typeinfo->poll(node->typeinfo, nodetree, disabled_hint)) { - const bNodeTree *grouptree = (const bNodeTree *)node->id; - if (grouptree) { - return nodeGroupPoll(nodetree, grouptree, disabled_hint); - } - - return true; /* without a linked node tree, group node is always ok */ + if (!node->typeinfo->poll(node->typeinfo, nodetree, disabled_hint)) { + return false; } - - return false; + const bNodeTree *grouptree = reinterpret_cast(node->id); + if (!grouptree) { + return true; + } + return nodeGroupPoll(nodetree, grouptree, disabled_hint); } bool nodeGroupPoll(const bNodeTree *nodetree, @@ -114,10 +112,9 @@ bool nodeGroupPoll(const bNodeTree *nodetree, return false; } - LISTBASE_FOREACH (const bNode *, node, &grouptree->nodes) { + for (const bNode *node : grouptree->all_nodes()) { if (node->typeinfo->poll_instance && - !node->typeinfo->poll_instance( - const_cast(node), const_cast(nodetree), r_disabled_hint)) { + !node->typeinfo->poll_instance(node, nodetree, r_disabled_hint)) { return false; } } diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc index 691ffc936a7b..cae24ef4b0ad 100644 --- a/source/blender/nodes/shader/node_shader_tree.cc +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -367,7 +367,7 @@ static void ntree_shader_groups_expand_inputs(bNodeTree *localtree) LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { if (socket->link != nullptr && !(socket->link->flag & NODE_LINK_MUTED)) { bNodeLink *link = socket->link; - /* Fix the case where the socket is actually converting the data. (see T71374) + /* Fix the case where the socket is actually converting the data. (see #71374) * We only do the case of lossy conversion to float. */ if ((socket->type == SOCK_FLOAT) && (link->fromsock->type != link->tosock->type)) { if (link->fromsock->type == SOCK_RGBA) { @@ -439,7 +439,7 @@ static void flatten_group_do(bNodeTree *ntree, bNode *gnode) LISTBASE_FOREACH_MUTABLE (bNode *, node, &ngroup->nodes) { /* Remove interface nodes. * This also removes remaining links to and from interface nodes. - * We must delay removal since sockets will reference this node. see: T52092 */ + * We must delay removal since sockets will reference this node. see: #52092 */ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) { BLI_linklist_prepend(&group_interface_nodes, node); } @@ -448,7 +448,7 @@ static void flatten_group_do(bNodeTree *ntree, bNode *gnode) BLI_addtail(&ntree->nodes, node); nodeUniqueID(ntree, node); /* ensure unique node name in the node tree */ - /* This is very slow and it has no use for GPU nodetree. (see T70609) */ + /* This is very slow and it has no use for GPU nodetree. (see #70609) */ // nodeUniqueName(ntree, node); } ngroup->runtime->nodes_by_id.clear(); diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc index cf160c2c2773..fe3f2e2c8d05 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.cc @@ -173,7 +173,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, flag |= GPU_MATFLAG_CLEARCOAT; } - /* Ref. T98190: Defines are optimizations for old compilers. + /* Ref. #98190: Defines are optimizations for old compilers. * Might become unnecessary with EEVEE-Next. */ if (use_diffuse == false && use_refract == false && use_clear == true) { flag |= GPU_MATFLAG_PRINCIPLED_CLEARCOAT; diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.cc b/source/blender/nodes/shader/nodes/node_shader_bump.cc index a9affe745288..86c5aa990133 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.cc +++ b/source/blender/nodes/shader/nodes/node_shader_bump.cc @@ -62,11 +62,11 @@ static int gpu_shader_bump(GPUMaterial *mat, /* TODO (Miguel Pozo): * Currently, this doesn't compute the actual differentials, just the height at dX and dY * offsets. The actual differentials are computed inside the GLSL node_bump function by - * substracting the height input. This avoids redundant computations when the height input is + * subtracting the height input. This avoids redundant computations when the height input is * also needed by regular nodes as part in the main function (See #103903 for context). * A better option would be to add a "value" input socket (in this case the height) to the - * differentiate node, but currently this kind of intermediate nodes are pruned in the codegen - * process (see #104265), so we need to fix that first. */ + * differentiate node, but currently this kind of intermediate nodes are pruned in the + * code generation process (see #104265), so we need to fix that first. */ GPUNodeLink *dheight = GPU_differentiate_float_function(height_function); float invert = (node->custom1) ? -1.0 : 1.0; diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.cc b/source/blender/nodes/shader/nodes/node_shader_geometry.cc index d7d5f4aa91f5..5ef2fec474b6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_geometry.cc +++ b/source/blender/nodes/shader/nodes/node_shader_geometry.cc @@ -41,7 +41,7 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, /* Normalize some vectors after dFdx/dFdy offsets. * This is the case for interpolated, non linear functions. * The resulting vector can still be a bit wrong but not as much. - * (see T70644) */ + * (see #70644) */ if (ELEM(i, 1, 2, 4)) { GPU_link(mat, "vector_math_normalize", diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc index a295bda9d079..bd0e195821ba 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.cc @@ -54,7 +54,7 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, /* Normalize some vectors after dFdx/dFdy offsets. * This is the case for interpolated, non linear functions. * The resulting vector can still be a bit wrong but not as much. - * (see T70644) */ + * (see #70644) */ if (ELEM(i, 1, 6)) { GPU_link(mat, "vector_math_normalize", diff --git a/source/blender/nodes/shader/nodes/node_shader_uvmap.cc b/source/blender/nodes/shader/nodes/node_shader_uvmap.cc index de8221e3e97f..d054457220c4 100644 --- a/source/blender/nodes/shader/nodes/node_shader_uvmap.cc +++ b/source/blender/nodes/shader/nodes/node_shader_uvmap.cc @@ -53,7 +53,7 @@ static int node_shader_gpu_uvmap(GPUMaterial *mat, /* NOTE: using CD_AUTO_FROM_NAME instead of CD_MTFACE as geometry nodes may overwrite data which * will also change the eCustomDataType. This will also make EEVEE and Cycles consistent. See - * T93179. */ + * #93179. */ GPUNodeLink *mtface = GPU_attribute(mat, CD_AUTO_FROM_NAME, attr->uv_map); GPU_stack_link(mat, node, "node_uvmap", in, out, mtface); diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc b/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc index 0e0f94968517..da75f9155071 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc @@ -49,7 +49,7 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat, NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage; /* NOTE: Using #CD_AUTO_FROM_NAME is necessary because there are multiple color attribute types, * and the type may change during evaluation anyway. This will also make EEVEE and Cycles - * consistent. See T93179. */ + * consistent. See #93179. */ GPUNodeLink *vertexColorLink; diff --git a/source/blender/nodes/texture/nodes/node_texture_common.cc b/source/blender/nodes/texture/nodes/node_texture_common.cc index 988195d852aa..7811f00ce331 100644 --- a/source/blender/nodes/texture/nodes/node_texture_common.cc +++ b/source/blender/nodes/texture/nodes/node_texture_common.cc @@ -69,7 +69,7 @@ static void group_copy_inputs(bNode *gnode, bNodeStack **in, bNodeStack *gstack) if (node->type == NODE_GROUP_INPUT) { for (sock = static_cast(node->outputs.first), a = 0; sock; sock = sock->next, a++) { - if (in[a]) { /* shouldn't need to check this T36694. */ + if (in[a]) { /* shouldn't need to check this #36694. */ ns = node_get_socket_stack(gstack, sock); if (ns) { copy_stack(ns, in[a]); @@ -95,7 +95,7 @@ static void group_copy_outputs(bNode *gnode, bNodeStack **out, bNodeStack *gstac int a; LISTBASE_FOREACH_INDEX (bNodeSocket *, sock, &group_output_node->inputs, a) { if (!out[a]) { - /* shouldn't need to check this T36694. */ + /* shouldn't need to check this #36694. */ continue; } diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index cb8dd0a8bc27..bf60e27d9670 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -109,7 +109,7 @@ void BPY_context_update(struct bContext *C); /** * Use for `CTX_*_set(..)` functions need to set values which are later read back as expected. * In this case we don't want the Python context to override the values as it causes problems - * see T66256. + * see #66256. * * \param dict_p: A pointer to #bContext.data.py_context so we can assign a new value. * \param dict_orig: The value of #bContext.data.py_context_orig to check if we need to copy. diff --git a/source/blender/python/generic/CMakeLists.txt b/source/blender/python/generic/CMakeLists.txt index 96345a2fa348..29964b67b340 100644 --- a/source/blender/python/generic/CMakeLists.txt +++ b/source/blender/python/generic/CMakeLists.txt @@ -7,8 +7,8 @@ set(INC ../../gpu ../../makesdna ../../makesrna - ../../../../intern/guardedalloc ../../../../intern/clog + ../../../../intern/guardedalloc ) set(INC_SYS diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 08cdbe102330..de18ef5f94b5 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -54,7 +54,7 @@ static PyObject *idprop_py_from_idp_string(const IDProperty *prop) } #ifdef USE_STRING_COERCE - return PyC_UnicodeFromByteAndSize(IDP_Array(prop), prop->len - 1); + return PyC_UnicodeFromBytesAndSize(IDP_Array(prop), prop->len - 1); #else return PyUnicode_FromStringAndSize(IDP_String(prop), prop->len - 1); #endif @@ -192,7 +192,7 @@ static int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject int alloc_len; PyObject *value_coerce = NULL; - st = (char *)PyC_UnicodeAsByte(value, &value_coerce); + st = (char *)PyC_UnicodeAsBytes(value, &value_coerce); alloc_len = strlen(st) + 1; st = PyUnicode_AsUTF8(value); @@ -433,7 +433,7 @@ static IDProperty *idp_from_PyUnicode(const char *name, PyObject *ob) #ifdef USE_STRING_COERCE Py_ssize_t value_size; PyObject *value_coerce = NULL; - val.string.str = PyC_UnicodeAsByteAndSize(ob, &value_size, &value_coerce); + val.string.str = PyC_UnicodeAsBytesAndSize(ob, &value_size, &value_coerce); val.string.len = (int)value_size + 1; val.string.subtype = IDP_STRING_SUB_UTF8; prop = IDP_New(IDP_STRING, &val, name); @@ -727,12 +727,12 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, else { IDProperty *prop_exist; - /* avoid freeing when types match in case they are referenced by the UI, see: T37073 + /* avoid freeing when types match in case they are referenced by the UI, see: #37073 * obviously this isn't a complete solution, but helps for common cases. */ prop_exist = IDP_GetPropertyFromGroup(group, prop->name); if ((prop_exist != NULL) && (prop_exist->type == prop->type) && (prop_exist->subtype == prop->subtype)) { - /* Preserve prev/next links!!! See T42593. */ + /* Preserve prev/next links!!! See #42593. */ prop->prev = prop_exist->prev; prop->next = prop_exist->next; prop->flag = prop_exist->flag; diff --git a/source/blender/python/generic/imbuf_py_api.c b/source/blender/python/generic/imbuf_py_api.c index 77d450d496e8..f17a9c07f3c7 100644 --- a/source/blender/python/generic/imbuf_py_api.c +++ b/source/blender/python/generic/imbuf_py_api.c @@ -261,7 +261,7 @@ static PyObject *py_imbuf_filepath_get(Py_ImBuf *self, void *UNUSED(closure)) { PY_IMBUF_CHECK_OBJ(self); ImBuf *ibuf = self->ibuf; - return PyC_UnicodeFromByte(ibuf->name); + return PyC_UnicodeFromBytes(ibuf->name); } static int py_imbuf_filepath_set(Py_ImBuf *self, PyObject *value, void *UNUSED(closure)) diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index ed9f6160eaa4..be9d36d0b0c1 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -839,7 +839,7 @@ static void pyc_exception_buffer_handle_system_exit(PyObject *error_type, * So print the error and exit now. This is necessary as the call to #PyErr_Print exits, * the temporary `sys.stderr` assignment causes the output to be suppressed, failing silently. * Instead, restore the error and print it. If Python changes it's behavior and doesn't exit in - * the future - continue to create the exception buffer, see: T99966. + * the future - continue to create the exception buffer, see: #99966. * * Arguably accessing a `SystemExit` exception as a buffer should be supported without exiting. * (by temporarily enabling inspection for example) however - it's not obvious exactly when this @@ -1012,7 +1012,7 @@ PyObject *PyC_ExceptionBuffer_Simple(void) * In some cases we need to coerce strings, avoid doing this inline. * \{ */ -const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObject **coerce) +const char *PyC_UnicodeAsBytesAndSize(PyObject *py_str, Py_ssize_t *size, PyObject **coerce) { const char *result; @@ -1039,7 +1039,7 @@ const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObjec return NULL; } -const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) +const char *PyC_UnicodeAsBytes(PyObject *py_str, PyObject **coerce) { const char *result; @@ -1064,7 +1064,7 @@ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) return NULL; } -PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size) +PyObject *PyC_UnicodeFromBytesAndSize(const char *str, Py_ssize_t size) { PyObject *result = PyUnicode_FromStringAndSize(str, size); if (result) { @@ -1079,9 +1079,9 @@ PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size) return result; } -PyObject *PyC_UnicodeFromByte(const char *str) +PyObject *PyC_UnicodeFromBytes(const char *str) { - return PyC_UnicodeFromByteAndSize(str, strlen(str)); + return PyC_UnicodeFromBytesAndSize(str, strlen(str)); } /** \} */ @@ -1101,7 +1101,7 @@ PyObject *PyC_DefaultNameSpace(const char *filename) if (filename) { /* __file__ mainly for nice UI'ness * NOTE: this won't map to a real file when executing text-blocks and buttons. */ - PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromByte(filename)); + PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromBytes(filename)); } PyModule_AddObject(mod_main, "__builtins__", builtins); Py_INCREF(builtins); /* AddObject steals a reference */ diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 51e36892cbdd..dba7c24afdae 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -105,14 +105,14 @@ void PyC_Tuple_Fill(PyObject *tuple, PyObject *value); void PyC_List_Fill(PyObject *list, PyObject *value); /* follow http://www.python.org/dev/peps/pep-0383/ */ -PyObject *PyC_UnicodeFromByte(const char *str); -PyObject *PyC_UnicodeFromByteAndSize(const char *str, Py_ssize_t size); -const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce); /* coerce must be NULL */ +PyObject *PyC_UnicodeFromBytes(const char *str); +PyObject *PyC_UnicodeFromBytesAndSize(const char *str, Py_ssize_t size); +const char *PyC_UnicodeAsBytes(PyObject *py_str, PyObject **coerce); /* coerce must be NULL */ /** * String conversion, escape non-unicode chars * \param coerce: must be set to NULL. */ -const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObject **coerce); +const char *PyC_UnicodeAsBytesAndSize(PyObject *py_str, Py_ssize_t *size, PyObject **coerce); /** * Description: This function creates a new Python dictionary object. diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c index 2738a4e47844..6e50a7f323dd 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.c +++ b/source/blender/python/gpu/gpu_py_offscreen.c @@ -365,7 +365,7 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar depsgraph = BKE_scene_ensure_depsgraph(G_MAIN, scene, view_layer); - /* Disable 'bgl' state since it interfere with off-screen drawing, see: T84402. */ + /* Disable 'bgl' state since it interfere with off-screen drawing, see: #84402. */ const bool is_bgl = GPU_bgl_get(); if (is_bgl) { GPU_bgl_end(); @@ -374,7 +374,7 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar GPU_offscreen_bind(self->ofs, true); /* Cache the #GPUViewport so the frame-buffers and associated textures are - * not reallocated each time, see: T89204 */ + * not reallocated each time, see: #89204 */ if (!self->viewport) { self->viewport = GPU_viewport_create(); } diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index 9352e7cc9b11..80c22bd7a974 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -269,7 +269,7 @@ static PyObject *pygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject } GPU_shader_bind(self->shader); - GPU_shader_uniform_vector(self->shader, location, length, count, pybuffer.buf); + GPU_shader_uniform_float_ex(self->shader, location, length, count, pybuffer.buf); PyBuffer_Release(&pybuffer); @@ -292,7 +292,7 @@ static PyObject *pygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject *a } GPU_shader_bind(self->shader); - GPU_shader_uniform_vector_int(self->shader, location, length, count, pybuffer.buf); + GPU_shader_uniform_int_ex(self->shader, location, length, count, pybuffer.buf); PyBuffer_Release(&pybuffer); @@ -367,7 +367,7 @@ static PyObject *pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args) } GPU_shader_bind(self->shader); - GPU_shader_uniform_vector_int(self->shader, location, length, 1, values); + GPU_shader_uniform_int_ex(self->shader, location, length, 1, values); Py_RETURN_NONE; } @@ -437,7 +437,7 @@ static PyObject *pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args) } GPU_shader_bind(self->shader); - GPU_shader_uniform_vector(self->shader, location, length, 1, values); + GPU_shader_uniform_float_ex(self->shader, location, length, 1, values); Py_RETURN_NONE; } @@ -509,7 +509,7 @@ static PyObject *pygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args) } GPU_shader_bind(self->shader); - GPU_shader_uniform_vector_int(self->shader, location, length, 1, values); + GPU_shader_uniform_int_ex(self->shader, location, length, 1, values); Py_RETURN_NONE; } @@ -533,7 +533,7 @@ static PyObject *pygpu_shader_uniform_sampler(BPyGPUShader *self, PyObject *args } GPU_shader_bind(self->shader); - int slot = GPU_shader_get_texture_binding(self->shader, name); + int slot = GPU_shader_get_sampler_binding(self->shader, name); GPU_texture_bind(py_texture->tex, slot); GPU_shader_uniform_1i(self->shader, name, slot); @@ -559,7 +559,7 @@ static PyObject *pygpu_shader_uniform_block(BPyGPUShader *self, PyObject *args) return NULL; } - int binding = GPU_shader_get_uniform_block_binding(self->shader, name); + int binding = GPU_shader_get_ubo_binding(self->shader, name); if (binding == -1) { PyErr_SetString( PyExc_BufferError, diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 36d53d69effe..78729ff54d39 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -74,11 +74,11 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self)) const char *path; path = BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, NULL); - item = PyC_UnicodeFromByte(path ? path : ""); + item = PyC_UnicodeFromBytes(path ? path : ""); BLI_assert(item != NULL); PyTuple_SET_ITEM(ret, 0, item); path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, NULL); - item = PyC_UnicodeFromByte(path ? path : ""); + item = PyC_UnicodeFromBytes(path ? path : ""); BLI_assert(item != NULL); PyTuple_SET_ITEM(ret, 1, item); @@ -90,7 +90,7 @@ static bool bpy_blend_foreach_path_cb(BPathForeachPathData *bpath_data, const char *path_src) { PyObject *py_list = bpath_data->user_data; - PyList_APPEND(py_list, PyC_UnicodeFromByte(path_src)); + PyList_APPEND(py_list, PyC_UnicodeFromBytes(path_src)); return false; /* Never edits the path. */ } @@ -238,7 +238,7 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj * but best leave it up to the script author to create */ path = BKE_appdir_folder_id_user_notest(type.value_found, subdir); - return PyC_UnicodeFromByte(path ? path : ""); + return PyC_UnicodeFromBytes(path ? path : ""); } PyDoc_STRVAR(bpy_system_resource_doc, @@ -279,7 +279,7 @@ static PyObject *bpy_system_resource(PyObject *UNUSED(self), PyObject *args, PyO path = BKE_appdir_folder_id(type.value_found, subdir); - return PyC_UnicodeFromByte(path ? path : ""); + return PyC_UnicodeFromBytes(path ? path : ""); } PyDoc_STRVAR( @@ -326,7 +326,7 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj path = BKE_appdir_resource_path_id_with_version(type.value_found, false, (major * 100) + minor); - return PyC_UnicodeFromByte(path ? path : ""); + return PyC_UnicodeFromBytes(path ? path : ""); } /* This is only exposed for tests, see: `tests/python/bl_pyapi_bpy_driver_secure_eval.py`. */ diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 70cf231bc265..434151e4bf21 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -153,7 +153,7 @@ static PyObject *make_app_info(void) SetObjItem(PyBool_FromLong(G.factory_startup)); /* build info, use bytes since we can't assume _any_ encoding: - * see patch T30154 for issue */ + * see patch #30154 for issue */ #ifdef BUILD_DATE SetBytesItem(build_date); SetBytesItem(build_time); @@ -312,7 +312,7 @@ static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void PyDoc_STRVAR(bpy_app_tempdir_doc, "String, the temp directory used by blender (read-only)"); static PyObject *bpy_app_tempdir_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyC_UnicodeFromByte(BKE_tempdir_session()); + return PyC_UnicodeFromBytes(BKE_tempdir_session()); } PyDoc_STRVAR( @@ -339,7 +339,7 @@ static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *c static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyC_UnicodeFromByte(G.autoexec_fail); + return PyC_UnicodeFromBytes(G.autoexec_fail); } PyDoc_STRVAR(bpy_app_binary_path_doc, @@ -348,7 +348,7 @@ PyDoc_STRVAR(bpy_app_binary_path_doc, "an empty string which script authors may point to a Blender binary."); static PyObject *bpy_app_binary_path_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyC_UnicodeFromByte(BKE_appdir_program_path()); + return PyC_UnicodeFromBytes(BKE_appdir_program_path()); } static int bpy_app_binary_path_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure)) @@ -359,7 +359,7 @@ static int bpy_app_binary_path_set(PyObject *UNUSED(self), PyObject *value, void return -1; #endif PyObject *value_coerce = NULL; - const char *filepath = PyC_UnicodeAsByte(value, &value_coerce); + const char *filepath = PyC_UnicodeAsBytes(value, &value_coerce); if (filepath == NULL) { PyErr_Format(PyExc_ValueError, "expected a string or bytes, got %s", Py_TYPE(value)->tp_name); return -1; @@ -557,7 +557,7 @@ PyObject *BPY_app_struct(void) BlenderAppType.tp_init = NULL; BlenderAppType.tp_new = NULL; BlenderAppType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ /* Kind of a hack on top of #PyStructSequence. */ py_struct_seq_getset_init(); diff --git a/source/blender/python/intern/bpy_app_alembic.c b/source/blender/python/intern/bpy_app_alembic.c index abecd3d8c1a1..afa71572d5a1 100644 --- a/source/blender/python/intern/bpy_app_alembic.c +++ b/source/blender/python/intern/bpy_app_alembic.c @@ -84,7 +84,7 @@ PyObject *BPY_app_alembic_struct(void) BlenderAppABCType.tp_init = NULL; BlenderAppABCType.tp_new = NULL; BlenderAppABCType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ return ret; } diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c index a744f3fd4fa5..9d90b66854e8 100644 --- a/source/blender/python/intern/bpy_app_build_options.c +++ b/source/blender/python/intern/bpy_app_build_options.c @@ -349,7 +349,7 @@ PyObject *BPY_app_build_options_struct(void) BlenderAppBuildOptionsType.tp_init = NULL; BlenderAppBuildOptionsType.tp_new = NULL; BlenderAppBuildOptionsType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ return ret; } diff --git a/source/blender/python/intern/bpy_app_ffmpeg.c b/source/blender/python/intern/bpy_app_ffmpeg.c index c14b6672e4db..10170d5439b2 100644 --- a/source/blender/python/intern/bpy_app_ffmpeg.c +++ b/source/blender/python/intern/bpy_app_ffmpeg.c @@ -126,7 +126,7 @@ PyObject *BPY_app_ffmpeg_struct(void) BlenderAppFFmpegType.tp_init = NULL; BlenderAppFFmpegType.tp_new = NULL; BlenderAppFFmpegType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ return ret; } diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 947ec5d60bb5..296d10fa84bb 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -242,7 +242,7 @@ PyObject *BPY_app_handlers_struct(void) BlenderAppCbType.tp_init = NULL; BlenderAppCbType.tp_new = NULL; BlenderAppCbType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ /* assign the C callbacks */ if (ret) { diff --git a/source/blender/python/intern/bpy_app_ocio.c b/source/blender/python/intern/bpy_app_ocio.c index 3f28d05830bd..0cea91908c02 100644 --- a/source/blender/python/intern/bpy_app_ocio.c +++ b/source/blender/python/intern/bpy_app_ocio.c @@ -90,7 +90,7 @@ PyObject *BPY_app_ocio_struct(void) BlenderAppOCIOType.tp_init = NULL; BlenderAppOCIOType.tp_new = NULL; BlenderAppOCIOType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ return ret; } diff --git a/source/blender/python/intern/bpy_app_oiio.c b/source/blender/python/intern/bpy_app_oiio.c index ec0bc31c8449..ae1c2176dd3d 100644 --- a/source/blender/python/intern/bpy_app_oiio.c +++ b/source/blender/python/intern/bpy_app_oiio.c @@ -86,7 +86,7 @@ PyObject *BPY_app_oiio_struct(void) BlenderAppOIIOType.tp_init = NULL; BlenderAppOIIOType.tp_new = NULL; BlenderAppOIIOType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ return ret; } diff --git a/source/blender/python/intern/bpy_app_opensubdiv.c b/source/blender/python/intern/bpy_app_opensubdiv.c index 61250147d672..5ffa23789e70 100644 --- a/source/blender/python/intern/bpy_app_opensubdiv.c +++ b/source/blender/python/intern/bpy_app_opensubdiv.c @@ -82,7 +82,7 @@ PyObject *BPY_app_opensubdiv_struct(void) /* prevent user from creating new instances */ BlenderAppOpenSubdivType.tp_init = NULL; BlenderAppOpenSubdivType.tp_new = NULL; - /* without this we can't do set(sys.modules) T29635. */ + /* without this we can't do set(sys.modules) #29635. */ BlenderAppOpenSubdivType.tp_hash = (hashfunc)_Py_HashPointer; return ret; diff --git a/source/blender/python/intern/bpy_app_openvdb.c b/source/blender/python/intern/bpy_app_openvdb.c index 6cc476cebccb..91ff0cd04ce3 100644 --- a/source/blender/python/intern/bpy_app_openvdb.c +++ b/source/blender/python/intern/bpy_app_openvdb.c @@ -88,7 +88,7 @@ PyObject *BPY_app_openvdb_struct(void) BlenderAppOVDBType.tp_init = NULL; BlenderAppOVDBType.tp_new = NULL; BlenderAppOVDBType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ return ret; } diff --git a/source/blender/python/intern/bpy_app_sdl.c b/source/blender/python/intern/bpy_app_sdl.c index ff659cf43c4b..6f13058b8e1c 100644 --- a/source/blender/python/intern/bpy_app_sdl.c +++ b/source/blender/python/intern/bpy_app_sdl.c @@ -123,7 +123,7 @@ PyObject *BPY_app_sdl_struct(void) BlenderAppSDLType.tp_init = NULL; BlenderAppSDLType.tp_new = NULL; BlenderAppSDLType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ return ret; } diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index ccd0228d9e4a..3fa3c5d75b17 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -854,7 +854,7 @@ PyObject *BPY_app_translations_struct(void) /* prevent user from creating new instances */ BlenderAppTranslationsType.tp_new = NULL; - /* without this we can't do set(sys.modules) T29635. */ + /* without this we can't do set(sys.modules) #29635. */ BlenderAppTranslationsType.tp_hash = (hashfunc)_Py_HashPointer; return ret; @@ -862,7 +862,7 @@ PyObject *BPY_app_translations_struct(void) void BPY_app_translations_end(void) { - /* In case the object remains in a module's name-space, see T44127. */ + /* In case the object remains in a module's name-space, see #44127. */ #ifdef WITH_INTERNATIONAL _clear_translations_cache(); #endif diff --git a/source/blender/python/intern/bpy_app_usd.c b/source/blender/python/intern/bpy_app_usd.c index 811a4e4c085f..3fcdb1aa3c73 100644 --- a/source/blender/python/intern/bpy_app_usd.c +++ b/source/blender/python/intern/bpy_app_usd.c @@ -85,7 +85,7 @@ PyObject *BPY_app_usd_struct(void) BlenderAppUSDType.tp_init = NULL; BlenderAppUSDType.tp_new = NULL; BlenderAppUSDType.tp_hash = (hashfunc) - _Py_HashPointer; /* without this we can't do set(sys.modules) T29635. */ + _Py_HashPointer; /* without this we can't do set(sys.modules) #29635. */ return ret; } diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index be1ae1abf5f5..ae19e99151b6 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -211,7 +211,7 @@ static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph) /** * Adds a variable `depsgraph` to the name-space. This can then be used to obtain evaluated - * data-blocks, and the current view layer and scene. See T75553. + * data-blocks, and the current view layer and scene. See #75553. */ static void bpy_pydriver_namespace_update_depsgraph(struct Depsgraph *depsgraph) { @@ -560,9 +560,9 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, /* (old) NOTE: PyGILState_Ensure() isn't always called because python can call * the bake operator which intern starts a thread which calls scene update * which does a driver update. to avoid a deadlock check #PyC_IsInterpreterActive() - * if #PyGILState_Ensure() is needed, see T27683. + * if #PyGILState_Ensure() is needed, see #27683. * - * (new) NOTE: checking if python is running is not thread-safe T28114 + * (new) NOTE: checking if python is running is not thread-safe #28114 * now release the GIL on python operator execution instead, using * #PyEval_SaveThread() / #PyEval_RestoreThread() so we don't lock up blender. * @@ -612,7 +612,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, gilstate = PyGILState_Ensure(); } - /* Needed since drivers are updated directly after undo where `main` is re-allocated T28807. */ + /* Needed since drivers are updated directly after undo where `main` is re-allocated #28807. */ BPY_update_rna_module(); /* Initialize global dictionary for Python driver evaluation settings. */ diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index e94adbedabe1..4fe39e1c5b05 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -316,7 +316,7 @@ void BPY_python_start(bContext *C, int argc, const char **argv) PyPreConfig preconfig; PyStatus status; - /* To narrow down reports where the systems Python is inexplicably used, see: T98131. */ + /* To narrow down reports where the systems Python is inexplicably used, see: #98131. */ CLOG_INFO( BPY_LOG_INTERFACE, 2, @@ -329,7 +329,7 @@ void BPY_python_start(bContext *C, int argc, const char **argv) } else { /* Only use the systems environment variables and site when explicitly requested. - * Since an incorrect 'PYTHONPATH' causes difficult to debug errors, see: T72807. + * Since an incorrect 'PYTHONPATH' causes difficult to debug errors, see: #72807. * An alternative to setting `preconfig.use_environment = 0` */ PyPreConfig_InitIsolatedConfig(&preconfig); } @@ -372,7 +372,7 @@ void BPY_python_start(bContext *C, int argc, const char **argv) config.pathconfig_warnings = 0; /* Allow the user site directory because this is used - * when PIP installing packages from Blender, see: T104000. + * when PIP installing packages from Blender, see: #104000. * * NOTE(@ideasman42): While an argument can be made for isolating Blender's Python * from the users home directory entirely, an alternative directory should be used in that @@ -507,7 +507,7 @@ void BPY_python_start(bContext *C, int argc, const char **argv) #endif #ifdef WITH_PYTHON_MODULE - /* Disable all add-ons at exit, not essential, it just avoids resource leaks, see T71362. */ + /* Disable all add-ons at exit, not essential, it just avoids resource leaks, see #71362. */ BPY_run_string_eval(C, (const char *[]){"atexit", "addon_utils", NULL}, "atexit.register(addon_utils.disable_all)"); diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c index 49f5261ba198..2d50980d6f0c 100644 --- a/source/blender/python/intern/bpy_interface_run.c +++ b/source/blender/python/intern/bpy_interface_run.c @@ -64,7 +64,7 @@ static void bpy_text_filepath_get(char *filepath, text->id.name + 2); } -/* Very annoying! Undo #_PyModule_Clear(), see T23871. */ +/* Very annoying! Undo #_PyModule_Clear(), see #23871. */ #define PYMODULE_CLEAR_WORKAROUND #ifdef PYMODULE_CLEAR_WORKAROUND @@ -118,7 +118,7 @@ static bool python_script_exec(bContext *C, char *buf; PyObject *filepath_dummy_py; - filepath_dummy_py = PyC_UnicodeFromByte(filepath_dummy); + filepath_dummy_py = PyC_UnicodeFromBytes(filepath_dummy); size_t buf_len_dummy; buf = txt_to_buf(text, &buf_len_dummy); @@ -154,7 +154,7 @@ static bool python_script_exec(bContext *C, * Note on use of 'globals()', it's important not copy the dictionary because * tools may inspect 'sys.modules["__main__"]' for variables defined in the code * where using a copy of 'globals()' causes code execution - * to leave the main namespace untouched. see: T51444 + * to leave the main namespace untouched. see: #51444 * * This leaves us with the problem of variables being included, * currently this is worked around using 'dict.__del__' it's ugly but works. diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index dec4c65e48d6..8777a0393dad 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -91,7 +91,7 @@ * * This struct adds/removes the user-count of each #PyObject it references, * it's needed in case the function is removed from the class (unlikely but possible), - * also when an annotation evaluates to a `lambda` with Python 3.10 and newer e.g: T86332. + * also when an annotation evaluates to a `lambda` with Python 3.10 and newer e.g: #86332. * * Pointers to this struct are held in: * diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 6480573a2f50..821846ddb4f8 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1403,7 +1403,7 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) ret = PyBytes_FromStringAndSize(buf, buf_len); } else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - ret = PyC_UnicodeFromByteAndSize(buf, buf_len); + ret = PyC_UnicodeFromBytesAndSize(buf, buf_len); } else { ret = PyUnicode_FromStringAndSize(buf, buf_len); @@ -1712,7 +1712,7 @@ static int pyrna_py_to_prop( PyObject *value_coerce = NULL; if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { /* TODO: get size. */ - param = PyC_UnicodeAsByte(value, &value_coerce); + param = PyC_UnicodeAsBytes(value, &value_coerce); } else { param = PyUnicode_AsUTF8(value); @@ -2264,7 +2264,7 @@ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_s } } /* It's important to end the iterator after `result` has been created - * so iterators may optionally invalidate items that were iterated over, see: T100286. */ + * so iterators may optionally invalidate items that were iterated over, see: #100286. */ RNA_property_collection_end(&iter); if (found) { if (result && (pyrna_prop_collection_subscript_is_valid_or_error(result) == -1)) { @@ -2384,7 +2384,7 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons } } /* It's important to end the iterator after `result` has been created - * so iterators may optionally invalidate items that were iterated over, see: T100286. */ + * so iterators may optionally invalidate items that were iterated over, see: #100286. */ RNA_property_collection_end(&iter); if (found) { if (result && (pyrna_prop_collection_subscript_is_valid_or_error(result) == -1)) { @@ -6057,7 +6057,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat ret = PyBytes_FromStringAndSize(data_ch, data_ch_len); } else if (ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) { - ret = PyC_UnicodeFromByteAndSize(data_ch, data_ch_len); + ret = PyC_UnicodeFromBytesAndSize(data_ch, data_ch_len); } else { ret = PyUnicode_FromStringAndSize(data_ch, data_ch_len); @@ -8495,7 +8495,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param } #ifdef USE_PEDANTIC_WRITE - /* Handle nested draw calls, see: T89253. */ + /* Handle nested draw calls, see: #89253. */ const bool rna_disallow_writes_prev = rna_disallow_writes; rna_disallow_writes = is_readonly ? true : false; #endif diff --git a/source/blender/python/intern/bpy_rna_context.c b/source/blender/python/intern/bpy_rna_context.c index 1d033fee026a..df0a10050a11 100644 --- a/source/blender/python/intern/bpy_rna_context.c +++ b/source/blender/python/intern/bpy_rna_context.c @@ -121,7 +121,7 @@ static PyObject *bpy_rna_context_temp_override_exit(BPyContextTempOverride *self bContext *C = self->context; /* Special case where the window is expected to be freed on file-read, - * in this case the window should not be restored, see: T92818. */ + * in this case the window should not be restored, see: #92818. */ bool do_restore = true; if (self->ctx_init.win) { wmWindowManager *wm = CTX_wm_manager(C); diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c index a74381eb5710..74d3f77b0c20 100644 --- a/source/blender/python/intern/bpy_rna_driver.c +++ b/source/blender/python/intern/bpy_rna_driver.c @@ -43,7 +43,7 @@ PyObject *pyrna_driver_get_variable_value(struct ChannelDriver *driver, struct D const PropertyType type = RNA_property_type(prop); if (type == PROP_ENUM) { /* Note that enum's are converted to strings by default, - * we want to avoid that, see: T52213 */ + * we want to avoid that, see: #52213 */ driver_arg = PyLong_FromLong(RNA_property_enum_get(&ptr, prop)); } else { diff --git a/source/blender/python/intern/bpy_rna_types_capi.c b/source/blender/python/intern/bpy_rna_types_capi.c index 45642cb1f1c5..dbcd35abff36 100644 --- a/source/blender/python/intern/bpy_rna_types_capi.c +++ b/source/blender/python/intern/bpy_rna_types_capi.c @@ -112,7 +112,7 @@ static PyObject *pyrna_WindowManager_clipboard_get(PyObject *UNUSED(self), void { int text_len = 0; char *text = WM_clipboard_text_get(false, &text_len); - PyObject *result = PyC_UnicodeFromByteAndSize(text ? text : "", text_len); + PyObject *result = PyC_UnicodeFromBytesAndSize(text ? text : "", text_len); if (text != NULL) { MEM_freeN(text); } @@ -124,7 +124,7 @@ static int pyrna_WindowManager_clipboard_set(PyObject *UNUSED(self), void *UNUSED(flag)) { PyObject *value_coerce = NULL; - const char *text = PyC_UnicodeAsByte(value, &value_coerce); + const char *text = PyC_UnicodeAsBytes(value, &value_coerce); if (text == NULL) { return -1; } diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index 2c1201922755..63da19b8c9e8 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -168,7 +168,7 @@ bool python_script_error_jump( { /* WARNING(@ideasman42): The normalized exception is restored (losing line number info). * Ideally this would leave the exception state as it found it, but that needs to be done - * carefully with regards to reference counting, see: T97731. */ + * carefully with regards to reference counting, see: #97731. */ bool success = false; PyObject *exception, *value; diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index d01c3d8587c4..84f694c3d589 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -2696,7 +2696,7 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure swizzleClosure = POINTER_AS_INT(closure); /* We must first copy current vec into tvec, else some org values may be lost. - * See T31760. + * See #31760. * Assuming self->vec_num can't be higher than MAX_DIMENSIONS! */ memcpy(tvec, self->vec, self->vec_num * sizeof(float)); @@ -2708,7 +2708,7 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure } /* We must copy back the whole tvec into vec, else some changes may be lost (e.g. xz...). - * See T31760. */ + * See #31760. */ memcpy(self->vec, tvec, self->vec_num * sizeof(float)); /* continue with BaseMathObject_WriteCallback at the end */ diff --git a/source/blender/render/intern/bake.cc b/source/blender/render/intern/bake.cc index dc2eb26a70ea..c8ecb827c6db 100644 --- a/source/blender/render/intern/bake.cc +++ b/source/blender/render/intern/bake.cc @@ -777,7 +777,7 @@ void RE_bake_pixels_populate(Mesh *me, /* NOTE(@ideasman42): workaround for pixel aligned UVs which are common and can screw * up our intersection tests where a pixel gets in between 2 faces or the middle of a quad, * camera aligned quads also have this problem but they are less common. - * Add a small offset to the UVs, fixes bug T18685. */ + * Add a small offset to the UVs, fixes bug #18685. */ vec[a][0] = (uv[0] - bk_image->uv_offset[0]) * float(bk_image->width) - (0.5f + 0.001f); vec[a][1] = (uv[1] - bk_image->uv_offset[1]) * float(bk_image->height) - (0.5f + 0.002f); } diff --git a/source/blender/render/intern/texture_image.c b/source/blender/render/intern/texture_image.c index 60a769348e85..8c7d842ee47e 100644 --- a/source/blender/render/intern/texture_image.c +++ b/source/blender/render/intern/texture_image.c @@ -220,7 +220,7 @@ int imagewrap(Tex *tex, } } - /* Keep this before interpolation T29761. */ + /* Keep this before interpolation #29761. */ if (ima) { if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) { if ((tex->imaflag & TEX_CALCALPHA) == 0) { @@ -235,7 +235,7 @@ int imagewrap(Tex *tex, filterx = (0.5f * tex->filtersize) / ibuf->x; filtery = (0.5f * tex->filtersize) / ibuf->y; - /* Important that this value is wrapped T27782. + /* Important that this value is wrapped #27782. * this applies the modifications made by the checks above, * back to the floating point values */ fx -= (float)(xi - x) / (float)ibuf->x; diff --git a/source/blender/render/intern/texture_margin.cc b/source/blender/render/intern/texture_margin.cc index f29fa3163758..e0e2781b5623 100644 --- a/source/blender/render/intern/texture_margin.cc +++ b/source/blender/render/intern/texture_margin.cc @@ -561,7 +561,7 @@ static void generate_margin(ImBuf *ibuf, /* NOTE(@ideasman42): workaround for pixel aligned UVs which are common and can screw up * our intersection tests where a pixel gets in between 2 faces or the middle of a quad, * camera aligned quads also have this problem but they are less common. - * Add a small offset to the UVs, fixes bug T18685. */ + * Add a small offset to the UVs, fixes bug #18685. */ vec[a][0] = (uv[0] - uv_offset[0]) * float(ibuf->x) - (0.5f + 0.001f); vec[a][1] = (uv[1] - uv_offset[1]) * float(ibuf->y) - (0.5f + 0.002f); } diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c index c6f4d47ac753..25f633ef27cd 100644 --- a/source/blender/sequencer/intern/sequencer.c +++ b/source/blender/sequencer/intern/sequencer.c @@ -562,10 +562,10 @@ static Sequence *seq_dupli(const Scene *scene_src, /* When using SEQ_DUPE_UNIQUE_NAME, it is mandatory to add new sequences in relevant container * (scene or meta's one), *before* checking for unique names. Otherwise the meta's list is empty - * and hence we miss all seqs in that meta that have already been duplicated (see T55668). + * and hence we miss all seqs in that meta that have already been duplicated (see #55668). * Note that unique name check itself could be done at a later step in calling code, once all * seqs have bee duplicated (that was first, simpler solution), but then handling of animation - * data will be broken (see T60194). */ + * data will be broken (see #60194). */ if (new_seq_list != NULL) { BLI_addtail(new_seq_list, seqn); } diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c index 7744bc4ce1cf..89da6bb17699 100644 --- a/source/blender/sequencer/intern/strip_add.c +++ b/source/blender/sequencer/intern/strip_add.c @@ -314,7 +314,7 @@ Sequence *SEQ_add_sound_strip(Main *bmain, Scene *scene, ListBase *seqbase, SeqL * line up with the video frames. Therefore we round this number to the * nearest frame as the audio track usually overshoots or undershoots the * end frame of the video by a little bit. - * See T47135 for under shoot example. */ + * See #47135 for under shoot example. */ seq->len = MAX2(1, round((info.length - sound->offset_time) * FPS)); Strip *strip = seq->strip; diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c index 1edc4b85f964..c81482c878cb 100644 --- a/source/blender/sequencer/intern/strip_transform.c +++ b/source/blender/sequencer/intern/strip_transform.c @@ -526,7 +526,7 @@ static void seq_transform_handle_overwrite(Scene *scene, SEQ_collection_free(targets); /* Remove covered strips. This must be done in separate loop, because `SEQ_edit_strip_split()` - * also uses `SEQ_edit_remove_flagged_sequences()`. See T91096. */ + * also uses `SEQ_edit_remove_flagged_sequences()`. See #91096. */ if (SEQ_collection_len(strips_to_delete) > 0) { Sequence *seq; SEQ_ITERATOR_FOREACH (seq, strips_to_delete) { @@ -575,7 +575,7 @@ void SEQ_transform_handle_overlap(Scene *scene, } /* If any effects still overlap, we need to move them up. - * In some cases other strips can be overlapping still, see T90646. */ + * In some cases other strips can be overlapping still, see #90646. */ Sequence *seq; SEQ_ITERATOR_FOREACH (seq, transformed_strips) { if (SEQ_transform_test_overlap(scene, seqbasep, seq)) { diff --git a/source/blender/simulation/intern/SIM_mass_spring.cpp b/source/blender/simulation/intern/SIM_mass_spring.cpp index 5858e16da6e5..a5413678de20 100644 --- a/source/blender/simulation/intern/SIM_mass_spring.cpp +++ b/source/blender/simulation/intern/SIM_mass_spring.cpp @@ -496,7 +496,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s) scaling = parms->bending + s->lin_stiffness * fabsf(parms->max_bend - parms->bending); kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON)); - /* Fix for T45084 for cloth stiffness must have cb proportional to kb */ + /* Fix for #45084 for cloth stiffness must have cb proportional to kb */ cb = kb * parms->bending_damping; SIM_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb); @@ -515,7 +515,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s) scaling = s->lin_stiffness * parms->bending; kb = scaling / (20.0f * (parms->avg_spring_len + FLT_EPSILON)); - /* Fix for T45084 for cloth stiffness must have cb proportional to kb */ + /* Fix for #45084 for cloth stiffness must have cb proportional to kb */ cb = kb * parms->bending_damping; /* XXX assuming same restlen for ij and jk segments here, diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 0c12bd15b5b4..d66cf407b55a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -622,7 +622,7 @@ int WM_operator_props_popup_confirm(struct bContext *C, /** * Same as #WM_operator_props_popup but call the operator first, * This way - the button values correspond to the result of the operator. - * Without this, first access to a button will make the result jump, see T32452. + * Without this, first access to a button will make the result jump, see #32452. */ int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, @@ -672,7 +672,7 @@ bool WM_operator_poll_context(struct bContext *C, struct wmOperatorType *ot, sho * \param store: Store properties for re-use when an operator has finished * (unless #PROP_SKIP_SAVE is set). * - * \warning do not use this within an operator to call itself! T29537. + * \warning do not use this within an operator to call itself! #29537. */ int WM_operator_call_ex(struct bContext *C, struct wmOperator *op, bool store); int WM_operator_call(struct bContext *C, struct wmOperator *op); @@ -1345,7 +1345,7 @@ bool WM_drag_is_ID_type(const struct wmDrag *drag, int idcode); */ wmDragAsset *WM_drag_create_asset_data(const struct AssetHandle *asset, const char *path, - int import_type); + int /* #eAssetImportMethod */ import_type); struct wmDragAsset *WM_drag_get_asset_data(const struct wmDrag *drag, int idcode); struct AssetMetaData *WM_drag_get_asset_meta_data(const struct wmDrag *drag, int idcode); /** diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index b23b5c67b1f0..bdde49a1495e 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -668,7 +668,7 @@ typedef struct wmTabletData { * - The reason to differentiate between "press" and the previous event state is * the previous event may be set by key-release events. In the case of a single key click * this isn't a problem however releasing other keys such as modifiers prevents click/click-drag - * events from being detected, see: T89989. + * events from being detected, see: #89989. * * - Mouse-wheel events are excluded even though they generate #KM_PRESS * as clicking and dragging don't make sense for mouse wheel events. @@ -1074,7 +1074,7 @@ typedef struct wmDragAsset { const char *path; int id_type; struct AssetMetaData *metadata; - int import_type; /* eFileAssetImportType */ + int import_method; /* eAssetImportType */ /* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the * #wmDropBox. diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c index 11c1bb618122..4fd130cc0c41 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c @@ -514,7 +514,7 @@ static int gizmo_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event) /* handle gizmo */ wmGizmoFnModal modal_fn = gz->custom_modal ? gz->custom_modal : gz->type->modal; if (modal_fn) { - /* Ugly hack to ensure Python won't get 'EVT_MODAL_MAP' which isn't supported, see T73727. + /* Ugly hack to ensure Python won't get 'EVT_MODAL_MAP' which isn't supported, see #73727. * note that we could move away from wrapping modal gizmos in a modal operator, * since it's causing the need for code like this. */ wmEvent *evil_event = (wmEvent *)event; @@ -997,7 +997,7 @@ wmGizmoGroup *WM_gizmomaptype_group_init_runtime_with_region(wmGizmoMapType *gzm wmGizmoGroup *gzgroup = wm_gizmogroup_new_from_type(gzmap, gzgt); - /* Don't allow duplicates when switching modes for e.g. see: T66229. */ + /* Don't allow duplicates when switching modes for e.g. see: #66229. */ LISTBASE_FOREACH (wmGizmoGroup *, gzgroup_iter, &gzmap->groups) { if (gzgroup_iter->type == gzgt) { if (gzgroup_iter != gzgroup) { diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index a08584bd65f6..03fb91c95d89 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -576,7 +576,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos, /* TODO: waiting for the GPU in the middle of the event loop for every * mouse move is bad for performance, we need to find a solution to not - * use the GPU or draw something once. (see T61474) */ + * use the GPU or draw something once. (see #61474) */ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0); /* do the drawing */ gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index aad7cc6ac934..671a69003dd2 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -619,7 +619,7 @@ void wm_close_and_free_all(bContext *C, ListBase *wmlist) BLI_remlink(wmlist, wm); /* Don't handle user counts as this is only ever called once #G_MAIN has already been freed via * #BKE_main_free so any ID's referenced by the window-manager (from ID properties) will crash. - * See: T100703. */ + * See: #100703. */ BKE_libblock_free_data(&wm->id, false); BKE_libblock_free_data_py(&wm->id); MEM_freeN(wm); diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index 74e760013fde..94f0d79a3a5b 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -291,7 +291,7 @@ void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2]) static void wm_cursor_warp_relative(wmWindow *win, int x, int y) { - /* NOTE: don't use wmEvent coords because of continuous grab T36409. */ + /* NOTE: don't use wmEvent coords because of continuous grab #36409. */ int cx, cy; wm_cursor_position_get(win, &cx, &cy); WM_cursor_warp(win, cx + x, cy + y); diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc index 4b4b516f0b9b..df621d253304 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.cc +++ b/source/blender/windowmanager/intern/wm_dragdrop.cc @@ -9,6 +9,7 @@ #include +#include "DNA_asset_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" @@ -563,7 +564,7 @@ wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset, const char *pat asset_drag->metadata = ED_asset_handle_get_metadata(asset); asset_drag->path = path; asset_drag->id_type = ED_asset_handle_get_id_type(asset); - asset_drag->import_type = import_type; + asset_drag->import_method = import_type; return asset_drag; } @@ -617,11 +618,11 @@ ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra) ViewLayer *view_layer = CTX_data_view_layer(asset_drag->evil_C); View3D *view3d = CTX_wm_view3d(asset_drag->evil_C); - switch ((eFileAssetImportType)asset_drag->import_type) { - case FILE_ASSET_IMPORT_LINK: + switch (eAssetImportMethod(asset_drag->import_method)) { + case ASSET_IMPORT_LINK: return WM_file_link_datablock( bmain, scene, view_layer, view3d, asset_drag->path, idtype, name, flag); - case FILE_ASSET_IMPORT_APPEND: + case ASSET_IMPORT_APPEND: return WM_file_append_datablock(bmain, scene, view_layer, @@ -631,7 +632,7 @@ ID *WM_drag_asset_id_import(wmDragAsset *asset_drag, const int flag_extra) name, flag | BLO_LIBLINK_APPEND_RECURSIVE | BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR); - case FILE_ASSET_IMPORT_APPEND_REUSE: + case ASSET_IMPORT_APPEND_REUSE: return WM_file_append_datablock(G_MAIN, scene, view_layer, @@ -655,7 +656,7 @@ bool WM_drag_asset_will_import_linked(const wmDrag *drag) } const wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0); - return asset_drag->import_type == FILE_ASSET_IMPORT_LINK; + return asset_drag->import_method == ASSET_IMPORT_LINK; } ID *WM_drag_get_local_ID_or_import_from_asset(const wmDrag *drag, int idcode) @@ -694,7 +695,7 @@ void WM_drag_free_imported_drag_ID(Main *bmain, wmDrag *drag, wmDropBox *drop) bmain, drop->ptr, static_cast(asset_drag->id_type)); if (id != nullptr) { /* Do not delete the dragged ID if it has any user, otherwise if it is a 're-used' ID it will - * cause T95636. Note that we need first to add the user that we want to remove in + * cause #95636. Note that we need first to add the user that we want to remove in * #BKE_id_free_us. */ id_us_plus(id); BKE_id_free_us(bmain, id); @@ -728,7 +729,7 @@ void WM_drag_add_asset_list_item(wmDrag *drag, const AssetHandle *asset) ED_asset_handle_get_full_library_path(asset, asset_blend_path); drag_asset->is_external = true; drag_asset->asset_data.external_info = WM_drag_create_asset_data( - asset, BLI_strdup(asset_blend_path), FILE_ASSET_IMPORT_APPEND); + asset, BLI_strdup(asset_blend_path), ASSET_IMPORT_APPEND); } BLI_addtail(&drag->asset_items, drag_asset); } diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index be1bdd665602..ebe670bfa21c 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -132,7 +132,7 @@ static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region) * deltas without it escaping from the window. In this case we never want to show the actual * cursor coordinates so limit reading the cursor location to when the cursor is grabbed and * wrapping in a region since this is the case when it would otherwise attempt to draw the - * cursor outside the view/window. See: T102792. */ + * cursor outside the view/window. See: #102792. */ if ((WM_capabilities_flag() & WM_CAPABILITY_CURSOR_WARP) && wm_window_grab_warp_region_is_set(win)) { int x = 0, y = 0; @@ -842,13 +842,13 @@ void wm_draw_region_blend(ARegion *region, int view, bool blend) int color_loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR); int rect_tex_loc = GPU_shader_get_uniform(shader, "rect_icon"); int rect_geo_loc = GPU_shader_get_uniform(shader, "rect_geom"); - int texture_bind_loc = GPU_shader_get_texture_binding(shader, "image"); + int texture_bind_loc = GPU_shader_get_sampler_binding(shader, "image"); GPU_texture_bind(texture, texture_bind_loc); - GPU_shader_uniform_vector(shader, rect_tex_loc, 4, 1, rectt); - GPU_shader_uniform_vector(shader, rect_geo_loc, 4, 1, rectg); - GPU_shader_uniform_vector(shader, color_loc, 4, 1, (const float[4]){1, 1, 1, 1}); + GPU_shader_uniform_float_ex(shader, rect_tex_loc, 4, 1, rectt); + GPU_shader_uniform_float_ex(shader, rect_geo_loc, 4, 1, rectg); + GPU_shader_uniform_float_ex(shader, color_loc, 4, 1, (const float[4]){1, 1, 1, 1}); GPUBatch *quad = GPU_batch_preset_quad(); GPU_batch_set_shader(quad, shader); @@ -1214,7 +1214,7 @@ uint *WM_window_pixels_read_offscreen(bContext *C, wmWindow *win, int r_size[2]) * not to initialize at all. * Confusingly there are some cases where this *does* work, depending on the state of the window * and prior calls to swap-buffers, however ensuring the state exactly as needed to satisfy a - * particular GPU back-end is fragile, see T98462. + * particular GPU back-end is fragile, see #98462. * * So provide an alternative to #WM_window_pixels_read that avoids using the front-buffer. */ @@ -1362,8 +1362,8 @@ void wm_draw_update(bContext *C) GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin); if (state == GHOST_kWindowStateMinimized) { - /* do not update minimized windows, gives issues on Intel (see T33223) - * and AMD (see T50856). it seems logical to skip update for invisible + /* do not update minimized windows, gives issues on Intel (see #33223) + * and AMD (see #50856). it seems logical to skip update for invisible * window anyway. */ continue; diff --git a/source/blender/windowmanager/intern/wm_event_query.c b/source/blender/windowmanager/intern/wm_event_query.c index a1d94c33f278..2e1afe808ad8 100644 --- a/source/blender/windowmanager/intern/wm_event_query.c +++ b/source/blender/windowmanager/intern/wm_event_query.c @@ -236,7 +236,7 @@ bool WM_event_is_modal_drag_exit(const wmEvent *event, } else { /* If the initial event wasn't a drag event then - * ignore #USER_RELEASECONFIRM setting: see T26756. */ + * ignore #USER_RELEASECONFIRM setting: see #26756. */ if (init_event_val != KM_CLICK_DRAG) { return 1; } @@ -582,7 +582,7 @@ int WM_event_absolute_delta_y(const struct wmEvent *event) * Most OS's use `Ctrl+Space` / `OsKey+Space` to switch IME, * so don't type in the space character. * - * \note Shift is excluded from this check since it prevented typing `Shift+Space`, see: T85517. + * \note Shift is excluded from this check since it prevented typing `Shift+Space`, see: #85517. */ bool WM_event_is_ime_switch(const struct wmEvent *event) { diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index 700b1d1f8b7f..52e0f43567e4 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -92,7 +92,7 @@ * Without tools using press events which would prevent click/drag events getting to the gizmos. * * This is not a fool proof solution since it's possible the gizmo operators would pass - * through these events when called, see: T65479. + * through these events when called, see: #65479. */ #define USE_GIZMO_MOUSE_PRIORITY_HACK @@ -434,7 +434,7 @@ void wm_event_do_depsgraph(bContext *C, bool is_after_open_file) if (wm->is_interface_locked) { return; } - /* Combine data-masks so one window doesn't disable UVs in another T26448. */ + /* Combine data-masks so one window doesn't disable UVs in another #26448. */ CustomData_MeshMasks win_combine_v3d_datamask = {0}; LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { const Scene *scene = WM_window_get_active_scene(win); @@ -450,7 +450,7 @@ void wm_event_do_depsgraph(bContext *C, bool is_after_open_file) Main *bmain = CTX_data_main(C); /* Copied to set's in scene_update_tagged_recursive() */ scene->customdata_mask = win_combine_v3d_datamask; - /* XXX, hack so operators can enforce data-masks T26482, GPU render. */ + /* XXX, hack so operators can enforce data-masks #26482, GPU render. */ CustomData_MeshMasks_update(&scene->customdata_mask, &scene->customdata_mask_modal); /* TODO(sergey): For now all dependency graphs which are evaluated from * workspace are considered active. This will work all fine with "locked" @@ -509,7 +509,7 @@ void wm_event_do_notifiers(bContext *C) /* Ensure inside render boundary. */ GPU_render_begin(); - /* Run the timer before assigning `wm` in the unlikely case a timer loads a file, see T80028. */ + /* Run the timer before assigning `wm` in the unlikely case a timer loads a file, see #80028. */ wm_event_execute_timers(C); wmWindowManager *wm = CTX_wm_manager(C); @@ -566,7 +566,7 @@ void wm_event_do_notifiers(bContext *C) bScreen *ref_screen = BKE_workspace_layout_screen_get( static_cast(note->reference)); - /* Free popup handlers only T35434. */ + /* Free popup handlers only #35434. */ UI_popup_handlers_remove_all(C, &win->modalhandlers); ED_screen_change(C, ref_screen); /* XXX: hum, think this over! */ @@ -789,7 +789,7 @@ static eHandlerActionFlag wm_handler_ui_call(bContext *C, } /* Don't block file-select events. Those are triggered by a separate file browser window. - * See T75292. */ + * See #75292. */ if (event->type == EVT_FILESELECT) { return WM_HANDLER_CONTINUE; } @@ -1144,8 +1144,8 @@ static void wm_operator_finished(bContext *C, else if (has_undo_step) { /* An undo step was added but the operator wasn't registered (and won't register it's self), * therefor a redo panel wouldn't redo this action but the previous registered action, - * causing the "redo" to remove/loose this operator. See: T101743. - * Register check is needed so nested operator calls don't clear the HUD. See: T103587. */ + * causing the "redo" to remove/loose this operator. See: #101743. + * Register check is needed so nested operator calls don't clear the HUD. See: #103587. */ if (!(has_register || do_register)) { if (repeat == 0) { hud_status = CLEAR; @@ -1228,7 +1228,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, const bool repeat, cons } } - /* XXX(@mont29): Disabled the repeat check to address part 2 of T31840. + /* XXX(@mont29): Disabled the repeat check to address part 2 of #31840. * Carefully checked all calls to wm_operator_exec and WM_operator_repeat, don't see any reason * why this was needed, but worth to note it in case something turns bad. */ if (retval & (OPERATOR_FINISHED | OPERATOR_CANCELLED) /* && repeat == 0 */) { @@ -2572,7 +2572,7 @@ static eHandlerActionFlag wm_handler_operator_call(bContext *C, wmGizmoGroup *gzgroup = WM_gizmomaptype_group_init_runtime_with_region( gzmap_type, gzgt, region); /* We can't rely on drawing to initialize gizmo's since disabling - * overlays/gizmos will prevent pre-drawing setup calls. (see T60905) */ + * overlays/gizmos will prevent pre-drawing setup calls. (see #60905) */ WM_gizmogroup_ensure_init(C, gzgroup); } } @@ -3059,7 +3059,7 @@ static eHandlerActionFlag wm_handlers_do_gizmo_handler(bContext *C, wmGizmo *gz = wm_gizmomap_highlight_get(gzmap); /* Needed so UI blocks over gizmos don't let events fall through to the gizmos, - * noticeable for the node editor - where dragging on a node should move it, see: T73212. + * noticeable for the node editor - where dragging on a node should move it, see: #73212. * note we still allow for starting the gizmo drag outside, then travel 'inside' the node. */ if (region->type->clip_gizmo_events_by_ui) { if (UI_region_block_find_mouse_over(region, event->xy, true)) { @@ -3245,7 +3245,7 @@ static eHandlerActionFlag wm_handlers_do_intern(bContext *C, * NOTE: check 'handlers->first' because in rare cases the handlers can be cleared * by the event that's called, for eg: * - * Calling a python script which changes the area.type, see T32232. */ + * Calling a python script which changes the area.type, see #32232. */ for (wmEventHandler *handler_base = static_cast(handlers->first), *handler_base_next; handler_base && handlers->first; @@ -3495,7 +3495,7 @@ static eHandlerActionFlag wm_handlers_do(bContext *C, wmEvent *event, ListBase * if (win->event_queue_check_drag) { if ((event->prev_press_type != event->type) && (ISKEYMODIFIER(event->type) || (event->type == event->prev_press_keymodifier))) { - /* Support releasing modifier keys without canceling the drag event, see T89989. */ + /* Support releasing modifier keys without canceling the drag event, see #89989. */ } else { CLOG_INFO( @@ -3562,7 +3562,7 @@ static eHandlerActionFlag wm_handlers_do(bContext *C, wmEvent *event, ListBase * } else if (ISMOUSE_WHEEL(event->type) || ISMOUSE_GESTURE(event->type)) { /* Modifiers which can trigger click event's, - * however we don't want this if the mouse wheel has been used, see T74607. */ + * however we don't want this if the mouse wheel has been used, see #74607. */ if (wm_action_not_handled(action)) { /* Pass. */ } @@ -3725,7 +3725,7 @@ static bool wm_event_pie_filter(wmWindow *win, const wmEvent *event) * In this case event handling exits early, however when "Load UI" is disabled * the even will still be in #wmWindow.event_queue. * - * Without this it's possible to continuously handle the same event, see: T76484. + * Without this it's possible to continuously handle the same event, see: #76484. */ static void wm_event_free_and_remove_from_queue_if_valid(wmEvent *event) { @@ -4063,7 +4063,7 @@ void wm_event_do_handlers(bContext *C) action |= wm_event_do_handlers_area_regions(C, event, area); - /* File-read case (Python), T29489. */ + /* File-read case (Python), #29489. */ if (CTX_wm_window(C) == nullptr) { wm_event_free_and_remove_from_queue_if_valid(event); GPU_render_end(); @@ -4109,7 +4109,7 @@ void wm_event_do_handlers(bContext *C) } /* If the drag even was handled, don't attempt to keep re-handing the same - * drag event on every cursor motion, see: T87511. */ + * drag event on every cursor motion, see: #87511. */ if (win->event_queue_check_drag_handled) { win->event_queue_check_drag = false; win->event_queue_check_drag_handled = false; @@ -4405,7 +4405,7 @@ wmEventHandler_Keymap *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap * allowing both the fallback-tool and active-tool to be activated * providing the key-map is configured so the keys don't conflict. * For example one mouse button can run the active-tool, another button for the fallback-tool. - * See T72567. + * See #72567. * * Follow #wmEventHandler_KeymapDynamicFn signature. */ @@ -5247,7 +5247,7 @@ static void wm_event_state_update_and_click_set_ex(wmEvent *event, event_state->type = event->type; /* It's important only to write into the `event_state` modifier for keyboard * events because emulate MMB clears one of the modifiers in `event->modifier`, - * making the second press not behave as if the modifier is pressed, see T96279. */ + * making the second press not behave as if the modifier is pressed, see #96279. */ if (is_keyboard) { event_state->modifier = event->modifier; } @@ -5359,7 +5359,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, const int type, event.prev_val = event.val; /* Always use modifiers from the active window since - * changes to modifiers aren't sent to inactive windows, see: T66088. */ + * changes to modifiers aren't sent to inactive windows, see: #66088. */ if ((wm->winactive != win) && (wm->winactive && wm->winactive->eventstate)) { event.modifier = wm->winactive->eventstate->modifier; event.keymodifier = wm->winactive->eventstate->keymodifier; diff --git a/source/blender/windowmanager/intern/wm_files.cc b/source/blender/windowmanager/intern/wm_files.cc index f9555e750059..3de5684e085b 100644 --- a/source/blender/windowmanager/intern/wm_files.cc +++ b/source/blender/windowmanager/intern/wm_files.cc @@ -220,7 +220,7 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist) * causing use-after-free error in later handling of the button callbacks in UI code * (see ui_apply_but_funcs_after()). * Tried solving this by always nullptr-ing context's menu when setting wm/win/etc., - * but it broke popups refreshing (see T47632), + * but it broke popups refreshing (see #47632), * so for now just handling this specific case here. */ CTX_wm_menu_set(C, nullptr); @@ -329,7 +329,7 @@ static void wm_window_match_replace_by_file_wm(bContext *C, * #Main.wm.first memory address in-place, while swapping all of it's contents. * * This is needed so items such as key-maps can be held by an add-on, - * without it pointing to invalid memory, see: T86431 */ + * without it pointing to invalid memory, see: #86431 */ { /* Referencing the window-manager pointer from elsewhere in the file is highly unlikely * however it's possible with ID-properties & animation-drivers. @@ -387,7 +387,7 @@ static void wm_window_match_replace_by_file_wm(bContext *C, } } } - /* make sure at least one window is kept open so we don't lose the context, check T42303 */ + /* make sure at least one window is kept open so we don't lose the context, check #42303 */ if (!has_match) { wm_window_substitute_old(oldwm, wm, @@ -473,7 +473,7 @@ static void wm_init_userdef(Main *bmain) UI_init_userdef(); - /* needed so loading a file from the command line respects user-pref T26156. */ + /* needed so loading a file from the command line respects user-pref #26156. */ SET_FLAG_FROM_TEST(G.fileflags, U.flag & USER_FILENOUI, G_FILE_NO_UI); /* set the python auto-execute setting from user prefs */ @@ -1100,7 +1100,7 @@ void wm_homefile_read_ex(bContext *C, /* Currently this only impacts preferences as it doesn't make much sense to keep the default * startup open in the case the app-template doesn't happen to define it's own startup. * Unlike preferences where we might want to only reset the app-template part of the preferences - * so as not to reset the preferences for all other Blender instances, see: T96427. */ + * so as not to reset the preferences for all other Blender instances, see: #96427. */ const bool use_factory_settings_app_template_only = params_homefile->use_factory_settings_app_template_only; const bool use_empty_data = params_homefile->use_empty_data; @@ -1168,7 +1168,7 @@ void wm_homefile_read_ex(bContext *C, if (CTX_py_init_get(C)) { /* This is restored by 'wm_file_read_post', disable before loading any preferences * so an add-on can read their own preferences when un-registering, - * and use new preferences if/when re-registering, see T67577. + * and use new preferences if/when re-registering, see #67577. * * Note that this fits into 'wm_file_read_pre' function but gets messy * since we need to know if 'reset_app_template' is true. */ @@ -1760,6 +1760,41 @@ bool write_crash_blend(void) return 0; } +/** + * Helper to check if file `filepath` can be written. + * \return true if it can, otherwise report an error and return false. + */ +static bool wm_file_write_check_with_report_on_failure(Main *bmain, + const char *filepath, + ReportList *reports) +{ + const int filepath_len = strlen(filepath); + if (filepath_len == 0) { + BKE_report(reports, RPT_ERROR, "Path is empty, cannot save"); + return false; + } + + if (filepath_len >= FILE_MAX) { + BKE_report(reports, RPT_ERROR, "Path too long, cannot save"); + return false; + } + + /* Check if file write permission is ok */ + if (BLI_exists(filepath) && !BLI_file_is_writable(filepath)) { + BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath); + return false; + } + + LISTBASE_FOREACH (Library *, li, &bmain->libraries) { + if (BLI_path_cmp(li->filepath_abs, filepath) == 0) { + BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath); + return false; + } + } + + return true; +} + /** * \see #wm_homefile_write_exec wraps #BLO_write_file in a similar way. */ @@ -1771,39 +1806,16 @@ static bool wm_file_write(bContext *C, ReportList *reports) { Main *bmain = CTX_data_main(C); - int len; int ok = false; BlendThumbnail *thumb = nullptr, *main_thumb = nullptr; ImBuf *ibuf_thumb = nullptr; - len = strlen(filepath); - - if (len == 0) { - BKE_report(reports, RPT_ERROR, "Path is empty, cannot save"); - return ok; - } - - if (len >= FILE_MAX) { - BKE_report(reports, RPT_ERROR, "Path too long, cannot save"); - return ok; - } - - /* Check if file write permission is ok */ - if (BLI_exists(filepath) && !BLI_file_is_writable(filepath)) { - BKE_reportf(reports, RPT_ERROR, "Cannot save blend file, path '%s' is not writable", filepath); - return ok; - } - /* NOTE: used to replace the file extension (to ensure '.blend'), * no need to now because the operator ensures, * its handy for scripts to save to a predefined name without blender editing it */ - /* send the OnSave event */ - LISTBASE_FOREACH (Library *, li, &bmain->libraries) { - if (BLI_path_cmp(li->filepath_abs, filepath) == 0) { - BKE_reportf(reports, RPT_ERROR, "Cannot overwrite used library '%.240s'", filepath); - return ok; - } + if (!wm_file_write_check_with_report_on_failure(bmain, filepath, reports)) { + return ok; } /* Call pre-save callbacks before writing preview, @@ -1815,10 +1827,10 @@ static bool wm_file_write(bContext *C, BKE_lib_override_library_main_operations_create(bmain, true, nullptr); /* NOTE: Ideally we would call `WM_redraw_windows` here to remove any open menus. - * But we can crash if saving from a script, see T92704 & T97627. + * But we can crash if saving from a script, see #92704 & #97627. * Just checking `!G.background && BLI_thread_is_main()` is not sufficient to fix this. * Additionally some EGL configurations don't support reading the front-buffer - * immediately after drawing, see: T98462. In that case off-screen drawing is necessary. */ + * immediately after drawing, see: #98462. In that case off-screen drawing is necessary. */ /* don't forget not to return without! */ WM_cursor_wait(true); @@ -1827,7 +1839,7 @@ static bool wm_file_write(bContext *C, /* Blend file thumbnail. * * - Save before exiting edit-mode, otherwise evaluated-mesh for shared data gets corrupted. - * See T27765. + * See #27765. * - Main can store a '.blend' thumbnail, * useful for background-mode or thumbnail customization. */ @@ -3288,7 +3300,7 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent * /* if we're saving for the first time and prefer relative paths - * any existing paths will be absolute, - * enable the option to remap paths to avoid confusion T37240. */ + * enable the option to remap paths to avoid confusion #37240. */ const char *blendfile_path = BKE_main_blendfile_path_from_global(); if ((blendfile_path[0] == '\0') && (U.flag & USER_RELPATHS)) { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "relative_remap"); diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index bbe53bf7355e..3af7d2f26f01 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -141,6 +141,9 @@ static int wm_link_append_flag(wmOperator *op) if (RNA_boolean_get(op->ptr, "do_reuse_local_id")) { flag |= BLO_LIBLINK_APPEND_LOCAL_ID_REUSE; } + if (RNA_boolean_get(op->ptr, "clear_asset_data")) { + flag |= BLO_LIBLINK_APPEND_ASSET_DATA_CLEAR; + } } if (RNA_boolean_get(op->ptr, "instance_collections")) { flag |= BLO_LIBLINK_COLLECTION_INSTANCE; @@ -400,6 +403,12 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link) "Re-Use Local Data", "Try to re-use previously matching appended data-blocks instead of appending a new copy"); RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + prop = RNA_def_boolean(ot->srna, + "clear_asset_data", + false, + "Clear Asset Data", + "Don't add asset meta-data or tags from the original data-block"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); prop = RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select new objects"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index bb03c2c14137..fecbcca3c90a 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -326,7 +326,7 @@ static void draw_filled_lasso(wmGesture *gt) IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_bind(state.shader); - GPU_shader_uniform_vector( + GPU_shader_uniform_float_ex( state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTexTiled( diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index e38929339051..ae8c446bd87b 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -330,7 +330,7 @@ static void gesture_circle_apply(bContext *C, wmOperator *op) /* When 'wait_for_input' is false, * use properties to get the selection state (typically tool settings). - * This is done so executing as a mode can select & de-select, see: T58594. */ + * This is done so executing as a mode can select & de-select, see: #58594. */ if (gesture->wait_for_input) { gesture_modal_state_to_operator(op, gesture->modal_state); } diff --git a/source/blender/windowmanager/intern/wm_init_exit.cc b/source/blender/windowmanager/intern/wm_init_exit.cc index 400921274ba4..243480c84e6c 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.cc +++ b/source/blender/windowmanager/intern/wm_init_exit.cc @@ -249,7 +249,7 @@ void WM_init(bContext *C, int argc, const char **argv) BLT_lang_init(); /* Must call first before doing any `.blend` file reading, - * since versioning code may create new IDs. See T57066. */ + * since versioning code may create new IDs. See #57066. */ BLT_lang_set(nullptr); /* Init icons before reading .blend files for preview icons, which can @@ -278,7 +278,7 @@ void WM_init(bContext *C, int argc, const char **argv) * - Some sub-systems depend on the preferences (initializing icons depend on the theme). * - Add-ons depends on the preferences to know what has been enabled. * - Add-ons depends on the window-manger to register their key-maps. - * - Evaluating the startup file depends on Python for animation-drivers (see T89046). + * - Evaluating the startup file depends on Python for animation-drivers (see #89046). * - Starting Python depends on the startup file so key-maps can be added in the window-manger. * * Loading preferences early, then application subsystems and finally the startup data would @@ -485,12 +485,12 @@ void WM_exit_ex(bContext *C, const bool do_python) #if defined(WITH_PYTHON) && !defined(WITH_PYTHON_MODULE) /* Without this, we there isn't a good way to manage false-positive resource leaks - * where a #PyObject references memory allocated with guarded-alloc, T71362. + * where a #PyObject references memory allocated with guarded-alloc, #71362. * * This allows add-ons to free resources when unregistered (which is good practice anyway). * * Don't run this code when built as a Python module as this runs when Python is in the - * process of shutting down, where running a snippet like this will crash, see T82675. + * process of shutting down, where running a snippet like this will crash, see #82675. * Instead use the `atexit` module, installed by #BPY_python_start */ const char *imports[2] = {"addon_utils", nullptr}; BPY_run_string_eval(C, imports, "addon_utils.disable_all()"); @@ -631,7 +631,7 @@ void WM_exit_ex(bContext *C, const bool do_python) BLI_task_scheduler_exit(); /* No need to call this early, rather do it late so that other - * pieces of Blender using sound may exit cleanly, see also T50676. */ + * pieces of Blender using sound may exit cleanly, see also #50676. */ BKE_sound_exit(); BKE_appdir_exit(); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index c6513a908cf7..9e4e06035376 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -102,7 +102,7 @@ static void wm_keymap_item_properties_set(wmKeyMapItem *kmi) /** * Similar to #wm_keymap_item_properties_set - * but checks for the #wmOperatorType having changed, see T38042. + * but checks for the #wmOperatorType having changed, see #38042. */ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi) { @@ -652,13 +652,13 @@ static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km) /* add item */ if (kmdi->add_item) { - /* Do not re-add an already existing keymap item! See T42088. */ - /* We seek only for exact copy here! See T42137. */ + /* Do not re-add an already existing keymap item! See #42088. */ + /* We seek only for exact copy here! See #42137. */ wmKeyMapItem *kmi_add = wm_keymap_find_item_equals(km, kmdi->add_item); /** If kmi_add is same as kmi_remove (can happen in some cases, * typically when we got kmi_remove from #wm_keymap_find_item_equals_result()), - * no need to add or remove anything, see T45579. */ + * no need to add or remove anything, see #45579. */ /** * \note This typically happens when we apply user-defined keymap diff to a base one that @@ -1313,7 +1313,7 @@ static wmKeyMapItem *wm_keymap_item_find_in_keymap(wmKeyMap *keymap, const struct wmKeyMapItemFind_Params *params) { LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { - /* skip disabled keymap items [T38447] */ + /* skip disabled keymap items [#38447] */ if (kmi->flag & KMI_INACTIVE) { continue; } @@ -1566,7 +1566,7 @@ static wmKeyMapItem *wm_keymap_item_find(const bContext *C, * Otherwise: * * If non-strict, unset properties always match set ones in IDP_EqualsProperties_ex. * * If strict, unset properties never match set ones in IDP_EqualsProperties_ex, - * and we do not want that to change (else we get things like T41757)! + * and we do not want that to change (else we get things like #41757)! * ...so in either case, re-running a comparison with unset props set to default is useless. */ if (!found && properties) { diff --git a/source/blender/windowmanager/intern/wm_keymap_utils.c b/source/blender/windowmanager/intern/wm_keymap_utils.c index 0817b10f86e0..cf8c0ebb8590 100644 --- a/source/blender/windowmanager/intern/wm_keymap_utils.c +++ b/source/blender/windowmanager/intern/wm_keymap_utils.c @@ -141,7 +141,7 @@ wmKeyMap *WM_keymap_guess_from_context(const bContext *C) km_id = "Grease Pencil Stroke Vertex Mode"; break; case CTX_MODE_SCULPT_CURVES: - km_id = "Curves Sculpt"; + km_id = "Sculpt Curves"; break; } } diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c index d7a01419450d..b90c110efbb3 100644 --- a/source/blender/windowmanager/intern/wm_operator_type.c +++ b/source/blender/windowmanager/intern/wm_operator_type.c @@ -384,7 +384,7 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event) retval = opm->type->modal(C, opm, event); OPERATOR_RETVAL_CHECK(retval); - /* if we're halfway through using a tool and cancel it, clear the options T37149. */ + /* if we're halfway through using a tool and cancel it, clear the options #37149. */ if (retval & OPERATOR_CANCELLED) { WM_operator_properties_clear(opm->ptr); } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 8ffaf8a06035..94b342129337 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1437,7 +1437,7 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2) uiBlock *block = arg2; /* Explicitly set UI_RETURN_OK flag, otherwise the menu might be canceled - * in case WM_operator_call_ex exits/reloads the current file (T49199). */ + * in case WM_operator_call_ex exits/reloads the current file (#49199). */ UI_popup_menu_retval_set(block, UI_RETURN_OK, true); @@ -1473,7 +1473,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *userD /* clear so the OK button is left alone */ UI_block_func_set(block, NULL, NULL, NULL); - /* new column so as not to interfere with custom layouts T26436. */ + /* new column so as not to interfere with custom layouts #26436. */ { uiLayout *col = uiLayoutColumn(layout, false); uiBlock *col_block = uiLayoutGetBlock(col); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 6378c756d4f6..31c0dfcceb08 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -650,7 +650,7 @@ static void build_pict_list_ex( } else { /* Load images into cache until the cache is full, - * this resolves choppiness for images that are slow to load, see: T81751. */ + * this resolves choppiness for images that are slow to load, see: #81751. */ #ifdef USE_FRAME_CACHE_LIMIT bool fill_cache = true; #else diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index 16e5f983beab..1bcd51ed9c75 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -179,7 +179,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *UNUSE /* note on UI_BLOCK_NO_WIN_CLIP, the window size is not always synchronized * with the OS when the splash shows, window clipping in this case gives - * ugly results and clipping the splash isn't useful anyway, just disable it T32938. */ + * ugly results and clipping the splash isn't useful anyway, just disable it #32938. */ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP); UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 48a0d47f26ad..6487fd978203 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -291,7 +291,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) else if (win_src->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { const bScreen *screen = WM_window_get_active_screen(win_src); - /* ED_workspace_layout_duplicate() can't handle other cases yet T44688 */ + /* ED_workspace_layout_duplicate() can't handle other cases yet #44688 */ if (screen->state != SCREENNORMAL) { BKE_report( op->reports, RPT_ERROR, "Failed to switch to Time Sequential mode when in fullscreen"); @@ -334,7 +334,7 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - /* Without this, the popup won't be freed properly, see T44688. */ + /* Without this, the popup won't be freed properly, see #44688. */ CTX_wm_window_set(C, win_src); win_src->stereo3d_format->display_mode = prev_display_mode; return OPERATOR_CANCELLED; diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index 6e08f607bae2..1a6aa974a7be 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -561,7 +561,7 @@ void WM_toolsystem_refresh_active(bContext *C) workspace->id.tag &= ~LIB_TAG_DOIT; /* Refresh to ensure data is initialized. * This is needed because undo can load a state which no longer has the underlying DNA data - * needed for the tool (un-initialized paint-slots for eg), see: T64339. */ + * needed for the tool (un-initialized paint-slots for eg), see: #64339. */ LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) { toolsystem_refresh_ref(C, workspace, tref); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 1f5b5fc3ff65..46213bea1209 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -85,7 +85,7 @@ /** * When windows are activated, simulate modifier press/release to match the current state of - * held modifier keys, see T40317. + * held modifier keys, see #40317. */ #define USE_WIN_ACTIVATE @@ -99,7 +99,7 @@ * opt to use this. * * NOTE(@ideasman42): Events generated for non-active windows are rare, - * this happens when using the mouse-wheel over an unfocused window, see: T103722. + * this happens when using the mouse-wheel over an unfocused window, see: #103722. */ #define USE_WIN_DEACTIVATE @@ -212,8 +212,8 @@ static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win) return; } - /* Prevents non-drawable state of main windows (bugs T22967, - * T25071 and possibly T22477 too). Always clear it even if + /* Prevents non-drawable state of main windows (bugs #22967, + * #25071 and possibly #22477 too). Always clear it even if * this window was not the drawable one, because we mess with * drawing context to discard the GW context. */ wm_window_clear_drawable(wm); @@ -632,7 +632,7 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, wm_window_swap_buffers(win); - /* Clear double buffer to avoids flickering of new windows on certain drivers. (See T97600) */ + /* Clear double buffer to avoids flickering of new windows on certain drivers. (See #97600) */ GPU_clear_color(0.55f, 0.55f, 0.55f, 1.0f); // GHOST_SetWindowState(ghostwin, GHOST_kWindowStateModified); @@ -666,7 +666,7 @@ static void wm_window_ghostwindow_ensure(wmWindowManager *wm, wmWindow *win, boo wm_init_state.override_flag &= ~WIN_OVERRIDE_WINSTATE; } - /* without this, cursor restore may fail, T45456 */ + /* without this, cursor restore may fail, #45456 */ if (win->cursor == 0) { win->cursor = WM_CURSOR_DEFAULT; } @@ -2134,7 +2134,7 @@ uint *WM_window_pixels_read(wmWindowManager *wm, wmWindow *win, int r_size[2]) { /* WARNING: Reading from the front-buffer immediately after drawing may fail, * for a slower but more reliable version of this function #WM_window_pixels_read_offscreen - * should be preferred. See it's comments for details on why it's needed, see also T98462. */ + * should be preferred. See it's comments for details on why it's needed, see also #98462. */ bool setup_context = wm->windrawable != win; if (setup_context) { diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index da8ec0ef82ab..0b31b13cef13 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -69,7 +69,7 @@ void wm_homefile_read(struct bContext *C, /** * Special case, support deferred execution of #wm_file_read_post, - * Needed when loading for the first time to workaround order of initialization bug, see T89046. + * Needed when loading for the first time to workaround order of initialization bug, see #89046. */ void wm_homefile_read_post(struct bContext *C, const struct wmFileReadPost_Params *params_file_read_post); diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 22b3d1976728..265c12cac3dc 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -1481,6 +1481,20 @@ install( ) +# ----------------------------------------------------------------------------- +# Bundle assets + +set(ASSET_BUNDLE_DIR ${CMAKE_SOURCE_DIR}/../lib/assets/publish/) + +if(EXISTS "${ASSET_BUNDLE_DIR}") + install( + DIRECTORY ${ASSET_BUNDLE_DIR} + DESTINATION ${TARGETDIR_VER}/datafiles/assets + PATTERN ".svn" EXCLUDE + ) +endif() + + # ----------------------------------------------------------------------------- # Setup link libraries diff --git a/source/creator/creator.c b/source/creator/creator.c index 63998b7b4c24..fe6d501164ad 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -301,7 +301,7 @@ int main(int argc, /* Un-buffered `stdout` makes `stdout` and `stderr` better synchronized, and helps * when stepping through code in a debugger (prints are immediately * visible). However disabling buffering causes lock contention on windows - * see T76767 for details, since this is a debugging aid, we do not enable + * see #76767 for details, since this is a debugging aid, we do not enable * the un-buffered behavior for release builds. */ #ifndef NDEBUG setvbuf(stdout, NULL, _IONBF, 0); diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index b39d581b54c8..41708cc81a86 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -1725,7 +1725,7 @@ static int arg_handle_scene_set(int argc, const char **argv, void *data) if (scene) { CTX_data_scene_set(C, scene); - /* Set the scene of the first window, see: T55991, + /* Set the scene of the first window, see: #55991, * otherwise scripts that run later won't get this scene back from the context. */ wmWindow *win = CTX_wm_window(C); if (win == NULL) { diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 2dc3e560e353..20a7e2e000ab 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -910,6 +910,12 @@ if(WITH_ALEMBIC) endif() if(WITH_USD) + add_blender_test( + usd_export_test + --python ${CMAKE_CURRENT_LIST_DIR}/bl_usd_export_test.py + -- + --testdir "${TEST_SRC_DIR}/usd" + ) add_blender_test( usd_import_test --python ${CMAKE_CURRENT_LIST_DIR}/bl_usd_import_test.py diff --git a/tests/python/alembic_export_tests.py b/tests/python/alembic_export_tests.py index 95ae3ee9feb2..4fb04405d053 100644 --- a/tests/python/alembic_export_tests.py +++ b/tests/python/alembic_export_tests.py @@ -396,7 +396,7 @@ class UVMapExportTest(AbstractAlembicTest): def test_uvmap_export(self, tempdir: pathlib.Path): """Minimal test for exporting multiple UV maps on an animated mesh. - This covers the issue reported in T77021. + This covers the issue reported in #77021. """ basename = 'T77021-multiple-uvmaps-animated-mesh' abc = tempdir / f'{basename}.abc' diff --git a/tests/python/bl_id_management.py b/tests/python/bl_id_management.py index 9ca53b4214b7..c29640d01e7b 100644 --- a/tests/python/bl_id_management.py +++ b/tests/python/bl_id_management.py @@ -173,7 +173,7 @@ class TestIdRename(TestHelper, unittest.TestCase): data = dt break data.name = name - # This can fail currently, see T71244. + # This can fail currently, see #71244. # ~ self.assertEqual(data.name, self.default_name + ".001") self.ensure_proper_order() diff --git a/tests/python/bl_keymap_completeness.py b/tests/python/bl_keymap_completeness.py index 97335a94c01c..1d16cf752a72 100644 --- a/tests/python/bl_keymap_completeness.py +++ b/tests/python/bl_keymap_completeness.py @@ -36,7 +36,7 @@ def check_maps(): # Keymap functions of tools are not in blender anyway... continue print("\t%s" % km_id) - # TODO T65963, broken keymap hierarchy tests disabled until fixed. + # TODO #65963, broken keymap hierarchy tests disabled until fixed. # err = True test = maps_bl - maps_py @@ -45,7 +45,7 @@ def check_maps(): for km_id in test: km = keyconf.keymaps[km_id] print(" ('%s', '%s', '%s', [])," % (km_id, km.space_type, km.region_type)) - # TODO T65963, broken keymap hierarchy tests disabled until fixed. + # TODO #65963, broken keymap hierarchy tests disabled until fixed. # err = True # Check space/region's are OK diff --git a/tests/python/bl_rigging_symmetrize.py b/tests/python/bl_rigging_symmetrize.py index 10ba99ac6e9f..035560b624e8 100644 --- a/tests/python/bl_rigging_symmetrize.py +++ b/tests/python/bl_rigging_symmetrize.py @@ -153,12 +153,12 @@ class ArmatureSymmetrizeTest(AbstractAnimationTest, unittest.TestCase): bpy.ops.wm.open_mainfile(filepath=str( self.testdir / "symm_test.blend")) - # T81541 (D9214) + # #81541 (D9214) arm = bpy.data.objects['transform_const_rig'] expected_arm = bpy.data.objects['expected_transform_const_rig'] self.assertEqualSymmetrize(arm, expected_arm) - # T66751 (D6009) + # #66751 (D6009) arm = bpy.data.objects['dragon_rig'] expected_arm = bpy.data.objects['expected_dragon_rig'] self.assertEqualSymmetrize(arm, expected_arm) diff --git a/tests/python/bl_usd_export_test.py b/tests/python/bl_usd_export_test.py new file mode 100644 index 000000000000..1080acaf7e68 --- /dev/null +++ b/tests/python/bl_usd_export_test.py @@ -0,0 +1,145 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +import enum +import pathlib +import pprint +import sys +import tempfile +import unittest +from pxr import Usd +from pxr import UsdUtils +from pxr import UsdGeom +from pxr import Gf + +import bpy + +args = None + + +class AbstractUSDTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls._tempdir = tempfile.TemporaryDirectory() + cls.testdir = args.testdir + cls.tempdir = pathlib.Path(cls._tempdir.name) + + return cls + + def setUp(self): + self.assertTrue( + self.testdir.exists(), "Test dir {0} should exist".format(self.testdir) + ) + + def tearDown(self): + self._tempdir.cleanup() + + +class USDExportTest(AbstractUSDTest): + def test_export_usdchecker(self): + """Test exporting a scene and verifying it passes the usdchecker test suite""" + bpy.ops.wm.open_mainfile( + filepath=str(self.testdir / "usd_materials_export.blend") + ) + export_path = self.tempdir / "usdchecker.usda" + res = bpy.ops.wm.usd_export( + filepath=str(export_path), + export_materials=True, + evaluation_mode="RENDER", + ) + self.assertEqual({'FINISHED'}, res, f"Unable to export to {export_path}") + + checker = UsdUtils.ComplianceChecker( + arkit=False, + skipARKitRootLayerCheck=False, + rootPackageOnly=False, + skipVariants=False, + verbose=False, + ) + checker.CheckCompliance(str(export_path)) + + failed_checks = {} + + # The ComplianceChecker does not know how to resolve tags, so + # it will flag "textures/test_grid_.png" as a missing reference. + # That reference is in fact OK, so we skip the rule for this test. + to_skip = ("MissingReferenceChecker",) + for rule in checker._rules: + name = rule.__class__.__name__ + if name in to_skip: + continue + + issues = rule.GetFailedChecks() + rule.GetWarnings() + rule.GetErrors() + if not issues: + continue + + failed_checks[name] = issues + + self.assertFalse(failed_checks, pprint.pformat(failed_checks)) + + def compareVec3d(self, first, second): + places = 5 + self.assertAlmostEqual(first[0], second[0], places) + self.assertAlmostEqual(first[1], second[1], places) + self.assertAlmostEqual(first[2], second[2], places) + + def test_export_extents(self): + """Test that exported scenes contain have a properly authored extent attribute on each boundable prim""" + bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "usd_extent_test.blend")) + export_path = self.tempdir / "usd_extent_test.usda" + res = bpy.ops.wm.usd_export( + filepath=str(export_path), + export_materials=True, + evaluation_mode="RENDER", + ) + self.assertEqual({'FINISHED'}, res, f"Unable to export to {export_path}") + + # if prims are missing, the exporter must have skipped some objects + stats = UsdUtils.ComputeUsdStageStats(str(export_path)) + self.assertEqual(stats["totalPrimCount"], 15, "Unexpected number of prims") + + # validate the overall world bounds of the scene + stage = Usd.Stage.Open(str(export_path)) + scenePrim = stage.GetPrimAtPath("/scene") + bboxcache = UsdGeom.BBoxCache(Usd.TimeCode.Default(), [UsdGeom.Tokens.default_]) + bounds = bboxcache.ComputeWorldBound(scenePrim) + bound_min = bounds.GetRange().GetMin() + bound_max = bounds.GetRange().GetMax() + self.compareVec3d(bound_min, Gf.Vec3d(-5.752975881, -1, -2.798513651)) + self.compareVec3d(bound_max, Gf.Vec3d(1, 2.9515805244, 2.7985136508)) + + # validate the locally authored extents + prim = stage.GetPrimAtPath("/scene/BigCube/BigCubeMesh") + extent = UsdGeom.Boundable(prim).GetExtentAttr().Get() + self.compareVec3d(Gf.Vec3d(extent[0]), Gf.Vec3d(-1, -1, -2.7985137)) + self.compareVec3d(Gf.Vec3d(extent[1]), Gf.Vec3d(1, 1, 2.7985137)) + prim = stage.GetPrimAtPath("/scene/LittleCube/LittleCubeMesh") + extent = UsdGeom.Boundable(prim).GetExtentAttr().Get() + self.compareVec3d(Gf.Vec3d(extent[0]), Gf.Vec3d(-1, -1, -1)) + self.compareVec3d(Gf.Vec3d(extent[1]), Gf.Vec3d(1, 1, 1)) + prim = stage.GetPrimAtPath("/scene/Volume/Volume") + extent = UsdGeom.Boundable(prim).GetExtentAttr().Get() + self.compareVec3d( + Gf.Vec3d(extent[0]), Gf.Vec3d(-0.7313742, -0.68043584, -0.5801515) + ) + self.compareVec3d( + Gf.Vec3d(extent[1]), Gf.Vec3d(0.7515701, 0.5500924, 0.9027928) + ) + + +def main(): + global args + import argparse + + if "--" in sys.argv: + argv = [sys.argv[0]] + sys.argv[sys.argv.index("--") + 1:] + else: + argv = sys.argv + + parser = argparse.ArgumentParser() + parser.add_argument("--testdir", required=True, type=pathlib.Path) + args, remaining = parser.parse_known_args(argv) + + unittest.main(argv=remaining) + + +if __name__ == "__main__": + main() diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py index 1d30a696e985..36eceb0558d1 100644 --- a/tests/python/cycles_render_tests.py +++ b/tests/python/cycles_render_tests.py @@ -139,7 +139,7 @@ def main(): else: report.set_compare_engine('cycles', 'CPU') - # Increase threshold for motion blur, see T78777. + # Increase threshold for motion blur, see #78777. test_dir_name = Path(test_dir).name if test_dir_name == 'motion_blur': report.set_fail_threshold(0.032) diff --git a/tests/python/operators.py b/tests/python/operators.py index 884910e159c1..da05ee59dbff 100644 --- a/tests/python/operators.py +++ b/tests/python/operators.py @@ -549,7 +549,7 @@ def main(): ), - # T87259 - test cases + # #87259 - test cases SpecMeshTest( "CubeEdgeUnsubdivide", "testCubeEdgeUnsubdivide", "expectedCubeEdgeUnsubdivide", [OperatorSpecEditMode("unsubdivide", {}, "EDGE", {i for i in range(6)})], diff --git a/tests/python/view_layer/test_evaluation_render_settings_a.py b/tests/python/view_layer/test_evaluation_render_settings_a.py index 526e7462716c..732877aa2881 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_a.py +++ b/tests/python/view_layer/test_evaluation_render_settings_a.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct diff --git a/tests/python/view_layer/test_evaluation_render_settings_b.py b/tests/python/view_layer/test_evaluation_render_settings_b.py index 1674ae6a93ee..9eef79733227 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_b.py +++ b/tests/python/view_layer/test_evaluation_render_settings_b.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct diff --git a/tests/python/view_layer/test_evaluation_render_settings_c.py b/tests/python/view_layer/test_evaluation_render_settings_c.py index ca572253dffd..7159a725f99a 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_c.py +++ b/tests/python/view_layer/test_evaluation_render_settings_c.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct diff --git a/tests/python/view_layer/test_evaluation_render_settings_d.py b/tests/python/view_layer/test_evaluation_render_settings_d.py index 2c2173af0d6b..3ef70d45f39c 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_d.py +++ b/tests/python/view_layer/test_evaluation_render_settings_d.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct diff --git a/tests/python/view_layer/test_evaluation_render_settings_e.py b/tests/python/view_layer/test_evaluation_render_settings_e.py index f2cc6f579d7b..d14c42b3ff6a 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_e.py +++ b/tests/python/view_layer/test_evaluation_render_settings_e.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct diff --git a/tests/python/view_layer/test_evaluation_render_settings_f.py b/tests/python/view_layer/test_evaluation_render_settings_f.py index 966bdbd4392a..56a41c2d5a6c 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_f.py +++ b/tests/python/view_layer/test_evaluation_render_settings_f.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct diff --git a/tests/python/view_layer/test_evaluation_render_settings_g.py b/tests/python/view_layer/test_evaluation_render_settings_g.py index dfc34e76975d..91f03ef7973a 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_g.py +++ b/tests/python/view_layer/test_evaluation_render_settings_g.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct diff --git a/tests/python/view_layer/test_evaluation_render_settings_h.py b/tests/python/view_layer/test_evaluation_render_settings_h.py index 0e3bc5faaa86..ed6965face69 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_h.py +++ b/tests/python/view_layer/test_evaluation_render_settings_h.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct diff --git a/tests/python/view_layer/test_evaluation_render_settings_i.py b/tests/python/view_layer/test_evaluation_render_settings_i.py index d44e00ae665f..958f78ea3dc0 100644 --- a/tests/python/view_layer/test_evaluation_render_settings_i.py +++ b/tests/python/view_layer/test_evaluation_render_settings_i.py @@ -16,7 +16,7 @@ from view_layer_common import * # ############################################################ class UnitTesting(ViewLayerTesting): - @unittest.skip("Uses the clay engine, that is removed T55454") + @unittest.skip("Uses the clay engine, that is removed #55454") def test_render_settings(self): """ See if the depsgraph evaluation is correct