WIP: Brush assets project #106303

Draft
Julian Eisel wants to merge 358 commits from brush-assets-project into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
445 changed files with 4901 additions and 3033 deletions
Showing only changes of commit 13c7bb4e55 - Show all commits

View File

@ -25,9 +25,14 @@ vendor,product,version,cve_number,remarks,comment
@TIFF_ID@,CVE-2022-3599,Ignored,issue in tiff command line tool not used by blender
@TIFF_ID@,CVE-2022-3626,Ignored,issue in tiff command line tool not used by blender
@TIFF_ID@,CVE-2022-3627,Ignored,issue in tiff command line tool not used by blender
@TIFF_ID@,CVE-2023-40745,Ignored,issue in tiff command line tool not used by blender
@TIFF_ID@,CVE-2023-41175,Ignored,issue in tiff command line tool not used by blender
@XML2_ID@,CVE-2016-3709,Ignored,not affecting blender and not considered a security issue upstream
@XML2_ID@,CVE-2023-39615,Ignored,not affecting blender and not considered a security issue upstream
@XML2_ID@,CVE-2020-7595,Ignored,already fixed in the libxml2 version used
@GMP_ID@,CVE-2021-43618,Mitigated,patched using upstream commit 561a9c25298e
@SQLITE_ID@,CVE-2022-35737,Ignored,only affects SQLITE_ENABLE_STAT4 compile option not used by blender or python
@SQLITE_ID@,CVE-2023-7104,Ignored,does not affect blender use of sqlite
@SQLITE_ID@,CVE-2024-0232,Ignored,does not affect blender use of sqlite
@ZLIB_ID@,CVE-2023-45853,Ignored,only affects minizip not used by blender
@SBOMCONTENTS@

View File

@ -9,7 +9,12 @@ set(OIDN_EXTRA_ARGS
-DOIDN_FILTER_RTLIGHTMAP=OFF
-DPython_EXECUTABLE=${PYTHON_BINARY}
)
if(NOT APPLE)
if(APPLE)
set(OIDN_EXTRA_ARGS
${OIDN_EXTRA_ARGS}
-DOIDN_DEVICE_METAL=ON
)
else()
set(OIDN_EXTRA_ARGS
${OIDN_EXTRA_ARGS}
-DOIDN_DEVICE_SYCL=ON

View File

@ -111,9 +111,9 @@ endif()
message("Checking for perl")
# download perl for libvpx
if(NOT EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-64bit-portable.zip")
if(NOT EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.38.0.1-64bit-portable.zip")
message("Downloading perl")
file(DOWNLOAD "http://strawberryperl.com/download/5.22.1.3/strawberry-perl-5.22.1.3-64bit-portable.zip" "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-64bit-portable.zip")
file(DOWNLOAD "https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_5380_5361/strawberry-perl-5.38.0.1-64bit-portable.zip" "${DOWNLOAD_DIR}/strawberry-perl-5.38.0.1-64bit-portable.zip")
endif()
# make perl root directory
@ -125,10 +125,10 @@ if(NOT EXISTS "${DOWNLOAD_DIR}/perl")
endif()
# extract perl
if((NOT EXISTS "${DOWNLOAD_DIR}/perl/portable.perl") AND (EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-64bit-portable.zip"))
if((NOT EXISTS "${DOWNLOAD_DIR}/perl/portable.perl") AND (EXISTS "${DOWNLOAD_DIR}/strawberry-perl-5.38.0.1-64bit-portable.zip"))
message("Extracting perl")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/strawberry-perl-5.22.1.3-64bit-portable.zip
COMMAND ${CMAKE_COMMAND} -E tar jxf ${DOWNLOAD_DIR}/strawberry-perl-5.38.0.1-64bit-portable.zip
WORKING_DIRECTORY ${DOWNLOAD_DIR}/perl
)
endif()

View File

@ -56,7 +56,7 @@ set(BLOSC_URI https://github.com/Blosc/c-blosc/archive/v${BLOSC_VERSION}.tar.gz)
set(BLOSC_HASH 134b55813b1dca57019d2a2dc1f7a923)
set(BLOSC_HASH_TYPE MD5)
set(BLOSC_FILE blosc-${BLOSC_VERSION}.tar.gz)
set(BLOSC_CPE "cpe:2.3:a:c-blosc2_project:c-blosc2:${BLOSC_VERSION}:*:*:*:*:*:*:*")
set(BLOSC_CPE "cpe:2.3:a:c-blosc_project:c-blosc:${BLOSC_VERSION}:*:*:*:*:*:*:*")
set(PTHREADS_VERSION 3.0.0)
set(PTHREADS_URI http://prdownloads.sourceforge.net/pthreads4w/pthreads4w-code-v${PTHREADS_VERSION}.zip)
@ -218,11 +218,11 @@ set(OSL_FILE OpenShadingLanguage-${OSL_VERSION}.tar.gz)
# BZIP2, FFI, SQLITE and change the versions in this file as well. For compliance
# reasons there can be no exceptions to this.
set(PYTHON_VERSION 3.11.6)
set(PYTHON_VERSION 3.11.7)
set(PYTHON_SHORT_VERSION 3.11)
set(PYTHON_SHORT_VERSION_NO_DOTS 311)
set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz)
set(PYTHON_HASH d0c5a1a31efe879723e51addf56dd206)
set(PYTHON_HASH d96c7e134c35a8c46236f8a0e566b69c)
set(PYTHON_HASH_TYPE MD5)
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*")
@ -318,9 +318,9 @@ set(FLAC_FILE flac-${FLAC_VERSION}.tar.xz)
set(FLAC_CPE "cpe:2.3:a:flac_project:flac:${FLAC_VERSION}:*:*:*:*:*:*:*")
set(FLAC_HOMEPAGE https://xiph.org/flac/)
set(VPX_VERSION 1.11.0)
set(VPX_VERSION 1.14.0)
set(VPX_URI https://github.com/webmproject/libvpx/archive/v${VPX_VERSION}/libvpx-v${VPX_VERSION}.tar.gz)
set(VPX_HASH 965e51c91ad9851e2337aebcc0f517440c637c506f3a03948062e3d5ea129a83)
set(VPX_HASH 5f21d2db27071c8a46f1725928a10227ae45c5cd1cad3727e4aafbe476e321fa)
set(VPX_HASH_TYPE SHA256)
set(VPX_FILE libvpx-v${VPX_VERSION}.tar.gz)
set(VPX_CPE "cpe:2.3:a:webmproject:libvpx:${VPX_VERSION}:*:*:*:*:*:*:*")
@ -347,9 +347,9 @@ set(OPENJPEG_HASH_TYPE SHA256)
set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz)
set(OPENJPEG_CPE "cpe:2.3:a:uclouvain:openjpeg:${OPENJPEG_VERSION}:*:*:*:*:*:*:*")
set(FFMPEG_VERSION 6.0)
set(FFMPEG_VERSION 6.1.1)
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
set(FFMPEG_HASH 47d062731c9f66a78380e35a19aac77cebceccd1c7cc309b9c82343ffc430c3d)
set(FFMPEG_HASH 5e3133939a61ef64ac9b47ffd29a5ea6e337a4023ef0ad972094b4da844e3a20)
set(FFMPEG_HASH_TYPE SHA256)
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*")
@ -479,9 +479,9 @@ set(LZMA_FILE xz-${LZMA_VERSION}.tar.bz2)
set(LZMA_HOMEPAGE https://tukaani.org/lzma/)
# NOTE: Python's build has been modified to use our ssl version.
set(SSL_VERSION 3.1.2)
set(SSL_VERSION 3.1.5)
set(SSL_URI https://www.openssl.org/source/openssl-${SSL_VERSION}.tar.gz)
set(SSL_HASH a0ce69b8b97ea6a35b96875235aa453b966ba3cba8af2de23657d8b6767d6539)
set(SSL_HASH 6ae015467dabf0469b139ada93319327be24b98251ffaeceda0221848dc09262)
set(SSL_HASH_TYPE SHA256)
set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*")
@ -490,10 +490,10 @@ set(SSL_HOMEPAGE https://www.openssl.org)
# Note: This will *HAVE* to match the version python ships on windows which
# is hardcoded in pythons PCbuild/get_externals.bat for compliance reasons there
# can be no exceptions to this.
set(SQLITE_VERSION 3.42.0)
set(SQLLITE_LONG_VERSION 3420000)
set(SQLITE_URI https://www.sqlite.org/2023/sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
set(SQLITE_HASH 036575929b174c1b829769255491ba2b32bda9ee)
set(SQLITE_VERSION 3.45.1)
set(SQLLITE_LONG_VERSION 3450100)
set(SQLITE_URI https://www.sqlite.org/2024/sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
set(SQLITE_HASH 650305e234add12fc1e6bef0b365d86a087b3d38)
set(SQLITE_HASH_TYPE SHA1)
set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
@ -517,9 +517,9 @@ set(MATERIALX_HASH fad8f4e19305fb2ee920cbff638f3560)
set(MATERIALX_HASH_TYPE MD5)
set(MATERIALX_FILE materialx-v${MATERIALX_VERSION}.tar.gz)
set(OIDN_VERSION 2.2.0-rc)
set(OIDN_VERSION 2.2.0-rc2)
set(OIDN_URI https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.tar.gz)
set(OIDN_HASH 896d43b65c3fe71144914a1d6b8a5bfb)
set(OIDN_HASH 14b261af3a719c49ab10e71583f1a61a)
set(OIDN_HASH_TYPE MD5)
set(OIDN_FILE oidn-${OIDN_VERSION}.src.tar.gz)

View File

@ -1,7 +1,7 @@
diff -Naur ffmpeg-clean/configure ffmpeg-dirty/configure
--- ffmpeg-clean/configure 2023-02-27 20:43:45.000000000 +0000
+++ ffmpeg-dirty/configure 2023-05-25 09:49:24.949566500 +0100
@@ -6563,7 +6563,7 @@
@@ -6675,7 +6675,7 @@
enabled jni && { [ $target_os = "android" ] && check_headers jni.h && enabled pthreads || die "ERROR: jni not found"; }
enabled ladspa && require_headers "ladspa.h dlfcn.h"
enabled lcms2 && require_pkg_config lcms2 "lcms2 >= 2.13" lcms2.h cmsCreateContext
@ -10,7 +10,7 @@ diff -Naur ffmpeg-clean/configure ffmpeg-dirty/configure
enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new ||
{ enabled gpl && require_pkg_config libaribb24 aribb24 "aribb24/aribb24.h" arib_instance_new; } ||
die "ERROR: libaribb24 requires version higher than 1.0.3 or --enable-gpl."; }
@@ -6654,16 +6654,15 @@
@@ -6767,18 +6767,17 @@
require libopencv opencv2/core/core_c.h cvCreateImageHeader -lopencv_core -lopencv_imgproc; } ||
require_pkg_config libopencv opencv opencv/cxcore.h cvCreateImageHeader; }
enabled libopenh264 && require_pkg_config libopenh264 openh264 wels/codec_api.h WelsGetCodecVersion
@ -18,7 +18,9 @@ diff -Naur ffmpeg-clean/configure ffmpeg-dirty/configure
- { require_pkg_config libopenjpeg "libopenjp2 >= 2.1.0" openjpeg.h opj_version -DOPJ_STATIC && add_cppflags -DOPJ_STATIC; } }
+enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version "-DOPJ_STATIC" -lopenjp2
enabled libopenmpt && require_pkg_config libopenmpt "libopenmpt >= 0.2.6557" libopenmpt/libopenmpt.h openmpt_module_create -lstdc++ && append libopenmpt_extralibs "-lstdc++"
enabled libopenvino && require libopenvino c_api/ie_c_api.h ie_c_api_version -linference_engine_c_api
enabled libopenvino && { { check_pkg_config libopenvino openvino openvino/c/openvino.h ov_core_create && enable openvino2; } ||
{ check_pkg_config libopenvino openvino c_api/ie_c_api.h ie_c_api_version ||
require libopenvino c_api/ie_c_api.h ie_c_api_version -linference_engine_c_api; } }
enabled libopus && {
enabled libopus_decoder && {
- require_pkg_config libopus opus opus_multistream.h opus_multistream_decoder_create
@ -30,9 +32,9 @@ diff -Naur ffmpeg-clean/configure ffmpeg-dirty/configure
}
}
enabled libplacebo && require_pkg_config libplacebo "libplacebo >= 4.192.0" libplacebo/vulkan.h pl_vulkan_create
@@ -6696,8 +6695,8 @@
enabled libvidstab && require_pkg_config libvidstab "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit
@@ -6812,8 +6811,8 @@
enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 2.0.0" libvmaf.h vmaf_init
enabled libvmaf && check_pkg_config libvmaf_cuda "libvmaf >= 2.0.0" libvmaf_cuda.h vmaf_cuda_state_init
enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc
-enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h vorbis_info_init &&
- require_pkg_config libvorbisenc vorbisenc vorbis/vorbisenc.h vorbis_encode_init
@ -41,7 +43,7 @@ diff -Naur ffmpeg-clean/configure ffmpeg-dirty/configure
enabled libvpx && {
enabled libvpx_vp8_decoder && {
@@ -6724,7 +6723,7 @@
@@ -6840,7 +6839,7 @@
enabled libwebp && {
enabled libwebp_encoder && require_pkg_config libwebp "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion
enabled libwebp_anim_encoder && check_pkg_config libwebp_anim_encoder "libwebpmux >= 0.4.0" webp/mux.h WebPAnimEncoderOptionsInit; }

View File

@ -2,6 +2,6 @@
@echo Setting up environment for MSYS2 MSVC 64-bit...
@set PATH=%CD%\usr\bin;%cd%\..\..\perl\site\bin;%cd%\..\..\perl\bin;%cd%\..\..\c\bin;%PATH%
@set PATH=%CD%\usr\bin;%cd%\..\..\perl\site\bin;%cd%\..\..\perl\perl\bin;%cd%\..\..\c\bin;%PATH%

View File

@ -1,49 +1,27 @@
diff -Naur oidn-2.0.1/core/CMakeLists.txt external_openimagedenoise/core/CMakeLists.txt
--- oidn-2.0.1/core/CMakeLists.txt 2023-06-26 09:06:31.000000000 -0600
+++ external_openimagedenoise/core/CMakeLists.txt 2023-07-01 10:54:06.347161100 -0600
@@ -76,7 +76,7 @@
add_library(OpenImageDenoise_core SHARED ${OIDN_CORE_SOURCES} ${OIDN_RESOURCE_FILE})
diff -Naur oidn-2.2.0/core/CMakeLists.txt external_openimagedenoise/core/CMakeLists.txt
--- oidn-2.2.0/core/CMakeLists.txt 2024-02-01 17:52:16 -0700
+++ external_openimagedenoise/core/CMakeLists.txt 2024-02-03 12:41:34 -0700
@@ -87,7 +87,7 @@
add_library(OpenImageDenoise_core ${OIDN_CORE_LIB_TYPE} ${OIDN_CORE_SOURCES} ${OIDN_RESOURCE_FILE})
set_property(TARGET OpenImageDenoise_core PROPERTY VERSION ${PROJECT_VERSION})
-
+target_compile_definitions(OpenImageDenoise_core PRIVATE SHARED_POSTFIX=\"$<$<CONFIG:Debug>:$<TARGET_PROPERTY:OpenImageDenoise_core,DEBUG_POSTFIX>>\")
target_link_libraries(OpenImageDenoise_core
PUBLIC
OpenImageDenoise_common
diff -Naur oidn-2.0.1/core/module.cpp external_openimagedenoise/core/module.cpp
--- oidn-2.0.1/core/module.cpp 2023-06-26 09:06:31.000000000 -0600
+++ external_openimagedenoise/core/module.cpp 2023-07-01 10:49:59.924876500 -0600
diff -Naur oidn-2.2.0/core/module.cpp external_openimagedenoise/core/module.cpp
--- oidn-2.2.0/core/module.cpp 2024-02-01 17:52:16 -0700
+++ external_openimagedenoise/core/module.cpp 2024-02-03 12:41:34 -0700
@@ -29,7 +29,7 @@
return true; // module already loaded
// Get the path of the module to load
- std::string filename = "OpenImageDenoise_" + name;
+ std::string filename = "OpenImageDenoise_" + name + SHARED_POSTFIX;
#if defined(_WIN32)
filename += ".dll";
#else
diff -Naur oidn-2.1.0/devices/CMakeLists.txt external_openimagedenoise/devices/CMakeLists.txt
--- oidn-2.1.0/devices/CMakeLists.txt 2023-10-11 14:04:08 -0600
+++ external_openimagedenoise/devices/CMakeLists.txt 2023-12-23 09:34:17 -0700
@@ -59,6 +59,8 @@
-DOIDN_API_NAMESPACE:STRING=${OIDN_API_NAMESPACE}
-DOIDN_WARN_AS_ERRORS:BOOL=${OIDN_WARN_AS_ERRORS}
-DOIDN_SANITIZER:STRING=${OIDN_SANITIZER}
+ -DPython_EXECUTABLE:STRING=${Python_EXECUTABLE}
+ -DCMAKE_DEBUG_POSTFIX:STRING=${CMAKE_DEBUG_POSTFIX}
BUILD_ALWAYS TRUE
DEPENDS
OpenImageDenoise_core
@@ -149,6 +151,7 @@
-DOIDN_API_NAMESPACE:STRING=${OIDN_API_NAMESPACE}
-DOIDN_WARN_AS_ERRORS:BOOL=${OIDN_WARN_AS_ERRORS}
-DOIDN_SANITIZER:STRING=${OIDN_SANITIZER}
+ -DPython_EXECUTABLE:STRING=${Python_EXECUTABLE}
BUILD_ALWAYS TRUE
DEPENDS
OpenImageDenoise_core
--- a/core/module.cpp 2023-11-16 19:07:32
+++ b/core/module.cpp 2023-11-16 19:08:01
@@ -37,7 +37,8 @@
"." + toString(OIDN_VERSION_MINOR) +
"." + toString(OIDN_VERSION_PATCH);
@ -54,3 +32,23 @@ diff -Naur oidn-2.1.0/devices/CMakeLists.txt external_openimagedenoise/devices/C
#else
filename = "lib" + filename + ".so" + versionStr;
#endif
diff -Naur oidn-2.2.0/devices/CMakeLists.txt external_openimagedenoise/devices/CMakeLists.txt
--- oidn-2.2.0/devices/CMakeLists.txt 2024-02-01 17:52:16 -0700
+++ external_openimagedenoise/devices/CMakeLists.txt 2024-02-03 13:10:31 -0700
@@ -65,6 +65,7 @@
-DOIDN_WARN_AS_ERRORS:BOOL=${OIDN_WARN_AS_ERRORS}
-DOIDN_SANITIZER:STRING=${OIDN_SANITIZER}
-DOIDN_DEVICE_CUDA_API:STRING=${OIDN_DEVICE_CUDA_API}
+ -DPython_EXECUTABLE:STRING=${Python_EXECUTABLE}
BUILD_ALWAYS TRUE
DEPENDS
OpenImageDenoise_core
@@ -155,6 +156,8 @@
-DOIDN_API_NAMESPACE:STRING=${OIDN_API_NAMESPACE}
-DOIDN_WARN_AS_ERRORS:BOOL=${OIDN_WARN_AS_ERRORS}
-DOIDN_SANITIZER:STRING=${OIDN_SANITIZER}
+ -DPython_EXECUTABLE:STRING=${Python_EXECUTABLE}
+ -DCMAKE_DEBUG_POSTFIX:STRING=${CMAKE_DEBUG_POSTFIX}
BUILD_ALWAYS TRUE
DEPENDS
OpenImageDenoise_core

View File

@ -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 = V4.1
PROJECT_NUMBER = V4.2
# 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

View File

@ -352,6 +352,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
items=enum_denoising_input_passes,
default='RGB_ALBEDO_NORMAL',
)
denoising_use_gpu: BoolProperty(
name="Denoise on GPU",
description="Perform denoising on GPU devices, if available. This is significantly faster than on CPU, but requires additional GPU memory. When large scenes need more GPU memory, this option can be disabled",
default=False,
)
use_preview_denoising: BoolProperty(
name="Use Viewport Denoising",
@ -382,6 +387,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
min=0, max=(1 << 24),
default=1,
)
preview_denoising_use_gpu: BoolProperty(
name="Denoise Preview on GPU",
description="Perform denoising on GPU devices, if available. This is significantly faster than on CPU, but requires additional GPU memory. When large scenes need more GPU memory, this option can be disabled",
default=True,
)
samples: IntProperty(
name="Samples",
@ -1591,6 +1601,22 @@ class CyclesPreferences(bpy.types.AddonPreferences):
def has_active_device(self):
return self.get_num_gpu_devices() > 0
def has_oidn_gpu_devices(self):
import _cycles
compute_device_type = self.get_compute_device_type()
# We need non-CPU devices, used for rendering and supporting OIDN GPU denoising
for device in _cycles.available_devices(compute_device_type):
device_type = device[1]
if device_type == 'CPU':
continue
has_device_oidn_support = device[5]
if has_device_oidn_support and self.find_existing_device_entry(device).use:
return True
return False
def _draw_devices(self, layout, device_type, devices):
box = layout.box()
@ -1685,12 +1711,13 @@ class CyclesPreferences(bpy.types.AddonPreferences):
import _cycles
has_peer_memory = 0
has_rt_api_support = False
has_rt_api_support = {'METAL': False, 'HIP': False, 'ONEAPI': False}
for device in _cycles.available_devices(compute_device_type):
if device[3] and self.find_existing_device_entry(device).use:
has_peer_memory += 1
if device[4] and self.find_existing_device_entry(device).use:
has_rt_api_support = True
device_type = device[1]
has_rt_api_support[device_type] = True
if has_peer_memory > 1:
row = layout.row()
@ -1708,25 +1735,25 @@ class CyclesPreferences(bpy.types.AddonPreferences):
# MetalRT only works on Apple Silicon and Navi2.
is_arm64 = platform.machine() == 'arm64'
if is_arm64 or (is_navi_2 and has_rt_api_support):
if is_arm64 or (is_navi_2 and has_rt_api_support['METAL']):
col = layout.column()
col.use_property_split = True
# Kernel specialization is only supported on Apple Silicon
if is_arm64:
col.prop(self, "kernel_optimization_level")
if has_rt_api_support:
if has_rt_api_support['METAL']:
col.prop(self, "metalrt")
if compute_device_type == 'HIP':
import platform
if platform.system() == "Windows": # HIP-RT is currently only supported on Windows
has_cuda, has_optix, has_hip, has_metal, has_oneapi, has_hiprt = _cycles.get_device_types()
row = layout.row()
row.enabled = has_hiprt
row.active = has_rt_api_support['HIP']
row.prop(self, "use_hiprt")
elif compute_device_type == 'ONEAPI' and _cycles.with_embree_gpu:
row = layout.row()
row.active = has_rt_api_support['ONEAPI']
row.prop(self, "use_oneapirt")
def draw(self, context):

View File

@ -157,6 +157,10 @@ def get_effective_preview_denoiser(context):
return 'OIDN'
def has_oidn_gpu_devices(context):
return context.preferences.addons[__package__].preferences.has_oidn_gpu_devices()
def use_mnee(context):
# The MNEE kernel doesn't compile on macOS < 13.
if use_metal(context):
@ -236,6 +240,11 @@ class CYCLES_RENDER_PT_sampling_viewport_denoise(CyclesButtonsPanel, Panel):
col.prop(cscene, "preview_denoising_start_sample", text="Start Sample")
if effective_preview_denoiser == 'OPENIMAGEDENOISE':
row = col.row()
row.active = not use_cpu(context) and has_oidn_gpu_devices(context)
row.prop(cscene, "preview_denoising_use_gpu", text="Use GPU")
class CYCLES_RENDER_PT_sampling_render(CyclesButtonsPanel, Panel):
bl_label = "Render"
@ -295,6 +304,11 @@ class CYCLES_RENDER_PT_sampling_render_denoise(CyclesButtonsPanel, Panel):
if cscene.denoiser == 'OPENIMAGEDENOISE':
col.prop(cscene, "denoising_prefilter", text="Prefilter")
if cscene.denoiser == 'OPENIMAGEDENOISE':
row = col.row()
row.active = not use_cpu(context) and has_oidn_gpu_devices(context)
row.prop(cscene, "denoising_use_gpu", text="Use GPU")
class CYCLES_RENDER_PT_sampling_path_guiding(CyclesButtonsPanel, Panel):
bl_label = "Path Guiding"

View File

@ -417,12 +417,14 @@ static PyObject *available_devices_func(PyObject * /*self*/, PyObject *args)
for (size_t i = 0; i < devices.size(); i++) {
DeviceInfo &device = devices[i];
string type_name = Device::string_from_type(device.type);
PyObject *device_tuple = PyTuple_New(5);
PyObject *device_tuple = PyTuple_New(6);
PyTuple_SET_ITEM(device_tuple, 0, pyunicode_from_string(device.description.c_str()));
PyTuple_SET_ITEM(device_tuple, 1, pyunicode_from_string(type_name.c_str()));
PyTuple_SET_ITEM(device_tuple, 2, pyunicode_from_string(device.id.c_str()));
PyTuple_SET_ITEM(device_tuple, 3, PyBool_FromLong(device.has_peer_memory));
PyTuple_SET_ITEM(device_tuple, 4, PyBool_FromLong(device.use_hardware_raytracing));
PyTuple_SET_ITEM(
device_tuple, 5, PyBool_FromLong(device.denoisers & DENOISER_OPENIMAGEDENOISE));
PyTuple_SET_ITEM(ret, i, device_tuple);
}

View File

@ -474,10 +474,12 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
* is that the interface and the integrator are technically out of sync. */
if (denoise_params.use) {
integrator->set_denoiser_type(denoise_params.type);
integrator->set_denoise_use_gpu(denoise_params.use_gpu);
integrator->set_denoise_start_sample(denoise_params.start_sample);
integrator->set_use_denoise_pass_albedo(denoise_params.use_pass_albedo);
integrator->set_use_denoise_pass_normal(denoise_params.use_pass_normal);
integrator->set_denoiser_prefilter(denoise_params.prefilter);
integrator->set_denoiser_quality(denoise_params.quality);
}
/* UPDATE_NONE as we don't want to tag the integrator as modified (this was done by the
@ -970,8 +972,12 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene,
/* Final Render Denoising */
denoising.use = get_boolean(cscene, "use_denoising");
denoising.type = (DenoiserType)get_enum(cscene, "denoiser", DENOISER_NUM, DENOISER_NONE);
denoising.use_gpu = get_boolean(cscene, "denoising_use_gpu");
denoising.prefilter = (DenoiserPrefilter)get_enum(
cscene, "denoising_prefilter", DENOISER_PREFILTER_NUM, DENOISER_PREFILTER_NONE);
/* This currently only affects NVIDIA and the difference in quality is too small to justify
* exposing a setting to the user. */
denoising.quality = DENOISER_QUALITY_HIGH;
input_passes = (DenoiserInput)get_enum(
cscene, "denoising_input_passes", DENOISER_INPUT_NUM, DENOISER_INPUT_RGB_ALBEDO_NORMAL);
@ -988,8 +994,12 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene,
denoising.use = get_boolean(cscene, "use_preview_denoising");
denoising.type = (DenoiserType)get_enum(
cscene, "preview_denoiser", DENOISER_NUM, DENOISER_NONE);
denoising.use_gpu = get_boolean(cscene, "preview_denoising_use_gpu");
denoising.prefilter = (DenoiserPrefilter)get_enum(
cscene, "preview_denoising_prefilter", DENOISER_PREFILTER_NUM, DENOISER_PREFILTER_FAST);
/* This currently only affects NVIDIA and the difference in quality is too small to justify
* exposing a setting to the user. */
denoising.quality = DENOISER_QUALITY_BALANCED;
denoising.start_sample = get_int(cscene, "preview_denoising_start_sample");
input_passes = (DenoiserInput)get_enum(

View File

@ -195,7 +195,11 @@ void device_cuda_info(vector<DeviceInfo> &devices)
VLOG_INFO << "Device has compute preemption or is not used for display.";
devices.push_back(info);
}
VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\".";
VLOG_INFO << "Added device \"" << info.description << "\" with id \"" << info.id << "\".";
if (info.denoisers & DENOISER_OPENIMAGEDENOISE)
VLOG_INFO << "Device with id \"" << info.id << "\" is supporting "
<< denoiserTypeToHumanReadable(DENOISER_OPENIMAGEDENOISE) << ".";
}
if (!display_devices.empty()) {

View File

@ -48,12 +48,25 @@ const NodeEnum *DenoiseParams::get_prefilter_enum()
return &prefilter_enum;
}
const NodeEnum *DenoiseParams::get_quality_enum()
{
static NodeEnum quality_enum;
if (quality_enum.empty()) {
quality_enum.insert("high", DENOISER_QUALITY_HIGH);
quality_enum.insert("balanced", DENOISER_QUALITY_BALANCED);
}
return &quality_enum;
}
NODE_DEFINE(DenoiseParams)
{
NodeType *type = NodeType::add("denoise_params", create);
const NodeEnum *type_enum = get_type_enum();
const NodeEnum *prefilter_enum = get_prefilter_enum();
const NodeEnum *quality_enum = get_quality_enum();
SOCKET_BOOLEAN(use, "Use", false);
@ -67,6 +80,7 @@ NODE_DEFINE(DenoiseParams)
SOCKET_BOOLEAN(temporally_stable, "Temporally Stable", false);
SOCKET_ENUM(prefilter, "Prefilter", *prefilter_enum, DENOISER_PREFILTER_FAST);
SOCKET_ENUM(quality, "Quality", *quality_enum, DENOISER_QUALITY_HIGH);
return type;
}

View File

@ -40,6 +40,12 @@ enum DenoiserPrefilter {
DENOISER_PREFILTER_NUM,
};
enum DenoiserQuality {
DENOISER_QUALITY_HIGH = 1,
DENOISER_QUALITY_BALANCED = 2,
DENOISER_QUALITY_NUM,
};
/* NOTE: Is not a real scene node. Using Node API for ease of (de)serialization.
* The default values here do not really matter as they are always initialized from the
* Integrator node. */
@ -63,20 +69,19 @@ class DenoiseParams : public Node {
/* Configure the denoiser to use motion vectors, previous image and a temporally stable model. */
bool temporally_stable = false;
/* If true, then allow, if supported, OpenImageDenoise to use GPU device.
* If false, then OpenImageDenoise will always use CPU regardless of GPU device
* precense. */
bool use_gpu = true;
DenoiserPrefilter prefilter = DENOISER_PREFILTER_FAST;
DenoiserQuality quality = DENOISER_QUALITY_HIGH;
static const NodeEnum *get_type_enum();
static const NodeEnum *get_prefilter_enum();
static const NodeEnum *get_quality_enum();
DenoiseParams();
bool modified(const DenoiseParams &other) const
{
return !(use == other.use && type == other.type && start_sample == other.start_sample &&
use_pass_albedo == other.use_pass_albedo &&
use_pass_normal == other.use_pass_normal &&
temporally_stable == other.temporally_stable && prefilter == other.prefilter);
}
};
CCL_NAMESPACE_END

View File

@ -257,6 +257,12 @@ class Device {
return false;
}
/* Returns native buffer handle for device pointer. */
virtual void *get_native_buffer(device_ptr /*ptr*/)
{
return nullptr;
}
/* Guiding */
/* Returns path guiding device handle. */

View File

@ -206,7 +206,11 @@ void device_hip_info(vector<DeviceInfo> &devices)
devices.push_back(info);
}
VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\".";
VLOG_INFO << "Added device \"" << info.description << "\" with id \"" << info.id << "\".";
if (info.denoisers & DENOISER_OPENIMAGEDENOISE)
VLOG_INFO << "Device with id \"" << info.id << "\" is supporting "
<< denoiserTypeToHumanReadable(DENOISER_OPENIMAGEDENOISE) << ".";
}
if (!display_devices.empty())

View File

@ -6,6 +6,7 @@
# include "device/metal/device.h"
# include "device/metal/device_impl.h"
# include "integrator/denoiser_oidn_gpu.h"
#endif
@ -55,6 +56,11 @@ void device_metal_info(vector<DeviceInfo> &devices)
info.display_device = true;
info.denoisers = DENOISER_NONE;
info.id = id;
# if defined(WITH_OPENIMAGEDENOISE)
if (OIDNDenoiserGPU::is_device_supported(info)) {
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
}
# endif
MetalGPUVendor vendor = MetalInfo::get_device_vendor(device);
@ -79,6 +85,12 @@ void device_metal_info(vector<DeviceInfo> &devices)
devices.push_back(info);
device_index++;
VLOG_INFO << "Added device \"" << info.description << "\" with id \"" << info.id << "\".";
if (info.denoisers & DENOISER_OPENIMAGEDENOISE)
VLOG_INFO << "Device with id \"" << info.id << "\" is supporting "
<< denoiserTypeToHumanReadable(DENOISER_OPENIMAGEDENOISE) << ".";
}
}

View File

@ -134,6 +134,8 @@ class MetalDevice : public Device {
virtual bool should_use_graphics_interop() override;
virtual void *get_native_buffer(device_ptr ptr) override;
virtual unique_ptr<DeviceQueue> gpu_queue_create() override;
virtual void build_bvh(BVH *bvh, Progress &progress, bool refit) override;

View File

@ -1389,6 +1389,11 @@ bool MetalDevice::should_use_graphics_interop()
return false;
}
void *MetalDevice::get_native_buffer(device_ptr ptr)
{
return ((MetalMem *)ptr)->mtlBuffer;
}
void MetalDevice::flush_delayed_free_list()
{
/* free any Metal buffers that may have been freed by host while a command

View File

@ -40,6 +40,8 @@ class MetalDeviceQueue : public DeviceQueue {
virtual void copy_to_device(device_memory &mem) override;
virtual void copy_from_device(device_memory &mem) override;
virtual void *native_queue() override;
protected:
void setup_capture();
void update_capture(DeviceKernel kernel);

View File

@ -979,6 +979,11 @@ void MetalDeviceQueue::close_blit_encoder()
}
}
void *MetalDeviceQueue::native_queue()
{
return mtlCommandQueue_;
}
CCL_NAMESPACE_END
#endif /* WITH_METAL */

View File

@ -131,7 +131,11 @@ static void device_iterator_cb(
# endif
devices->push_back(info);
VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\".";
VLOG_INFO << "Added device \"" << info.description << "\" with id \"" << info.id << "\".";
if (info.denoisers & DENOISER_OPENIMAGEDENOISE)
VLOG_INFO << "Device with id \"" << info.id << "\" is supporting "
<< denoiserTypeToHumanReadable(DENOISER_OPENIMAGEDENOISE) << ".";
}
#endif

View File

@ -157,6 +157,11 @@ class DeviceQueue {
/* Device this queue has been created for. */
Device *device;
virtual void *native_queue()
{
return nullptr;
}
protected:
/* Hide construction so that allocation via `Device` API is enforced. */
explicit DeviceQueue(Device *device);

View File

@ -27,7 +27,9 @@ unique_ptr<Denoiser> Denoiser::create(Device *path_trace_device, const DenoisePa
#endif
#ifdef WITH_OPENIMAGEDENOISE
if (params.type == DENOISER_OPENIMAGEDENOISE && path_trace_device->info.type != DEVICE_CPU &&
/* If available and allowed, then we will use OpenImageDenoise on GPU, otherwise on CPU. */
if (params.type == DENOISER_OPENIMAGEDENOISE && params.use_gpu &&
path_trace_device->info.type != DEVICE_CPU &&
OIDNDenoiserGPU::is_device_supported(path_trace_device->info))
{
return make_unique<OIDNDenoiserGPU>(path_trace_device, params);

View File

@ -324,9 +324,9 @@ void DenoiserGPU::denoise_color_read(const DenoiseContext &context, const Denois
denoiser_queue_.get(), pass_access_info, 1.0f, context.num_samples);
PassAccessor::Destination destination(pass_access_info.type);
destination.d_pixels = context.render_buffers->buffer.device_pointer +
pass.denoised_offset * sizeof(float);
destination.d_pixels = context.render_buffers->buffer.device_pointer;
destination.num_components = 3;
destination.pixel_offset = pass.denoised_offset;
destination.pixel_stride = context.buffer_params.pass_stride;
BufferParams buffer_params = context.buffer_params;

View File

@ -164,6 +164,18 @@ class OIDNDenoiseContext {
oidn_filter.setProgressMonitorFunction(oidn_progress_monitor_function, denoiser_);
oidn_filter.set("hdr", true);
oidn_filter.set("srgb", false);
# if OIDN_VERSION_MAJOR >= 2
switch (denoise_params_.quality) {
case DENOISER_QUALITY_BALANCED:
oidn_filter.set("quality", OIDN_QUALITY_BALANCED);
break;
case DENOISER_QUALITY_HIGH:
default:
oidn_filter.set("quality", OIDN_QUALITY_HIGH);
}
# endif
if (denoise_params_.prefilter == DENOISER_PREFILTER_NONE ||
denoise_params_.prefilter == DENOISER_PREFILTER_ACCURATE)
{

View File

@ -47,6 +47,20 @@ bool OIDNDenoiserGPU::is_device_supported(const DeviceInfo &device)
case DEVICE_OPTIX:
device_type = OIDN_DEVICE_TYPE_CUDA;
break;
# endif
# ifdef OIDN_DEVICE_METAL
case DEVICE_METAL: {
int num_devices = oidnGetNumPhysicalDevices();
for (int i = 0; i < num_devices; i++) {
if (oidnGetPhysicalDeviceUInt(i, "type") == OIDN_DEVICE_TYPE_METAL) {
const char *name = oidnGetPhysicalDeviceString(i, "name");
if (device.id.find(name) != std::string::npos) {
return true;
}
}
}
return false;
}
# endif
case DEVICE_CPU:
/* This is the GPU denoiser - CPU devices shouldn't end up here. */
@ -111,6 +125,9 @@ uint OIDNDenoiserGPU::get_device_type_mask() const
# ifdef OIDN_DEVICE_SYCL
device_mask |= DEVICE_MASK_ONEAPI;
# endif
# ifdef OIDN_DEVICE_METAL
device_mask |= DEVICE_MASK_METAL;
# endif
# ifdef OIDN_DEVICE_CUDA
device_mask |= DEVICE_MASK_CUDA;
device_mask |= DEVICE_MASK_OPTIX;
@ -132,14 +149,61 @@ OIDNFilter OIDNDenoiserGPU::create_filter()
denoiser_device_->set_error(error_message);
}
}
# if OIDN_VERSION_MAJOR >= 2
switch (quality_) {
case DENOISER_QUALITY_BALANCED:
oidnSetFilterInt(filter, "quality", OIDN_QUALITY_BALANCED);
break;
case DENOISER_QUALITY_HIGH:
default:
oidnSetFilterInt(filter, "quality", OIDN_QUALITY_HIGH);
}
# endif
return filter;
}
bool OIDNDenoiserGPU::commit_and_execute_filter(OIDNFilter filter, ExecMode mode)
{
const char *error_message = nullptr;
OIDNError err = OIDN_ERROR_NONE;
for (;;) {
oidnCommitFilter(filter);
if (mode == ExecMode::ASYNC) {
oidnExecuteFilterAsync(filter);
}
else {
oidnExecuteFilter(filter);
}
/* If OIDN runs out of memory, reduce mem limit and retry */
err = oidnGetDeviceError(oidn_device_, (const char **)&error_message);
if (err != OIDN_ERROR_OUT_OF_MEMORY || max_mem_ < 200) {
break;
}
max_mem_ = max_mem_ / 2;
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
}
if (err != OIDN_ERROR_NONE) {
if (error_message == nullptr) {
error_message = "Unspecified OIDN error";
}
LOG(ERROR) << "OIDN error: " << error_message;
denoiser_device_->set_error(error_message);
return false;
}
return true;
}
bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
{
const bool recreate_denoiser = (oidn_device_ == nullptr) || (oidn_filter_ == nullptr) ||
(use_pass_albedo_ != context.use_pass_albedo) ||
(use_pass_normal_ != context.use_pass_normal);
(use_pass_normal_ != context.use_pass_normal) ||
(quality_ != params_.quality);
if (!recreate_denoiser) {
return true;
}
@ -161,6 +225,13 @@ bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
1);
break;
# endif
# if defined(OIDN_DEVICE_METAL) && defined(WITH_METAL)
case DEVICE_METAL: {
denoiser_queue_->init_execution();
const MTLCommandQueue_id queue = (const MTLCommandQueue_id)denoiser_queue_->native_queue();
oidn_device_ = oidnNewMetalDevice(&queue, 1);
} break;
# endif
# if defined(OIDN_DEVICE_CUDA) && defined(WITH_CUDA)
case DEVICE_CUDA:
case DEVICE_OPTIX: {
@ -192,6 +263,8 @@ bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
oidnCommitDevice(oidn_device_);
quality_ = params_.quality;
oidn_filter_ = create_filter();
if (oidn_filter_ == nullptr) {
return false;
@ -199,12 +272,6 @@ bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
oidnSetFilterBool(oidn_filter_, "hdr", true);
oidnSetFilterBool(oidn_filter_, "srgb", false);
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
if (params_.prefilter == DENOISER_PREFILTER_NONE ||
params_.prefilter == DENOISER_PREFILTER_ACCURATE)
{
oidnSetFilterInt(oidn_filter_, "cleanAux", true);
}
if (context.use_pass_albedo) {
albedo_filter_ = create_filter();
@ -249,24 +316,25 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
/* Color pass. */
const int64_t pass_stride_in_bytes = context.buffer_params.pass_stride * sizeof(float);
oidnSetSharedFilterImage(oidn_filter_,
"color",
(void *)context.render_buffers->buffer.device_pointer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
pass.denoised_offset * sizeof(float),
pass_stride_in_bytes,
pass_stride_in_bytes * context.buffer_params.stride);
oidnSetSharedFilterImage(oidn_filter_,
"output",
(void *)context.render_buffers->buffer.device_pointer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
pass.denoised_offset * sizeof(float),
pass_stride_in_bytes,
pass_stride_in_bytes * context.buffer_params.stride);
set_filter_pass(oidn_filter_,
"color",
context.render_buffers->buffer.device_pointer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
pass.denoised_offset * sizeof(float),
pass_stride_in_bytes,
pass_stride_in_bytes * context.buffer_params.stride);
set_filter_pass(oidn_filter_,
"output",
context.render_buffers->buffer.device_pointer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
pass.denoised_offset * sizeof(float),
pass_stride_in_bytes,
pass_stride_in_bytes * context.buffer_params.stride);
/* Optional albedo and color passes. */
if (context.num_input_passes > 1) {
@ -275,125 +343,126 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
const int64_t row_stride_in_bytes = context.guiding_params.stride * pixel_stride_in_bytes;
if (context.use_pass_albedo) {
if (params_.prefilter == DENOISER_PREFILTER_NONE) {
oidnSetSharedFilterImage(oidn_filter_,
"albedo",
(void *)d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
}
else {
oidnSetSharedFilterImage(albedo_filter_,
"color",
(void *)d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnSetSharedFilterImage(albedo_filter_,
"output",
(void *)d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnCommitFilter(albedo_filter_);
oidnExecuteFilterAsync(albedo_filter_);
set_filter_pass(oidn_filter_,
"albedo",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnSetSharedFilterImage(oidn_filter_,
"albedo",
(void *)d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
if (params_.prefilter == DENOISER_PREFILTER_ACCURATE) {
set_filter_pass(albedo_filter_,
"albedo",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
set_filter_pass(albedo_filter_,
"output",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_albedo * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
if (!commit_and_execute_filter(albedo_filter_, ExecMode::ASYNC)) {
return false;
}
}
}
if (context.use_pass_normal) {
if (params_.prefilter == DENOISER_PREFILTER_NONE) {
oidnSetSharedFilterImage(oidn_filter_,
"normal",
(void *)d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
}
else {
oidnSetSharedFilterImage(normal_filter_,
"color",
(void *)d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
set_filter_pass(oidn_filter_,
"normal",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnSetSharedFilterImage(normal_filter_,
"output",
(void *)d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
if (params_.prefilter == DENOISER_PREFILTER_ACCURATE) {
set_filter_pass(normal_filter_,
"normal",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnCommitFilter(normal_filter_);
oidnExecuteFilterAsync(normal_filter_);
set_filter_pass(normal_filter_,
"output",
d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnSetSharedFilterImage(oidn_filter_,
"normal",
(void *)d_guiding_buffer,
OIDN_FORMAT_FLOAT3,
context.buffer_params.width,
context.buffer_params.height,
context.guiding_params.pass_normal * sizeof(float),
pixel_stride_in_bytes,
row_stride_in_bytes);
if (!commit_and_execute_filter(normal_filter_, ExecMode::ASYNC)) {
return false;
}
}
}
}
oidnCommitFilter(oidn_filter_);
oidnExecuteFilter(oidn_filter_);
oidnSetFilterInt(oidn_filter_, "cleanAux", params_.prefilter != DENOISER_PREFILTER_FAST);
return commit_and_execute_filter(oidn_filter_);
}
const char *out_message = nullptr;
OIDNError err = oidnGetDeviceError(oidn_device_, (const char **)&out_message);
if (OIDN_ERROR_NONE != err) {
/* If OIDN runs out of memory, reduce mem limit and retry */
while (err == OIDN_ERROR_OUT_OF_MEMORY && max_mem_ > 200) {
max_mem_ = max_mem_ / 2;
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
oidnCommitFilter(oidn_filter_);
oidnExecuteFilter(oidn_filter_);
err = oidnGetDeviceError(oidn_device_, &out_message);
}
if (out_message) {
LOG(ERROR) << "OIDN error: " << out_message;
denoiser_device_->set_error(out_message);
}
else {
LOG(ERROR) << "OIDN error: unspecified";
denoiser_device_->set_error("Unspecified OIDN error");
}
return false;
void OIDNDenoiserGPU::set_filter_pass(OIDNFilter filter,
const char *name,
device_ptr ptr,
int format,
int width,
int height,
size_t offset_in_bytes,
size_t pixel_stride_in_bytes,
size_t row_stride_in_bytes)
{
# if defined(OIDN_DEVICE_METAL) && defined(WITH_METAL)
if (denoiser_device_->info.type == DEVICE_METAL) {
void *mtl_buffer = denoiser_device_->get_native_buffer(ptr);
OIDNBuffer oidn_buffer = oidnNewSharedBufferFromMetal(oidn_device_, mtl_buffer);
oidnSetFilterImage(filter,
name,
oidn_buffer,
(OIDNFormat)format,
width,
height,
offset_in_bytes,
pixel_stride_in_bytes,
row_stride_in_bytes);
oidnReleaseBuffer(oidn_buffer);
}
else
# endif
{
oidnSetSharedFilterImage(filter,
name,
(void *)ptr,
(OIDNFormat)format,
width,
height,
offset_in_bytes,
pixel_stride_in_bytes,
row_stride_in_bytes);
}
return true;
}
CCL_NAMESPACE_END

View File

@ -36,6 +36,11 @@ class OIDNDenoiserGPU : public DenoiserGPU {
static bool is_device_supported(const DeviceInfo &device);
protected:
enum class ExecMode {
SYNC,
ASYNC,
};
virtual uint get_device_type_mask() const override;
/* Create OIDN denoiser descriptor if needed.
@ -50,6 +55,17 @@ class OIDNDenoiserGPU : public DenoiserGPU {
virtual bool denoise_run(const DenoiseContext &context, const DenoisePass &pass) override;
OIDNFilter create_filter();
bool commit_and_execute_filter(OIDNFilter filter, ExecMode mode = ExecMode::SYNC);
void set_filter_pass(OIDNFilter filter,
const char *name,
device_ptr ptr,
int format,
int width,
int height,
size_t offset_in_bytes,
size_t pixel_stride_in_bytes,
size_t row_stride_in_bytes);
OIDNDevice oidn_device_ = nullptr;
OIDNFilter oidn_filter_ = nullptr;
@ -61,8 +77,10 @@ class OIDNDenoiserGPU : public DenoiserGPU {
bool use_pass_albedo_ = false;
bool use_pass_normal_ = false;
DenoiserQuality quality_ = DENOISER_QUALITY_HIGH;
int max_mem_ = 3000;
/* Filter memory usage limit if we ran out of memory with OIDN's default limit. */
int max_mem_ = 768;
};
CCL_NAMESPACE_END

View File

@ -69,6 +69,10 @@ class PassAccessor {
* Allows to get pixels of render buffer into a partial slice of the destination. */
int offset = 0;
/* Offset in floats from the beginning of pixels storage.
* Is ignored for half4 destination. */
int pixel_offset = 0;
/* Number of floats per pixel. When zero is the same as `num_components`.
*
* NOTE: Is ignored for half4 destination, as the half4 pixels are always 4-component

View File

@ -47,7 +47,7 @@ inline void PassAccessorCPU::run_get_pass_kernel_processor_float(
parallel_for(0, buffer_params.window_height, [&](int64_t y) {
const float *buffer = window_data + y * buffer_row_stride;
float *pixel = destination.pixels +
float *pixel = destination.pixels + destination.pixel_offset +
(y * buffer_params.width + destination.offset) * pixel_stride;
func(kfilm_convert, buffer, pixel, buffer_params.window_width, pass_stride, pixel_stride);
});

View File

@ -48,6 +48,7 @@ void PassAccessorGPU::run_film_convert_kernels(DeviceKernel kernel,
&buffer_params.window_width,
&offset,
&buffer_params.stride,
&destination.pixel_offset,
&destination.offset,
&destination_stride);

View File

@ -809,6 +809,7 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb
int width, \
int offset, \
int stride, \
int channel_offset, \
int rgba_offset, \
int rgba_stride) \
{ \
@ -824,7 +825,7 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb
ccl_global const float *buffer = render_buffer + offset + \
buffer_pixel_index * kfilm_convert.pass_stride; \
\
ccl_global float *pixel = pixels + \
ccl_global float *pixel = pixels + channel_offset + \
(render_pixel_index + rgba_offset) * kfilm_convert.pixel_stride; \
\
FILM_GET_PASS_PIXEL_F32(variant, input_channel_count); \

View File

@ -136,6 +136,10 @@ NODE_DEFINE(Integrator)
denoiser_prefilter_enum.insert("fast", DENOISER_PREFILTER_FAST);
denoiser_prefilter_enum.insert("accurate", DENOISER_PREFILTER_ACCURATE);
static NodeEnum denoiser_quality_enum;
denoiser_quality_enum.insert("high", DENOISER_QUALITY_HIGH);
denoiser_quality_enum.insert("balanced", DENOISER_QUALITY_BALANCED);
/* Default to accurate denoising with OpenImageDenoise. For interactive viewport
* it's best use OptiX and disable the normal pass since it does not always have
* the desired effect for that denoiser. */
@ -148,6 +152,8 @@ NODE_DEFINE(Integrator)
"Denoiser Prefilter",
denoiser_prefilter_enum,
DENOISER_PREFILTER_ACCURATE);
SOCKET_BOOLEAN(denoise_use_gpu, "Denoise on GPU", true);
SOCKET_ENUM(denoiser_quality, "Denoiser Quality", denoiser_quality_enum, DENOISER_QUALITY_HIGH);
return type;
}
@ -393,12 +399,15 @@ DenoiseParams Integrator::get_denoise_params() const
denoise_params.type = denoiser_type;
denoise_params.use_gpu = denoise_use_gpu;
denoise_params.start_sample = denoise_start_sample;
denoise_params.use_pass_albedo = use_denoise_pass_albedo;
denoise_params.use_pass_normal = use_denoise_pass_normal;
denoise_params.prefilter = denoiser_prefilter;
denoise_params.quality = denoiser_quality;
return denoise_params;
}

View File

@ -98,6 +98,8 @@ class Integrator : public Node {
NODE_SOCKET_API(bool, use_denoise_pass_albedo);
NODE_SOCKET_API(bool, use_denoise_pass_normal);
NODE_SOCKET_API(DenoiserPrefilter, denoiser_prefilter);
NODE_SOCKET_API(bool, denoise_use_gpu);
NODE_SOCKET_API(DenoiserQuality, denoiser_quality);
enum : uint32_t {
AO_PASS_MODIFIED = (1 << 0),

View File

@ -8,9 +8,13 @@ echo by dragging them into the text area of your bug report, please include both
echo blender_debug_output.txt and blender_system_info.txt in your report.
echo.
pause
mkdir "%temp%\blender\debug_logs" > NUL 2>&1
echo.
echo Starting blender and waiting for it to exit....
setlocal
set PYTHONPATH=
"%~dp0\blender" --debug --debug-gpu --debug-cycles --python-expr "import bpy; bpy.ops.wm.sysinfo(filepath=r'%temp%\blender\debug_logs\blender_system_info.txt')" > "%temp%\blender\debug_logs\blender_debug_output.txt" 2>&1 < %0
explorer "%temp%\blender\debug_logs"
set DEBUGLOGS="%temp%\blender\debug_logs"
mkdir "%DEBUGLOGS%" > NUL 2>&1
"%~dp0\blender" --debug --debug-gpu --debug-cycles --python-expr "import bpy; bpy.context.preferences.filepaths.temporary_directory=r'%DEBUGLOGS%'; bpy.ops.wm.sysinfo(filepath=r'%DEBUGLOGS%\blender_system_info.txt')" > "%DEBUGLOGS%\blender_debug_output.txt" 2>&1 < %0
explorer "%DEBUGLOGS%"

View File

@ -8,9 +8,13 @@ echo by dragging them into the text area of your bug report, please include both
echo blender_debug_output.txt and blender_system_info.txt in your report.
echo.
pause
mkdir "%temp%\blender\debug_logs" > NUL 2>&1
echo.
echo Starting blender and waiting for it to exit....
setlocal
set PYTHONPATH=
"%~dp0\blender" --debug --debug-gpu --debug-gpu-force-workarounds --python-expr "import bpy; bpy.ops.wm.sysinfo(filepath=r'%temp%\blender\debug_logs\blender_system_info.txt')" > "%temp%\blender\debug_logs\blender_debug_output.txt" 2>&1 < %0
explorer "%temp%\blender\debug_logs"
set DEBUGLOGS="%temp%\blender\debug_logs"
mkdir "%DEBUGLOGS%" > NUL 2>&1
"%~dp0\blender" --debug --debug-gpu --debug-gpu-force-workarounds --python-expr "import bpy; bpy.context.preferences.filepaths.temporary_directory=r'%DEBUGLOGS%'; bpy.ops.wm.sysinfo(filepath=r'%DEBUGLOGS%\blender_system_info.txt')" > "%DEBUGLOGS%\blender_debug_output.txt" 2>&1 < %0
explorer "%DEBUGLOGS%"

View File

@ -8,9 +8,13 @@ echo by dragging them into the text area of your bug report, please include both
echo blender_debug_output.txt and blender_system_info.txt in your report.
echo.
pause
mkdir "%temp%\blender\debug_logs" > NUL 2>&1
echo.
echo Starting blender and waiting for it to exit....
setlocal
set PYTHONPATH=
"%~dp0\blender" --debug --debug-cycles --python-expr "import bpy; bpy.ops.wm.sysinfo(filepath=r'%temp%\blender\debug_logs\blender_system_info.txt')" > "%temp%\blender\debug_logs\blender_debug_output.txt" 2>&1 < %0
explorer "%temp%\blender\debug_logs"
set DEBUGLOGS="%temp%\blender\debug_logs"
mkdir "%DEBUGLOGS%" > NUL 2>&1
"%~dp0\blender" --debug --debug-cycles --python-expr "import bpy; bpy.context.preferences.filepaths.temporary_directory=r'%DEBUGLOGS%'; bpy.ops.wm.sysinfo(filepath=r'%DEBUGLOGS%\blender_system_info.txt')" > "%DEBUGLOGS%\blender_debug_output.txt" 2>&1 < %0
explorer "%DEBUGLOGS%"

View File

@ -8,9 +8,13 @@ echo by dragging them into the text area of your bug report, please include both
echo blender_debug_output.txt and blender_system_info.txt in your report.
echo.
pause
mkdir "%temp%\blender\debug_logs" > NUL 2>&1
echo.
echo Starting blender and waiting for it to exit....
setlocal
set PYTHONPATH=
"%~dp0\blender" --factory-startup --python-expr "import bpy; bpy.ops.wm.sysinfo(filepath=r'%temp%\blender\debug_logs\blender_system_info.txt')" > "%temp%\blender\debug_logs\blender_debug_output.txt" 2>&1
explorer "%temp%\blender\debug_logs"
set DEBUGLOGS="%temp%\blender\debug_logs"
mkdir "%DEBUGLOGS%" > NUL 2>&1
"%~dp0\blender" --factory-startup --python-expr "import bpy; bpy.context.preferences.filepaths.temporary_directory=r'%DEBUGLOGS%'; bpy.ops.wm.sysinfo(filepath=r'%DEBUGLOGS%\blender_system_info.txt')" > "%DEBUGLOGS%\blender_debug_output.txt" 2>&1 < %0
explorer "%DEBUGLOGS%"

View File

@ -11,6 +11,7 @@ import os
import re
import sys
import glob
from pathlib import PurePath
# XXX Relative import does not work here when used from Blender...
from bl_i18n_utils import settings as settings_i18n, utils
@ -575,6 +576,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
("pgettext_tip", ("tip_",)),
("pgettext_rpt", ("rpt_",)),
("pgettext_data", ("data_",)),
("poll_message_set", ()),
)
pgettext_variants_args = {"msgid": (0, {"msgctxt": 1})}
@ -664,6 +666,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
root_node = ast.parse(filedata.read(), fp, 'exec')
fp_rel = make_rel(fp)
fp_rel = PurePath(fp_rel).as_posix()
for node in ast.walk(root_node):
if type(node) == ast.Call:

View File

@ -15,6 +15,7 @@ from bl_i18n_utils import (
settings,
utils_rtl,
)
from typing import Dict
##### Misc Utils #####
@ -737,6 +738,7 @@ class I18nMessages:
self._reverse_cache = None
if rebuild_now:
src_to_msg, ctxt_to_msg, msgid_to_msg, msgstr_to_msg = {}, {}, {}, {}
ctxt_to_msg.setdefault(self.settings.DEFAULT_CONTEXT, set())
for key, msg in self.msgs.items():
if msg.is_commented:
continue
@ -799,7 +801,7 @@ class I18nMessages:
rlbl = getattr(msgs, msgmap["rna_label"]["msgstr"])
# print("rna label: " + rlbl, rlbl in msgid_to_msg, rlbl in msgstr_to_msg)
if rlbl:
k = ctxt_to_msg[rna_ctxt].copy()
k = ctxt_to_msg.get(rna_ctxt, set()).copy()
if k and rlbl in msgid_to_msg:
k &= msgid_to_msg[rlbl]
elif k and rlbl in msgstr_to_msg:
@ -1253,7 +1255,7 @@ class I18n:
def __init__(self, kind=None, src=None, langs=set(), settings=settings):
self.settings = settings
self.trans = {}
self.trans: Dict[str, I18nMessages] = {}
self.src = {} # Should have the same keys as self.trans (plus PARSER_PY_ID for py file)!
self.dst = self._dst # A callable that transforms src_path into dst_path!
if kind and src:
@ -1485,6 +1487,7 @@ class I18n:
if langs:
translations &= langs
translations = [('"' + lng + '"', " " * (len(lng) + 6), self.trans[lng]) for lng in sorted(translations)]
print("Translated keys saved to .py file:")
print(*(k for k in keys.keys()))
for key in keys.keys():
if ref.msgs[key].is_commented:

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2019-2023 Blender Authors
# SPDX-FileCopyrightText: 2019-2024 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
@ -73,6 +73,7 @@ url_manual_mapping = (
("bpy.ops.object.simulation_nodes_cache_calculate_to_frame*", "physics/simulation_nodes.html#bpy-ops-object-simulation-nodes-cache-calculate-to-frame"),
("bpy.types.brushcurvessculptsettings.density_add_attempts*", "sculpt_paint/curves_sculpting/tools/density_curves.html#bpy-types-brushcurvessculptsettings-density-add-attempts"),
("bpy.types.brushgpencilsettings.use_random_press_strength*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-random-press-strength"),
("bpy.types.cyclesmaterialsettings.use_bump_map_correction*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-use-bump-map-correction"),
("bpy.types.fluiddomainsettings.use_collision_border_front*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-collision-border-front"),
("bpy.types.fluiddomainsettings.use_collision_border_right*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-collision-border-right"),
("bpy.types.lineartgpencilmodifier.shadow_region_filtering*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-shadow-region-filtering"),
@ -94,6 +95,7 @@ url_manual_mapping = (
("bpy.types.fluiddomainsettings.use_collision_border_left*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-collision-border-left"),
("bpy.types.lineartgpencilmodifier.use_intersection_match*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-intersection-match"),
("bpy.types.rendersettings_simplify_gpencil_view_modifier*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-view-modifier"),
("bpy.types.sequencertimelineoverlay.show_strip_tag_color*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-strip-tag-color"),
("bpy.types.spaceoutliner.use_filter_object_grease_pencil*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-filter-object-grease-pencil"),
("bpy.types.brushcurvessculptsettings.interpolate_length*", "sculpt_paint/curves_sculpting/tools/add_curves.html#bpy-types-brushcurvessculptsettings-interpolate-length"),
("bpy.types.brushgpencilsettings.eraser_thickness_factor*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-eraser-thickness-factor"),
@ -243,6 +245,7 @@ url_manual_mapping = (
("bpy.types.linestylegeometrymodifier_simplification*", "render/freestyle/view_layer/line_style/modifiers/geometry/simplification.html#bpy-types-linestylegeometrymodifier-simplification"),
("bpy.types.materialgpencilstyle.use_overlap_strokes*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-use-overlap-strokes"),
("bpy.types.movietrackingtrack.use_grayscale_preview*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-use-grayscale-preview"),
("bpy.types.nodetreeinterfacesocket.hide_in_modifier*", "interface/controls/nodes/groups.html#bpy-types-nodetreeinterfacesocket-hide-in-modifier"),
("bpy.types.sequencertimelineoverlay.show_strip_name*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-strip-name"),
("bpy.types.sequencertimelineoverlay.show_thumbnails*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-thumbnails"),
("bpy.types.spacespreadsheet.geometry_component_type*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-geometry-component-type"),
@ -259,6 +262,7 @@ url_manual_mapping = (
("bpy.types.clothsettings.compression_stiffness_max*", "physics/cloth/settings/property_weights.html#bpy-types-clothsettings-compression-stiffness-max"),
("bpy.types.colormanagedsequencercolorspacesettings*", "render/color_management.html#bpy-types-colormanagedsequencercolorspacesettings"),
("bpy.types.colormanagedviewsettings.view_transform*", "render/color_management.html#bpy-types-colormanagedviewsettings-view-transform"),
("bpy.types.compositornodetree.use_groupnode_buffer*", "compositing/sidebar.html#bpy-types-compositornodetree-use-groupnode-buffer"),
("bpy.types.cyclesmaterialsettings.volume_step_rate*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-volume-step-rate"),
("bpy.types.cyclesobjectsettings.is_caustics_caster*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-is-caustics-caster"),
("bpy.types.cyclesrendersettings.adaptive_threshold*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-adaptive-threshold"),
@ -287,6 +291,7 @@ url_manual_mapping = (
("bpy.types.movietrackingplanetrack.use_auto_keying*", "movie_clip/tracking/clip/sidebar/track/plane_track.html#bpy-types-movietrackingplanetrack-use-auto-keying"),
("bpy.types.movietrackingsettings.use_tripod_solver*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingsettings-use-tripod-solver"),
("bpy.types.nodesmodifier.simulation_bake_directory*", "modeling/modifiers/generate/geometry_nodes.html#bpy-types-nodesmodifier-simulation-bake-directory"),
("bpy.types.nodetreeinterfacesocket.force_non_field*", "interface/controls/nodes/groups.html#bpy-types-nodetreeinterfacesocket-force-non-field"),
("bpy.types.rendersettings.simplify_child_particles*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-child-particles"),
("bpy.types.rendersettings.use_high_quality_normals*", "render/eevee/render_settings/performance.html#bpy-types-rendersettings-use-high-quality-normals"),
("bpy.types.sculpt.automasking_start_normal_falloff*", "sculpt_paint/sculpting/controls.html#bpy-types-sculpt-automasking-start-normal-falloff"),
@ -337,6 +342,7 @@ url_manual_mapping = (
("bpy.types.linestylethicknessmodifier_calligraphy*", "render/freestyle/view_layer/line_style/modifiers/thickness/calligraphy.html#bpy-types-linestylethicknessmodifier-calligraphy"),
("bpy.types.materiallineart.use_material_mask_bits*", "render/materials/line_art.html#bpy-types-materiallineart-use-material-mask-bits"),
("bpy.types.movietrackingdopesheet.use_invert_sort*", "movie_clip/tracking/dope_sheet.html#bpy-types-movietrackingdopesheet-use-invert-sort"),
("bpy.types.nodetreeinterfacesocket*.default_value*", "interface/controls/nodes/groups.html#bpy-types-nodetreeinterfacesocket-default-value"),
("bpy.types.rendersettings_simplify_gpencil_onplay*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-onplay"),
("bpy.types.rigidbodyconstraint.breaking_threshold*", "physics/rigid_body/constraints/introduction.html#bpy-types-rigidbodyconstraint-breaking-threshold"),
("bpy.types.sculpt.use_automasking_cavity_inverted*", "sculpt_paint/sculpting/controls.html#bpy-types-sculpt-use-automasking-cavity-inverted"),
@ -428,6 +434,7 @@ url_manual_mapping = (
("bpy.types.clothcollisionsettings.use_collision*", "physics/cloth/settings/collisions.html#bpy-types-clothcollisionsettings-use-collision"),
("bpy.types.clothsettings.uniform_pressure_force*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-uniform-pressure-force"),
("bpy.types.collection.lineart_intersection_mask*", "scene_layout/collections/collections.html#bpy-types-collection-lineart-intersection-mask"),
("bpy.types.compositornodetree.use_viewer_border*", "compositing/sidebar.html#bpy-types-compositornodetree-use-viewer-border"),
("bpy.types.cyclesobjectsettings.use_camera_cull*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-use-camera-cull"),
("bpy.types.cyclesobjectsettings.use_motion_blur*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-use-motion-blur"),
("bpy.types.cyclesrendersettings.diffuse_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-diffuse-bounces"),
@ -459,7 +466,6 @@ url_manual_mapping = (
("bpy.types.movietrackingcamera.distortion_model*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-distortion-model"),
("bpy.types.movietrackingtrack.use_alpha_preview*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-use-alpha-preview"),
("bpy.types.movietrackingtrack.use_green_channel*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-use-green-channel"),
("bpy.types.nodesocketinterface.hide_in_modifier*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-hide-in-modifier"),
("bpy.types.rendersettings.resolution_percentage*", "render/output/properties/format.html#bpy-types-rendersettings-resolution-percentage"),
("bpy.types.rendersettings_simplify_gpencil_tint*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-tint"),
("bpy.types.softbodysettings.use_estimate_matrix*", "physics/soft_body/settings/solver.html#bpy-types-softbodysettings-use-estimate-matrix"),
@ -490,7 +496,6 @@ url_manual_mapping = (
("bpy.types.clothsettings.compression_stiffness*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-compression-stiffness"),
("bpy.types.clothsettings.tension_stiffness_max*", "physics/cloth/settings/property_weights.html#bpy-types-clothsettings-tension-stiffness-max"),
("bpy.types.clothsettings.vertex_group_pressure*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-pressure"),
("bpy.types.cyclesmaterialsettings.displacement*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-displacement"),
("bpy.types.cyclesrendersettings.fast_gi_method*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-fast-gi-method"),
("bpy.types.cyclesrendersettings.glossy_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-glossy-bounces"),
("bpy.types.cyclesrendersettings.use_light_tree*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-use-light-tree"),
@ -512,7 +517,7 @@ url_manual_mapping = (
("bpy.types.fluiddomainsettings.particle_radius*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-particle-radius"),
("bpy.types.fluiddomainsettings.slice_per_voxel*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-slice-per-voxel"),
("bpy.types.fluiddomainsettings.surface_tension*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-surface-tension"),
("bpy.types.fluiddomainsettings.viscosity_value*", "physics/fluid/type/domain/liquid/viscosity.html#bpy-types-fluiddomainsettings-viscosity-value"),
("bpy.types.fluiddomainsettings.viscosity_value*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-viscosity-value"),
("bpy.types.fluideffectorsettings.effector_type*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings-effector-type"),
("bpy.types.fluidflowsettings.use_particle_size*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-particle-size"),
("bpy.types.freestylelineset.face_mark_negation*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-face-mark-negation"),
@ -526,10 +531,12 @@ url_manual_mapping = (
("bpy.types.materialgpencilstyle.alignment_mode*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-alignment-mode"),
("bpy.types.movietrackingtrack.use_blue_channel*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-use-blue-channel"),
("bpy.types.movietrackingtrack.use_custom_color*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-use-custom-color"),
("bpy.types.nodetreeinterfacesocket.description*", "interface/controls/nodes/groups.html#bpy-types-nodetreeinterfacesocket-description"),
("bpy.types.objectlineart.intersection_priority*", "scene_layout/object/properties/line_art.html#bpy-types-objectlineart-intersection-priority"),
("bpy.types.particlesettings.use_modifier_stack*", "physics/particles/emitter/emission.html#bpy-types-particlesettings-use-modifier-stack"),
("bpy.types.rendersettings.sequencer_gl_preview*", "editors/video_sequencer/preview/sidebar.html#bpy-types-rendersettings-sequencer-gl-preview"),
("bpy.types.rendersettings.simplify_subdivision*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-subdivision"),
("bpy.types.rendersettings.use_simplify_normals*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-use-simplify-normals"),
("bpy.types.sculpt.use_automasking_start_normal*", "sculpt_paint/sculpting/controls.html#bpy-types-sculpt-use-automasking-start-normal"),
("bpy.types.sequencerpreviewoverlay.show_cursor*", "editors/video_sequencer/preview/display/overlays.html#bpy-types-sequencerpreviewoverlay-show-cursor"),
("bpy.types.softbodysettings.use_edge_collision*", "physics/soft_body/settings/edges.html#bpy-types-softbodysettings-use-edge-collision"),
@ -606,7 +613,9 @@ url_manual_mapping = (
("bpy.types.moviesequence.animation_offset_end*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-moviesequence-animation-offset-end"),
("bpy.types.movietrackingdopesheet.sort_method*", "movie_clip/tracking/dope_sheet.html#bpy-types-movietrackingdopesheet-sort-method"),
("bpy.types.movietrackingtrack.use_red_channel*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-use-red-channel"),
("bpy.types.nodesocketinterface*.default_value*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-default-value"),
("bpy.types.nodetreeinterfacesocket*.max_value*", "interface/controls/nodes/groups.html#bpy-types-nodetreeinterfacesocket-max-value"),
("bpy.types.nodetreeinterfacesocket*.min_value*", "interface/controls/nodes/groups.html#bpy-types-nodetreeinterfacesocket-min-value"),
("bpy.types.nodetreeinterfacesocket.hide_value*", "interface/controls/nodes/groups.html#bpy-types-nodetreeinterfacesocket-hide-value"),
("bpy.types.object.add_rest_position_attribute*", "animation/shape_keys/shape_keys_panel.html#bpy-types-object-add-rest-position-attribute"),
("bpy.types.rendersettings.line_thickness_mode*", "render/freestyle/render.html#bpy-types-rendersettings-line-thickness-mode"),
("bpy.types.rendersettings.motion_blur_shutter*", "render/cycles/render_settings/motion_blur.html#bpy-types-rendersettings-motion-blur-shutter"),
@ -646,6 +655,7 @@ url_manual_mapping = (
("bpy.types.clothsettings.vertex_group_intern*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-intern"),
("bpy.types.clothsettings.vertex_group_shrink*", "physics/cloth/settings/property_weights.html#bpy-types-clothsettings-vertex-group-shrink"),
("bpy.types.colormanagedviewsettings.exposure*", "render/color_management.html#bpy-types-colormanagedviewsettings-exposure"),
("bpy.types.compositornodetree.render_quality*", "compositing/sidebar.html#bpy-types-compositornodetree-render-quality"),
("bpy.types.cyclesobjectsettings.motion_steps*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-motion-steps"),
("bpy.types.cyclesrendersettings.filter_width*", "render/cycles/render_settings/film.html#bpy-types-cyclesrendersettings-filter-width"),
("bpy.types.fluiddomainsettings.cfl_condition*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-cfl-condition"),
@ -654,7 +664,7 @@ url_manual_mapping = (
("bpy.types.fluiddomainsettings.timesteps_min*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-timesteps-min"),
("bpy.types.fluiddomainsettings.use_diffusion*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-use-diffusion"),
("bpy.types.fluiddomainsettings.use_fractions*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-use-fractions"),
("bpy.types.fluiddomainsettings.use_viscosity*", "physics/fluid/type/domain/liquid/viscosity.html#bpy-types-fluiddomainsettings-use-viscosity"),
("bpy.types.fluiddomainsettings.use_viscosity*", "physics/fluid/type/domain/liquid/diffusion.html#bpy-types-fluiddomainsettings-use-viscosity"),
("bpy.types.fluidflowsettings.particle_system*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-particle-system"),
("bpy.types.fluidflowsettings.velocity_factor*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-velocity-factor"),
("bpy.types.fluidflowsettings.velocity_normal*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-velocity-normal"),
@ -677,6 +687,7 @@ url_manual_mapping = (
("bpy.types.rendersettings.preview_pixel_size*", "render/cycles/render_settings/performance.html#bpy-types-rendersettings-preview-pixel-size"),
("bpy.types.rendersettings.use_crop_to_border*", "render/output/properties/format.html#bpy-types-rendersettings-use-crop-to-border"),
("bpy.types.rendersettings.use_file_extension*", "render/output/properties/output.html#bpy-types-rendersettings-use-file-extension"),
("bpy.types.scene.use_custom_simulation_range*", "scene_layout/scene/properties.html#bpy-types-scene-use-custom-simulation-range"),
("bpy.types.sculpt.constant_detail_resolution*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-constant-detail-resolution"),
("bpy.types.sequencemodifier.input_mask_strip*", "editors/video_sequencer/sequencer/sidebar/modifiers.html#bpy-types-sequencemodifier-input-mask-strip"),
("bpy.types.sequencertoolsettings.pivot_point*", "editors/video_sequencer/preview/controls/pivot_point.html#bpy-types-sequencertoolsettings-pivot-point"),
@ -725,6 +736,7 @@ url_manual_mapping = (
("bpy.types.cyclesrendersettings.max_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-max-bounces"),
("bpy.types.cyclesrendersettings.use_fast_gi*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-use-fast-gi"),
("bpy.types.cyclesrendersettings.use_guiding*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-use-guiding"),
("bpy.types.drivervariable.type.context_prop*", "animation/drivers/drivers_panel.html#bpy-types-drivervariable-type-context-prop"),
("bpy.types.editbone.bbone_custom_handle_end*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-custom-handle-end"),
("bpy.types.editbone.bbone_handle_type_start*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-handle-type-start"),
("bpy.types.fieldsettings.guide_clump_amount*", "physics/forces/force_fields/types/curve_guide.html#bpy-types-fieldsettings-guide-clump-amount"),
@ -792,7 +804,6 @@ url_manual_mapping = (
("bpy.ops.outliner.collection_exclude_clear*", "editors/outliner/editing.html#bpy-ops-outliner-collection-exclude-clear"),
("bpy.ops.outliner.collection_holdout_clear*", "render/layers/introduction.html#bpy-ops-outliner-collection-holdout-clear"),
("bpy.ops.sculpt.face_set_change_visibility*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-face-set-change-visibility"),
("bpy.ops.sculpt.face_set_invert_visibility*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-set-invert-visibility"),
("bpy.ops.sculpt.face_sets_randomize_colors*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-sets-randomize-colors"),
("bpy.ops.sequencer.retiming_transition_add*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-retiming-transition-add"),
("bpy.types.animvizmotionpaths.frame_before*", "animation/motion_paths.html#bpy-types-animvizmotionpaths-frame-before"),
@ -806,6 +817,8 @@ url_manual_mapping = (
("bpy.types.clothsettings.tension_stiffness*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-tension-stiffness"),
("bpy.types.clothsettings.vertex_group_mass*", "physics/cloth/settings/shape.html#bpy-types-clothsettings-vertex-group-mass"),
("bpy.types.compositornodeconvertcolorspace*", "compositing/types/color/convert_colorspace.html#bpy-types-compositornodeconvertcolorspace"),
("bpy.types.compositornodetree.edit_quality*", "compositing/sidebar.html#bpy-types-compositornodetree-edit-quality"),
("bpy.types.compositornodetree.use_two_pass*", "compositing/sidebar.html#bpy-types-compositornodetree-use-two-pass"),
("bpy.types.cyclescurverendersettings.shape*", "render/cycles/render_settings/hair.html#bpy-types-cyclescurverendersettings-shape"),
("bpy.types.cycleslightsettings.cast_shadow*", "render/cycles/light_settings.html#bpy-types-cycleslightsettings-cast-shadow"),
("bpy.types.cycleslightsettings.max_bounces*", "render/cycles/light_settings.html#bpy-types-cycleslightsettings-max-bounces"),
@ -850,7 +863,6 @@ url_manual_mapping = (
("bpy.types.materialgpencilstyle.fill_style*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-fill-style"),
("bpy.types.materialgpencilstyle.mix_factor*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-mix-factor"),
("bpy.types.materialgpencilstyle.pass_index*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-pass-index"),
("bpy.types.nodesocketinterface.description*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-description"),
("bpy.types.rendersettings.dither_intensity*", "render/output/properties/post_processing.html#bpy-types-rendersettings-dither-intensity"),
("bpy.types.rendersettings.film_transparent*", "render/cycles/render_settings/film.html#bpy-types-rendersettings-film-transparent"),
("bpy.types.rendersettings.simplify_volumes*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-volumes"),
@ -864,6 +876,7 @@ url_manual_mapping = (
("bpy.types.spacefilebrowser.recent_folders*", "editors/file_browser.html#bpy-types-spacefilebrowser-recent-folders"),
("bpy.types.spacefilebrowser.system_folders*", "editors/file_browser.html#bpy-types-spacefilebrowser-system-folders"),
("bpy.types.spacenodeeditor.show_annotation*", "interface/controls/nodes/introduction.html#bpy-types-spacenodeeditor-show-annotation"),
("bpy.types.spacenodeeditor.use_auto_render*", "compositing/sidebar.html#bpy-types-spacenodeeditor-use-auto-render"),
("bpy.types.spaceoutliner.use_filter_object*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-filter-object"),
("bpy.types.spacesequenceeditor.use_proxies*", "editors/video_sequencer/preview/sidebar.html#bpy-types-spacesequenceeditor-use-proxies"),
("bpy.types.spaceuveditor.edge_display_type*", "editors/uv/overlays.html#bpy-types-spaceuveditor-edge-display-type"),
@ -952,9 +965,6 @@ url_manual_mapping = (
("bpy.types.movietrackingobject.keyframe_a*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingobject-keyframe-a"),
("bpy.types.movietrackingobject.keyframe_b*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingobject-keyframe-b"),
("bpy.types.movietrackingtrack.weight_stab*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-weight-stab"),
("bpy.types.nodesocketinterface*.max_value*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-max-value"),
("bpy.types.nodesocketinterface*.min_value*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-min-value"),
("bpy.types.nodesocketinterface.hide_value*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-hide-value"),
("bpy.types.object.use_shape_key_edit_mode*", "animation/shape_keys/shape_keys_panel.html#bpy-types-object-use-shape-key-edit-mode"),
("bpy.types.objectlineart.crease_threshold*", "scene_layout/object/properties/line_art.html#bpy-types-objectlineart-crease-threshold"),
("bpy.types.rendersettings.use_compositing*", "render/output/properties/post_processing.html#bpy-types-rendersettings-use-compositing"),
@ -1012,6 +1022,8 @@ url_manual_mapping = (
("bpy.types.colormanagedviewsettings.look*", "render/color_management.html#bpy-types-colormanagedviewsettings-look"),
("bpy.types.compositornodecolorcorrection*", "compositing/types/color/adjust/color_correction.html#bpy-types-compositornodecolorcorrection"),
("bpy.types.compositornodemoviedistortion*", "compositing/types/transform/movie_distortion.html#bpy-types-compositornodemoviedistortion"),
("bpy.types.compositornodetree.chunk_size*", "compositing/sidebar.html#bpy-types-compositornodetree-chunk-size"),
("bpy.types.compositornodetree.use_opencl*", "compositing/sidebar.html#bpy-types-compositornodetree-use-opencl"),
("bpy.types.cyclesrendersettings.caustics*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-caustics"),
("bpy.types.cyclesrendersettings.denoiser*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-denoiser"),
("bpy.types.editbone.use_inherit_rotation*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-use-inherit-rotation"),
@ -1113,6 +1125,7 @@ url_manual_mapping = (
("bpy.types.clothsettings.rest_shape_key*", "physics/cloth/settings/shape.html#bpy-types-clothsettings-rest-shape-key"),
("bpy.types.compositornodebrightcontrast*", "compositing/types/color/adjust/bright_contrast.html#bpy-types-compositornodebrightcontrast"),
("bpy.types.compositornodedoubleedgemask*", "compositing/types/mask/double_edge_mask.html#bpy-types-compositornodedoubleedgemask"),
("bpy.types.compositornodetree.precision*", "compositing/sidebar.html#bpy-types-compositornodetree-precision"),
("bpy.types.cyclesrendersettings.samples*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-samples"),
("bpy.types.dopesheet.show_only_selected*", "editors/dope_sheet/introduction.html#bpy-types-dopesheet-show-only-selected"),
("bpy.types.ffmpegsettings.audio_bitrate*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-bitrate"),
@ -1140,11 +1153,13 @@ url_manual_mapping = (
("bpy.types.geometrynodetoolsetselection*", "modeling/geometry_nodes/geometry/write/set_selection.html#bpy-types-geometrynodetoolsetselection"),
("bpy.types.geometrynodetree.is_modifier*", "editors/geometry_node.html#bpy-types-geometrynodetree-is-modifier"),
("bpy.types.greasepencil.edit_line_color*", "grease_pencil/properties/display.html#bpy-types-greasepencil-edit-line-color"),
("bpy.types.material.displacement_method*", "render/cycles/material_settings.html#bpy-types-material-displacement-method"),
("bpy.types.material.preview_render_type*", "render/materials/preview.html#bpy-types-material-preview-render-type"),
("bpy.types.materialgpencilstyle.pattern*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-pattern"),
("bpy.types.materialgpencilstyle.texture*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-texture"),
("bpy.types.modifier.use_apply_on_spline*", "modeling/modifiers/introduction.html#bpy-types-modifier-use-apply-on-spline"),
("bpy.types.movietrackingplanetrack.name*", "movie_clip/tracking/clip/sidebar/track/plane_track.html#bpy-types-movietrackingplanetrack-name"),
("bpy.types.nodetreeinterfacesocket.name*", "interface/controls/nodes/groups.html#bpy-types-nodetreeinterfacesocket-name"),
("bpy.types.object.use_empty_image_alpha*", "modeling/empties.html#bpy-types-object-use-empty-image-alpha"),
("bpy.types.rendersettings.frame_map_new*", "render/output/properties/frame_range.html#bpy-types-rendersettings-frame-map-new"),
("bpy.types.rendersettings.frame_map_old*", "render/output/properties/frame_range.html#bpy-types-rendersettings-frame-map-old"),
@ -1153,6 +1168,7 @@ url_manual_mapping = (
("bpy.types.rendersettings.use_sequencer*", "render/output/properties/post_processing.html#bpy-types-rendersettings-use-sequencer"),
("bpy.types.sceneeevee.volumetric_shadow*", "render/eevee/render_settings/volumetrics.html#bpy-types-sceneeevee-volumetric-shadow"),
("bpy.types.sequenceeditor.overlay_frame*", "editors/video_sequencer/preview/sidebar.html#bpy-types-sequenceeditor-overlay-frame"),
("bpy.types.sequenceeditor.proxy_storage*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-types-sequenceeditor-proxy-storage"),
("bpy.types.sequencetimelinechannel.lock*", "editors/video_sequencer/sequencer/channels.html#bpy-types-sequencetimelinechannel-lock"),
("bpy.types.sequencetimelinechannel.mute*", "editors/video_sequencer/sequencer/channels.html#bpy-types-sequencetimelinechannel-mute"),
("bpy.types.sequencetimelinechannel.name*", "editors/video_sequencer/sequencer/channels.html#bpy-types-sequencetimelinechannel-name"),
@ -1227,6 +1243,7 @@ url_manual_mapping = (
("bpy.types.compositornodedistancematte*", "compositing/types/keying/distance_key.html#bpy-types-compositornodedistancematte"),
("bpy.types.compositornodeseparatecolor*", "compositing/types/color/mix/separate_color.html#bpy-types-compositornodeseparatecolor"),
("bpy.types.compositornodesetalpha.mode*", "compositing/types/color/set_alpha.html#bpy-types-compositornodesetalpha-mode"),
("bpy.types.compositornodeviewer.center*", "compositing/types/output/viewer.html#bpy-types-compositornodeviewer-center"),
("bpy.types.curves.use_sculpt_collision*", "sculpt_paint/curves_sculpting/introduction.html#bpy-types-curves-use-sculpt-collision"),
("bpy.types.dopesheet.use_filter_invert*", "editors/graph_editor/channels/introduction.html#bpy-types-dopesheet-use-filter-invert"),
("bpy.types.editbone.bbone_mapping_mode*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-mapping-mode"),
@ -1289,6 +1306,7 @@ url_manual_mapping = (
("bpy.types.sequence.show_retiming_keys*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequence-show-retiming-keys"),
("bpy.types.sequenceeditor.show_overlay*", "editors/video_sequencer/preview/sidebar.html#bpy-types-sequenceeditor-show-overlay"),
("bpy.types.sequenceeditor.use_prefetch*", "editors/video_sequencer/preview/sidebar.html#bpy-types-sequenceeditor-use-prefetch"),
("bpy.types.sequenceproxy.use_overwrite*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-types-sequenceproxy-use-overwrite"),
("bpy.types.softbodysettings.ball_stiff*", "physics/soft_body/settings/self_collision.html#bpy-types-softbodysettings-ball-stiff"),
("bpy.types.soundsequence.show_waveform*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-soundsequence-show-waveform"),
("bpy.types.spaceclipeditor.show_stable*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-stable"),
@ -1467,7 +1485,6 @@ url_manual_mapping = (
("bpy.types.compositornodedilateerode*", "compositing/types/filter/dilate_erode.html#bpy-types-compositornodedilateerode"),
("bpy.types.compositornodeellipsemask*", "compositing/types/mask/ellipse_mask.html#bpy-types-compositornodeellipsemask"),
("bpy.types.compositornodeseparatexyz*", "compositing/types/vector/separate_xyz.html#bpy-types-compositornodeseparatexyz"),
("bpy.types.compositornodesplitviewer*", "compositing/types/output/split_viewer.html#bpy-types-compositornodesplitviewer"),
("bpy.types.curve.render_resolution_u*", "modeling/curves/properties/shape.html#bpy-types-curve-render-resolution-u"),
("bpy.types.cyclesrendersettings.seed*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-seed"),
("bpy.types.dynamicpaintbrushsettings*", "physics/dynamic_paint/brush.html#bpy-types-dynamicpaintbrushsettings"),
@ -1580,6 +1597,7 @@ url_manual_mapping = (
("bpy.ops.sculpt.set_persistent_base*", "sculpt_paint/sculpting/tools/layer.html#bpy-ops-sculpt-set-persistent-base"),
("bpy.ops.sequencer.crossfade_sounds*", "video_editing/edit/montage/strips/transitions/sound_crossfade.html#bpy-ops-sequencer-crossfade-sounds"),
("bpy.ops.sequencer.export_subtitles*", "editors/video_sequencer/preview/header.html#bpy-ops-sequencer-export-subtitles"),
("bpy.ops.sequencer.previewrange_set*", "editors/video_sequencer/sequencer/navigating.html#bpy-ops-sequencer-previewrange-set"),
("bpy.ops.sequencer.retiming_key_add*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-retiming-key-add"),
("bpy.ops.text.jump_to_file_at_point*", "editors/text_editor.html#bpy-ops-text-jump-to-file-at-point"),
("bpy.ops.transform.edge_bevelweight*", "modeling/meshes/editing/edge/edge_data.html#bpy-ops-transform-edge-bevelweight"),
@ -1653,13 +1671,13 @@ url_manual_mapping = (
("bpy.types.mesh.use_mirror_topology*", "modeling/meshes/tools/tool_settings.html#bpy-types-mesh-use-mirror-topology"),
("bpy.types.movieclip.display_aspect*", "editors/clip/display/clip_display.html#bpy-types-movieclip-display-aspect"),
("bpy.types.movietrackingtrack.color*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-color"),
("bpy.types.nodesocketinterface.name*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-name"),
("bpy.types.object.is_shadow_catcher*", "render/cycles/object_settings/object_data.html#bpy-types-object-is-shadow-catcher"),
("bpy.types.particleinstancemodifier*", "modeling/modifiers/physics/particle_instance.html#bpy-types-particleinstancemodifier"),
("bpy.types.rendersettings.hair_type*", "render/eevee/render_settings/hair.html#bpy-types-rendersettings-hair-type"),
("bpy.types.rendersettings.tile_size*", "render/cycles/render_settings/performance.html#bpy-types-rendersettings-tile-size"),
("bpy.types.rigidbodyobject.friction*", "physics/rigid_body/properties/collisions.html#bpy-types-rigidbodyobject-friction"),
("bpy.types.scenedisplay.viewport_aa*", "render/workbench/sampling.html#bpy-types-scenedisplay-viewport-aa"),
("bpy.types.sequenceeditor.proxy_dir*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-types-sequenceeditor-proxy-dir"),
("bpy.types.sequencertimelineoverlay*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay"),
("bpy.types.sequencetransform.filter*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequencetransform-filter"),
("bpy.types.sequencetransform.offset*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequencetransform-offset"),
@ -1697,6 +1715,7 @@ url_manual_mapping = (
("bpy.ops.geometry.attribute_remove*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-geometry-attribute-remove"),
("bpy.ops.gpencil.frame_clean_loose*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-frame-clean-loose"),
("bpy.ops.gpencil.selectmode_toggle*", "grease_pencil/selecting.html#bpy-ops-gpencil-selectmode-toggle"),
("bpy.ops.graph.scale_from_neighbor*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-scale-from-neighbor"),
("bpy.ops.mask.feather_weight_clear*", "movie_clip/masking/editing.html#bpy-ops-mask-feather-weight-clear"),
("bpy.ops.mask.primitive_circle_add*", "movie_clip/masking/scurve.html#bpy-ops-mask-primitive-circle-add"),
("bpy.ops.mask.primitive_square_add*", "movie_clip/masking/scurve.html#bpy-ops-mask-primitive-square-add"),
@ -1719,6 +1738,7 @@ url_manual_mapping = (
("bpy.ops.render.play_rendered_anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
("bpy.ops.sculpt.set_pivot_position*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-set-pivot-position"),
("bpy.ops.sculpt.trim_lasso_gesture*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-trim-lasso-gesture"),
("bpy.ops.sculpt_curves.select_ends*", "sculpt_paint/curves_sculpting/introduction.html#bpy-ops-sculpt-curves-select-ends"),
("bpy.ops.sculpt_curves.select_grow*", "sculpt_paint/curves_sculpting/introduction.html#bpy-ops-sculpt-curves-select-grow"),
("bpy.ops.sequencer.image_strip_add*", "video_editing/edit/montage/strips/image.html#bpy-ops-sequencer-image-strip-add"),
("bpy.ops.sequencer.images_separate*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-images-separate"),
@ -1802,6 +1822,7 @@ url_manual_mapping = (
("bpy.types.limitdistanceconstraint*", "animation/constraints/transform/limit_distance.html#bpy-types-limitdistanceconstraint"),
("bpy.types.limitlocationconstraint*", "animation/constraints/transform/limit_location.html#bpy-types-limitlocationconstraint"),
("bpy.types.limitrotationconstraint*", "animation/constraints/transform/limit_rotation.html#bpy-types-limitrotationconstraint"),
("bpy.types.moviesequence.use_proxy*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-types-moviesequence-use-proxy"),
("bpy.types.movietrackingtrack.lock*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-lock"),
("bpy.types.movietrackingtrack.name*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-name"),
("bpy.types.multiplygpencilmodifier*", "grease_pencil/modifiers/generate/multiple_strokes.html#bpy-types-multiplygpencilmodifier"),
@ -1844,6 +1865,7 @@ url_manual_mapping = (
("bpy.ops.gpencil.vertex_color_set*", "grease_pencil/modes/vertex_paint/editing.html#bpy-ops-gpencil-vertex-color-set"),
("bpy.ops.graph.extrapolation_type*", "editors/graph_editor/channels/editing.html#bpy-ops-graph-extrapolation-type"),
("bpy.ops.graph.interpolation_type*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-interpolation-type"),
("bpy.ops.graph.select_key_handles*", "editors/graph_editor/introduction.html#bpy-ops-graph-select-key-handles"),
("bpy.ops.image.match_movie_length*", "editors/image/image_settings.html#bpy-ops-image-match-movie-length"),
("bpy.ops.mesh.customdata_skin_add*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-skin-add"),
("bpy.ops.mesh.dissolve_degenerate*", "modeling/meshes/editing/mesh/cleanup.html#bpy-ops-mesh-dissolve-degenerate"),
@ -1851,6 +1873,7 @@ url_manual_mapping = (
("bpy.ops.mesh.mark_freestyle_face*", "modeling/meshes/editing/face/face_data.html#bpy-ops-mesh-mark-freestyle-face"),
("bpy.ops.mesh.primitive_plane_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-plane-add"),
("bpy.ops.mesh.primitive_torus_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-torus-add"),
("bpy.ops.mesh.select_by_attribute*", "modeling/meshes/selecting/by_attribute.html#bpy-ops-mesh-select-by-attribute"),
("bpy.ops.mesh.select_non_manifold*", "modeling/meshes/selecting/all_by_trait.html#bpy-ops-mesh-select-non-manifold"),
("bpy.ops.nla.selected_objects_add*", "editors/nla/introduction.html#bpy-ops-nla-selected-objects-add"),
("bpy.ops.object.constraints_clear*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-clear"),
@ -1870,14 +1893,15 @@ url_manual_mapping = (
("bpy.ops.scene.view_layer_add_aov*", "render/layers/passes.html#bpy-ops-scene-view-layer-add-aov"),
("bpy.ops.screen.spacedata_cleanup*", "advanced/operators.html#bpy-ops-screen-spacedata-cleanup"),
("bpy.ops.sculpt.detail_flood_fill*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-ops-sculpt-detail-flood-fill"),
("bpy.ops.sculpt_curves.select_end*", "sculpt_paint/curves_sculpting/introduction.html#bpy-ops-sculpt-curves-select-end"),
("bpy.ops.sequencer.duplicate_move*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-duplicate-move"),
("bpy.ops.sequencer.enable_proxies*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-ops-sequencer-enable-proxies"),
("bpy.ops.sequencer.retiming_reset*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-retiming-reset"),
("bpy.ops.sequencer.select_grouped*", "video_editing/edit/montage/selecting.html#bpy-ops-sequencer-select-grouped"),
("bpy.ops.sequencer.select_handles*", "video_editing/edit/montage/selecting.html#bpy-ops-sequencer-select-handles"),
("bpy.ops.ui.copy_data_path_button*", "interface/controls/buttons/menus.html#bpy-ops-ui-copy-data-path-button"),
("bpy.ops.uv.average_islands_scale*", "modeling/meshes/uv/editing.html#bpy-ops-uv-average-islands-scale"),
("bpy.ops.wm.read_factory_settings*", "interface/window_system/topbar.html#bpy-ops-wm-read-factory-settings"),
("bpy.ops.wm.read_factory_userpref*", "editors/preferences/introduction.html#bpy-ops-wm-read-factory-userpref"),
("bpy.types.action.use_frame_range*", "animation/actions.html#bpy-types-action-use-frame-range"),
("bpy.types.armature.axes_position*", "animation/armatures/properties/display.html#bpy-types-armature-axes-position"),
("bpy.types.armature.pose_position*", "animation/armatures/properties/introduction.html#bpy-types-armature-pose-position"),
@ -1934,6 +1958,7 @@ url_manual_mapping = (
("bpy.types.geometrynodeinputimage*", "modeling/geometry_nodes/input/constant/image.html#bpy-types-geometrynodeinputimage"),
("bpy.types.geometrynodeinputindex*", "modeling/geometry_nodes/geometry/read/input_index.html#bpy-types-geometrynodeinputindex"),
("bpy.types.geometrynodeisviewport*", "modeling/geometry_nodes/input/scene/is_viewport.html#bpy-types-geometrynodeisviewport"),
("bpy.types.geometrynodemenuswitch*", "modeling/geometry_nodes/utilities/menu_switch.html#bpy-types-geometrynodemenuswitch"),
("bpy.types.geometrynodemeshcircle*", "modeling/geometry_nodes/mesh/primitives/mesh_circle.html#bpy-types-geometrynodemeshcircle"),
("bpy.types.geometrynodeobjectinfo*", "modeling/geometry_nodes/input/scene/object_info.html#bpy-types-geometrynodeobjectinfo"),
("bpy.types.geometrynodeselfobject*", "modeling/geometry_nodes/input/scene/self_object.html#bpy-types-geometrynodeselfobject"),
@ -1966,6 +1991,7 @@ url_manual_mapping = (
("bpy.types.sceneeevee.motion_blur*", "render/eevee/render_settings/motion_blur.html#bpy-types-sceneeevee-motion-blur"),
("bpy.types.sceneeevee.taa_samples*", "render/eevee/render_settings/sampling.html#bpy-types-sceneeevee-taa-samples"),
("bpy.types.sculpt.radial_symmetry*", "sculpt_paint/sculpting/tool_settings/symmetry.html#bpy-types-sculpt-radial-symmetry"),
("bpy.types.sequenceproxy.timecode*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-types-sequenceproxy-timecode"),
("bpy.types.shadernodecombinecolor*", "render/shader_nodes/converter/combine_color.html#bpy-types-shadernodecombinecolor"),
("bpy.types.shadernodedisplacement*", "render/shader_nodes/vector/displacement.html#bpy-types-shadernodedisplacement"),
("bpy.types.shadernodelightfalloff*", "render/shader_nodes/color/light_falloff.html#bpy-types-shadernodelightfalloff"),
@ -2038,6 +2064,7 @@ url_manual_mapping = (
("bpy.ops.outliner.show_one_level*", "editors/outliner/editing.html#bpy-ops-outliner-show-one-level"),
("bpy.ops.paint.brush_colors_flip*", "sculpt_paint/brush/brush_settings.html#bpy-ops-paint-brush-colors-flip"),
("bpy.ops.paint.vertex_color_dirt*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-dirt"),
("bpy.ops.paint.visibility_invert*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-paint-visibility-invert"),
("bpy.ops.paint.weight_from_bones*", "sculpt_paint/weight_paint/editing.html#bpy-ops-paint-weight-from-bones"),
("bpy.ops.paintcurve.delete_point*", "sculpt_paint/brush/stroke.html#bpy-ops-paintcurve-delete-point"),
("bpy.ops.pose.paths_range_update*", "animation/motion_paths.html#bpy-ops-pose-paths-range-update"),
@ -2046,6 +2073,7 @@ url_manual_mapping = (
("bpy.ops.screen.screen_full_area*", "interface/window_system/areas.html#bpy-ops-screen-screen-full-area"),
("bpy.ops.sculpt.face_sets_create*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-sets-create"),
("bpy.ops.sculpt.trim_box_gesture*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-trim-box-gesture"),
("bpy.ops.sequencer.rebuild_proxy*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-ops-sequencer-rebuild-proxy"),
("bpy.ops.sequencer.retiming_show*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-retiming-show"),
("bpy.ops.sequencer.select_linked*", "video_editing/edit/montage/selecting.html#bpy-ops-sequencer-select-linked"),
("bpy.ops.transform.rotate_normal*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-transform-rotate-normal"),
@ -2122,6 +2150,7 @@ url_manual_mapping = (
("bpy.types.sculpt.detail_percent*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-detail-percent"),
("bpy.types.sculpt.gravity_object*", "sculpt_paint/sculpting/tool_settings/options.html#bpy-types-sculpt-gravity-object"),
("bpy.types.sculpt.show_face_sets*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-types-sculpt-show-face-sets"),
("bpy.types.sequenceproxy.quality*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-types-sequenceproxy-quality"),
("bpy.types.shadernodebsdfdiffuse*", "render/shader_nodes/shader/diffuse.html#bpy-types-shadernodebsdfdiffuse"),
("bpy.types.shadernodelayerweight*", "render/shader_nodes/input/layer_weight.html#bpy-types-shadernodelayerweight"),
("bpy.types.shadernodenewgeometry*", "render/shader_nodes/input/geometry.html#bpy-types-shadernodenewgeometry"),
@ -2163,6 +2192,7 @@ url_manual_mapping = (
("bpy.ops.gpencil.stroke_outline*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-outline"),
("bpy.ops.graph.blend_to_default*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-blend-to-default"),
("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"),
("bpy.ops.graph.select_leftright*", "editors/graph_editor/introduction.html#bpy-ops-graph-select-leftright"),
("bpy.ops.graph.sound_to_samples*", "editors/graph_editor/channels/editing.html#bpy-ops-graph-sound-to-samples"),
("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"),
@ -2370,6 +2400,7 @@ url_manual_mapping = (
("bpy.types.compositornodeimage*", "compositing/types/input/image.html#bpy-types-compositornodeimage"),
("bpy.types.compositornodemapuv*", "compositing/types/transform/map_uv.html#bpy-types-compositornodemapuv"),
("bpy.types.compositornodescale*", "compositing/types/transform/scale.html#bpy-types-compositornodescale"),
("bpy.types.compositornodesplit*", "compositing/types/utilities/split.html#bpy-types-compositornodesplit"),
("bpy.types.compositornodevalue*", "compositing/types/input/constant/value.html#bpy-types-compositornodevalue"),
("bpy.types.copyscaleconstraint*", "animation/constraints/transform/copy_scale.html#bpy-types-copyscaleconstraint"),
("bpy.types.curve.path_duration*", "modeling/curves/properties/path_animation.html#bpy-types-curve-path-duration"),
@ -2401,6 +2432,7 @@ url_manual_mapping = (
("bpy.types.rigidbodyconstraint*", "physics/rigid_body/constraints/index.html#bpy-types-rigidbodyconstraint"),
("bpy.types.rigifyarmaturelayer*", "addons/rigging/rigify/metarigs.html#bpy-types-rigifyarmaturelayer"),
("bpy.types.scene.show_subframe*", "editors/timeline.html#bpy-types-scene-show-subframe"),
("bpy.types.sequenceproxy.build*", "editors/video_sequencer/sequencer/sidebar/proxy.html#bpy-types-sequenceproxy-build"),
("bpy.types.shadernodeaddshader*", "render/shader_nodes/shader/add.html#bpy-types-shadernodeaddshader"),
("bpy.types.shadernodeattribute*", "render/shader_nodes/input/attribute.html#bpy-types-shadernodeattribute"),
("bpy.types.shadernodeblackbody*", "render/shader_nodes/converter/blackbody.html#bpy-types-shadernodeblackbody"),
@ -2412,6 +2444,7 @@ url_manual_mapping = (
("bpy.types.shadernodeoutputaov*", "render/shader_nodes/output/aov.html#bpy-types-shadernodeoutputaov"),
("bpy.types.shadernodepointinfo*", "render/shader_nodes/input/point_info.html#bpy-types-shadernodepointinfo"),
("bpy.types.shadernodewireframe*", "render/shader_nodes/input/wireframe.html#bpy-types-shadernodewireframe"),
("bpy.types.shapekey.lock_shape*", "animation/shape_keys/shape_keys_panel.html#bpy-types-shapekey-lock-shape"),
("bpy.types.shapekey.slider_max*", "animation/shape_keys/shape_keys_panel.html#bpy-types-shapekey-slider-max"),
("bpy.types.shapekey.slider_min*", "animation/shape_keys/shape_keys_panel.html#bpy-types-shapekey-slider-min"),
("bpy.types.spacesequenceeditor*", "editors/video_sequencer/index.html#bpy-types-spacesequenceeditor"),
@ -2491,6 +2524,7 @@ url_manual_mapping = (
("bpy.ops.sculpt.face_set_edit*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-set-edit"),
("bpy.ops.sequencer.gap_insert*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-gap-insert"),
("bpy.ops.sequencer.gap_remove*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-gap-remove"),
("bpy.ops.sequencer.hold_split*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-hold-split"),
("bpy.ops.sequencer.rendersize*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-rendersize"),
("bpy.ops.sequencer.select_all*", "video_editing/edit/montage/selecting.html#bpy-ops-sequencer-select-all"),
("bpy.ops.sequencer.select_box*", "video_editing/edit/montage/selecting.html#bpy-ops-sequencer-select-box"),
@ -2609,8 +2643,11 @@ url_manual_mapping = (
("bpy.ops.gpencil.stroke_trim*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-trim"),
("bpy.ops.gpencil.trace_image*", "grease_pencil/modes/object/trace_image.html#bpy-ops-gpencil-trace-image"),
("bpy.ops.graph.blend_to_ease*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-blend-to-ease"),
("bpy.ops.graph.channels_bake*", "editors/graph_editor/channels/editing.html#bpy-ops-graph-channels-bake"),
("bpy.ops.graph.fmodifier_add*", "editors/graph_editor/channels/editing.html#bpy-ops-graph-fmodifier-add"),
("bpy.ops.graph.scale_average*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-scale-average"),
("bpy.ops.graph.select_column*", "editors/graph_editor/introduction.html#bpy-ops-graph-select-column"),
("bpy.ops.graph.select_linked*", "editors/graph_editor/introduction.html#bpy-ops-graph-select-linked"),
("bpy.ops.image.external_edit*", "editors/image/editing.html#bpy-ops-image-external-edit"),
("bpy.ops.mesh.colors_reverse*", "modeling/meshes/editing/face/face_data.html#bpy-ops-mesh-colors-reverse"),
("bpy.ops.mesh.dissolve_edges*", "modeling/meshes/editing/mesh/delete.html#bpy-ops-mesh-dissolve-edges"),
@ -2889,6 +2926,8 @@ url_manual_mapping = (
("bpy.ops.graph.easing_type*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-easing-type"),
("bpy.ops.graph.handle_type*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-handle-type"),
("bpy.ops.graph.match_slope*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-match-slope"),
("bpy.ops.graph.select_less*", "editors/graph_editor/introduction.html#bpy-ops-graph-select-less"),
("bpy.ops.graph.select_more*", "editors/graph_editor/introduction.html#bpy-ops-graph-select-more"),
("bpy.ops.graph.time_offset*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-time-offset"),
("bpy.ops.marker.select_all*", "animation/markers.html#bpy-ops-marker-select-all"),
("bpy.ops.mask.copy_splines*", "movie_clip/masking/editing.html#bpy-ops-mask-copy-splines"),
@ -2919,7 +2958,6 @@ url_manual_mapping = (
("bpy.ops.screen.area_split*", "interface/window_system/areas.html#bpy-ops-screen-area-split"),
("bpy.ops.screen.screenshot*", "interface/window_system/topbar.html#bpy-ops-screen-screenshot"),
("bpy.ops.sculpt.dirty_mask*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-dirty-mask"),
("bpy.ops.sculpt.reveal_all*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-reveal-all"),
("bpy.ops.sculpt.symmetrize*", "sculpt_paint/sculpting/tool_settings/symmetry.html#bpy-ops-sculpt-symmetrize"),
("bpy.ops.uv.align_rotation*", "modeling/meshes/uv/editing.html#bpy-ops-uv-align-rotation"),
("bpy.ops.uv.remove_doubles*", "modeling/meshes/uv/editing.html#bpy-ops-uv-remove-doubles"),
@ -2988,6 +3026,8 @@ url_manual_mapping = (
("bpy.ops.font.textbox_add*", "modeling/texts/properties.html#bpy-ops-font-textbox-add"),
("bpy.ops.gpencil.dissolve*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-dissolve"),
("bpy.ops.graph.frame_jump*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-frame-jump"),
("bpy.ops.graph.select_all*", "editors/graph_editor/introduction.html#bpy-ops-graph-select-all"),
("bpy.ops.graph.select_box*", "editors/graph_editor/introduction.html#bpy-ops-graph-select-box"),
("bpy.ops.marker.duplicate*", "animation/markers.html#bpy-ops-marker-duplicate"),
("bpy.ops.mask.select_less*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-less"),
("bpy.ops.mask.select_more*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-more"),
@ -3028,8 +3068,10 @@ url_manual_mapping = (
("bpy.ops.view3d.view_roll*", "editors/3dview/navigate/navigation.html#bpy-ops-view3d-view-roll"),
("bpy.ops.wm.open_mainfile*", "files/blend/open_save.html#bpy-ops-wm-open-mainfile"),
("bpy.ops.wm.owner_disable*", "interface/window_system/workspaces.html#bpy-ops-wm-owner-disable"),
("bpy.ops.wm.read_userpref*", "editors/preferences/introduction.html#bpy-ops-wm-read-userpref"),
("bpy.ops.wm.save_homefile*", "interface/window_system/topbar.html#bpy-ops-wm-save-homefile"),
("bpy.ops.wm.save_mainfile*", "files/blend/open_save.html#bpy-ops-wm-save-mainfile"),
("bpy.ops.wm.save_userpref*", "editors/preferences/introduction.html#bpy-ops-wm-save-userpref"),
("bpy.types.arealight.size*", "render/lights/light_object.html#bpy-types-arealight-size"),
("bpy.types.attributegroup*", "modeling/meshes/properties/object_data.html#bpy-types-attributegroup"),
("bpy.types.bone.show_wire*", "animation/armatures/bones/properties/display.html#bpy-types-bone-show-wire"),
@ -3115,6 +3157,7 @@ url_manual_mapping = (
("bpy.ops.object.join_uvs*", "scene_layout/object/editing/link_transfer/copy_uvmaps.html#bpy-ops-object-join-uvs"),
("bpy.ops.object.mode_set*", "editors/3dview/modes.html#bpy-ops-object-mode-set"),
("bpy.ops.outliner.delete*", "editors/outliner/editing.html#bpy-ops-outliner-delete"),
("bpy.ops.paint.hide_show*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-paint-hide-show"),
("bpy.ops.paintcurve.draw*", "sculpt_paint/brush/stroke.html#bpy-ops-paintcurve-draw"),
("bpy.ops.pose.relax_rest*", "animation/armatures/posing/editing/in_betweens.html#bpy-ops-pose-relax-rest"),
("bpy.ops.pose.select_all*", "animation/armatures/posing/selecting.html#bpy-ops-pose-select-all"),

View File

@ -1299,7 +1299,6 @@ def km_outliner(params):
("outliner.show_one_level", {"type": 'NUMPAD_MINUS', "value": 'PRESS'},
{"properties": [("open", False)]}),
*_template_items_select_actions(params, "outliner.select_all"),
("outliner.expanded_toggle", {"type": 'A', "value": 'PRESS', "shift": True}, None),
("outliner.keyingset_add_selected", {"type": 'K', "value": 'PRESS'}, None),
("outliner.keyingset_remove_selected", {"type": 'K', "value": 'PRESS', "alt": True}, None),
("anim.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None),
@ -1318,6 +1317,11 @@ def km_outliner(params):
# Copy/paste.
("outliner.id_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
("outliner.id_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
op_menu("VIEW3D_MT_add", {"type": 'A', "value": 'PRESS', "shift": True}),
("object.duplicate", {"type": 'D', "value": 'PRESS', "shift": True}, None),
("object.duplicate", {"type": 'D', "value": 'PRESS', "alt": True},
{"properties": [("linked", True)]}),
])
return keymap
@ -4612,6 +4616,8 @@ def km_grease_pencil_edit_mode(params):
# Dissolve
("grease_pencil.dissolve", {"type": 'X', "value": 'PRESS', "ctrl": True}, None),
("grease_pencil.dissolve", {"type": 'DEL', "value": 'PRESS', "ctrl": True}, None),
# Separate
("grease_pencil.separate", {"type": 'P', "value": 'PRESS'}, None),
# Delete all active frames
("grease_pencil.delete_frame", {"type": 'DEL', "value": 'PRESS', "shift": True},
{"properties": [("type", "ALL_FRAMES")]}),

View File

@ -557,6 +557,8 @@ def km_outliner(params):
# Copy/paste.
("outliner.id_copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None),
("outliner.id_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None),
("object.duplicate", {"type": 'D', "value": 'PRESS', "ctrl": True}, None),
])
return keymap

View File

@ -6,10 +6,12 @@ import bpy
from bpy.types import (
Menu,
Operator,
OperatorFileListElement,
WindowManager,
)
from bpy.props import (
BoolProperty,
CollectionProperty,
StringProperty,
)
from bpy.app.translations import (
@ -622,7 +624,7 @@ class AddPresetOperator(AddPresetBase, Operator):
ret = []
for prop_id, prop in operator_rna.properties.items():
if not (prop.is_hidden or prop.is_skip_save):
if not prop.is_skip_preset:
if prop_id not in properties_blacklist:
ret.append("op.%s" % prop_id)
@ -655,6 +657,74 @@ class WM_MT_operator_presets(Menu):
preset_operator = "script.execute_preset"
class WM_OT_operator_presets_cleanup(Operator):
bl_idname = "wm.operator_presets_cleanup"
bl_label = "Clean Up Operator Presets"
bl_description = "Remove outdated operator properties from presets that may cause problems"
operator: StringProperty(name="operator")
properties: CollectionProperty(name="properties", type=OperatorFileListElement)
def cleanup_preset(self, filepath, properties):
from pathlib import Path
file = Path(filepath)
if not (file.is_file() and filepath.suffix == ".py"):
return
lines = file.read_text().splitlines(True)
if len(lines) == 0:
return
new_lines = []
for line in lines:
if not any(line.startswith(("op.%s" % prop)) for prop in properties):
new_lines.append(line)
file.write_text("".join(new_lines))
def cleanup_operators_presets(self, operators, properties):
base_preset_directory = bpy.utils.user_resource(
'SCRIPTS', path="presets", create=False)
for operator in operators:
from pathlib import Path
operator_path = AddPresetOperator.operator_path(operator)
directory = Path(base_preset_directory, operator_path)
if not directory.is_dir():
continue
for filepath in directory.iterdir():
self.cleanup_preset(filepath, properties)
def execute(self, context):
properties = []
operators = []
if self.operator:
operators.append(self.operator)
for prop in self.properties:
properties.append(prop.name)
else:
# Cleanup by default I/O Operators Presets
operators = ['WM_OT_alembic_export',
'WM_OT_alembic_import',
'WM_OT_collada_export',
'WM_OT_collada_import',
'WM_OT_gpencil_export_svg',
'WM_OT_gpencil_export_pdf',
'WM_OT_gpencil_export_svg',
'WM_OT_gpencil_import_svg',
'WM_OT_obj_export',
'WM_OT_obj_import',
'WM_OT_ply_export',
'WM_OT_ply_import',
'WM_OT_stl_export',
'WM_OT_stl_import',
'WM_OT_usd_export',
'WM_OT_usd_import',
]
properties = ["filepath", "directory", "files", "filename"]
self.cleanup_operators_presets(operators, properties)
return {'FINISHED'}
class AddPresetGpencilBrush(AddPresetBase, Operator):
"""Add or remove grease pencil brush preset"""
bl_idname = "scene.gpencil_brush_preset_add"
@ -748,4 +818,5 @@ classes = (
AddPresetEEVEERaytracing,
ExecutePreset,
WM_MT_operator_presets,
WM_OT_operator_presets_cleanup,
)

View File

@ -148,6 +148,8 @@ class PREFERENCES_OT_copy_prev(Operator):
# Reload preferences and `recent-files.txt`.
bpy.ops.wm.read_userpref()
bpy.ops.wm.read_history()
# Fix operator presets that have unwanted filepath properties
bpy.ops.wm.operator_presets_cleanup()
# don't loose users work if they open the splash later.
if bpy.data.is_saved is bpy.data.is_dirty is False:

View File

@ -3487,7 +3487,8 @@ class WM_MT_region_toggle_pie(Menu):
text = enum_items[region_type].name
attr = cls._region_info[region_type]
value = getattr(space_data, attr)
props = pie.operator("wm.context_toggle", text=text, icon='CHECKBOX_HLT' if value else 'CHECKBOX_DEHLT')
props = pie.operator("wm.context_toggle", text=text, text_ctxt=i18n_contexts.default,
icon='CHECKBOX_HLT' if value else 'CHECKBOX_DEHLT')
props.data_path = "space_data." + attr
def draw(self, context):

View File

@ -7,6 +7,7 @@ from bpy.types import Menu
from bl_ui import node_add_menu
from bpy.app.translations import (
pgettext_iface as iface_,
contexts as i18n_contexts,
)
@ -231,6 +232,7 @@ class NODE_MT_category_compositor_mask(Menu):
class NODE_MT_category_compositor_tracking(Menu):
bl_idname = "NODE_MT_category_compositor_tracking"
bl_label = "Tracking"
bl_translation_context = i18n_contexts.id_movieclip
def draw(self, _context):
layout = self.layout

View File

@ -542,6 +542,7 @@ class NODE_MT_category_GEO_UTILITIES(Menu):
layout.menu("NODE_MT_category_GEO_UTILITIES_FIELD")
layout.menu("NODE_MT_category_GEO_UTILITIES_MATH")
layout.menu("NODE_MT_category_GEO_UTILITIES_ROTATION")
layout.menu("NODE_MT_category_GEO_UTILITIES_DEPRECATED")
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeIndexSwitch")
node_add_menu.add_node_type(layout, "GeometryNodeMenuSwitch")
@ -551,6 +552,15 @@ class NODE_MT_category_GEO_UTILITIES(Menu):
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_UTILITIES_DEPRECATED(Menu):
bl_idname = "NODE_MT_category_GEO_UTILITIES_DEPRECATED"
bl_label = "Deprecated"
def draw(self, context):
layout = self.layout
node_add_menu.add_node_type(layout, "FunctionNodeRotateEuler")
class NODE_MT_category_GEO_UTILITIES_FIELD(Menu):
bl_idname = "NODE_MT_category_GEO_UTILITIES_FIELD"
bl_label = "Field"
@ -769,6 +779,7 @@ classes = (
NODE_MT_category_GEO_UTILITIES_FIELD,
NODE_MT_category_GEO_UTILITIES_MATH,
NODE_MT_category_GEO_UTILITIES_ROTATION,
NODE_MT_category_GEO_UTILITIES_DEPRECATED,
NODE_MT_category_GEO_GROUP,
)

View File

@ -42,6 +42,9 @@ class MotionPathButtonsPanel:
start_end_group.prop(mps, "frame_end", text="End")
col.prop(mps, "frame_step", text="Step")
row = col.row()
row.prop(mps, "bake_in_camera_space", text="Bake to Active Camera")
if bones:
op_category = "pose"
icon = 'BONE_DATA'

View File

@ -118,13 +118,15 @@ class DATA_PT_bone_collections(ArmatureButtonsPanel, Panel):
col = row.column(align=True)
col.operator("armature.collection_add", icon='ADD', text="")
col.operator("armature.collection_remove", icon='REMOVE', text="")
col.separator()
col.menu("ARMATURE_MT_collection_context_menu", icon='DOWNARROW_HLT', text="")
if active_bcoll:
col.separator()
col.operator("armature.collection_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("armature.collection_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
col.separator()
col.menu("ARMATURE_MT_collection_context_menu", icon='DOWNARROW_HLT', text="")
row = layout.row()

View File

@ -380,7 +380,7 @@ class DATA_PT_camera_background_image(CameraButtonsPanel, Panel):
col = box.column()
if bg.image is not None:
col.prop(bg.image, "use_view_as_render")
col.prop(bg, "alpha", slider=True)
col.prop(bg, "alpha")
col.row().prop(bg, "display_depth", expand=True)
col.row().prop(bg, "frame_method", expand=True)

View File

@ -15,6 +15,17 @@ class DataButtonsPanel:
return hasattr(context, "grease_pencil") and context.grease_pencil
class LayerDataButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
@classmethod
def poll(cls, context):
grease_pencil = context.grease_pencil
return grease_pencil and grease_pencil.layers.active
class DATA_PT_context_grease_pencil(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
@ -67,13 +78,59 @@ class DATA_PT_grease_pencil_layers(DataButtonsPanel, Panel):
layout.use_property_decorate = True
col = layout.column(align=True)
col = layout.row(align=True)
col.prop(layer, "opacity", text="Opacity", slider=True)
row = layout.row(align=True)
row.prop(layer, "opacity", text="Opacity", slider=True)
class DATA_PT_grease_pencil_layer_transform(LayerDataButtonsPanel, Panel):
bl_label = "Transform"
bl_parent_id = "DATA_PT_grease_pencil_layers"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
grease_pencil = context.grease_pencil
layer = grease_pencil.layers.active
layout.active = not layer.lock
row = layout.row(align=True)
row.prop(layer, "translation")
row = layout.row(align=True)
row.prop(layer, "rotation")
row = layout.row(align=True)
row.prop(layer, "scale")
class DATA_PT_grease_pencil_layer_relations(LayerDataButtonsPanel, Panel):
bl_label = "Relations"
bl_parent_id = "DATA_PT_grease_pencil_layers"
bl_options = {'DEFAULT_CLOSED'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
grease_pencil = context.grease_pencil
layer = grease_pencil.layers.active
layout.active = not layer.lock
row = layout.row(align=True)
row.prop(layer, "parent", text="Parent")
if layer.parent and layer.parent.type == 'ARMATURE':
row = layout.row(align=True)
row.prop_search(layer, "parent_bone", layer.parent.data, "bones", text="Bone")
classes = (
DATA_PT_context_grease_pencil,
DATA_PT_grease_pencil_layers,
DATA_PT_grease_pencil_layer_transform,
DATA_PT_grease_pencil_layer_relations,
GREASE_PENCIL_MT_grease_pencil_add_layer_extra,
)

View File

@ -608,7 +608,7 @@ class GreasePencilMaterialsPanel:
row.operator("grease_pencil.stroke_material_set", text="Assign")
elif not is_grease_pencil_version3 and ob.data.use_stroke_edit_mode:
row = layout.row(align=True)
row.operator("gpencil.stroke_material_set", text="Assign")
row.operator("gpencil.stroke_change_color", text="Assign")
row.operator("gpencil.material_select", text="Select").deselect = False
row.operator("gpencil.material_select", text="Deselect").deselect = True
# stroke color

View File

@ -212,10 +212,10 @@ class MASK_PT_point:
if parent.parent in tracking.objects:
ob = tracking.objects[parent.parent]
col.prop_search(parent, "sub_parent", ob,
tracks_list, icon='ANIM_DATA', text="Track")
tracks_list, icon='ANIM_DATA', text="Track", text_ctxt=i18n_contexts.id_movieclip)
else:
col.prop_search(parent, "sub_parent", tracking,
tracks_list, icon='ANIM_DATA', text="Track")
tracks_list, icon='ANIM_DATA', text="Track", text_ctxt=i18n_contexts.id_movieclip)
class MASK_PT_display:

View File

@ -395,7 +395,7 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
col = layout.column(heading="Ray Visibility")
col.prop(ob, "visible_shadow", text="Shadow", toggle=False)
if ob.type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'CURVES', 'POINTCLOUD', 'VOLUME', 'LIGHT'}:
if ob.type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'CURVES', 'POINTCLOUD', 'VOLUME'}:
layout.separator()
col = layout.column(heading="Light Probes")
col.prop(ob, "hide_probe_volume", text="Volume", toggle=False, invert_checkbox=True)

View File

@ -319,6 +319,32 @@ class VIEWLAYER_PT_layer_passes_lightgroups(ViewLayerLightgroupsPanel):
COMPAT_ENGINES = {'CYCLES'}
class VIEWLAYER_PT_filter(ViewLayerButtonsPanel, Panel):
bl_label = "Filter"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE_NEXT'}
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
scene = context.scene
rd = scene.render
view_layer = context.view_layer
col = layout.column(heading="Include")
col.prop(view_layer, "use_sky", text="Environment")
col.prop(view_layer, "use_solid", text="Surfaces")
col.prop(view_layer, "use_strand", text="Curves")
col.prop(view_layer, "use_volumes", text="Volumes")
col = layout.column(heading="Use")
sub = col.row()
sub.prop(view_layer, "use_motion_blur", text="Motion Blur")
sub.active = scene.eevee.use_motion_blur
class VIEWLAYER_PT_layer_custom_props(PropertyPanel, Panel):
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@ -340,6 +366,7 @@ classes = (
VIEWLAYER_PT_layer_passes_cryptomatte,
VIEWLAYER_PT_layer_passes_aov,
VIEWLAYER_PT_layer_passes_lightgroups,
VIEWLAYER_PT_filter,
VIEWLAYER_PT_layer_custom_props,
VIEWLAYER_UL_aov,
)

View File

@ -363,7 +363,7 @@ class CLIP_PT_tools_clip(Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Clip"
bl_translation_context = bpy.app.translations.contexts.id_movieclip
bl_translation_context = i18n_contexts.id_movieclip
bl_category = "Track"
@classmethod
@ -473,6 +473,7 @@ class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Track"
bl_translation_context = i18n_contexts.id_movieclip
bl_category = "Track"
bl_options = {'DEFAULT_CLOSED'}
@ -725,6 +726,7 @@ class CLIP_PT_track(CLIP_PT_tracking_panel, Panel):
bl_region_type = 'UI'
bl_category = "Track"
bl_label = "Track"
bl_translation_context = i18n_contexts.id_movieclip
def draw(self, context):
layout = self.layout
@ -1265,7 +1267,6 @@ class CLIP_PT_tools_scenesetup(Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'TOOLS'
bl_label = "Scene Setup"
bl_translation_context = bpy.app.translations.contexts.id_movieclip
bl_category = "Solve"
@classmethod
@ -1364,7 +1365,7 @@ class CLIP_MT_view(Menu):
class CLIP_MT_clip(Menu):
bl_label = "Clip"
bl_translation_context = bpy.app.translations.contexts.id_movieclip
bl_translation_context = i18n_contexts.id_movieclip
def draw(self, context):
layout = self.layout

View File

@ -159,6 +159,7 @@ class GRAPH_MT_view(Menu):
layout.prop(st, "use_realtime_update")
layout.prop(st, "show_sliders")
layout.prop(st, "use_auto_merge_keyframes")
layout.prop(st, "autolock_translation_axis")
layout.separator()
if st.mode != 'DRIVERS':

View File

@ -1431,8 +1431,11 @@ class IMAGE_PT_view_vectorscope(ImageScopesPanel, Panel):
layout = self.layout
sima = context.space_data
layout.template_vectorscope(sima, "scopes")
layout.prop(sima.scopes, "vectorscope_alpha")
row = layout.split(factor=0.75)
row.prop(sima.scopes, "vectorscope_alpha")
row.prop(sima.scopes, "vectorscope_mode", text="")
class IMAGE_PT_sample_line(ImageScopesPanel, Panel):

View File

@ -206,6 +206,7 @@ class NLA_MT_add(Menu):
class NLA_MT_tracks(Menu):
bl_label = "Track"
bl_translation_context = i18n_contexts.id_action
def draw(self, _context):
layout = self.layout

View File

@ -155,6 +155,7 @@ class OUTLINER_MT_view_pie(Menu):
pie = layout.menu_pie()
pie.operator("outliner.show_hierarchy")
pie.operator("outliner.show_active", icon='ZOOM_SELECTED')
pie.operator("outliner.expanded_toggle")
class OUTLINER_MT_edit_datablocks(Menu):

View File

@ -454,6 +454,7 @@ class TOPBAR_MT_blender_system(Menu):
layout.separator()
layout.operator("screen.spacedata_cleanup")
layout.operator("wm.operator_presets_cleanup")
class TOPBAR_MT_templates_more(Menu):

View File

@ -1597,12 +1597,12 @@ class USERPREF_UL_asset_libraries(UIList):
class USERPREF_UL_extension_repos(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index):
repo = item
icon = 'WORLD' if repo.use_remote_path else 'DISK_DRIVE'
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(repo, "name", text="", emboss=False)
layout.prop(repo, "name", text="", icon=icon, emboss=False)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.prop(repo, "name", text="", emboss=False)
layout.prop(repo, "name", text="", icon=icon, emboss=False)
# Show an error icon if this repository has unusable settings.
if repo.enabled:
@ -2047,7 +2047,7 @@ class USERPREF_PT_extensions_repos(Panel):
layout.use_property_decorate = False
paths = context.preferences.filepaths
active_library_index = paths.active_extension_repo
active_repo_index = paths.active_extension_repo
row = layout.row()
@ -2060,10 +2060,14 @@ class USERPREF_PT_extensions_repos(Panel):
col = row.column(align=True)
col.operator_menu_enum("preferences.extension_repo_add", "type", text="", icon='ADD')
props = col.operator_menu_enum("preferences.extension_repo_remove", "type", text="", icon='REMOVE')
props.index = active_library_index
props.index = active_repo_index
col.separator()
col.operator("preferences.extension_repo_sync", text="", icon='FILE_REFRESH')
col.operator("preferences.extension_repo_upgrade", text="", icon='IMPORT')
try:
active_repo = None if active_library_index < 0 else paths.extension_repos[active_library_index]
active_repo = None if active_repo_index < 0 else paths.extension_repos[active_repo_index]
except IndexError:
active_repo = None
@ -2072,14 +2076,16 @@ class USERPREF_PT_extensions_repos(Panel):
layout.separator()
layout.prop(active_repo, "use_remote_path", text="Use Remote URL")
row = layout.row()
# NOTE: changing repositories from remote to local & vice versa could be supported but is obscure enough
# that it can be hidden entirely. If there is a some justification to show this, it can be exposed.
# For now it can be accessed from Python if someone is.
# `layout.prop(active_repo, "use_remote_path", text="Use Remote URL")`
if active_repo.use_remote_path:
row = layout.row()
if active_repo.remote_path == "":
row.alert = True
else:
row.active = False
row.prop(active_repo, "remote_path", text="")
row.prop(active_repo, "remote_path", text="URL")
if layout_panel := self._panel_layout_kludge(layout, text="Advanced"):

View File

@ -1134,11 +1134,12 @@ class VIEW3D_MT_editor_menus(Menu):
elif mode_string == 'VERTEX_GPENCIL':
layout.menu("VIEW3D_MT_select_edit_gpencil")
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
mesh = obj.data
if mesh.use_paint_mask:
layout.menu("VIEW3D_MT_select_paint_mask")
elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
layout.menu("VIEW3D_MT_select_paint_mask_vertex")
if obj.type == 'MESH':
mesh = obj.data
if mesh.use_paint_mask:
layout.menu("VIEW3D_MT_select_paint_mask")
elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
layout.menu("VIEW3D_MT_select_paint_mask_vertex")
elif mode_string not in {'SCULPT', 'SCULPT_CURVES', 'PAINT_GREASE_PENCIL'}:
layout.menu("VIEW3D_MT_select_%s" % mode_string.lower())
@ -3173,6 +3174,7 @@ class VIEW3D_MT_object_parent(Menu):
class VIEW3D_MT_object_track(Menu):
bl_label = "Track"
bl_translation_context = i18n_contexts.constraint
def draw(self, _context):
layout = self.layout
@ -3541,8 +3543,10 @@ class VIEW3D_MT_paint_weight(Menu):
layout.menu("VIEW3D_MT_paint_weight_lock", text="Locks")
def draw(self, _context):
self.draw_generic(self.layout, is_editmode=False)
def draw(self, context):
obj = context.active_object
if obj.type == 'MESH':
self.draw_generic(self.layout, is_editmode=False)
class VIEW3D_MT_sculpt(Menu):
@ -4448,6 +4452,7 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
col.operator("mesh.mark_sharp")
col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
col.operator("mesh.set_sharpness_by_angle")
if with_freestyle:
col.separator()
@ -5808,6 +5813,10 @@ class VIEW3D_MT_edit_greasepencil(Menu):
layout.separator()
layout.operator_menu_enum("grease_pencil.separate", "mode", text="Separate")
layout.separator()
layout.menu("GREASE_PENCIL_MT_layer_active", text="Active Layer")
layout.separator()
@ -8208,6 +8217,10 @@ class VIEW3D_MT_greasepencil_edit_context_menu(Menu):
col.menu("VIEW3D_MT_mirror", text="Mirror Points")
col.separator()
col.operator("grease_pencil.separate", text="Separate").mode = 'SELECTED'
# Removal Operators
col.separator()
@ -8237,6 +8250,10 @@ class VIEW3D_MT_greasepencil_edit_context_menu(Menu):
col.menu("VIEW3D_MT_mirror")
col.separator()
col.operator("grease_pencil.separate", text="Separate").mode = 'SELECTED'
def draw_gpencil_layer_active(context, layout):
gpl = context.active_gpencil_layer

View File

@ -65,6 +65,7 @@ class AssetLibrary {
*/
std::unique_ptr<AssetStorage> asset_storage_;
protected:
std::optional<eAssetImportMethod> 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. */

View File

@ -15,10 +15,11 @@ 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_all.cc
intern/asset_library_essentials.cc
intern/asset_library_from_preferences.cc
intern/asset_library_on_disk.cc
intern/asset_library_runtime.cc
intern/asset_library_service.cc
@ -34,6 +35,8 @@ set(SRC
AS_asset_representation.hh
AS_essentials_library.hh
intern/asset_library_all.hh
intern/asset_library_essentials.hh
intern/asset_library_from_preferences.hh
intern/asset_library_on_disk.hh
intern/asset_library_runtime.hh
intern/asset_library_service.hh

View File

@ -6,14 +6,23 @@
* \ingroup asset_system
*/
#include "BLI_path_util.h"
#include "BKE_appdir.hh"
#include "utils.hh"
#include "AS_essentials_library.hh"
#include "asset_library_essentials.hh"
namespace blender::asset_system {
EssentialsAssetLibrary::EssentialsAssetLibrary()
: OnDiskAssetLibrary(ASSET_LIBRARY_ESSENTIALS,
{},
utils::normalize_directory_path(essentials_directory_path()))
{
import_method_ = ASSET_IMPORT_APPEND_REUSE;
}
StringRefNull essentials_directory_path()
{
static std::string path = []() {

View File

@ -0,0 +1,20 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup asset_system
*/
#pragma once
#include "asset_library_on_disk.hh"
namespace blender::asset_system {
class EssentialsAssetLibrary : public OnDiskAssetLibrary {
public:
EssentialsAssetLibrary();
};
} // namespace blender::asset_system

View File

@ -0,0 +1,18 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup asset_system
*/
#include "asset_library_from_preferences.hh"
namespace blender::asset_system {
PreferencesOnDiskAssetLibrary::PreferencesOnDiskAssetLibrary(StringRef name, StringRef root_path)
: OnDiskAssetLibrary(ASSET_LIBRARY_CUSTOM, name, root_path)
{
}
} // namespace blender::asset_system

View File

@ -0,0 +1,20 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup asset_system
*/
#pragma once
#include "asset_library_on_disk.hh"
namespace blender::asset_system {
class PreferencesOnDiskAssetLibrary : public OnDiskAssetLibrary {
public:
PreferencesOnDiskAssetLibrary(StringRef name = "", StringRef root_path = "");
};
} // namespace blender::asset_system

View File

@ -20,6 +20,8 @@
#include "AS_asset_library.hh"
#include "AS_essentials_library.hh"
#include "asset_library_all.hh"
#include "asset_library_essentials.hh"
#include "asset_library_from_preferences.hh"
#include "asset_library_on_disk.hh"
#include "asset_library_runtime.hh"
#include "asset_library_service.hh"
@ -72,10 +74,7 @@ AssetLibrary *AssetLibraryService::get_asset_library(
return nullptr;
}
AssetLibrary *library = get_asset_library_on_disk_builtin(type, root_path);
library->import_method_ = ASSET_IMPORT_APPEND_REUSE;
return library;
return get_asset_library_on_disk_builtin(type, root_path);
}
case ASSET_LIBRARY_LOCAL: {
/* For the "Current File" library we get the asset library root path based on main. */
@ -132,8 +131,19 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(eAssetLibraryType l
return lib;
}
std::unique_ptr lib_uptr = std::make_unique<OnDiskAssetLibrary>(
library_type, name, normalized_root_path);
std::unique_ptr<OnDiskAssetLibrary> lib_uptr;
switch (library_type) {
case ASSET_LIBRARY_CUSTOM:
lib_uptr = std::make_unique<PreferencesOnDiskAssetLibrary>(name, normalized_root_path);
break;
case ASSET_LIBRARY_ESSENTIALS:
lib_uptr = std::make_unique<EssentialsAssetLibrary>();
break;
default:
lib_uptr = std::make_unique<OnDiskAssetLibrary>(library_type, name, normalized_root_path);
break;
}
AssetLibrary *lib = lib_uptr.get();
lib->load_catalogs();

View File

@ -21,7 +21,7 @@ extern "C" {
*/
/** Blender major and minor version. */
#define BLENDER_VERSION 401
#define BLENDER_VERSION 402
/** Blender patch version for bug-fix releases. */
#define BLENDER_VERSION_PATCH 0
/** Blender release cycle stage: alpha/beta/rc/release. */
@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 17
#define BLENDER_FILE_SUBVERSION 1
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@ -112,6 +112,8 @@ typedef enum {
BKE_CB_EVT_TRANSLATION_UPDATE_POST,
BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE,
BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST,
BKE_CB_EVT_EXTENSION_REPOS_SYNC,
BKE_CB_EVT_EXTENSION_REPOS_UPGRADE,
BKE_CB_EVT_TOT,
} eCbEvent;

View File

@ -93,7 +93,7 @@ void BKE_object_defgroup_unique_name(bDeformGroup *dg, Object *ob);
MDeformWeight *BKE_defvert_find_index(const MDeformVert *dv, int defgroup);
/**
* Ensures that `dv` has a deform weight entry for the specified defweight group.
* Ensures that `dv` has a deform weight entry for the specified group (`defgroup`).
*
* \note this function is mirrored in editmesh_tools.cc, for use for edit-vertices.
*/

View File

@ -34,14 +34,6 @@ namespace blender::bke {
namespace greasepencil {
struct DrawingTransforms {
float4x4 world_space_to_layer_space;
float4x4 layer_space_to_world_space;
DrawingTransforms() = default;
DrawingTransforms(const Object &grease_pencil_ob);
};
class DrawingRuntime {
public:
/**
@ -447,6 +439,23 @@ class Layer : public ::GreasePencilLayer {
*/
void update_from_dna_read();
/**
* Returns the transformation from layer space to object space.
*/
float4x4 to_object_space(const Object &object) const;
/**
* Returns the transformation from layer space to world space.
*/
float4x4 to_world_space(const Object &object) const;
/**
* Returns the name of the parent bone. Should only be used in case the parent object is an
* armature.
*/
StringRefNull parent_bone_name() const;
void set_parent_bone_name(const char *new_name);
private:
using SortedKeysIterator = const int *;
@ -460,6 +469,16 @@ class Layer : public ::GreasePencilLayer {
*/
SortedKeysIterator remove_leading_null_frames_in_range(SortedKeysIterator begin,
SortedKeysIterator end);
/**
* The local transform of the layer (in layer space, not object space).
*/
float4x4 local_transform() const;
/**
* Get the parent to world marix for this layer.
*/
float4x4 parent_to_world(const Object &parent) const;
};
class LayerGroupRuntime {
@ -706,6 +725,7 @@ TREENODE_COMMON_METHODS_FORWARD_IMPL(LayerGroup);
namespace convert {
void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
const ListBase &vertex_group_names,
GreasePencilDrawing &r_drawing);
void legacy_gpencil_to_grease_pencil(Main &main, GreasePencil &grease_pencil, bGPdata &gpd);

View File

@ -421,9 +421,6 @@ void BKE_modifier_free(ModifierData *md);
*/
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md);
/* Generate new UID for the given modifier. */
void BKE_modifier_session_uid_generate(ModifierData *md);
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md);
ModifierData *BKE_modifier_copy_ex(const ModifierData *md, int flag);
@ -472,8 +469,20 @@ void BKE_modifiers_foreach_tex_link(Object *ob, TexWalkFunc walk, void *user_dat
ModifierData *BKE_modifiers_findby_type(const Object *ob, ModifierType type);
ModifierData *BKE_modifiers_findby_name(const Object *ob, const char *name);
ModifierData *BKE_modifiers_findby_session_uid(const Object *ob, const SessionUID *session_uid);
ModifierData *BKE_modifiers_findby_persistent_uid(const Object *ob, int persistent_uid);
void BKE_modifiers_clear_errors(Object *ob);
/**
* Updates `md.persistent_uid` so that it is a valid identifier (>=1) and is unique in the object.
*/
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md);
/**
* Returns true when all the modifier identifiers are positive and unique. This should generally be
* true and should only be used by asserts.
*/
bool BKE_modifiers_persistent_uids_are_valid(const Object &object);
/**
* used for buttons, to find out if the 'draw deformed in edit-mode option is there.
*
@ -584,8 +593,6 @@ void BKE_modifier_deform_vertsEM(ModifierData *md,
*/
Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval);
void BKE_modifier_check_uids_unique_and_report(const Object *object);
void BKE_modifier_blend_write(BlendWriter *writer, const ID *id_owner, ListBase *modbase);
void BKE_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb, Object *ob);

View File

@ -396,6 +396,8 @@ typedef struct bNodeType {
/** True when the node cannot be muted. */
bool no_muting;
/** True when the node still works but it's usage is discouraged. */
const char *deprecation_notice;
/* RNA integration */
ExtensionRNA rna_ext;

View File

@ -115,7 +115,8 @@ bool BKE_object_copy_gpencil_modifier(Object *ob_dst, GpencilModifierData *gmd_s
* Copy the whole stack of modifiers from one object into another.
*
* \warning *Does not* clear modifier stack and related data (particle systems, soft-body,
* etc.) in `ob_dst`, if needed calling code must do it.
* etc.) in `ob_dst`, if needed calling code must do it. The caller is also responsible for
* ensuring the modifier identifiers are unique.
*
* \param do_copy_all: If true, even modifiers that should not support copying (like Hook one)
* will be duplicated.

View File

@ -149,6 +149,13 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports,
if (*dst != nullptr) {
mpath = *dst;
if (avs->path_bakeflag & MOTIONPATH_BAKE_CAMERA_SPACE) {
mpath->flag |= MOTIONPATH_FLAG_BAKE_CAMERA;
}
else {
mpath->flag &= ~MOTIONPATH_FLAG_BAKE_CAMERA;
}
/* Only reuse a path if it was already a valid path, and of the expected length. */
if (mpath->start_frame != mpath->end_frame && mpath->length == expected_length) {
mpath->start_frame = avs->path_sf;
@ -176,6 +183,13 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports,
mpath->flag &= ~MOTIONPATH_FLAG_BHEAD;
}
if (avs->path_bakeflag & MOTIONPATH_BAKE_CAMERA_SPACE) {
mpath->flag |= MOTIONPATH_FLAG_BAKE_CAMERA;
}
else {
mpath->flag &= ~MOTIONPATH_FLAG_BAKE_CAMERA;
}
/* Set default custom values (RGB). */
mpath->color[0] = 1.0;
mpath->color[1] = 0.0;

View File

@ -22,7 +22,7 @@ BakeDataBlockID::BakeDataBlockID(const ID &id)
{
this->type = GS(id.name);
this->id_name = id.name + 2;
if (id.lib) {
if (ID_IS_LINKED(&id)) {
this->lib_name = id.lib->id.name + 2;
}
}

View File

@ -46,7 +46,7 @@
#endif
#ifdef WITH_USD
# include "usd.h"
# include "usd.hh"
#endif
static void cachefile_handle_free(CacheFile *cache_file);
@ -188,7 +188,8 @@ void BKE_cachefile_reader_open(CacheFile *cache_file,
case CACHEFILE_TYPE_USD:
# ifdef WITH_USD
/* Open USD cache reader. */
*reader = CacheReader_open_usd_object(cache_file->handle, *reader, object, object_path);
*reader = blender::io::usd::CacheReader_open_usd_object(
cache_file->handle, *reader, object, object_path);
# endif
break;
case CACHE_FILE_TYPE_INVALID:
@ -232,7 +233,7 @@ void BKE_cachefile_reader_free(CacheFile *cache_file, CacheReader **reader)
break;
case CACHEFILE_TYPE_USD:
# ifdef WITH_USD
USD_CacheReader_free(*reader);
blender::io::usd::USD_CacheReader_free(*reader);
# endif
break;
case CACHE_FILE_TYPE_INVALID:
@ -272,7 +273,7 @@ static void cachefile_handle_free(CacheFile *cache_file)
break;
case CACHEFILE_TYPE_USD:
# ifdef WITH_USD
USD_CacheReader_free(*reader);
blender::io::usd::USD_CacheReader_free(*reader);
# endif
break;
case CACHE_FILE_TYPE_INVALID:
@ -299,7 +300,7 @@ static void cachefile_handle_free(CacheFile *cache_file)
break;
case CACHEFILE_TYPE_USD:
# ifdef WITH_USD
USD_free_handle(cache_file->handle);
blender::io::usd::USD_free_handle(cache_file->handle);
# endif
break;
case CACHE_FILE_TYPE_INVALID:
@ -365,7 +366,8 @@ void BKE_cachefile_eval(Main *bmain, Depsgraph *depsgraph, CacheFile *cache_file
#ifdef WITH_USD
if (BLI_path_extension_check_glob(filepath, "*.usd;*.usda;*.usdc;*.usdz")) {
cache_file->type = CACHEFILE_TYPE_USD;
cache_file->handle = USD_create_handle(bmain, filepath, &cache_file->object_paths);
cache_file->handle = blender::io::usd::USD_create_handle(
bmain, filepath, &cache_file->object_paths);
STRNCPY(cache_file->handle_filepath, filepath);
}
#endif

View File

@ -1359,6 +1359,12 @@ static void save_sample_line(
scopes->vecscope[idx + 0] = yuv[1];
scopes->vecscope[idx + 1] = yuv[2];
int color_idx = (idx / 2) * 4;
scopes->vecscope_rgb[color_idx + 0] = rgb[0];
scopes->vecscope_rgb[color_idx + 1] = rgb[1];
scopes->vecscope_rgb[color_idx + 2] = rgb[2];
scopes->vecscope_rgb[color_idx + 3] = scopes->vecscope_alpha;
/* Waveform. */
switch (scopes->wavefrm_mode) {
case SCOPES_WAVEFRM_RGB:
@ -1707,6 +1713,7 @@ void BKE_scopes_update(Scopes *scopes,
}
if (scopes->vecscope) {
MEM_freeN(scopes->vecscope);
MEM_freeN(scopes->vecscope_rgb);
}
scopes->waveform_1 = static_cast<float *>(
@ -1717,6 +1724,8 @@ void BKE_scopes_update(Scopes *scopes,
MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "waveform point channel 3"));
scopes->vecscope = static_cast<float *>(
MEM_callocN(scopes->waveform_tot * 2 * sizeof(float), "vectorscope point channel"));
scopes->vecscope_rgb = static_cast<float *>(
MEM_callocN(scopes->waveform_tot * 4 * sizeof(float), "vectorscope color channel"));
if (ibuf->float_buffer.data) {
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
@ -1794,6 +1803,7 @@ void BKE_scopes_free(Scopes *scopes)
MEM_SAFE_FREE(scopes->waveform_2);
MEM_SAFE_FREE(scopes->waveform_3);
MEM_SAFE_FREE(scopes->vecscope);
MEM_SAFE_FREE(scopes->vecscope_rgb);
}
void BKE_scopes_new(Scopes *scopes)
@ -1810,6 +1820,7 @@ void BKE_scopes_new(Scopes *scopes)
scopes->waveform_2 = nullptr;
scopes->waveform_3 = nullptr;
scopes->vecscope = nullptr;
scopes->vecscope_rgb = nullptr;
}
void BKE_color_managed_display_settings_init(ColorManagedDisplaySettings *settings)

View File

@ -88,7 +88,7 @@
#endif
#ifdef WITH_USD
# include "usd.h"
# include "usd.hh"
#endif
/* ---------------------------------------------------------------------------- */
@ -5395,7 +5395,8 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa
break;
case CACHEFILE_TYPE_USD:
# ifdef WITH_USD
USD_get_transform(data->reader, cob->matrix, time * FPS, cache_file->scale);
blender::io::usd::USD_get_transform(
data->reader, cob->matrix, time * FPS, cache_file->scale);
# endif
break;
case CACHE_FILE_TYPE_INVALID:

View File

@ -89,89 +89,85 @@ CurvesGeometry::CurvesGeometry(const int point_num, const int curve_num)
this->runtime->type_counts[CURVE_TYPE_CATMULL_ROM] = curve_num;
}
/**
* \note Expects `dst` to be initialized, since the original attributes must be freed.
*/
static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
CurvesGeometry::CurvesGeometry(const CurvesGeometry &other)
{
CustomData_free(&dst.point_data, dst.point_num);
CustomData_free(&dst.curve_data, dst.curve_num);
dst.point_num = src.point_num;
dst.curve_num = src.curve_num;
CustomData_copy(&src.point_data, &dst.point_data, CD_MASK_ALL, dst.point_num);
CustomData_copy(&src.curve_data, &dst.curve_data, CD_MASK_ALL, dst.curve_num);
dst.vertex_group_active_index = src.vertex_group_active_index;
BKE_defgroup_copy_list(&dst.vertex_group_names, &src.vertex_group_names);
implicit_sharing::copy_shared_pointer(src.curve_offsets,
src.runtime->curve_offsets_sharing_info,
&dst.curve_offsets,
&dst.runtime->curve_offsets_sharing_info);
dst.tag_topology_changed();
/* Though type counts are a cache, they must be copied because they are calculated eagerly. */
dst.runtime->type_counts = src.runtime->type_counts;
dst.runtime->evaluated_offsets_cache = src.runtime->evaluated_offsets_cache;
dst.runtime->nurbs_basis_cache = src.runtime->nurbs_basis_cache;
dst.runtime->evaluated_position_cache = src.runtime->evaluated_position_cache;
dst.runtime->bounds_cache = src.runtime->bounds_cache;
dst.runtime->evaluated_length_cache = src.runtime->evaluated_length_cache;
dst.runtime->evaluated_tangent_cache = src.runtime->evaluated_tangent_cache;
dst.runtime->evaluated_normal_cache = src.runtime->evaluated_normal_cache;
if (src.runtime->bake_materials) {
dst.runtime->bake_materials = std::make_unique<bake::BakeMaterialsList>(
*src.runtime->bake_materials);
this->curve_offsets = other.curve_offsets;
if (other.runtime->curve_offsets_sharing_info) {
other.runtime->curve_offsets_sharing_info->add_user();
}
}
CurvesGeometry::CurvesGeometry(const CurvesGeometry &other) : CurvesGeometry()
{
copy_curves_geometry(*this, other);
CustomData_copy(&other.point_data, &this->point_data, CD_MASK_ALL, other.point_num);
CustomData_copy(&other.curve_data, &this->curve_data, CD_MASK_ALL, other.curve_num);
this->point_num = other.point_num;
this->curve_num = other.curve_num;
BKE_defgroup_copy_list(&this->vertex_group_names, &other.vertex_group_names);
this->vertex_group_active_index = other.vertex_group_active_index;
this->runtime = MEM_new<CurvesGeometryRuntime>(
__func__,
CurvesGeometryRuntime{other.runtime->curve_offsets_sharing_info,
other.runtime->type_counts,
other.runtime->evaluated_offsets_cache,
other.runtime->nurbs_basis_cache,
other.runtime->evaluated_position_cache,
other.runtime->bounds_cache,
other.runtime->evaluated_length_cache,
other.runtime->evaluated_tangent_cache,
other.runtime->evaluated_normal_cache,
{}});
if (other.runtime->bake_materials) {
this->runtime->bake_materials = std::make_unique<bake::BakeMaterialsList>(
*other.runtime->bake_materials);
}
}
CurvesGeometry &CurvesGeometry::operator=(const CurvesGeometry &other)
{
if (this != &other) {
copy_curves_geometry(*this, other);
if (this == &other) {
return *this;
}
std::destroy_at(this);
new (this) CurvesGeometry(other);
return *this;
}
/* The source should be empty, but in a valid state so that using it further will work. */
static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src)
CurvesGeometry::CurvesGeometry(CurvesGeometry &&other)
{
dst.point_num = src.point_num;
std::swap(dst.point_data, src.point_data);
CustomData_free(&src.point_data, src.point_num);
src.point_num = 0;
this->curve_offsets = other.curve_offsets;
other.curve_offsets = nullptr;
dst.curve_num = src.curve_num;
std::swap(dst.curve_data, src.curve_data);
CustomData_free(&src.curve_data, src.curve_num);
src.curve_num = 0;
this->point_data = other.point_data;
CustomData_reset(&other.point_data);
std::swap(dst.curve_offsets, src.curve_offsets);
this->curve_data = other.curve_data;
CustomData_reset(&other.curve_data);
std::swap(dst.vertex_group_names.first, src.vertex_group_names.first);
std::swap(dst.vertex_group_names.last, src.vertex_group_names.last);
std::swap(dst.vertex_group_active_index, src.vertex_group_active_index);
this->point_num = other.point_num;
other.point_num = 0;
std::swap(dst.runtime, src.runtime);
}
this->curve_num = other.curve_num;
other.curve_num = 0;
CurvesGeometry::CurvesGeometry(CurvesGeometry &&other) : CurvesGeometry()
{
move_curves_geometry(*this, other);
this->vertex_group_names = other.vertex_group_names;
BLI_listbase_clear(&other.vertex_group_names);
this->vertex_group_active_index = other.vertex_group_active_index;
other.vertex_group_active_index = 0;
this->runtime = other.runtime;
other.runtime = nullptr;
}
CurvesGeometry &CurvesGeometry::operator=(CurvesGeometry &&other)
{
if (this != &other) {
move_curves_geometry(*this, other);
if (this == &other) {
return *this;
}
std::destroy_at(this);
new (this) CurvesGeometry(std::move(other));
return *this;
}
@ -179,11 +175,12 @@ CurvesGeometry::~CurvesGeometry()
{
CustomData_free(&this->point_data, this->point_num);
CustomData_free(&this->curve_data, this->curve_num);
implicit_sharing::free_shared_data(&this->curve_offsets,
&this->runtime->curve_offsets_sharing_info);
BLI_freelistN(&this->vertex_group_names);
MEM_delete(this->runtime);
this->runtime = nullptr;
if (this->runtime) {
implicit_sharing::free_shared_data(&this->curve_offsets,
&this->runtime->curve_offsets_sharing_info);
MEM_delete(this->runtime);
}
}
/** \} */

View File

@ -26,6 +26,8 @@
#include "BLI_sort_utils.h"
#include "BLI_string_utils.hh"
#include "BLT_translation.h"
#include "BKE_anim_data.h"
#include "BKE_animsys.h"
#include "BKE_context.hh"
@ -169,7 +171,7 @@ void BKE_fmodifier_name_set(FModifier *fcm, const char *name)
* Ensure the name is unique. */
const FModifierTypeInfo *fmi = get_fmodifier_typeinfo(fcm->type);
ListBase list = BLI_listbase_from_link((Link *)fcm);
BLI_uniquename(&list, fcm, fmi->name, '.', offsetof(FModifier, name), sizeof(fcm->name));
BLI_uniquename(&list, fcm, DATA_(fmi->name), '.', offsetof(FModifier, name), sizeof(fcm->name));
}
void BKE_fmodifiers_foreach_id(ListBase *fmodifiers, LibraryForeachIDData *data)

View File

@ -8,6 +8,7 @@
#include <iostream>
#include "BKE_action.h"
#include "BKE_anim_data.h"
#include "BKE_curves.hh"
#include "BKE_customdata.hh"
@ -25,8 +26,10 @@
#include "BLI_bounds.hh"
#include "BLI_map.hh"
#include "BLI_math_euler_types.hh"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_memarena.h"
#include "BLI_memory_utils.hh"
@ -240,14 +243,6 @@ IDTypeInfo IDType_ID_GP = {
namespace blender::bke::greasepencil {
DrawingTransforms::DrawingTransforms(const Object &grease_pencil_ob)
{
/* TODO: For now layer space = object space. This needs to change once the layers have a
* transform. */
this->layer_space_to_world_space = float4x4_view(grease_pencil_ob.object_to_world);
this->world_space_to_layer_space = math::invert(this->layer_space_to_world_space);
}
static const std::string ATTR_RADIUS = "radius";
static const std::string ATTR_OPACITY = "opacity";
static const std::string ATTR_VERTEX_COLOR = "vertex_color";
@ -664,6 +659,13 @@ Layer::Layer()
this->opacity = 1.0f;
this->parent = nullptr;
this->parsubstr = nullptr;
zero_v3(this->translation);
zero_v3(this->rotation);
copy_v3_fl(this->scale, 1.0f);
BLI_listbase_clear(&this->masks);
this->runtime = MEM_new<LayerRuntime>(__func__);
@ -680,11 +682,18 @@ Layer::Layer(const Layer &other) : Layer()
/* TODO: duplicate masks. */
/* Note: We do not duplicate the frame storage since it is only needed for writing. */
/* Note: We do not duplicate the frame storage since it is only needed for writing to file. */
this->blend_mode = other.blend_mode;
this->opacity = other.opacity;
this->parent = other.parent;
this->set_parent_bone_name(other.parsubstr);
copy_v3_v3(this->translation, other.translation);
copy_v3_v3(this->rotation, other.rotation);
copy_v3_v3(this->scale, other.scale);
this->runtime->frames_ = other.runtime->frames_;
this->runtime->sorted_keys_cache_ = other.runtime->sorted_keys_cache_;
/* TODO: what about masks cache? */
@ -702,6 +711,8 @@ Layer::~Layer()
MEM_freeN(mask);
}
MEM_SAFE_FREE(this->parsubstr);
MEM_delete(this->runtime);
this->runtime = nullptr;
}
@ -946,6 +957,57 @@ void Layer::update_from_dna_read()
}
}
float4x4 Layer::to_world_space(const Object &object) const
{
if (this->parent == nullptr) {
return float4x4(object.object_to_world) * this->local_transform();
}
const Object &parent = *this->parent;
return this->parent_to_world(parent) * this->local_transform();
}
float4x4 Layer::to_object_space(const Object &object) const
{
if (this->parent == nullptr) {
return this->local_transform();
}
const Object &parent = *this->parent;
return float4x4(object.world_to_object) * this->parent_to_world(parent) *
this->local_transform();
}
StringRefNull Layer::parent_bone_name() const
{
return (this->parsubstr != nullptr) ? StringRefNull(this->parsubstr) : StringRefNull();
}
void Layer::set_parent_bone_name(const char *new_name)
{
if (this->parsubstr != nullptr) {
MEM_freeN(this->parsubstr);
}
this->parsubstr = BLI_strdup_null(new_name);
}
float4x4 Layer::parent_to_world(const Object &parent) const
{
const float4x4 parent_object_to_world(parent.object_to_world);
if (parent.type == OB_ARMATURE && !this->parent_bone_name().is_empty()) {
if (bPoseChannel *channel = BKE_pose_channel_find_name(parent.pose,
this->parent_bone_name().c_str()))
{
return parent_object_to_world * float4x4_view(channel->pose_mat);
}
}
return parent_object_to_world;
}
float4x4 Layer::local_transform() const
{
return math::from_loc_rot_scale<float4x4, math::EulerXYZ>(
float3(this->translation), float3(this->rotation), float3(this->scale));
}
LayerGroup::LayerGroup()
{
new (&this->base) TreeNode(GP_LAYER_TREE_GROUP);

View File

@ -8,6 +8,7 @@
#include "BKE_attribute.hh"
#include "BKE_curves.hh"
#include "BKE_deform.hh"
#include "BKE_grease_pencil.hh"
#include "BKE_material.h"
@ -19,10 +20,52 @@
#include "DNA_gpencil_legacy_types.h"
#include "DNA_grease_pencil_types.h"
#include "DNA_meshdata_types.h"
namespace blender::bke::greasepencil::convert {
/**
* Find vertex groups that have assigned vertices in this drawing.
* Returns:
* - ListBase with used vertex group names (bDeformGroup)
* - Array of indices in the new vertex group list for remapping
*/
static void find_used_vertex_groups(const bGPDframe &gpf,
const ListBase &all_names,
ListBase &r_vertex_group_names,
Array<int> &r_indices)
{
const int num_vertex_groups = BLI_listbase_count(&all_names);
Array<int> is_group_used(num_vertex_groups, false);
LISTBASE_FOREACH (bGPDstroke *, gps, &gpf.strokes) {
if (!gps->dvert) {
continue;
}
Span<MDeformVert> dverts = {gps->dvert, gps->totpoints};
for (const MDeformVert &dvert : dverts) {
for (const MDeformWeight &weight : Span<MDeformWeight>{dvert.dw, dvert.totweight}) {
is_group_used[weight.def_nr] = true;
}
}
}
BLI_listbase_clear(&r_vertex_group_names);
r_indices.reinitialize(num_vertex_groups);
int new_group_i = 0;
int old_group_i;
LISTBASE_FOREACH_INDEX (const bDeformGroup *, def_group, &all_names, old_group_i) {
if (!is_group_used[old_group_i]) {
r_indices[old_group_i] = -1;
continue;
}
r_indices[old_group_i] = new_group_i++;
bDeformGroup *def_group_copy = static_cast<bDeformGroup *>(MEM_dupallocN(def_group));
BLI_addtail(&r_vertex_group_names, def_group_copy);
}
}
void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
const ListBase &vertex_group_names,
GreasePencilDrawing &r_drawing)
{
/* Construct an empty CurvesGeometry in-place. */
@ -54,6 +97,25 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
/* All strokes are poly curves. */
curves.fill_curve_types(CURVE_TYPE_POLY);
/* Find used vertex groups in this drawing. */
ListBase stroke_vertex_group_names;
Array<int> stroke_def_nr_map;
find_used_vertex_groups(gpf, vertex_group_names, stroke_vertex_group_names, stroke_def_nr_map);
BLI_assert(BLI_listbase_is_empty(&curves.vertex_group_names));
curves.vertex_group_names = stroke_vertex_group_names;
const bool use_dverts = !BLI_listbase_is_empty(&curves.vertex_group_names);
/* Copy vertex weights and map the vertex group indices. */
auto copy_dvert = [&](const MDeformVert &src_dvert, MDeformVert &dst_dvert) {
dst_dvert = src_dvert;
dst_dvert.dw = static_cast<MDeformWeight *>(MEM_dupallocN(src_dvert.dw));
const MutableSpan<MDeformWeight> vertex_weights = {dst_dvert.dw, dst_dvert.totweight};
for (MDeformWeight &weight : vertex_weights) {
/* Map def_nr to the reduced vertex group list. */
weight.def_nr = stroke_def_nr_map[weight.def_nr];
}
};
/* Point Attributes. */
MutableSpan<float3> positions = curves.positions_for_write();
MutableSpan<float> radii = drawing.radii_for_write();
@ -66,6 +128,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
attributes.lookup_or_add_for_write_span<ColorGeometry4f>("vertex_color", AttrDomain::Point);
SpanAttributeWriter<bool> selection = attributes.lookup_or_add_for_write_span<bool>(
".selection", AttrDomain::Point);
MutableSpan<MDeformVert> dverts = use_dverts ? curves.wrap().deform_verts_for_write() :
MutableSpan<MDeformVert>();
/* Curve Attributes. */
SpanAttributeWriter<bool> stroke_cyclic = attributes.lookup_or_add_for_write_span<bool>(
@ -126,6 +190,8 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
MutableSpan<ColorGeometry4f> stroke_vertex_colors = vertex_colors.span.slice(
stroke_points_range);
MutableSpan<bool> stroke_selections = selection.span.slice(stroke_points_range);
MutableSpan<MDeformVert> stroke_dverts = use_dverts ? dverts.slice(stroke_points_range) :
MutableSpan<MDeformVert>();
/* Do first point. */
const bGPDspoint &first_pt = stroke_points.first();
@ -143,6 +209,9 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
stroke_rotations.first() = first_pt.uv_rot;
stroke_vertex_colors.first() = ColorGeometry4f(first_pt.vert_color);
stroke_selections.first() = (first_pt.flag & GP_SPOINT_SELECT) != 0;
if (use_dverts && gps->dvert) {
copy_dvert(gps->dvert[0], stroke_dverts.first());
}
/* Do the rest of the points. */
for (const int i : stroke_points.index_range().drop_back(1)) {
@ -156,6 +225,9 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
stroke_rotations[point_i] = pt.uv_rot;
stroke_vertex_colors[point_i] = ColorGeometry4f(pt.vert_color);
stroke_selections[point_i] = (pt.flag & GP_SPOINT_SELECT) != 0;
if (use_dverts && gps->dvert) {
copy_dvert(gps->dvert[point_i], stroke_dverts[point_i]);
}
}
}
@ -210,6 +282,13 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
new_layer.blend_mode = int8_t(gpl->blend_mode);
new_layer.parent = gpl->parent;
new_layer.set_parent_bone_name(gpl->parsubstr);
copy_v3_v3(new_layer.translation, gpl->location);
copy_v3_v3(new_layer.rotation, gpl->rotation);
copy_v3_v3(new_layer.scale, gpl->scale);
/* Convert the layer masks. */
LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
LayerMask *new_mask = new LayerMask(mask->name);
@ -225,7 +304,7 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
grease_pencil.drawing_array[i]);
/* Convert the frame to a drawing. */
legacy_gpencil_frame_to_grease_pencil_drawing(*gpf, drawing);
legacy_gpencil_frame_to_grease_pencil_drawing(*gpf, gpd.vertex_group_names, drawing);
/* Add the frame to the layer. */
if (GreasePencilFrame *new_frame = new_layer.add_frame(gpf->framenum, i)) {
@ -242,6 +321,10 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
/* TODO: Update drawing user counts. */
}
/* Copy vertex group names and settings. */
BKE_defgroup_copy_list(&grease_pencil.vertex_group_names, &gpd.vertex_group_names);
grease_pencil.vertex_group_active_index = gpd.vertex_group_active_index;
/* Convert the onion skinning settings. */
grease_pencil.onion_skinning_settings.opacity = gpd.onion_factor;
grease_pencil.onion_skinning_settings.mode = gpd.onion_mode;

View File

@ -428,7 +428,7 @@ static ImageGPUTextures image_get_gpu_texture(Image *ima,
void *lock;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, (use_viewers) ? &lock : nullptr);
if (ibuf == nullptr) {
BKE_image_release_ibuf(ima, ibuf, (use_viewers) ? &lock : nullptr);
BKE_image_release_ibuf(ima, ibuf, (use_viewers) ? lock : nullptr);
*tex = image_gpu_texture_error_create(textarget);
result.texture = *tex;
@ -473,7 +473,7 @@ static ImageGPUTextures image_get_gpu_texture(Image *ima,
GPU_texture_original_size_set(*tex, ibuf->x, ibuf->y);
}
BKE_image_release_ibuf(ima, ibuf, (use_viewers) ? &lock : nullptr);
BKE_image_release_ibuf(ima, ibuf, (use_viewers) ? lock : nullptr);
return result;
}

View File

@ -2273,6 +2273,7 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
else {
BLI_addtail(&object->modifiers, md);
}
BKE_modifiers_persistent_uid_init(*object, md->modifier);
md->settings.properties = bke::idprop::create_group("Nodes Modifier Settings").release();
IDProperty *angle_prop =

View File

@ -36,6 +36,7 @@
#include "BLI_linklist.h"
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_rand.hh"
#include "BLI_session_uid.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
@ -161,9 +162,6 @@ static ModifierData *modifier_allocate_and_init(ModifierType type)
ModifierData *BKE_modifier_new(int type)
{
ModifierData *md = modifier_allocate_and_init(ModifierType(type));
BKE_modifier_session_uid_generate(md);
return md;
}
@ -220,11 +218,6 @@ void BKE_modifier_remove_from_list(Object *ob, ModifierData *md)
BLI_remlink(&ob->modifiers, md);
}
void BKE_modifier_session_uid_generate(ModifierData *md)
{
md->session_uid = BLI_session_uid_generate();
}
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
{
if (modifiers && md) {
@ -266,10 +259,10 @@ ModifierData *BKE_modifiers_findby_name(const Object *ob, const char *name)
BLI_findstring(&(ob->modifiers), name, offsetof(ModifierData, name)));
}
ModifierData *BKE_modifiers_findby_session_uid(const Object *ob, const SessionUID *session_uid)
ModifierData *BKE_modifiers_findby_persistent_uid(const Object *ob, const int persistent_uid)
{
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (BLI_session_uid_is_equal(&md->session_uid, session_uid)) {
if (md->persistent_uid == persistent_uid) {
return md;
}
}
@ -358,6 +351,7 @@ void BKE_modifier_copydata_ex(const ModifierData *md, ModifierData *target, cons
target->mode = md->mode;
target->flag = md->flag;
target->ui_expand_flag = md->ui_expand_flag;
target->persistent_uid = md->persistent_uid;
if (mti->copy_data) {
mti->copy_data(md, target, flag);
@ -368,17 +362,6 @@ void BKE_modifier_copydata_ex(const ModifierData *md, ModifierData *target, cons
mti->foreach_ID_link(target, nullptr, modifier_copy_data_id_us_cb, nullptr);
}
}
if (flag & LIB_ID_CREATE_NO_MAIN) {
/* Make sure UID is the same between the source and the target.
* This is needed in the cases when UID is to be preserved and when there is no copy_data
* callback, or the copy_data does not do full byte copy of the modifier data. */
target->session_uid = md->session_uid;
}
else {
/* In the case copy_data made full byte copy force UID to be re-generated. */
BKE_modifier_session_uid_generate(target);
}
}
void BKE_modifier_copydata(const ModifierData *md, ModifierData *target)
@ -985,7 +968,7 @@ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval)
ModifierData *BKE_modifier_get_original(const Object *object, ModifierData *md)
{
const Object *object_orig = DEG_get_original_object((Object *)object);
return BKE_modifiers_findby_session_uid(object_orig, &md->session_uid);
return BKE_modifiers_findby_persistent_uid(object_orig, md->persistent_uid);
}
ModifierData *BKE_modifier_get_evaluated(Depsgraph *depsgraph, Object *object, ModifierData *md)
@ -994,30 +977,49 @@ ModifierData *BKE_modifier_get_evaluated(Depsgraph *depsgraph, Object *object, M
if (object_eval == object) {
return md;
}
return BKE_modifiers_findby_session_uid(object_eval, &md->session_uid);
return BKE_modifiers_findby_persistent_uid(object_eval, md->persistent_uid);
}
void BKE_modifier_check_uids_unique_and_report(const Object *object)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
{
GSet *used_uids = BLI_gset_new(
BLI_session_uid_ghash_hash, BLI_session_uid_ghash_compare, "modifier used uids");
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
const SessionUID *session_uid = &md->session_uid;
if (!BLI_session_uid_is_generated(session_uid)) {
printf("Modifier %s -> %s does not have UID generated.\n", object->id.name + 2, md->name);
continue;
}
if (BLI_gset_lookup(used_uids, session_uid) != nullptr) {
printf("Modifier %s -> %s has duplicate UID generated.\n", object->id.name + 2, md->name);
continue;
}
BLI_gset_insert(used_uids, (void *)session_uid);
uint64_t hash = blender::get_default_hash(blender::StringRef(md.name));
if (ID_IS_LINKED(&object)) {
hash = blender::get_default_hash(hash, blender::StringRef(object.id.lib->filepath_abs));
}
if (ID_IS_OVERRIDE_LIBRARY_REAL(&object)) {
BLI_assert(ID_IS_LINKED(object.id.override_library->reference));
hash = blender::get_default_hash(
hash, blender::StringRef(object.id.override_library->reference->lib->filepath_abs));
}
blender::RandomNumberGenerator rng{uint32_t(hash)};
while (true) {
const int new_uid = rng.get_int32();
if (new_uid <= 0) {
continue;
}
if (BKE_modifiers_findby_persistent_uid(&object, new_uid) != nullptr) {
continue;
}
md.persistent_uid = new_uid;
break;
}
}
BLI_gset_free(used_uids, nullptr);
bool BKE_modifiers_persistent_uids_are_valid(const Object &object)
{
blender::Set<int> uids;
int modifiers_num = 0;
LISTBASE_FOREACH (const ModifierData *, md, &object.modifiers) {
if (md->persistent_uid <= 0) {
return false;
}
uids.add(md->persistent_uid);
modifiers_num++;
}
if (uids.size() != modifiers_num) {
return false;
}
return true;
}
void BKE_modifier_blend_write(BlendWriter *writer, const ID *id_owner, ListBase *modbase)
@ -1245,8 +1247,6 @@ void BKE_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb, Object
BLO_read_list(reader, lb);
LISTBASE_FOREACH (ModifierData *, md, lb) {
BKE_modifier_session_uid_generate(md);
md->error = nullptr;
md->runtime = nullptr;

View File

@ -250,6 +250,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in
BLI_listbase_clear(&ob_dst->greasepencil_modifiers);
/* NOTE: Also takes care of soft-body and particle systems copying. */
BKE_object_modifier_stack_copy(ob_dst, ob_src, true, flag_subdata);
BLI_assert(BKE_modifiers_persistent_uids_are_valid(*ob_dst));
BLI_listbase_clear((ListBase *)&ob_dst->drawdata);
BLI_listbase_clear(&ob_dst->pc_ids);
@ -766,6 +767,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
wmd->width = wav->width;
BLI_addtail(&ob->modifiers, wmd);
BKE_modifiers_persistent_uid_init(*ob, wmd->modifier);
BLI_remlink(&ob->effect, paf);
MEM_freeN(paf);
@ -784,6 +786,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
bmd->seed = 1;
BLI_addtail(&ob->modifiers, bmd);
BKE_modifiers_persistent_uid_init(*ob, bmd->modifier);
BLI_remlink(&ob->effect, paf);
MEM_freeN(paf);
@ -871,6 +874,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
BLI_remlink(&ob->hooks, hook);
BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)hmd);
BKE_modifiers_persistent_uid_init(*ob, hmd->modifier);
MEM_freeN(hook);
}
@ -1423,6 +1427,7 @@ bool BKE_object_copy_modifier(
BLI_addtail(&ob_dst->modifiers, md_dst);
BKE_modifier_unique_name(&ob_dst->modifiers, md_dst);
BKE_modifiers_persistent_uid_init(*ob_dst, *md_dst);
}
BKE_object_modifier_set_active(ob_dst, md_dst);
@ -5324,7 +5329,6 @@ void BKE_object_to_curve_clear(Object *object)
void BKE_object_check_uids_unique_and_report(const Object *object)
{
BKE_pose_check_uids_unique_and_report(object->pose);
BKE_modifier_check_uids_unique_and_report(object);
}
SubsurfModifierData *BKE_object_get_last_subsurf_modifier(const Object *ob)

View File

@ -3958,6 +3958,7 @@ static ModifierData *object_add_or_copy_particle_system(
psmd->psys = psys;
BLI_addtail(&ob->modifiers, md);
BKE_object_modifier_set_active(ob, md);
BKE_modifiers_persistent_uid_init(*ob, *md);
psys->totpart = 0;
psys->flag = PSYS_CURRENT;

View File

@ -500,7 +500,7 @@ MovieTrackingTrack *BKE_tracking_track_add_empty(MovieTracking *tracking, ListBa
const MovieTrackingSettings *settings = &tracking->settings;
MovieTrackingTrack *track = MEM_cnew<MovieTrackingTrack>("add_marker_exec track");
STRNCPY(track->name, "Track");
STRNCPY(track->name, CTX_DATA_(BLT_I18NCONTEXT_ID_MOVIECLIP, "Track"));
/* Fill track's settings from default settings. */
track->motion_model = settings->default_motion_model;

View File

@ -1844,6 +1844,18 @@ static bool ch_is_op(char op)
}
}
static bool ch_is_op_unary(char op)
{
switch (op) {
case '+':
case '-':
case '~':
return true;
default:
return false;
}
}
/**
* Helper function for #unit_distribute_negatives to find the next negative to distribute.
*
@ -1912,6 +1924,18 @@ static char *find_next_op(const char *str, char *remaining_str, int remaining_st
return remaining_str + i;
}
/**
* Skip over multiple successive unary operators (typically `-`), skipping spaces.
* This allows for `--90d` to be handled properly, see: #117783.
*/
static char *skip_unary_op(char *str)
{
while (*str == ' ' || ch_is_op_unary(*str)) {
str++;
}
return str;
}
/**
* Put parentheses around blocks of values after negative signs to get rid of an implied "+"
* between numbers without an operation between them. For example:
@ -1937,8 +1961,9 @@ static bool unit_distribute_negatives(char *str, const int str_maxncpy)
memmove(remaining_str + 1, remaining_str, remaining_str_maxncpy - 2);
*remaining_str = '(';
/* Add the ')' before the next operation or at the end. */
remaining_str = find_next_op(str, remaining_str + 1, remaining_str_maxncpy);
/* Add the ')' before the next operation or at the end.
* Unary operators are skipped to allow `--` to be a supported prefix. */
remaining_str = find_next_op(str, skip_unary_op(remaining_str + 1), remaining_str_maxncpy);
remaining_str_maxncpy = str_maxncpy - int(remaining_str - str);
memmove(remaining_str + 1, remaining_str, remaining_str_maxncpy - 2);
*remaining_str = ')';

View File

@ -307,8 +307,8 @@ class Any {
return buffer_.ptr();
}
else {
/* Using #malloc so that the #unique_ptr can free the memory. */
T *value = static_cast<T *>(malloc(sizeof(T)));
/* Using raw allocation here. The caller is responsible for constructing the value. */
T *value = static_cast<T *>(::operator new(sizeof(T)));
new (&buffer_) std::unique_ptr<T>(value);
return value;
}

View File

@ -626,7 +626,7 @@ constexpr bool operator>=(StringRef a, StringRef b)
* \{ */
/**
* Support using the fmt library with #StringRef and implicitly also #StringRefNull.
* Support using the `fmt` library with #StringRef and implicitly also #StringRefNull.
*/
inline std::string_view format_as(StringRef str)
{

View File

@ -34,6 +34,10 @@ struct SearchItem {
* number is not based on an actual clock.
*/
int recent_time;
/**
* Deprecated items can still be found via search, but are at the bottom of the list.
*/
bool is_deprecated;
};
struct RecentCache {

View File

@ -343,7 +343,7 @@ static std::optional<float> score_query_against_words(Span<StringRef> query_word
Array<int, 64> word_match_map(item.normalized_words.size(), unused_word);
/* Start with some high score, because otherwise the final score might become negative. */
float total_match_score = 1000;
float total_match_score = item.is_deprecated ? 500 : 1000;
for (const int query_word_index : query_words.index_range()) {
const StringRef query_word = query_words[query_word_index];
@ -514,6 +514,9 @@ void StringSearchBase::add_impl(const StringRef str, void *user_data, const int
}
}
/* Not checking for the "D" to avoid problems with upper/lower-case. */
const bool is_deprecated = str.find("eprecated") != StringRef::not_found;
items_.append({user_data,
allocator_.construct_array_copy(words.as_span()),
allocator_.construct_array_copy(word_group_ids.as_span()),
@ -521,7 +524,8 @@ void StringSearchBase::add_impl(const StringRef str, void *user_data, const int
main_group_length,
int(str.size()),
weight,
recent_time});
recent_time,
is_deprecated});
}
Vector<void *> StringSearchBase::query_impl(const StringRef query) const

View File

@ -27,6 +27,7 @@
#include "DNA_modifier_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_world_types.h"
#include "DNA_defaults.h"
@ -61,6 +62,7 @@
#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "SEQ_iterator.hh"
#include "SEQ_retiming.hh"
#include "SEQ_sequencer.hh"
@ -1936,6 +1938,15 @@ static void fix_geometry_nodes_object_info_scale(bNodeTree &ntree)
}
}
static bool seq_filter_bilinear_to_auto(Sequence *seq, void * /*user_data*/)
{
StripTransform *transform = seq->strip->transform;
if (transform != nullptr && transform->filter == SEQ_TRANSFORM_FILTER_BILINEAR) {
transform->filter = SEQ_TRANSFORM_FILTER_AUTO;
}
return true;
}
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
@ -2848,6 +2859,44 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 18)) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
if (scene->ed != nullptr) {
SEQ_for_each_callback(&scene->ed->seqbase, seq_filter_bilinear_to_auto, nullptr);
}
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 19)) {
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
if (ntree->type == NTREE_GEOMETRY) {
version_node_socket_name(ntree, FN_NODE_ROTATE_ROTATION, "Rotation 1", "Rotation");
version_node_socket_name(ntree, FN_NODE_ROTATE_ROTATION, "Rotation 2", "Rotate By");
}
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 20)) {
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
int uid = 1;
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
/* These identifiers are not necessarily stable for linked data. If the linked data has a
* new modifier inserted, the identifiers of other modifiers can change. */
md->persistent_uid = uid++;
}
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 1)) {
using namespace blender::bke::greasepencil;
/* Initialize newly added scale layer transform to one. */
LISTBASE_FOREACH (GreasePencil *, grease_pencil, &bmain->grease_pencils) {
for (Layer *layer : grease_pencil->layers_for_write()) {
copy_v3_fl(layer->scale, 1.0f);
}
}
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.

Some files were not shown because too many files have changed in this diff Show More