Fix #103244: ghosting in Eevee with sculpt paint brush and canvas #104557

Open
Colin Marmond wants to merge 9 commits from Kdaf/blender:fix-103244-sculpt-lighting-using-paint-brush-on-image into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
963 changed files with 11293 additions and 5979 deletions
Showing only changes of commit df59b56569 - Show all commits

View File

@ -1,8 +0,0 @@
{
"project_id" : "Blender",
"conduit_uri" : "https://developer.blender.org/",
"phabricator.uri" : "https://developer.blender.org/",
"git.default-relative-commit" : "origin/master",
"arc.land.update.default" : "rebase",
"arc.land.onto.default" : "master"
}

View File

@ -236,6 +236,8 @@ ForEachMacros:
- LOOP_UNSELECTED_POINTS
- LOOP_VISIBLE_KEYS
- LOOP_VISIBLE_POINTS
- LIGHT_FOREACH_BEGIN_DIRECTIONAL
- LIGHT_FOREACH_BEGIN_LOCAL
- LISTBASE_CIRCULAR_BACKWARD_BEGIN
- LISTBASE_CIRCULAR_FORWARD_BEGIN
- LISTBASE_FOREACH

4
.gitmodules vendored
View File

@ -2,15 +2,19 @@
path = release/scripts/addons
url = ../blender-addons.git
branch = main
ignore = all
[submodule "release/scripts/addons_contrib"]
path = release/scripts/addons_contrib
url = ../blender-addons-contrib.git
branch = main
ignore = all
[submodule "release/datafiles/locale"]
path = release/datafiles/locale
url = ../blender-translations.git
branch = main
ignore = all
[submodule "source/tools"]
path = source/tools
url = ../blender-dev-tools.git
branch = main
ignore = all

View File

@ -524,7 +524,7 @@ endif()
if(NOT APPLE)
option(WITH_CYCLES_DEVICE_HIP "Enable Cycles AMD HIP support" ON)
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 gfx1100 gfx1101 gfx1102 CACHE STRING "AMD HIP architectures to build binaries for")
set(CYCLES_HIP_BINARIES_ARCH gfx900 gfx906 gfx90c gfx902 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 gfx1035 gfx1100 gfx1101 gfx1102 CACHE STRING "AMD HIP architectures to build binaries for")
mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
endif()
@ -625,8 +625,10 @@ mark_as_advanced(
# Vulkan
option(WITH_VULKAN_BACKEND "Enable Vulkan as graphics backend (only for development)" OFF)
option(WITH_VULKAN_GUARDEDALLOC "Use guardedalloc for host allocations done inside Vulkan (development option)" OFF)
mark_as_advanced(
WITH_VULKAN_BACKEND
WITH_VULKAN_GUARDEDALLOC
)
# Metal

View File

@ -299,7 +299,11 @@ else
ifneq ("$(wildcard $(DEPS_BUILD_DIR)/build.ninja)","")
DEPS_BUILD_COMMAND:=ninja
else
DEPS_BUILD_COMMAND:=make -s
ifeq ($(OS), Darwin)
DEPS_BUILD_COMMAND:=make -s
else
DEPS_BUILD_COMMAND:="$(BLENDER_DIR)/build_files/build_environment/linux/make_deps_wrapper.sh" -s
endif
endif
endif
@ -398,7 +402,7 @@ endif
deps: .FORCE
@echo
@echo Configuring dependencies in \"$(DEPS_BUILD_DIR)\"
@echo Configuring dependencies in \"$(DEPS_BUILD_DIR)\", install to \"$(DEPS_INSTALL_DIR)\"
@cmake -H"$(DEPS_SOURCE_DIR)" \
-B"$(DEPS_BUILD_DIR)" \

View File

@ -10,7 +10,7 @@ ExternalProject_Add(external_epoxy
URL_HASH ${EPOXY_HASH_TYPE}=${EPOXY_HASH}
PREFIX ${BUILD_DIR}/epoxy
PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/epoxy/src/external_epoxy/ < ${PATCH_DIR}/epoxy.diff
CONFIGURE_COMMAND ${CONFIGURE_ENV} && ${MESON} setup --prefix ${LIBDIR}/epoxy --default-library ${EPOXY_LIB_TYPE} --libdir lib ${BUILD_DIR}/epoxy/src/external_epoxy-build ${BUILD_DIR}/epoxy/src/external_epoxy -Dtests=false
CONFIGURE_COMMAND ${CONFIGURE_ENV} && ${MESON} setup --prefix ${LIBDIR}/epoxy --default-library ${EPOXY_LIB_TYPE} --libdir lib ${BUILD_DIR}/epoxy/src/external_epoxy-build ${BUILD_DIR}/epoxy/src/external_epoxy -Dtests=false ${MESON_BUILD_TYPE}
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)

View File

@ -9,7 +9,7 @@ ExternalProject_Add(external_fribidi
URL_HASH ${FRIBIDI_HASH_TYPE}=${FRIBIDI_HASH}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
PREFIX ${BUILD_DIR}/fribidi
CONFIGURE_COMMAND ${MESON} setup --prefix ${LIBDIR}/fribidi -Ddocs=false --default-library static --libdir lib ${BUILD_DIR}/fribidi/src/external_fribidi-build ${BUILD_DIR}/fribidi/src/external_fribidi
CONFIGURE_COMMAND ${MESON} setup --prefix ${LIBDIR}/fribidi ${MESON_BUILD_TYPE} -Ddocs=false --default-library static --libdir lib ${BUILD_DIR}/fribidi/src/external_fribidi-build ${BUILD_DIR}/fribidi/src/external_fribidi
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
INSTALL_DIR ${LIBDIR}/fribidi

View File

@ -22,7 +22,7 @@ elseif(UNIX AND NOT APPLE)
)
endif()
# Boolean crashes with Arm assembly, see T103423.
# Boolean crashes with Arm assembly, see #103423.
if(BLENDER_PLATFORM_ARM)
set(GMP_OPTIONS
${GMP_OPTIONS}

View File

@ -21,6 +21,7 @@ set(HARFBUZZ_EXTRA_OPTIONS
# Only used for command line utilities,
# disable as this would add an addition & unnecessary build-dependency.
-Dcairo=disabled
${MESON_BUILD_TYPE}
)
ExternalProject_Add(external_harfbuzz
@ -59,3 +60,10 @@ if(BUILD_MODE STREQUAL Release AND WIN32)
DEPENDEES install
)
endif()
if(BUILD_MODE STREQUAL Debug AND WIN32)
ExternalProject_Add_Step(external_harfbuzz after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/harfbuzz/lib/libharfbuzz.a ${HARVEST_TARGET}/harfbuzz/lib/libharfbuzz_d.lib
DEPENDEES install
)
endif()

View File

@ -15,7 +15,7 @@ llvm-config = '${LIBDIR}/llvm/bin/llvm-config'"
)
set(MESA_EXTRA_FLAGS
-Dbuildtype=release
${MESON_BUILD_TYPE}
-Dc_args=${MESA_CFLAGS}
-Dcpp_args=${MESA_CXXFLAGS}
-Dc_link_args=${MESA_LDFLAGS}

View File

@ -16,8 +16,10 @@ message("BuildMode = ${BUILD_MODE}")
if(BUILD_MODE STREQUAL "Debug")
set(LIBDIR ${CMAKE_CURRENT_BINARY_DIR}/Debug)
set(MESON_BUILD_TYPE -Dbuildtype=debug)
else()
set(LIBDIR ${CMAKE_CURRENT_BINARY_DIR}/Release)
set(MESON_BUILD_TYPE -Dbuildtype=release)
endif()
set(DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/downloads" CACHE STRING "Path for downloaded files")

View File

@ -13,7 +13,7 @@ ExternalProject_Add(external_wayland
# NOTE: `-lm` is needed for `libxml2` which is a static library that uses `libm.so`,
# without this, math symbols such as `floor` aren't found.
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/expat/lib/pkgconfig:${LIBDIR}/xml2/lib/pkgconfig:${LIBDIR}/ffi/lib/pkgconfig:$PKG_CONFIG_PATH
${MESON} --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -D "c_link_args=-L${LIBDIR}/ffi/lib -lm" . ../external_wayland
${MESON} --prefix ${LIBDIR}/wayland ${MESON_BUILD_TYPE} -Ddocumentation=false -Dtests=false -D "c_link_args=-L${LIBDIR}/ffi/lib -lm" . ../external_wayland
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)

View File

@ -7,7 +7,7 @@ ExternalProject_Add(external_wayland_protocols
PREFIX ${BUILD_DIR}/wayland-protocols
# Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own WAYLAND.
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/wayland/lib64/pkgconfig:$PKG_CONFIG_PATH
${MESON} --prefix ${LIBDIR}/wayland-protocols . ../external_wayland_protocols -Dtests=false
${MESON} --prefix ${LIBDIR}/wayland-protocols ${MESON_BUILD_TYPE} . ../external_wayland_protocols -Dtests=false
BUILD_COMMAND ninja
INSTALL_COMMAND ninja install
)

View File

@ -17,11 +17,13 @@ ExternalProject_Add(external_xvidcore
INSTALL_DIR ${LIBDIR}/xvidcore
)
ExternalProject_Add_Step(external_xvidcore after_install
COMMAND ${CMAKE_COMMAND} -E rename ${LIBDIR}/xvidcore/lib/xvidcore.a ${LIBDIR}/xvidcore/lib/libxvidcore.a || true
COMMAND ${CMAKE_COMMAND} -E remove ${LIBDIR}/xvidcore/lib/xvidcore.dll.a
DEPENDEES install
)
if(WIN32)
ExternalProject_Add_Step(external_xvidcore after_install
COMMAND ${CMAKE_COMMAND} -E rename ${LIBDIR}/xvidcore/lib/xvidcore.a ${LIBDIR}/xvidcore/lib/libxvidcore.a || true
COMMAND ${CMAKE_COMMAND} -E remove ${LIBDIR}/xvidcore/lib/xvidcore.dll.a
DEPENDEES install
)
endif()
if(MSVC)
set_target_properties(external_xvidcore PROPERTIES FOLDER Mingw)

View File

@ -0,0 +1,74 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# This script ensures:
# - One dependency is built at a time.
# - That dependency uses all available cores.
#
# Without this, simply calling `make -j$(nproc)` from the `${CMAKE_BUILD_DIR}/deps/`
# directory will build many projects at once.
#
# This is undesirable for the following reasons:
#
# - The output from projects is mixed together,
# making it difficult to track down the cause of a build failure.
#
# - Larger dependencies such as LLVM can bottleneck the build process,
# making it necessary to cancel the build and manually run build commands in each directory.
#
# - Building many projects at once means canceling (Control-C) can lead to the build being in an undefined state.
# It's possible canceling happens as a patch is being applied or files are being copied.
# (steps that aren't part of the compilation process where it's typically safe to cancel).
if [[ -z "$MY_MAKE_CALL_LEVEL" ]]; then
export MY_MAKE_CALL_LEVEL=0
export MY_MAKEFLAGS=$MAKEFLAGS
# Extract the jobs argument (`-jN`, `-j N`, `--jobs=N`).
add_next=0
for i in "$@"; do
case $i in
-j*)
export MY_JOBS_ARG=$i
if [ "$MY_JOBS_ARG" = "-j" ]; then
add_next=1
fi
;;
--jobs=*)
shift # past argument=value
MY_JOBS_ARG=$i
;;
*)
if (( add_next == 1 )); then
MY_JOBS_ARG="$MY_JOBS_ARG $i"
add_next=0
fi
;;
esac
done
unset i add_next
if [[ -z "$MY_JOBS_ARG" ]]; then
MY_JOBS_ARG="-j$(nproc)"
fi
export MY_JOBS_ARG
# Support user defined `MAKEFLAGS`.
export MAKEFLAGS="$MY_MAKEFLAGS -j1"
else
export MY_MAKE_CALL_LEVEL=$(( MY_MAKE_CALL_LEVEL + 1 ))
if (( MY_MAKE_CALL_LEVEL == 1 )); then
# Important to set jobs to 1, otherwise user defined jobs argument is used.
export MAKEFLAGS="$MY_MAKEFLAGS -j1"
elif (( MY_MAKE_CALL_LEVEL == 2 )); then
# This is the level used by each sub-project.
export MAKEFLAGS="$MY_MAKEFLAGS $MY_JOBS_ARG"
fi
# Else leave `MY_MAKEFLAGS` flags as-is, avoids setting a high number of jobs on recursive
# calls (which may easily run out of memory). Let the job-server handle the rest.
fi
# Useful for troubleshooting the wrapper.
# echo "Call level: $MY_MAKE_CALL_LEVEL, args=$@".
# Call actual make but ensure recursive calls run via this script.
exec make MAKE="$0" "$@"

View File

@ -85,7 +85,7 @@ if(NOT APPLE)
set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_HIP_BINARIES ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_HIP_BINARIES OFF CACHE BOOL "" FORCE)
set(WITH_CYCLES_DEVICE_ONEAPI ON CACHE BOOL "" FORCE)
set(WITH_CYCLES_ONEAPI_BINARIES ON CACHE BOOL "" FORCE)
endif()

View File

@ -544,7 +544,7 @@ endfunction()
function(setup_platform_linker_libs
target
)
# jemalloc must be early in the list, to be before pthread (see T57998)
# jemalloc must be early in the list, to be before pthread (see #57998).
if(WITH_MEM_JEMALLOC)
target_link_libraries(${target} ${JEMALLOC_LIBRARIES})
endif()

View File

@ -440,7 +440,7 @@ string(APPEND PLATFORM_LINKFLAGS " -stdlib=libc++")
# Make stack size more similar to Embree, required for Embree.
string(APPEND PLATFORM_LINKFLAGS_EXECUTABLE " -Wl,-stack_size,0x100000")
# Suppress ranlib "has no symbols" warnings (workaround for T48250)
# Suppress ranlib "has no symbols" warnings (workaround for #48250).
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
# llvm-ranlib doesn't support this flag. Xcode's libtool does.

View File

@ -121,7 +121,7 @@ if(WITH_WINDOWS_BUNDLE_CRT)
include(InstallRequiredSystemLibraries)
# ucrtbase(d).dll cannot be in the manifest, due to the way windows 10 handles
# redirects for this dll, for details see T88813.
# redirects for this dll, for details see #88813.
foreach(lib ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS})
string(FIND ${lib} "ucrtbase" pos)
if(NOT pos EQUAL -1)
@ -295,7 +295,7 @@ unset(MATERIALX_LIB_FOLDER_EXISTS)
if(NOT MSVC_CLANG AND # Available with MSVC 15.7+ but not for CLANG.
NOT WITH_WINDOWS_SCCACHE AND # And not when sccache is enabled
NOT VS_CLANG_TIDY) # Clang-tidy does not like these options
add_compile_options(/experimental:external /external:templates- /external:I "${LIBDIR}" /external:W0)
add_compile_options(/experimental:external /external:I "${LIBDIR}" /external:W0)
endif()
# Add each of our libraries to our cmake_prefix_path so find_package() could work

View File

@ -142,7 +142,7 @@ def cmake_advanced_info() -> Union[Tuple[List[str], List[Tuple[str, str]]], Tupl
make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
if make_exe is None:
print("Make command not found in: %r not found" % project_path)
print("Make command not found: CMAKE_MAKE_PROGRAM")
return None, None
make_exe_basename = os.path.basename(make_exe)

View File

@ -42,6 +42,7 @@ def parse_arguments() -> argparse.Namespace:
parser.add_argument("--svn-branch", default=None)
parser.add_argument("--git-command", default="git")
parser.add_argument("--use-linux-libraries", action="store_true")
parser.add_argument("--architecture", type=str, choices=("x86_64", "amd64", "arm64",))
return parser.parse_args()
@ -51,6 +52,19 @@ def get_blender_git_root() -> str:
# Setup for precompiled libraries and tests from svn.
def get_effective_architecture(args: argparse.Namespace) -> str:
architecture = args.architecture
if architecture:
assert isinstance(architecture, str)
return architecture
# Check platform.version to detect arm64 with x86_64 python binary.
if "ARM64" in platform.version():
return "arm64"
return platform.machine().lower()
def svn_update(args: argparse.Namespace, release_version: Optional[str]) -> None:
svn_non_interactive = [args.svn_command, '--non-interactive']
@ -58,11 +72,11 @@ def svn_update(args: argparse.Namespace, release_version: Optional[str]) -> None
svn_url = make_utils.svn_libraries_base_url(release_version, args.svn_branch)
# Checkout precompiled libraries
architecture = get_effective_architecture(args)
if sys.platform == 'darwin':
# Check platform.version to detect arm64 with x86_64 python binary.
if platform.machine() == 'arm64' or ('ARM64' in platform.version()):
if architecture == 'arm64':
lib_platform = "darwin_arm64"
elif platform.machine() == 'x86_64':
elif architecture == 'x86_64':
lib_platform = "darwin"
else:
lib_platform = None
@ -256,14 +270,15 @@ if __name__ == "__main__":
blender_skip_msg = ""
submodules_skip_msg = ""
# Test if we are building a specific release version.
branch = make_utils.git_branch(args.git_command)
if branch == 'HEAD':
sys.stderr.write('Blender git repository is in detached HEAD state, must be in a branch\n')
sys.exit(1)
tag = make_utils.git_tag(args.git_command)
release_version = make_utils.git_branch_release_version(branch, tag)
blender_version = make_utils. parse_blender_version()
if blender_version.cycle != 'alpha':
major = blender_version.version // 100
minor = blender_version.version % 100
branch = f"blender-v{major}.{minor}-release"
release_version: Optional[str] = f"{major}.{minor}"
else:
branch = 'main'
release_version = None
if not args.no_libraries:
svn_update(args, release_version)

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 = V3.5
PROJECT_NUMBER = V3.6
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@ -476,7 +476,7 @@ MODULE_GROUPING = {
# -------------------------------BLENDER----------------------------------------
# converting bytes to strings, due to T30154
# Converting bytes to strings, due to #30154.
BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8')
BLENDER_REVISION_TIMESTAMP = bpy.app.build_commit_timestamp
@ -487,7 +487,7 @@ BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
if BLENDER_REVISION != "Unknown":
# SHA1 Git hash
BLENDER_VERSION_HASH = BLENDER_REVISION
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://developer.blender.org/rB%s>%s</a>" % (
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://projects.blender.org/blender/blender/commit/%s>%s</a>" % (
BLENDER_VERSION_HASH, BLENDER_VERSION_HASH,
)
BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
@ -647,7 +647,7 @@ def undocumented_message(module_name, type_name, identifier):
module_name, type_name, identifier,
)
return "Undocumented, consider `contributing <https://developer.blender.org/T51061>`__."
return "Undocumented, consider `contributing <https://developer.blender.org/>`__."
def range_str(val):
@ -2200,7 +2200,7 @@ def write_rst_enum_items(basepath, key, key_no_prefix, enum_items):
Write a single page for a static enum in RST.
This helps avoiding very large lists being in-lined in many places which is an issue
especially with icons in ``bpy.types.UILayout``. See T87008.
especially with icons in ``bpy.types.UILayout``. See #87008.
"""
filepath = os.path.join(basepath, "%s.rst" % key_no_prefix)
with open(filepath, "w", encoding="utf-8") as fh:

View File

@ -1676,17 +1676,20 @@ class CyclesPreferences(bpy.types.AddonPreferences):
col.label(text="and NVIDIA driver version %s or newer" % driver_version,
icon='BLANK1', translate=False)
elif device_type == 'HIP':
import sys
if sys.platform[:3] == "win":
driver_version = "21.Q4"
col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1')
col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version,
icon='BLANK1', translate=False)
elif sys.platform.startswith("linux"):
driver_version = "22.10"
col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1')
col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1',
translate=False)
if True:
col.label(text="HIP temporarily disabled due to compiler bugs", icon='BLANK1')
else:
import sys
if sys.platform[:3] == "win":
driver_version = "21.Q4"
col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1')
col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version,
icon='BLANK1', translate=False)
elif sys.platform.startswith("linux"):
driver_version = "22.10"
col.label(text="Requires AMD GPU with Vega or RDNA architecture", icon='BLANK1')
col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1',
translate=False)
elif device_type == 'ONEAPI':
import sys
if sys.platform.startswith("win"):

View File

@ -20,7 +20,7 @@ class CyclesPresetPanel(PresetPanel, Panel):
@staticmethod
def post_cb(context):
# Modify an arbitrary built-in scene property to force a depsgraph
# update, because add-on properties don't. (see T62325)
# update, because add-on properties don't. (see #62325)
render = context.scene.render
render.filter_size = render.filter_size

View File

@ -105,11 +105,12 @@ GPUShader *BlenderFallbackDisplayShader::bind(int width, int height)
/* Bind shader now to enable uniform assignment. */
GPU_shader_bind(shader_program_);
GPU_shader_uniform_int(shader_program_, image_texture_location_, 0);
int slot = 0;
GPU_shader_uniform_int_ex(shader_program_, image_texture_location_, 1, 1, &slot);
float size[2];
size[0] = width;
size[1] = height;
GPU_shader_uniform_vector(shader_program_, fullscreen_location_, 2, 1, size);
GPU_shader_uniform_float_ex(shader_program_, fullscreen_location_, 2, 1, size);
return shader_program_;
}

View File

@ -20,7 +20,7 @@ BlenderImageLoader::BlenderImageLoader(BL::Image b_image,
: b_image(b_image),
frame(frame),
tile_number(tile_number),
/* Don't free cache for preview render to avoid race condition from T93560, to be fixed
/* Don't free cache for preview render to avoid race condition from #93560, to be fixed
* properly later as we are close to release. */
free_cache(!is_preview_render && !b_image.has_data())
{
@ -72,7 +72,7 @@ bool BlenderImageLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaDat
metadata.colorspace = u_colorspace_raw;
}
else {
/* In some cases (e.g. T94135), the colorspace setting in Blender gets updated as part of the
/* In some cases (e.g. #94135), the colorspace setting in Blender gets updated as part of the
* metadata queries in this function, so update the colorspace setting here. */
PointerRNA colorspace_ptr = b_image.colorspace_settings().ptr;
metadata.colorspace = get_enum_identifier(colorspace_ptr, "name");

View File

@ -24,7 +24,7 @@ void BlenderSync::sync_light(BL::Object &b_parent,
Light *light = light_map.find(key);
/* Check if the transform was modified, in case a linked collection is moved we do not get a
* specific depsgraph update (T88515). This also mimics the behavior for Objects. */
* specific depsgraph update (#88515). This also mimics the behavior for Objects. */
const bool tfm_updated = (light && light->get_tfm() != tfm);
/* Update if either object or light data changed. */

View File

@ -94,7 +94,7 @@ void python_thread_state_restore(void **python_thread_state)
*python_thread_state = NULL;
}
static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
static const char *PyC_UnicodeAsBytes(PyObject *py_str, PyObject **coerce)
{
const char *result = PyUnicode_AsUTF8(py_str);
if (result) {
@ -131,8 +131,8 @@ static PyObject *init_func(PyObject * /*self*/, PyObject *args)
}
PyObject *path_coerce = nullptr, *user_path_coerce = nullptr;
path_init(PyC_UnicodeAsByte(path, &path_coerce),
PyC_UnicodeAsByte(user_path, &user_path_coerce));
path_init(PyC_UnicodeAsBytes(path, &path_coerce),
PyC_UnicodeAsBytes(user_path, &user_path_coerce));
Py_XDECREF(path_coerce);
Py_XDECREF(user_path_coerce);

View File

@ -404,7 +404,7 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
* point we know that we've got everything to render current view layer.
*/
/* At the moment we only free if we are not doing multi-view
* (or if we are rendering the last view). See T58142/D4239 for discussion.
* (or if we are rendering the last view). See #58142/D4239 for discussion.
*/
if (view_index == num_views - 1) {
free_blender_memory_if_possible();

View File

@ -766,7 +766,7 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
(BlenderSession::headless || is_interface_locked) &&
/* Baking re-uses the depsgraph multiple times, clearing crashes
* reading un-evaluated mesh data which isn't aligned with the
* geometry we're baking, see T71012. */
* geometry we're baking, see #71012. */
!scene->bake_manager->get_baking() &&
/* Persistent data must main caches for performance and correctness. */
!is_persistent_data;

View File

@ -42,12 +42,15 @@ endif()
###########################################################################
if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
find_package(HIP)
set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
set(WITH_CYCLES_HIP_BINARIES OFF)
message(STATUS "HIP temporarily disabled due to compiler bugs")
if(HIP_FOUND)
message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
endif()
# find_package(HIP)
# set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
# if(HIP_FOUND)
# message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
# endif()
endif()
if(NOT WITH_HIP_DYNLOAD)

View File

@ -906,7 +906,7 @@ bool HIPDevice::should_use_graphics_interop()
* possible, but from the empiric measurements it can be considerably slower than using naive
* pixels copy. */
/* Disable graphics interop for now, because of driver bug in 21.40. See T92972 */
/* Disable graphics interop for now, because of driver bug in 21.40. See #92972 */
# if 0
HIPContextScope scope(this);

View File

@ -51,7 +51,7 @@ static inline bool hipSupportsDevice(const int hipDevId)
hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId);
hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId);
return (major >= 10);
return (major >= 9);
}
CCL_NAMESPACE_END

View File

@ -586,7 +586,7 @@ void MetalDevice::erase_allocation(device_memory &mem)
if (it != metal_mem_map.end()) {
MetalMem *mmem = it->second.get();
/* blank out reference to MetalMem* in the launch params (fixes crash T94736) */
/* blank out reference to MetalMem* in the launch params (fixes crash #94736) */
if (mmem->pointer_index >= 0) {
device_ptr *pointers = (device_ptr *)&launch_params;
pointers[mmem->pointer_index] = 0;

View File

@ -886,7 +886,7 @@ int RenderScheduler::get_num_samples_during_navigation(int resolution_divider) c
{
/* Special trick for fast navigation: schedule multiple samples during fast navigation
* (which will prefer to use lower resolution to keep up with refresh rate). This gives more
* usable visual feedback for artists. There are a couple of tricks though. */
* usable visual feedback for artists. */
if (is_denoise_active_during_update()) {
/* When denoising is used during navigation prefer using a higher resolution with less samples
@ -896,25 +896,12 @@ int RenderScheduler::get_num_samples_during_navigation(int resolution_divider) c
return 1;
}
if (resolution_divider <= pixel_size_) {
/* When resolution divider is at or below pixel size, schedule one sample. This doesn't effect
* the sample count at this resolution division, but instead assists in the calculation of
* the resolution divider. */
return 1;
}
if (resolution_divider == pixel_size_ * 2) {
/* When resolution divider is the previous step to the final resolution, schedule two samples.
* This is so that rendering on lower resolution does not exceed time that it takes to render
* first sample at the full resolution. */
return 2;
}
/* Always render 4 samples, even if scene is configured for less.
* The idea here is to have enough information on the screen. Resolution divider of 2 allows us
* to have 4 time extra samples, so overall worst case timing is the same as the final resolution
* at one sample. */
return 4;
/* Schedule samples equal to the resolution divider up to a maximum of 4.
* The idea is to have enough information on the screen by increasing the sample count as the
* resolution is decreased. */
/* NOTE: Changing this formula will change the formula in
* `RenderScheduler::calculate_resolution_divider_for_time()`. */
return min(max(1, resolution_divider / pixel_size_), 4);
}
bool RenderScheduler::work_need_adaptive_filter() const
@ -1100,9 +1087,10 @@ void RenderScheduler::update_start_resolution_divider()
/* TODO(sergey): Need to add hysteresis to avoid resolution divider bouncing around when actual
* render time is somewhere on a boundary between two resolutions. */
/* Never increase resolution to higher than the pixel size (which is possible if the scene is
* simple and compute device is fast). */
start_resolution_divider_ = max(resolution_divider_for_update, pixel_size_);
/* Don't let resolution drop below the desired one. It's better to be slow than provide an
* unreadable viewport render. */
start_resolution_divider_ = min(resolution_divider_for_update,
default_start_resolution_divider_);
VLOG_WORK << "Calculated resolution divider is " << start_resolution_divider_;
}
@ -1187,24 +1175,24 @@ void RenderScheduler::check_time_limit_reached()
int RenderScheduler::calculate_resolution_divider_for_time(double desired_time, double actual_time)
{
/* TODO(sergey): There should a non-iterative analytical formula here. */
const double ratio_between_times = actual_time / desired_time;
int resolution_divider = 1;
/* We can pass `ratio_between_times` to `get_num_samples_during_navigation()` to get our
* navigation samples because the equation for calculating the resolution divider is as follows:
* `actual_time / desired_time = sqr(resolution_divider) / sample_count`.
* While `resolution_divider` is less than or equal to 4, `resolution_divider = sample_count`
* (This relationship is determined in `get_num_samples_during_navigation()`). With some
* substitution we end up with `actual_time / desired_time = resolution_divider` while the
* resolution divider is less than or equal to 4. Once the resolution divider increases above 4,
* the relationship of `actual_time / desired_time = resolution_divider` is no longer true,
* however the sample count retrieved from `get_num_samples_during_navigation()` is still
* accurate if we continue using this assumption. It should be noted that the interaction between
* `pixel_size`, sample count, and resolution divider are automatically accounted for and that's
* why `pixel_size` isn't included in any of the equations. */
const int navigation_samples = get_num_samples_during_navigation(
ceil_to_int(ratio_between_times));
/* This algorithm iterates through resolution dividers until a divider is found that achieves
* the desired render time. A limit of default_start_resolution_divider_ is put in place as the
* maximum resolution divider to avoid an unreadable viewport due to a low resolution.
* pre_resolution_division_samples and post_resolution_division_samples are used in this
* calculation to better predict the performance impact of changing resolution divisions as
* the sample count can also change between resolution divisions. */
while (actual_time > desired_time && resolution_divider < default_start_resolution_divider_) {
int pre_resolution_division_samples = get_num_samples_during_navigation(resolution_divider);
resolution_divider = resolution_divider * 2;
int post_resolution_division_samples = get_num_samples_during_navigation(resolution_divider);
actual_time /= 4.0 * pre_resolution_division_samples / post_resolution_division_samples;
}
return resolution_divider;
return ceil_to_int(sqrt(navigation_samples * ratio_between_times));
}
int calculate_resolution_divider_for_resolution(int width, int height, int resolution)

View File

@ -412,11 +412,12 @@ if(WITH_CYCLES_CUDA_BINARIES)
# warn for other versions
if((CUDA_VERSION STREQUAL "101") OR
(CUDA_VERSION STREQUAL "102") OR
(CUDA_VERSION_MAJOR STREQUAL "11"))
(CUDA_VERSION_MAJOR STREQUAL "11") OR
(CUDA_VERSION_MAJOR STREQUAL "12"))
else()
message(WARNING
"CUDA version ${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR} detected, "
"build may succeed but only CUDA 11, 10.2 and 10.1 have been tested")
"build may succeed but only CUDA 12, 11, 10.2 and 10.1 have been tested")
endif()
# build for each arch
@ -514,6 +515,16 @@ if(WITH_CYCLES_CUDA_BINARIES)
else()
message(STATUS "CUDA binaries for ${arch} require CUDA 10 or earlier, skipped.")
endif()
elseif(${arch} MATCHES ".*_3.")
if(DEFINED CUDA11_NVCC_EXECUTABLE)
set(cuda_nvcc_executable ${CUDA11_NVCC_EXECUTABLE})
set(cuda_toolkit_root_dir ${CUDA11_TOOLKIT_ROOT_DIR})
elseif("${CUDA_VERSION}" LESS 120) # Support for sm_35, sm_37 was removed in CUDA 12
set(cuda_nvcc_executable ${CUDA_NVCC_EXECUTABLE})
set(cuda_toolkit_root_dir ${CUDA_TOOLKIT_ROOT_DIR})
else()
message(STATUS "CUDA binaries for ${arch} require CUDA 11 or earlier, skipped.")
endif()
elseif(${arch} MATCHES ".*_7." AND "${CUDA_VERSION}" LESS 100)
message(STATUS "CUDA binaries for ${arch} require CUDA 10.0+, skipped.")
elseif(${arch} MATCHES ".*_8.")

View File

@ -686,7 +686,7 @@ ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd,
albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value;
break;
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
albedo *= bsdf_principled_hair_albedo(sc);
albedo *= bsdf_principled_hair_albedo(sd, sc);
break;
default:
break;

View File

@ -478,10 +478,18 @@ ccl_device_inline float bsdf_principled_hair_albedo_roughness_scale(
return (((((0.245f * x) + 5.574f) * x - 10.73f) * x + 2.532f) * x - 0.215f) * x + 5.969f;
}
ccl_device Spectrum bsdf_principled_hair_albedo(ccl_private const ShaderClosure *sc)
ccl_device Spectrum bsdf_principled_hair_albedo(ccl_private const ShaderData *sd,
ccl_private const ShaderClosure *sc)
{
ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)sc;
return exp(-sqrt(bsdf->sigma) * bsdf_principled_hair_albedo_roughness_scale(bsdf->v));
const float cos_theta_o = cos_from_sin(dot(sd->wi, safe_normalize(sd->dPdu)));
const float cos_gamma_o = cos_from_sin(bsdf->extra->geom.w);
const float f = fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta);
const float roughness_scale = bsdf_principled_hair_albedo_roughness_scale(bsdf->v);
/* TODO(lukas): Adding the Fresnel term here as a workaround until the proper refactor. */
return exp(-sqrt(bsdf->sigma) * roughness_scale) + make_spectrum(f);
}
ccl_device_inline Spectrum

View File

@ -10,7 +10,7 @@
#ifndef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
# define KERNEL_STUB
#else
/* SSE optimization disabled for now on 32 bit, see bug T36316. */
/* SSE optimization disabled for now on 32 bit, see bug #36316. */
# if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
# define __KERNEL_SSE__
# define __KERNEL_SSE2__

View File

@ -10,7 +10,7 @@
#ifndef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
# define KERNEL_STUB
#else
/* SSE optimization disabled for now on 32 bit, see bug T36316. */
/* SSE optimization disabled for now on 32 bit, see bug #36316. */
# if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
# define __KERNEL_SSE2__
# endif

View File

@ -10,7 +10,7 @@
#ifndef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
# define KERNEL_STUB
#else
/* SSE optimization disabled for now on 32 bit, see bug T36316. */
/* SSE optimization disabled for now on 32 bit, see bug #36316. */
# if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
# define __KERNEL_SSE2__
# define __KERNEL_SSE3__

View File

@ -645,7 +645,7 @@ ccl_device_inline void kernel_gpu_film_convert_half_write(ccl_global uchar4 *rgb
const int y,
const half4 half_pixel)
{
/* Work around HIP issue with half float display, see T92972. */
/* Work around HIP issue with half float display, see #92972. */
#ifdef __KERNEL_HIP__
ccl_global half *out = ((ccl_global half *)rgba) + (rgba_offset + y * rgba_stride + x) * 4;
out[0] = half_pixel.x;

View File

@ -122,7 +122,7 @@ KERNEL_STRUCT_MEMBER(guiding, bool, use_surface_guiding, KERNEL_FEATURE_PATH_GUI
KERNEL_STRUCT_MEMBER(guiding, float, sample_surface_guiding_rand, KERNEL_FEATURE_PATH_GUIDING)
/* The probability to use surface guiding (i.e., diffuse sampling prob * guiding prob)*/
KERNEL_STRUCT_MEMBER(guiding, float, surface_guiding_sampling_prob, KERNEL_FEATURE_PATH_GUIDING)
/* Probability of sampling a BSSRDF closure instead of a BSDF closure*/
/* Probability of sampling a BSSRDF closure instead of a BSDF closure. */
KERNEL_STRUCT_MEMBER(guiding, float, bssrdf_sampling_prob, KERNEL_FEATURE_PATH_GUIDING)
/* If volume guiding is enabled */
KERNEL_STRUCT_MEMBER(guiding, bool, use_volume_guiding, KERNEL_FEATURE_PATH_GUIDING)

View File

@ -1177,7 +1177,7 @@ void LightManager::device_update(Device *device,
void LightManager::device_free(Device *, DeviceScene *dscene, const bool free_background)
{
/* to-do: check if the light tree member variables need to be wrapped in a conditional too*/
/* TODO: check if the light tree member variables need to be wrapped in a conditional too. */
dscene->light_tree_nodes.free();
dscene->light_tree_emitters.free();
dscene->light_to_tree.free();

View File

@ -394,7 +394,7 @@ bool OSLShaderManager::osl_compile(const string &inputfile, const string &output
/* Compile.
*
* Mutex protected because the OSL compiler does not appear to be thread safe, see T92503. */
* Mutex protected because the OSL compiler does not appear to be thread safe, see #92503. */
static thread_mutex osl_compiler_mutex;
thread_scoped_lock lock(osl_compiler_mutex);

View File

@ -573,7 +573,7 @@ void ShaderManager::device_update_common(Device * /*device*/,
kfilm->is_rec709 = is_rec709;
}
void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
void ShaderManager::device_free_common(Device * /*device*/, DeviceScene *dscene, Scene * /*scene*/)
{
dscene->shaders.free();
}

View File

@ -520,7 +520,7 @@ bool TileManager::write_tile(const RenderBuffers &tile_buffers)
/* If there is an overscan used for the tile copy pixels into single continuous block of memory
* without any "gaps".
* This is a workaround for bug in OIIO (https://github.com/OpenImageIO/oiio/pull/3176).
* Our task reference: T93008. */
* Our task reference: #93008. */
if (tile_params.window_x || tile_params.window_y ||
tile_params.window_width != tile_params.width ||
tile_params.window_height != tile_params.height) {

View File

@ -421,7 +421,7 @@ ccl_device_inline float fast_expf(float x)
#if !defined(__KERNEL_GPU__) && !defined(_MSC_VER)
/* MSVC seems to have a code-gen bug here in at least SSE41/AVX, see
* T78047 and T78869 for details. Just disable for now, it only makes
* #78047 and #78869 for details. Just disable for now, it only makes
* a small difference in denoising performance. */
ccl_device float4 fast_exp2f4(float4 x)
{

View File

@ -516,7 +516,7 @@ GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles()
/* OpenGL on Metal
*
* Use Metal layer to avoid Viewport lagging on macOS, see T60043. */
* Use Metal layer to avoid Viewport lagging on macOS, see #60043. */
static const MTLPixelFormat METAL_FRAMEBUFFERPIXEL_FORMAT = MTLPixelFormatBGRA8Unorm;
static const OSType METAL_CORE_VIDEO_PIXEL_FORMAT = kCVPixelFormatType_32BGRA;

View File

@ -141,7 +141,7 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
/* -------------------------------------------------------------------- */
#else
/* Important to initialize only GLXEW (_not_ GLEW),
* since this breaks w/ Mesa's `swrast`, see: T46431. */
* since this breaks w/ Mesa's `swrast`, see: #46431. */
glxewInit();
#endif /* USE_GLXEW_INIT_WORKAROUND */

View File

@ -302,7 +302,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
switch (product_id) {
case 0xC62E: /* Plugged in. */
case 0xC62F: /* Wireless. */
case 0xC658: /* Wireless (3DConnexion Universal Wireless Receiver in WIN32), see T82412. */
case 0xC658: /* Wireless (3DConnexion Universal Wireless Receiver in WIN32), see #82412. */
{
device_type_ = NDOF_SpaceMouseWireless;
hid_map_button_num_ = 2;
@ -341,7 +341,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
hid_map_button_mask_ = int(~(UINT_MAX << hid_map_button_num_));
}
CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", hid_map_button_num_, (uint)hid_map_button_mask_);
CLOG_INFO(LOG, 2, "%d buttons -> hex:%X", hid_map_button_num_, uint(hid_map_button_mask_));
return device_type_ != NDOF_UnknownDevice;
}
@ -445,14 +445,14 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
2,
"button=%d, press=%d (out of range %d, ignoring!)",
button_number,
(int)press,
int(press),
hid_map_button_num_);
return;
}
const NDOF_ButtonT button = hid_map_[button_number];
if (button == NDOF_BUTTON_NONE) {
CLOG_INFO(
LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, (int)press);
LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, int(press));
return;
}
@ -460,7 +460,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
2,
"button=%d, press=%d, name=%s",
button_number,
(int)press,
int(press),
ndof_button_names[button]);
GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow();

View File

@ -141,7 +141,7 @@ constexpr size_t events_pending_default_size = 4096 / sizeof(void *);
* \{ */
/**
* GNOME (mutter 42.2 had a bug with confine not respecting scale - Hi-DPI), See: T98793.
* GNOME (mutter 42.2 had a bug with confine not respecting scale - Hi-DPI), See: #98793.
* Even though this has been fixed, at time of writing it's not yet in a release.
* Workaround the problem by implementing confine with a software cursor.
* While this isn't ideal, it's not adding a lot of overhead as software
@ -176,7 +176,7 @@ static bool use_gnome_confine_hack = false;
/**
* KDE (plasma 5.26.1) has a bug where the cursor surface needs to be committed
* (via `wl_surface_commit`) when it was hidden and is being set to visible again, see: T102048.
* (via `wl_surface_commit`) when it was hidden and is being set to visible again, see: #102048.
* See: https://bugs.kde.org/show_bug.cgi?id=461001
*/
#define USE_KDE_TABLET_HIDDEN_CURSOR_HACK
@ -197,8 +197,8 @@ static bool use_gnome_confine_hack = false;
* \{ */
/**
* Fix short-cut part of keyboard reading code not properly handling some keys, see: T102194.
* \note This is similar to X11 workaround by the same name, see: T47228.
* Fix short-cut part of keyboard reading code not properly handling some keys, see: #102194.
* \note This is similar to X11 workaround by the same name, see: #47228.
*/
#define USE_NON_LATIN_KB_WORKAROUND
@ -1328,7 +1328,7 @@ static void ghost_wl_display_report_error(struct wl_display *display)
* So in practice re-connecting to the display server isn't an option.
*
* Exit since leaving the process open will simply flood the output and do nothing.
* Although as the process is in a valid state, auto-save for e.g. is possible, see: T100855. */
* Although as the process is in a valid state, auto-save for e.g. is possible, see: #100855. */
::exit(-1);
}
@ -1442,7 +1442,7 @@ static GHOST_TKey xkb_map_gkey(const xkb_keysym_t sym)
/* Additional keys for non US layouts. */
/* Uses the same physical key as #XKB_KEY_KP_Decimal for QWERTZ layout, see: T102287. */
/* Uses the same physical key as #XKB_KEY_KP_Decimal for QWERTZ layout, see: #102287. */
GXMAP(gkey, XKB_KEY_KP_Separator, GHOST_kKeyNumpadPeriod);
default:
@ -3810,7 +3810,7 @@ static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(
/* NOTE(@ideasman42): Only perform the number-locked lookup as a fallback
* when a number-pad key has been pressed. This is important as some key-maps use number lock
* for switching other layers (in particular `de(neo_qwertz)` turns on layer-4), see: T96170.
* for switching other layers (in particular `de(neo_qwertz)` turns on layer-4), see: #96170.
* Alternative solutions could be to inspect the layout however this could get involved
* and turning on the number-lock is only needed for a limited set of keys. */
@ -4467,7 +4467,7 @@ static void xdg_output_handle_logical_size(void *data,
#ifdef USE_GNOME_CONFINE_HACK
/* Use a bug in GNOME to check GNOME is in use. If the bug is fixed this won't cause an issue
* as T98793 has been fixed up-stream too, but not in a release at time of writing. */
* as #98793 has been fixed up-stream too, but not in a release at time of writing. */
use_gnome_confine_hack = true;
#endif

View File

@ -208,7 +208,7 @@ class GHOST_SystemWayland : public GHOST_System {
* Clear all references to this output.
*
* \note The compositor should have already called the `wl_surface_listener.leave` callback,
* however some compositors may not (see T103586).
* however some compositors may not (see #103586).
* So remove references to the output before it's destroyed to avoid crashing.
*
* \return true when any references were removed.

View File

@ -565,8 +565,8 @@ GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw, bool *r_key_down)
/**
* \note this function can be extended to include other exotic cases as they arise.
*
* This function was added in response to bug T25715.
* This is going to be a long list T42426.
* This function was added in response to bug #25715.
* This is going to be a long list #42426.
*/
GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short scanCode) const
{
@ -1083,7 +1083,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
* so the box needs to small enough not to let the cursor escape the window but large
* enough that the cursor isn't being warped every time.
* If this was not the case it would be less trouble to simply warp the cursor to the
* center of the screen on every motion, see: D16558 (alternative fix for T102346). */
* center of the screen on every motion, see: D16558 (alternative fix for #102346). */
const int32_t subregion_div = 4; /* One quarter of the region. */
const int32_t size[2] = {bounds.getWidth(), bounds.getHeight()};
const int32_t center[2] = {(bounds.m_l + bounds.m_r) / 2, (bounds.m_t + bounds.m_b) / 2};
@ -1209,7 +1209,7 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
const bool ctrl_pressed = has_state && state[VK_CONTROL] & 0x80;
const bool alt_pressed = has_state && state[VK_MENU] & 0x80;
/* We can be here with !key_down if processing dead keys (diacritics). See T103119. */
/* We can be here with !key_down if processing dead keys (diacritics). See #103119. */
/* No text with control key pressed (Alt can be used to insert special characters though!). */
if (ctrl_pressed && !alt_pressed) {

View File

@ -46,7 +46,7 @@
#ifdef WITH_X11_XFIXES
# include <X11/extensions/Xfixes.h>
/* Workaround for XWayland grab glitch: T53004. */
/* Workaround for XWayland grab glitch: #53004. */
# define WITH_XWAYLAND_HACK
#endif
@ -71,11 +71,11 @@
# define USE_XINPUT_HOTPLUG
#endif
/* see T34039 Fix Alt key glitch on Unity desktop */
/* see #34039 Fix Alt key glitch on Unity desktop */
#define USE_UNITY_WORKAROUND
/* Fix 'shortcut' part of keyboard reading code only ever using first defined key-map
* instead of active one. See T47228 and D1746 */
* instead of active one. See #47228 and D1746 */
#define USE_NON_LATIN_KB_WORKAROUND
static uchar bit_is_on(const uchar *ptr, int bit)
@ -928,7 +928,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
window->getClientBounds(bounds);
/* TODO(@ideasman42): warp the cursor to `window->getCursorGrabInitPos`,
* on every motion event, see: D16557 (alternative fix for T102346). */
* on every motion event, see: D16557 (alternative fix for #102346). */
const int32_t subregion_div = 4; /* One quarter of the region. */
const int32_t size[2] = {bounds.getWidth(), bounds.getHeight()};
const int32_t center[2] = {
@ -964,7 +964,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
if (x_new != xme.x_root || y_new != xme.y_root) {
/* Use time of last event to avoid wrapping several times on the 'same' actual wrap.
* Note that we need to deal with X and Y separately as those might wrap at the same time
* but still in two different events (corner case, see T74918).
* but still in two different events (corner case, see #74918).
* We also have to add a few extra milliseconds of 'padding', as sometimes we get two
* close events that will generate extra wrap on the same axis within those few
* milliseconds. */
@ -1028,7 +1028,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
/* XXX: Code below is kinda awfully convoluted... Issues are:
* - In keyboards like Latin ones, numbers need a 'Shift' to be accessed but key_sym
* is unmodified (or anyone swapping the keys with `xmodmap`).
* - #XLookupKeysym seems to always use first defined key-map (see T47228), which generates
* - #XLookupKeysym seems to always use first defined key-map (see #47228), which generates
* key-codes unusable by ghost_key_from_keysym for non-Latin-compatible key-maps.
*
* To address this, we:
@ -1715,7 +1715,7 @@ GHOST_TSuccess GHOST_SystemX11::setCursorPosition(int32_t x, int32_t y)
#if defined(WITH_X11_XINPUT) && defined(USE_X11_XINPUT_WARP)
if ((m_xinput_version.present) && (m_xinput_version.major_version >= 2)) {
/* Needed to account for XInput "Coordinate Transformation Matrix", see T48901 */
/* Needed to account for XInput "Coordinate Transformation Matrix", see #48901 */
int device_id;
if (XIGetClientPointer(m_display, None, &device_id) != False) {
XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, relx, rely);

View File

@ -20,8 +20,8 @@
/* Disable XINPUT warp, currently not implemented by Xorg for multi-head display.
* (see comment in XSERVER `Xi/xiwarppointer.c` -> `FIXME: panoramix stuff is missing` ~ v1.13.4)
* If this is supported we can add back XINPUT for warping (fixing T48901).
* For now disable (see T50383). */
* If this is supported we can add back XINPUT for warping (fixing #48901).
* For now disable (see #50383). */
// # define USE_X11_XINPUT_WARP
#endif

View File

@ -306,14 +306,23 @@ static void gwl_window_frame_update_from_pending(GWL_Window *win);
#ifdef USE_EVENT_BACKGROUND_THREAD
enum eGWL_PendingWindowActions {
PENDING_FRAME_CONFIGURE = 0,
PENDING_EGL_RESIZE,
/**
* The state of the window frame has changed, apply the state from #GWL_Window::frame_pending.
*/
PENDING_WINDOW_FRAME_CONFIGURE = 0,
/** The EGL buffer must be resized to match #GWL_WindowFrame::size. */
PENDING_EGL_WINDOW_RESIZE,
# ifdef GHOST_OPENGL_ALPHA
/** Draw an opaque region behind the window. */
PENDING_OPAQUE_SET,
# endif
PENDING_SCALE_UPDATE,
/**
* The DPI for a monitor has changed or the monitors (outputs)
* this window is visible on may have changed. Recalculate the windows scale.
*/
PENDING_OUTPUT_SCALE_UPDATE,
};
# define PENDING_NUM (PENDING_SCALE_UPDATE + 1)
# define PENDING_NUM (PENDING_OUTPUT_SCALE_UPDATE + 1)
static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWindowActions type)
{
@ -323,10 +332,10 @@ static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWin
static void gwl_window_pending_actions_handle(GWL_Window *win)
{
if (win->pending_actions[PENDING_FRAME_CONFIGURE].exchange(false)) {
if (win->pending_actions[PENDING_WINDOW_FRAME_CONFIGURE].exchange(false)) {
gwl_window_frame_update_from_pending(win);
}
if (win->pending_actions[PENDING_EGL_RESIZE].exchange(false)) {
if (win->pending_actions[PENDING_EGL_WINDOW_RESIZE].exchange(false)) {
wl_egl_window_resize(win->egl_window, UNPACK2(win->frame.size), 0, 0);
}
# ifdef GHOST_OPENGL_ALPHA
@ -334,7 +343,7 @@ static void gwl_window_pending_actions_handle(GWL_Window *win)
win->ghost_window->setOpaque();
}
# endif
if (win->pending_actions[PENDING_SCALE_UPDATE].exchange(false)) {
if (win->pending_actions[PENDING_OUTPUT_SCALE_UPDATE].exchange(false)) {
win->ghost_window->outputs_changed_update_scale();
}
}
@ -342,9 +351,10 @@ static void gwl_window_pending_actions_handle(GWL_Window *win)
#endif /* USE_EVENT_BACKGROUND_THREAD */
/**
* Update the window's #GWL_WindowFrame
* Update the window's #GWL_WindowFrame.
* The caller must handle locking & run from the main thread.
*/
static void gwl_window_frame_update_from_pending_lockfree(GWL_Window *win)
static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win)
{
#ifdef USE_EVENT_BACKGROUND_THREAD
GHOST_ASSERT(win->ghost_system->main_thread_id == std::this_thread::get_id(),
@ -381,7 +391,7 @@ static void gwl_window_frame_update_from_pending(GWL_Window *win)
#ifdef USE_EVENT_BACKGROUND_THREAD
std::lock_guard lock_frame_guard{win->frame_pending_mutex};
#endif
gwl_window_frame_update_from_pending_lockfree(win);
gwl_window_frame_update_from_pending_no_lock(win);
}
/** \} */
@ -576,12 +586,12 @@ static void frame_handle_configure(struct libdecor_frame *frame,
GHOST_SystemWayland *system = win->ghost_system;
const bool is_main_thread = system->main_thread_id == std::this_thread::get_id();
if (!is_main_thread) {
gwl_window_pending_actions_tag(win, PENDING_FRAME_CONFIGURE);
gwl_window_pending_actions_tag(win, PENDING_WINDOW_FRAME_CONFIGURE);
}
else
# endif
{
gwl_window_frame_update_from_pending_lockfree(win);
gwl_window_frame_update_from_pending_no_lock(win);
}
}
}
@ -671,7 +681,7 @@ static void xdg_surface_handle_configure(void *data,
if (!is_main_thread) {
/* NOTE(@ideasman42): this only gets one redraw,
* I could not find a case where this causes problems. */
gwl_window_pending_actions_tag(win, PENDING_FRAME_CONFIGURE);
gwl_window_pending_actions_tag(win, PENDING_WINDOW_FRAME_CONFIGURE);
}
else
#endif
@ -812,12 +822,12 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
* when the `window_->scale` changed. */
const int32_t size_min[2] = {320, 240};
/* This value is expected to match the base name of the `.desktop` file. see T101805.
/* This value is expected to match the base name of the `.desktop` file. see #101805.
*
* NOTE: the XDG desktop-entry-spec defines that this should follow the "reverse DNS" convention.
* For e.g. `org.blender.Blender` - however the `.desktop` file distributed with Blender is
* simply called `blender.desktop`, so the it's important to follow that name.
* Other distributions such as SNAP & FLATPAK may need to change this value T101779.
* Other distributions such as SNAP & FLATPAK may need to change this value #101779.
* Currently there isn't a way to configure this, we may want to support that. */
const char *xdg_app_id = (
#ifdef WITH_GHOST_WAYLAND_APP_ID
@ -1080,7 +1090,7 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
/* NOTE(@ideasman42): Flushing will often run the appropriate handlers event
* (#wl_surface_listener.leave in particular) to avoid attempted access to the freed surfaces.
* This is not fool-proof though, hence the call to #window_surface_unref, see: T99078. */
* This is not fool-proof though, hence the call to #window_surface_unref, see: #99078. */
wl_display_flush(system_->wl_display());
delete window_;
@ -1373,7 +1383,7 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
{
#ifdef USE_EVENT_BACKGROUND_THREAD
if (system_->main_thread_id != std::this_thread::get_id()) {
gwl_window_pending_actions_tag(window_, PENDING_SCALE_UPDATE);
gwl_window_pending_actions_tag(window_, PENDING_OUTPUT_SCALE_UPDATE);
return false;
}
#endif

View File

@ -15,7 +15,7 @@
#include <wayland-util.h> /* For #wl_fixed_t */
/**
* Define to workaround for a bug/limitation in WAYLAND, see: T100855 & upstream report:
* Define to workaround for a bug/limitation in WAYLAND, see: #100855 & upstream report:
* https://gitlab.freedesktop.org/wayland/wayland/-/issues/159
*
* Consume events from WAYLAND in a thread, this is needed because overflowing the event queue

View File

@ -93,7 +93,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
RECT win_rect = {left, top, long(left + width), long(top + height)};
adjustWindowRectForClosestMonitor(&win_rect, style, extended_style);
adjustWindowRectForDesktop(&win_rect, style, extended_style);
wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0);
m_hWnd = ::CreateWindowExW(extended_style, /* window extended style */
@ -154,7 +154,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
if (parentwindow) {
/* Release any parent capture to allow immediate interaction (T90110). */
/* Release any parent capture to allow immediate interaction (#90110). */
::ReleaseCapture();
parentwindow->lostMouseCapture();
}
@ -298,24 +298,55 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
m_directManipulationHelper = NULL;
}
void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect,
DWORD dwStyle,
DWORD dwExStyle)
void GHOST_WindowWin32::adjustWindowRectForDesktop(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle)
{
/* Get Details of the closest monitor. */
HMONITOR hmonitor = MonitorFromRect(win_rect, MONITOR_DEFAULTTONEAREST);
/* Windows can span multiple monitors, but must be usable. The desktop can have a larger
* surface than all monitors combined, for example when two monitors are aligned diagonally.
* Therefore we ensure that all the window's corners are within some monitor's Work area. */
POINT pt;
HMONITOR hmonitor;
MONITORINFOEX monitor;
monitor.cbSize = sizeof(MONITORINFOEX);
monitor.dwFlags = 0;
GetMonitorInfo(hmonitor, &monitor);
/* Constrain requested size and position to fit within this monitor. */
LONG width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect->right - win_rect->left);
LONG height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect->bottom - win_rect->top);
win_rect->left = min(max(monitor.rcWork.left, win_rect->left), monitor.rcWork.right - width);
win_rect->right = win_rect->left + width;
win_rect->top = min(max(monitor.rcWork.top, win_rect->top), monitor.rcWork.bottom - height);
win_rect->bottom = win_rect->top + height;
/* We'll need this value before it is altered for checking later. */
LONG requested_top = win_rect->top;
/* Note that with MonitorFromPoint using MONITOR_DEFAULTTONEAREST, it will return
* the exact monitor if there is one at the location or the nearest monitor if not. */
/* Top-left. */
pt.x = win_rect->left;
pt.y = win_rect->top;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->top = max(win_rect->top, monitor.rcWork.top);
win_rect->left = max(win_rect->left, monitor.rcWork.left);
/* Top-right. */
pt.x = win_rect->right;
pt.y = win_rect->top;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->top = max(win_rect->top, monitor.rcWork.top);
win_rect->right = min(win_rect->right, monitor.rcWork.right);
/* Bottom-left. */
pt.x = win_rect->left;
pt.y = win_rect->bottom;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->bottom = min(win_rect->bottom, monitor.rcWork.bottom);
win_rect->left = max(win_rect->left, monitor.rcWork.left);
/* Bottom-right. */
pt.x = win_rect->right;
pt.y = win_rect->bottom;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->bottom = min(win_rect->bottom, monitor.rcWork.bottom);
win_rect->right = min(win_rect->right, monitor.rcWork.right);
/* With Windows 10 and newer we can adjust for chrome that differs with DPI and scale. */
GHOST_WIN32_AdjustWindowRectExForDpi fpAdjustWindowRectExForDpi = nullptr;
@ -327,6 +358,9 @@ void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect,
/* Adjust to allow for caption, borders, shadows, scaling, etc. Resulting values can be
* correctly outside of monitor bounds. NOTE: You cannot specify #WS_OVERLAPPED when calling. */
if (fpAdjustWindowRectExForDpi) {
/* Use the DPI of the monitor that is at the middle of the rect. */
hmonitor = MonitorFromRect(win_rect, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
UINT dpiX, dpiY;
GetDpiForMonitor(hmonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
fpAdjustWindowRectExForDpi(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle, dpiX);
@ -335,7 +369,12 @@ void GHOST_WindowWin32::adjustWindowRectForClosestMonitor(LPRECT win_rect,
AdjustWindowRectEx(win_rect, dwStyle & ~WS_OVERLAPPED, FALSE, dwExStyle);
}
/* But never allow a top position that can hide part of the title bar. */
/* Don't hide the title bar. Check the working area of the monitor at the top-left corner, using
* the original top since the justWindowRects might have altered it to different monitor. */
pt.x = win_rect->left;
pt.y = requested_top;
hmonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
GetMonitorInfo(hmonitor, &monitor);
win_rect->top = max(monitor.rcWork.top, win_rect->top);
}

View File

@ -87,12 +87,12 @@ class GHOST_WindowWin32 : public GHOST_Window {
~GHOST_WindowWin32();
/**
* Adjusts a requested window rect to fit and position correctly in monitor.
* Adjusts a requested window rect to fit and position within the desktop.
* \param win_rect: pointer to rectangle that will be modified.
* \param dwStyle: The Window Style of the window whose required size is to be calculated.
* \param dwExStyle: The Extended Window Style of the window.
*/
void adjustWindowRectForClosestMonitor(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle);
void adjustWindowRectForDesktop(LPRECT win_rect, DWORD dwStyle, DWORD dwExStyle);
/**
* Returns indication as to whether the window is valid.

View File

@ -418,7 +418,7 @@ void GHOST_WindowX11::refreshXInputDevices()
for (GHOST_SystemX11::GHOST_TabletX11 &xtablet : m_system->GetXTablets()) {
/* With modern XInput (XLIB 1.6.2 at least and/or EVDEV 2.9.0) and some 'no-name' tablets
* like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
* otherwise we do not get any tablet motion event once pen is pressed... See T43367.
* otherwise we do not get any tablet motion event once pen is pressed... See #43367.
*/
XEventClass ev;
@ -1467,7 +1467,7 @@ GHOST_TSuccess GHOST_WindowX11::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
}
}
/* Perform this last so to workaround XWayland bug, see: T53004. */
/* Perform this last so to workaround XWayland bug, see: #53004. */
if (m_cursorGrab == GHOST_kGrabHide) {
setWindowCursorVisibility(true);
}

View File

@ -281,6 +281,8 @@ inline T *MEM_new(const char *allocation_name, Args &&...args)
*/
template<typename T> inline void MEM_delete(const T *ptr)
{
static_assert(!std::is_void_v<T>,
"MEM_delete on a void pointer not possible. Cast it to a non-void type?");
if (ptr == nullptr) {
/* Support #ptr being null, because C++ `delete` supports that as well. */
return;

View File

@ -108,7 +108,7 @@ void bl_locale_set(const char *locale)
}
/* Extra catch on `std::runtime_error` is needed for macOS/Clang as it seems that exceptions
* like `boost::locale::conv::conversion_error` (which inherit from `std::runtime_error`) are
* not caught by their ancestor `std::exception`. See T88877#1177108 */
* not caught by their ancestor `std::exception`. See #88877#1177108 */
catch (std::runtime_error const &e) {
std::cout << "bl_locale_set(" << locale << "): " << e.what() << " \n";
}

View File

@ -23,7 +23,7 @@ const char *osx_user_locale()
[myNSLocale autorelease];
// This produces gettext-invalid locale in recent macOS versions (11.4),
// like `ko-Kore_KR` instead of `ko_KR`. See T88877.
// like `ko-Kore_KR` instead of `ko_KR`. See #88877.
// NSString *nsIdentifier = [myNSLocale localeIdentifier];
const NSString *nsIdentifier = [myNSLocale languageCode];

View File

@ -193,7 +193,7 @@ static bool createGPUShader(OCIO_GPUShader &shader,
info.fragment_source("gpu_shader_display_transform_frag.glsl");
info.fragment_source_generated = source;
/* T96502: Work around for incorrect OCIO GLSL code generation when using
/* #96502: Work around for incorrect OCIO GLSL code generation when using
* GradingPrimaryTransform. Should be reevaluated when changing to a next version of OCIO.
* (currently v2.1.1). */
info.define("inf 1e32");

View File

@ -145,7 +145,7 @@ const UserDef U_default = {
.ndof_flag = (NDOF_MODE_ORBIT | NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM |
NDOF_SHOULD_ROTATE |
/* Software from the driver authors follows this convention
* so invert this by default, see: T67579. */
* so invert this by default, see: #67579. */
NDOF_ROTX_INVERT_AXIS | NDOF_ROTY_INVERT_AXIS | NDOF_ROTZ_INVERT_AXIS |
NDOF_PANX_INVERT_AXIS | NDOF_PANY_INVERT_AXIS | NDOF_PANZ_INVERT_AXIS |
NDOF_ZOOM_INVERT | NDOF_CAMERA_PAN_ZOOM),

View File

@ -370,6 +370,7 @@ const bTheme U_theme_default = {
.clipping_border_3d = RGBA(0x3f3f3fff),
.bundle_solid = RGBA(0xc8c8c8ff),
.camera_path = RGBA(0x000000ff),
.camera_passepartout = RGBA(0x000000),
.gp_vertex_size = 3,
.gp_vertex = RGBA(0x000000ff),
.gp_vertex_select = RGBA(0xff8500ff),

View File

@ -286,7 +286,7 @@ class pySketchyChainingIterator(ChainingIterator):
if not found:
# This is a fatal error condition: self.current_edge must be found
# among the edges seen by the AdjacencyIterator [bug T35695].
# among the edges seen by the AdjacencyIterator [bug #35695].
if bpy.app.debug_freestyle:
print('pySketchyChainingIterator: current edge not found')
return None

View File

@ -113,7 +113,7 @@ def expand(line, cursor, namespace, *, private=True):
if len(matches) == 1:
scrollback = ''
else:
# causes blender bug T27495 since string keys may contain '.'
# causes blender bug #27495 since string keys may contain '.'
# scrollback = ' '.join([m.split('.')[-1] for m in matches])
# add white space to align with the cursor

View File

@ -30,7 +30,7 @@ def url_prefill_from_blender(*, addon_info=None):
"**Blender Version**\n"
)
fh.write(
"Broken: version: %s, branch: %s, commit date: %s %s, hash: `rB%s`\n" % (
"Broken: version: %s, branch: %s, commit date: %s %s, hash: `%s`\n" % (
bpy.app.version_string,
bpy.app.build_branch.decode('utf-8', 'replace'),
bpy.app.build_commit_date.decode('utf-8', 'replace'),

View File

@ -32,7 +32,7 @@ class _BPyOpsSubModOp:
# XXX You never quite know what you get from bpy.types,
# with operators... Operator and OperatorProperties
# are shadowing each other, and not in the same way for
# native ops and py ones! See T39158.
# native ops and py ones! See #39158.
# op_class = getattr(bpy.types, idname)
op_class = _op_get_rna_type(idname)
descr = op_class.description

View File

@ -259,15 +259,15 @@ def bake_action_iter(
if is_new_action:
action = bpy.data.actions.new("Action")
# Only leave tweak mode if we actually need to modify the action (T57159)
# Only leave tweak mode if we actually need to modify the action (#57159)
if action != atd.action:
# Leave tweak mode before trying to modify the action (T48397)
# Leave tweak mode before trying to modify the action (#48397)
if atd.use_tweak_mode:
atd.use_tweak_mode = False
atd.action = action
# Baking the action only makes sense in Replace mode, so force it (T69105)
# Baking the action only makes sense in Replace mode, so force it (#69105)
if not atd.use_tweak_mode:
atd.action_blend_type = 'REPLACE'

View File

@ -111,7 +111,7 @@ def orientation_helper(axis_forward='Y', axis_up='Z'):
"""
def wrapper(cls):
# Without that, we may end up adding those fields to some **parent** class' __annotations__ property
# (like the ImportHelper or ExportHelper ones)! See T58772.
# (like the ImportHelper or ExportHelper ones)! See #58772.
if "__annotations__" not in cls.__dict__:
setattr(cls, "__annotations__", {})

View File

@ -564,7 +564,7 @@ class Mesh(bpy_types.ID):
face_lengths = tuple(map(len, faces))
# NOTE: check non-empty lists by length because of how `numpy` handles truth tests, see: T90268.
# NOTE: check non-empty lists by length because of how `numpy` handles truth tests, see: #90268.
vertices_len = len(vertices)
edges_len = len(edges)
faces_len = len(faces)

View File

@ -991,6 +991,7 @@ url_manual_mapping = (
("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/read/face_area.html#bpy-types-geometrynodeinputmeshfacearea"),
("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/read/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"),
("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"),
("bpy.types.geometrynodematerialselection*", "modeling/geometry_nodes/material/material_selection.html#bpy-types-geometrynodematerialselection"),
("bpy.types.gpencillayer.viewlayer_render*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-viewlayer-render"),
("bpy.types.imagepaint.use_normal_falloff*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-use-normal-falloff"),
("bpy.types.layercollection.hide_viewport*", "editors/outliner/interface.html#bpy-types-layercollection-hide-viewport"),
@ -2027,6 +2028,7 @@ url_manual_mapping = (
("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"),
("bpy.ops.mball.delete_metaelems*", "modeling/metas/editing.html#bpy-ops-mball-delete-metaelems"),
("bpy.ops.mball.reveal_metaelems*", "modeling/metas/properties.html#bpy-ops-mball-reveal-metaelems"),
("bpy.ops.mesh.bridge_edge_loops*", "modeling/meshes/editing/edge/bridge_edge_loops.html#bpy-ops-mesh-bridge-edge-loops"),
("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"),
("bpy.ops.mesh.loop_multi_select*", "modeling/meshes/selecting/loops.html#bpy-ops-mesh-loop-multi-select"),
("bpy.ops.mesh.vert_connect_path*", "modeling/meshes/editing/vertex/connect_vertex_path.html#bpy-ops-mesh-vert-connect-path"),
@ -3021,6 +3023,7 @@ url_manual_mapping = (
("bpy.types.bakesettings*", "render/cycles/baking.html#bpy-types-bakesettings"),
("bpy.types.blendtexture*", "render/materials/legacy_textures/types/blend.html#bpy-types-blendtexture"),
("bpy.types.brush.height*", "sculpt_paint/sculpting/tools/layer.html#bpy-types-brush-height"),
("bpy.types.brush.jitter*", "sculpt_paint/brush/stroke.html#bpy-types-brush-jitter"),
("bpy.types.castmodifier*", "modeling/modifiers/deform/cast.html#bpy-types-castmodifier"),
("bpy.types.curve.offset*", "modeling/curves/properties/geometry.html#bpy-types-curve-offset"),
("bpy.types.geometrynode*", "modeling/geometry_nodes/index.html#bpy-types-geometrynode"),

View File

@ -29,11 +29,11 @@
icon_modifier="#84b8ffff"
icon_shading="#ea7581ff"
icon_folder="#e3c16eff"
icon_border_intensity="0.85"
icon_border_intensity="1"
>
<wcol_regular>
<ThemeWidgetColors
outline="#b8b8b8"
outline="#4d4d4d"
inner="#dbdbdbff"
inner_sel="#668cccff"
item="#191919ff"
@ -48,7 +48,7 @@
</wcol_regular>
<wcol_tool>
<ThemeWidgetColors
outline="#b8b8b8"
outline="#4d4d4d"
inner="#dbdbdbff"
inner_sel="#5680c2ff"
item="#191919ff"
@ -63,7 +63,7 @@
</wcol_tool>
<wcol_toolbar_item>
<ThemeWidgetColors
outline="#363636"
outline="#4d4d4d"
inner="#434343ff"
inner_sel="#5680c2ff"
item="#e6e6e6cc"
@ -78,7 +78,7 @@
</wcol_toolbar_item>
<wcol_radio>
<ThemeWidgetColors
outline="#434343"
outline="#4d4d4d"
inner="#3b3b3bff"
inner_sel="#5680c2e6"
item="#ffffffff"
@ -93,7 +93,7 @@
</wcol_radio>
<wcol_text>
<ThemeWidgetColors
outline="#666666"
outline="#4d4d4d"
inner="#282828ff"
inner_sel="#333333ff"
item="#5680c2ff"
@ -108,7 +108,7 @@
</wcol_text>
<wcol_option>
<ThemeWidgetColors
outline="#373737"
outline="#4d4d4d"
inner="#3c3c3cff"
inner_sel="#5680c2ff"
item="#ffffffff"
@ -123,8 +123,8 @@
</wcol_option>
<wcol_toggle>
<ThemeWidgetColors
outline="#999999"
inner="#c0c0c0ff"
outline="#4d4d4d"
inner="#dbdbdbff"
inner_sel="#5680c2ff"
item="#191919ff"
text="#000000"
@ -138,7 +138,7 @@
</wcol_toggle>
<wcol_num>
<ThemeWidgetColors
outline="#b8b8b8"
outline="#4d4d4d"
inner="#d3d3d3ff"
inner_sel="#5680c2ff"
item="#80b1ffff"
@ -153,7 +153,7 @@
</wcol_num>
<wcol_numslider>
<ThemeWidgetColors
outline="#b8b8b8"
outline="#4d4d4d"
inner="#999999ff"
inner_sel="#999999ff"
item="#e6e6e6ff"
@ -168,8 +168,8 @@
</wcol_numslider>
<wcol_box>
<ThemeWidgetColors
outline="#959595"
inner="#cccccc80"
outline="#4d4d4d"
inner="#80808080"
inner_sel="#5680c2ff"
item="#191919ff"
text="#333333"
@ -183,7 +183,7 @@
</wcol_box>
<wcol_menu>
<ThemeWidgetColors
outline="#3b3b3b"
outline="#3d3d3d"
inner="#3b3b3bff"
inner_sel="#767676ff"
item="#808080ff"
@ -217,7 +217,7 @@
inner="#c0c0c0ff"
inner_sel="#cdcdcdff"
item="#727272ff"
text="#1a1a1a"
text="#4d4d4d"
text_sel="#1a1a1a"
show_shaded="FALSE"
shadetop="25"
@ -304,11 +304,11 @@
<wcol_list_item>
<ThemeWidgetColors
outline="#e6e6e6"
inner="#00000000"
inner_sel="#808080ff"
inner="#1a1a1a00"
inner_sel="#c0c0c0ff"
item="#1a1a1aff"
text="#1a1a1a"
text_sel="#ffffff"
text_sel="#000000"
show_shaded="FALSE"
shadetop="0"
shadedown="0"
@ -316,6 +316,21 @@
>
</ThemeWidgetColors>
</wcol_list_item>
<wcol_view_item>
<ThemeWidgetColors
outline="#e6e6e6"
inner="#c0c0c044"
inner_sel="#c0c0c0ff"
item="#1a1a1aff"
text="#1a1a1a"
text_sel="#000000"
show_shaded="FALSE"
shadetop="0"
shadedown="0"
roundness="0.4"
>
</ThemeWidgetColors>
</wcol_view_item>
<wcol_state>
<ThemeWidgetStateColors
inner_anim="#73be4c"
@ -334,8 +349,8 @@
</wcol_state>
<wcol_tab>
<ThemeWidgetColors
outline="#656565"
inner="#818181ff"
outline="#333333"
inner="#808080cc"
inner_sel="#b3b3b3ff"
item="#28292dff"
text="#1a1a1a"
@ -414,6 +429,7 @@
bone_locked_weight="#ff000080"
bundle_solid="#c8c8c8"
camera_path="#000000"
camera_passepartout="#000000"
skin_root="#b44d4d"
view_overlay="#000000"
transform="#ffffff"
@ -452,9 +468,9 @@
</gradients>
<panelcolors>
<ThemePanelColors
header="#b3b3b3ff"
back="#b3b3b3cc"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -519,9 +535,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -552,7 +568,7 @@
header="#adadadff"
header_text="#000000"
header_text_hi="#ffffff"
button="#999999e6"
button="#b3b3b3ff"
button_title="#1a1a1a"
button_text="#000000"
button_text_hi="#000000"
@ -565,9 +581,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -623,9 +639,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -698,9 +714,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -783,9 +799,9 @@
>
<panelcolors>
<ThemePanelColors
header="#b3b3b3ff"
back="#b3b3b3cc"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -843,14 +859,23 @@
>
<panelcolors>
<ThemePanelColors
header="#b3b3b3ff"
back="#b3b3b3cc"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
</ThemeSpaceGeneric>
</space>
<space_list>
<ThemeSpaceListGeneric
list="#181818"
list_title="#ffffff"
list_text="#ffffff"
list_text_hi="#ffffff"
>
</ThemeSpaceListGeneric>
</space_list>
</ThemeSequenceEditor>
</sequence_editor>
<properties>
@ -871,7 +896,7 @@
button_title="#000000"
button_text="#000000"
button_text_hi="#000000"
navigation_bar="#656565ff"
navigation_bar="#1d1d1dff"
execution_buts="#00000000"
tab_active="#6697e6"
tab_inactive="#535353"
@ -880,9 +905,9 @@
>
<panelcolors>
<ThemePanelColors
header="#b3b3b300"
back="#a3a3a3cc"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -927,9 +952,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -939,44 +964,44 @@
</text_editor>
<node_editor>
<ThemeNodeEditor
grid="#1B1B1B"
node_selected="#f15800"
node_active="#f15800"
wire="#191919"
wire_inner="#999999"
wire_select="#ffa733"
selected_text="#7f7070"
node_backdrop="#e6e6e6ff"
converter_node="#66c4ff"
color_node="#ffcb4d"
group_node="#59b36ab9"
group_socket_node="#dfc300"
frame_node="#9b9b9b60"
matte_node="#977474"
distor_node="#749797"
grid="#282828"
node_selected="#ed5700"
node_active="#ffffff"
wire="#1a1a1aff"
wire_inner="#8d8d8d"
wire_select="#ffffffb3"
selected_text="#7f7f7f"
node_backdrop="#666666ff"
converter_node="#12adff"
color_node="#cccc00"
group_node="#3b660a"
group_socket_node="#000000"
frame_node="#0f0f0fcc"
matte_node="#973c3c"
distor_node="#4c9797"
noodle_curving="4"
grid_levels="3"
dash_alpha="0.5"
input_node="#cb3d4a"
output_node="#cb3d4a"
filter_node="#6c696f"
vector_node="#9999ff"
texture_node="#ffc399"
shader_node="#ea7581"
script_node="#6c696f"
input_node="#ff3371"
output_node="#4d0017"
filter_node="#551a80"
vector_node="#4d4dff"
texture_node="#e66800"
shader_node="#24b524"
script_node="#084d4d"
pattern_node="#6c696f"
layout_node="#6c696f"
geometry_node="#00d7a4"
attribute_node="#3f5980"
geometry_node="#00d6a3"
attribute_node="#001566"
>
<space>
<ThemeSpaceGeneric
back="#353535"
title="#000000"
text="#000000"
back="#1d1d1d"
title="#eeeeee"
text="#e6e6e6"
text_hi="#ffffff"
header="#b3b3b3ff"
header_text="#000000"
header_text="#eeeeee"
header_text_hi="#ffffff"
button="#99999900"
button_title="#1a1a1a"
@ -991,9 +1016,9 @@
>
<panelcolors>
<ThemePanelColors
header="#b3b3b3ff"
back="#b3b3b3cc"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1013,8 +1038,8 @@
<outliner>
<ThemeOutliner
match="#337f33"
selected_highlight="#7a8e99"
active="#92aab7"
selected_highlight="#7a8499"
active="#929eb7"
selected_object="#ffddb3"
active_object="#ffffff"
edited_object="#0080624d"
@ -1042,9 +1067,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1091,9 +1116,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1125,9 +1150,9 @@
>
<panelcolors>
<ThemePanelColors
header="#b3b3b300"
back="#a3a3a3cc"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1137,26 +1162,26 @@
</preferences>
<console>
<ThemeConsole
line_output="#6080ff"
line_input="#ffffff"
line_info="#00aa00"
line_error="#dc6060"
cursor="#dc6060"
line_output="#71a8ff"
line_input="#f2f2f2"
line_info="#95d600"
line_error="#ff4d84"
cursor="#ff0000"
select="#ffffff30"
>
<space>
<ThemeSpaceGeneric
back="#000000"
title="#000000"
text="#000000"
back="#1d1d1d"
title="#eeeeee"
text="#e6e6e6"
text_hi="#ffffff"
header="#b3b3b3ff"
header_text="#000000"
header_text_hi="#ffffff"
button="#7272727f"
button_title="#000000"
button_text="#000000"
button_text_hi="#000000"
button="#30303000"
button_title="#ffffff"
button_text="#cccccc"
button_text_hi="#ffffff"
navigation_bar="#00000000"
execution_buts="#00000000"
tab_active="#6697e6"
@ -1166,9 +1191,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1231,9 +1256,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1274,9 +1299,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1292,7 +1317,7 @@
title="#ffffff"
text="#ffffff"
text_hi="#ffffff"
header="#adadadff"
header="#999999ff"
header_text="#1a1a1a"
header_text_hi="#ffffff"
button="#2f303500"
@ -1308,9 +1333,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1331,7 +1356,7 @@
header="#adadadff"
header_text="#000000"
header_text_hi="#ffffff"
button="#999999e6"
button="#b3b3b3ff"
button_title="#1a1a1a"
button_text="#000000"
button_text_hi="#000000"
@ -1344,9 +1369,9 @@
>
<panelcolors>
<ThemePanelColors
header="#42424200"
back="#00000028"
sub_back="#00000024"
header="#ccccccff"
back="#ccccccff"
sub_back="#0000000f"
>
</ThemePanelColors>
</panelcolors>
@ -1585,8 +1610,8 @@
shadow="3"
shadow_offset_x="0"
shadow_offset_y="-1"
shadow_alpha="0.3"
shadow_value="0.7"
shadow_alpha="1"
shadow_value="0.8"
>
</ThemeFontStyle>
</panel_title>
@ -1596,8 +1621,8 @@
shadow="3"
shadow_offset_x="0"
shadow_offset_y="-1"
shadow_alpha="0.3"
shadow_value="0.7"
shadow_alpha="0"
shadow_value="0.8"
>
</ThemeFontStyle>
</widget_label>
@ -1607,8 +1632,8 @@
shadow="1"
shadow_offset_x="0"
shadow_offset_y="-1"
shadow_alpha="0.3"
shadow_value="0.7"
shadow_alpha="0"
shadow_value="0.8"
>
</ThemeFontStyle>
</widget>

View File

@ -86,7 +86,7 @@ class Prefs(bpy.types.KeyConfigPreferences):
update=update_fn,
)
# Experimental: only show with developer extras, see: T96544.
# Experimental: only show with developer extras, see: #96544.
use_tweak_select_passthrough: BoolProperty(
name="Tweak Select: Mouse Select & Move",
description=(
@ -96,7 +96,7 @@ class Prefs(bpy.types.KeyConfigPreferences):
default=False,
update=update_fn,
)
# Experimental: only show with developer extras, see: T96544.
# Experimental: only show with developer extras, see: #96544.
use_tweak_tool_lmb_interaction: BoolProperty(
name="Tweak Tool: Left Mouse Select & Move",
description=(

View File

@ -37,7 +37,7 @@ class Params:
# instead be bound to a binding that doesn't de-select all, this way:
# - Click-drag moves the current selection.
# - Click selects only the item at the cursor position.
# See: T97032.
# See: #97032.
"use_tweak_select_passthrough",
"use_tweak_tool_lmb_interaction",
"use_mouse_emulate_3_button",
@ -465,7 +465,7 @@ def _template_items_tool_select(
fallback=False,
):
if not params.legacy and not fallback:
# Experimental support for LMB interaction for the tweak tool. see: T96544.
# Experimental support for LMB interaction for the tweak tool. see: #96544.
# NOTE: For RMB-select this is a much bigger change as it disables 3D cursor placement on LMB.
# For LMB-select this means an LMB -drag will not first de-select all (similar to node/graph editor).
select_passthrough = False
@ -498,7 +498,7 @@ def _template_items_tool_select(
{"properties": [("toggle", True), *operator_props]}),
# Fallback key-map must transform as the primary tool is expected
# to be accessed via gizmos in this case. See: T96885.
# to be accessed via gizmos in this case. See: #96885.
*(() if not fallback else (
("transform.translate", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'},
{"properties": [("release_confirm", True)]}),
@ -3478,7 +3478,7 @@ def km_animation_channels(params):
# Selection.
*_template_items_select_actions(params, "anim.channels_select_all"),
("anim.channels_select_box", {"type": 'B', "value": 'PRESS'}, None),
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'},
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG'},
{"properties": [("extend", False)]}),
("anim.channels_select_box", {"type": 'LEFTMOUSE', "value": 'CLICK_DRAG', "shift": True},
{"properties": [("extend", True)]}),
@ -3513,6 +3513,9 @@ def km_animation_channels(params):
("anim.channels_ungroup", {"type": 'G', "value": 'PRESS', "ctrl": True, "alt": True}, None),
# Menus.
*_template_items_context_menu("DOPESHEET_MT_channel_context_menu", params.context_menu_event),
# View
("anim.channel_view_pick", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "alt": True}, None),
("anim.channels_view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
])
return keymap
@ -4730,7 +4733,7 @@ def _template_paint_radial_control(paint, rotation=False, secondary_rotation=Fal
def _template_view3d_select(*, type, value, legacy, select_passthrough, exclude_mod=None):
# NOTE: `exclude_mod` is needed since we don't want this tool to exclude Control-RMB actions when this is used
# as a tool key-map with RMB-select and `use_fallback_tool` is enabled with RMB select. See T92467.
# as a tool key-map with RMB-select and `use_fallback_tool` is enabled with RMB select. See #92467.
props_vert_without_handles = ()
if select_passthrough:
@ -5628,6 +5631,11 @@ def km_curves(params):
("curves.disable_selection", {"type": 'ONE', "value": 'PRESS', "alt": True}, None),
("curves.disable_selection", {"type": 'TWO', "value": 'PRESS', "alt": True}, None),
*_template_items_select_actions(params, "curves.select_all"),
("curves.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
("curves.delete", {"type": 'X', "value": 'PRESS'}, None),
("curves.delete", {"type": 'DEL', "value": 'PRESS'}, None),
("curves.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
("curves.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
])
return keymap
@ -5682,7 +5690,7 @@ def km_object_non_modal(params):
])
else:
items.extend([
# NOTE: this shortcut (while not temporary) is not ideal, see: T89757.
# NOTE: this shortcut (while not temporary) is not ideal, see: #89757.
("object.transfer_mode", {"type": 'Q', "value": 'PRESS', "alt": True}, None),
])
@ -6344,9 +6352,8 @@ def km_node_link_modal_map(_params):
return keymap
# Fallback for gizmos that don't have custom a custom key-map.
def km_generic_gizmo(_params):
keymap = (
"Generic Gizmo",

View File

@ -6,8 +6,8 @@ from bpy.types import Operator
from bpy.app.translations import pgettext_data as data_
def geometry_node_group_empty_new():
group = bpy.data.node_groups.new(data_("Geometry Nodes"), 'GeometryNodeTree')
def build_default_empty_geometry_node_group(name):
group = bpy.data.node_groups.new(name, 'GeometryNodeTree')
group.inputs.new('NodeSocketGeometry', data_("Geometry"))
group.outputs.new('NodeSocketGeometry', data_("Geometry"))
input_node = group.nodes.new('NodeGroupInput')
@ -20,8 +20,12 @@ def geometry_node_group_empty_new():
input_node.location.x = -200 - input_node.width
output_node.location.x = 200
group.links.new(output_node.inputs[0], input_node.outputs[0])
return group
def geometry_node_group_empty_new():
group = build_default_empty_geometry_node_group(data_("Geometry Nodes"))
group.links.new(group.nodes[data_("Group Input")].outputs[0], group.nodes[data_("Group Output")].inputs[0])
return group
@ -35,6 +39,160 @@ def geometry_modifier_poll(context):
return True
def get_context_modifier(context):
if context.area.type == 'PROPERTIES':
modifier = context.modifier
else:
modifier = context.object.modifiers.active
if modifier is None or modifier.type != 'NODES':
return None
return modifier
def edit_geometry_nodes_modifier_poll(context):
return get_context_modifier(context) is not None
def socket_idname_to_attribute_type(idname):
if idname.startswith("NodeSocketInt"):
return "INT"
elif idname.startswith("NodeSocketColor"):
return "FLOAT_COLOR"
elif idname.startswith("NodeSocketVector"):
return "FLOAT_VECTOR"
elif idname.startswith("NodeSocketBool"):
return "BOOLEAN"
elif idname.startswith("NodeSocketFloat"):
return "FLOAT"
raise ValueError("Unsupported socket type")
return ""
def modifier_attribute_name_get(modifier, identifier):
try:
return modifier[identifier + "_attribute_name"]
except KeyError:
return None
def modifier_input_use_attribute(modifier, identifier):
try:
return modifier[identifier + "_use_attribute"] != 0
except KeyError:
return False
def get_socket_with_identifier(sockets, identifier):
for socket in sockets:
if socket.identifier == identifier:
return socket
return None
def get_enabled_socket_with_name(sockets, name):
for socket in sockets:
if socket.name == name and socket.enabled:
return socket
return None
class MoveModifierToNodes(Operator):
"""Move inputs and outputs from in the modifier to a new node group"""
bl_idname = "object.geometry_nodes_move_to_nodes"
bl_label = "Move to Nodes"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return edit_geometry_nodes_modifier_poll(context)
def execute(self, context):
modifier = get_context_modifier(context)
if not modifier:
return {'CANCELLED'}
old_group = modifier.node_group
if not old_group:
return {'CANCELLED'}
wrapper_name = old_group.name + ".wrapper"
group = build_default_empty_geometry_node_group(wrapper_name)
group_node = group.nodes.new("GeometryNodeGroup")
group_node.node_tree = old_group
group_node.update()
group_input_node = group.nodes[data_("Group Input")]
group_output_node = group.nodes[data_("Group Output")]
# Copy default values for inputs and create named attribute input nodes.
input_nodes = []
first_geometry_input = None
for input_socket in old_group.inputs:
identifier = input_socket.identifier
group_node_input = get_socket_with_identifier(group_node.inputs, identifier)
if modifier_input_use_attribute(modifier, identifier):
input_node = group.nodes.new("GeometryNodeInputNamedAttribute")
input_nodes.append(input_node)
input_node.data_type = socket_idname_to_attribute_type(input_socket.bl_socket_idname)
attribute_name = modifier_attribute_name_get(modifier, identifier)
input_node.inputs["Name"].default_value = attribute_name
output_socket = get_enabled_socket_with_name(input_node.outputs, "Attribute")
group.links.new(output_socket, group_node_input)
elif hasattr(input_socket, "default_value"):
group_node_input.default_value = modifier[identifier]
elif input_socket.bl_socket_idname == 'NodeSocketGeometry':
if not first_geometry_input:
first_geometry_input = group_node_input
group.links.new(group_input_node.outputs[0], first_geometry_input)
# Adjust locations of named attribute input nodes and group input node to make some space.
if input_nodes:
for i, node in enumerate(input_nodes):
node.location.x = -175
node.location.y = i * -50
group_input_node.location.x = -350
# Connect outputs to store named attribute nodes to replace modifier attribute outputs.
store_nodes = []
first_geometry_output = None
for output_socket in old_group.outputs:
identifier = output_socket.identifier
group_node_output = get_socket_with_identifier(group_node.outputs, identifier)
attribute_name = modifier_attribute_name_get(modifier, identifier)
if attribute_name:
store_node = group.nodes.new("GeometryNodeStoreNamedAttribute")
store_nodes.append(store_node)
store_node.data_type = socket_idname_to_attribute_type(output_socket.bl_socket_idname)
store_node.domain = output_socket.attribute_domain
store_node.inputs["Name"].default_value = attribute_name
input_socket = get_enabled_socket_with_name(store_node.inputs, "Value")
group.links.new(group_node_output, input_socket)
elif output_socket.bl_socket_idname == 'NodeSocketGeometry':
if not first_geometry_output:
first_geometry_output = group_node_output
# Adjust locations of store named attribute nodes and move group output.
# Note that the node group has its sockets names translated, while the built-in nodes don't.
if store_nodes:
for i, node in enumerate(store_nodes):
node.location.x = (i + 1) * 175
node.location.y = 0
group_output_node.location.x = (len(store_nodes) + 1) * 175
group.links.new(first_geometry_output, store_nodes[0].inputs["Geometry"])
for i in range(len(store_nodes) - 1):
group.links.new(store_nodes[i].outputs["Geometry"], store_nodes[i + 1].inputs["Geometry"])
group.links.new(store_nodes[-1].outputs["Geometry"], group_output_node.inputs[data_("Geometry")])
else:
group.links.new(first_geometry_output, group_output_node.inputs[data_("Geometry")])
modifier.node_group = group
return {'FINISHED'}
class NewGeometryNodesModifier(Operator):
"""Create a new modifier with a new geometry node group"""
@ -48,7 +206,6 @@ class NewGeometryNodesModifier(Operator):
def execute(self, context):
modifier = context.object.modifiers.new(data_("GeometryNodes"), "NODES")
if not modifier:
return {'CANCELLED'}
@ -70,11 +227,7 @@ class NewGeometryNodeTreeAssign(Operator):
return geometry_modifier_poll(context)
def execute(self, context):
if context.area.type == 'PROPERTIES':
modifier = context.modifier
else:
modifier = context.object.modifiers.active
modifier = get_context_modifier(context)
if not modifier:
return {'CANCELLED'}
@ -87,4 +240,5 @@ class NewGeometryNodeTreeAssign(Operator):
classes = (
NewGeometryNodesModifier,
NewGeometryNodeTreeAssign,
MoveModifierToNodes,
)

View File

@ -790,7 +790,7 @@ class TransformsToDeltasAnim(Operator):
continue
# first pass over F-Curves: ensure that we don't have conflicting
# transforms already (e.g. if this was applied already) T29110.
# transforms already (e.g. if this was applied already) #29110.
existingFCurves = {}
for fcu in adt.action.fcurves:
# get "delta" path - i.e. the final paths which may clash

View File

@ -36,67 +36,136 @@ class ObjectModeOperator:
class QuickFur(ObjectModeOperator, Operator):
"""Add fur setup to the selected objects"""
"""Add a fur setup to the selected objects"""
bl_idname = "object.quick_fur"
bl_label = "Quick Fur"
bl_options = {'REGISTER', 'UNDO'}
density: EnumProperty(
name="Fur Density",
name="Density",
items=(
('LIGHT', "Light", ""),
('LOW', "Low", ""),
('MEDIUM', "Medium", ""),
('HEAVY', "Heavy", ""),
('HIGH', "High", ""),
),
default='MEDIUM',
)
view_percentage: IntProperty(
name="View %",
min=1, max=100,
soft_min=1, soft_max=100,
default=10,
)
length: FloatProperty(
name="Length",
min=0.001, max=100,
soft_min=0.01, soft_max=10,
default=0.1,
subtype='DISTANCE'
)
radius: FloatProperty(
name="Hair Radius",
min=0.0, max=10,
soft_min=0.0001, soft_max=0.1,
default=0.001,
subtype='DISTANCE'
)
view_percentage: FloatProperty(
name="View Percentage",
min=0.0, max=1.0,
default=1.0,
subtype='FACTOR'
)
apply_hair_guides: BoolProperty(
name="Apply Hair Guides",
default=True,
)
use_noise: BoolProperty(
name="Noise",
default=True,
)
use_frizz: BoolProperty(
name="Frizz",
default=True,
)
def execute(self, context):
fake_context = context.copy()
mesh_objects = [obj for obj in context.selected_objects
if obj.type == 'MESH']
import os
mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH']
if not mesh_objects:
self.report({'ERROR'}, "Select at least one mesh object")
return {'CANCELLED'}
mat = bpy.data.materials.new("Fur Material")
if self.density == 'LOW':
count = 1000
elif self.density == 'MEDIUM':
count = 10000
elif self.density == 'HIGH':
count = 100000
for obj in mesh_objects:
fake_context["object"] = obj
bpy.ops.object.particle_system_add(fake_context)
node_groups_to_append = {"Generate Hair Curves", "Set Hair Curve Profile", "Interpolate Hair Curves"}
if self.use_noise:
node_groups_to_append.add("Hair Curves Noise")
if self.use_frizz:
node_groups_to_append.add("Frizz Hair Curves")
assets_directory = os.path.join(bpy.utils.system_resource('DATAFILES'),
"assets",
"geometry_nodes",
"procedural_hair_node_assets.blend",
"NodeTree")
for name in node_groups_to_append:
bpy.ops.wm.append(directory=assets_directory,
filename=name,
use_recursive=True,
clear_asset_data=True,
do_reuse_local_id=True)
generate_group = bpy.data.node_groups["Generate Hair Curves"]
interpolate_group = bpy.data.node_groups["Interpolate Hair Curves"]
radius_group = bpy.data.node_groups["Set Hair Curve Profile"]
noise_group = bpy.data.node_groups["Hair Curves Noise"] if self.use_noise else None
frizz_group = bpy.data.node_groups["Frizz Hair Curves"] if self.use_frizz else None
psys = obj.particle_systems[-1]
psys.settings.type = 'HAIR'
material = bpy.data.materials.new("Fur Material")
if self.density == 'LIGHT':
psys.settings.count = 100
elif self.density == 'MEDIUM':
psys.settings.count = 1000
elif self.density == 'HEAVY':
psys.settings.count = 10000
for mesh_object in mesh_objects:
mesh = mesh_object.data
with context.temp_override(active_object=mesh_object):
bpy.ops.object.curves_empty_hair_add()
curves_object = context.active_object
curves = curves_object.data
curves.materials.append(material)
psys.settings.child_nbr = self.view_percentage
psys.settings.hair_length = self.length
psys.settings.use_strand_primitive = True
psys.settings.use_hair_bspline = True
psys.settings.child_type = 'INTERPOLATED'
psys.settings.tip_radius = 0.25
area = 0.0
for poly in mesh.polygons:
area += poly.area
density = count / area
obj.data.materials.append(mat)
psys.settings.material = len(obj.data.materials)
generate_modifier = curves_object.modifiers.new(name="Generate", type='NODES')
generate_modifier.node_group = generate_group
generate_modifier["Input_2"] = mesh_object
generate_modifier["Input_18_attribute_name"] = curves.surface_uv_map
generate_modifier["Input_20"] = self.length
generate_modifier["Input_22"] = material
generate_modifier["Input_15"] = density * 0.01
curves_object.modifiers.move(1, 0)
radius_modifier = curves_object.modifiers.new(name="Set Hair Curve Profile", type='NODES')
radius_modifier.node_group = radius_group
radius_modifier["Input_3"] = self.radius
interpolate_modifier = curves_object.modifiers.new(name="Interpolate Hair Curves", type='NODES')
interpolate_modifier.node_group = interpolate_group
interpolate_modifier["Input_2"] = mesh_object
interpolate_modifier["Input_18_attribute_name"] = curves.surface_uv_map
interpolate_modifier["Input_15"] = density
interpolate_modifier["Input_17"] = self.view_percentage
interpolate_modifier["Input_24"] = True
if noise_group:
noise_modifier = curves_object.modifiers.new(name="Hair Curves Noise", type='NODES')
noise_modifier.node_group = noise_group
if frizz_group:
frizz_modifier = curves_object.modifiers.new(name="Frizz Hair Curves", type='NODES')
frizz_modifier.node_group = frizz_group
if self.apply_hair_guides:
with context.temp_override(object=curves_object):
bpy.ops.object.modifier_apply(modifier=generate_modifier.name)
return {'FINISHED'}

View File

@ -700,7 +700,7 @@ class PREFERENCES_OT_addon_install(Operator):
addons_new.discard("modules")
# disable any addons we may have enabled previously and removed.
# this is unlikely but do just in case. bug T23978.
# this is unlikely but do just in case. bug #23978.
for new_addon in addons_new:
addon_utils.disable(new_addon, default_set=True)

View File

@ -581,7 +581,7 @@ class LightMapPack(Operator):
# Proper solution would be to make undo stack aware of such things,
# but for now just disable redo. Keep undo here so unwanted changes to uv
# coords might be undone.
# This fixes infinite image creation reported there T30968 (sergey)
# This fixes infinite image creation reported there #30968 (sergey)
bl_options = {'UNDO'}
PREF_CONTEXT: bpy.props.EnumProperty(

View File

@ -90,7 +90,7 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
tone_range = max_tone - min_tone
if tone_range < 0.0001:
# weak, don't cancel, see T43345
# weak, don't cancel, see #43345
tone_range = 0.0
else:
tone_range = 1.0 / tone_range

View File

@ -42,7 +42,7 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
bpy.ops.mesh.extrude_vertices_move('INVOKE_REGION_WIN')
# ignore return from operators above because they are 'RUNNING_MODAL',
# and cause this one not to be freed. T24671.
# and cause this one not to be freed. #24671.
return {'FINISHED'}
def invoke(self, context, _event):
@ -104,7 +104,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
'INVOKE_REGION_WIN',
TRANSFORM_OT_translate={
# Don't set the constraint axis since users will expect MMB
# to use the user setting, see: T61637
# to use the user setting, see: #61637
# "orient_type": 'NORMAL',
# Not a popular choice, too restrictive for retopo.
# "constraint_axis": (True, True, False)})
@ -114,7 +114,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(Operator):
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN')
# ignore return from operators above because they are 'RUNNING_MODAL',
# and cause this one not to be freed. T24671.
# and cause this one not to be freed. #24671.
return {'FINISHED'}
def execute(self, context):

View File

@ -556,7 +556,7 @@ class WM_OT_context_toggle_enum(Operator):
class WM_OT_context_cycle_int(Operator):
"""Set a context value (useful for cycling active material, """ \
"""vertex keys, groups, etc.)"""
"""shape keys, groups, etc.)"""
bl_idname = "wm.context_cycle_int"
bl_label = "Context Int Cycle"
bl_options = {'UNDO', 'INTERNAL'}
@ -1249,7 +1249,31 @@ class WM_OT_doc_view_manual(Operator):
# XXX, for some reason all RNA ID's are stored lowercase
# Adding case into all ID's isn't worth the hassle so force lowercase.
rna_id = rna_id.lower()
# NOTE: `fnmatch` in Python is slow as it translate the string to a regular-expression
# which needs to be compiled (as of Python 3.11), this is slow enough to cause a noticeable
# delay when opening manual links (approaching half a second).
#
# Resolve by matching characters that have a special meaning to `fnmatch`.
# The characters that can occur as the first special character are `*?[`.
# If any of these are used we must let `fnmatch` run its own matching logic.
# However, in most cases a literal prefix is used making it considerably faster
# to do a simple `startswith` check before performing a full match.
# An alternative solution could be to use `fnmatch` from C which is significantly
# faster than Python's, see !104581 for details.
import re
re_match_non_special = re.compile(r"^[^?\*\[]+").match
for pattern, url_suffix in url_mapping:
# Simple optimization, makes a big difference (over 50x speedup).
# Even when `non_special.end()` is zero (resulting in an empty-string),
# the `startswith` check succeeds so there is no need to check for an empty match.
non_special = re_match_non_special(pattern)
if non_special is None or not rna_id.startswith(pattern[:non_special.end()]):
continue
# End simple optimization.
if fnmatchcase(rna_id, pattern):
if verbose:
print(" match found: '%s' --> '%s'" % (pattern, url_suffix))
@ -1725,7 +1749,7 @@ class WM_OT_properties_edit(Operator):
for nt in adt.nla_tracks:
_update_strips(nt.strips)
# Otherwise existing buttons which reference freed memory may crash Blender (T26510).
# Otherwise existing buttons which reference freed memory may crash Blender (#26510).
for win in context.window_manager.windows:
for area in win.screen.areas:
area.tag_redraw()

View File

@ -35,19 +35,10 @@ def draw_node_group_add_menu(context, layout):
if node_tree:
from nodeitems_builtins import node_tree_group_type
def contains_group(nodetree, group):
if nodetree == group:
return True
for node in nodetree.nodes:
if node.bl_idname in node_tree_group_type.values() and node.node_tree is not None:
if contains_group(node.node_tree, group):
return True
return False
groups = [
group for group in context.blend_data.node_groups
if (group.bl_idname == node_tree.bl_idname and
not contains_group(group, node_tree) and
not group.contains_tree(node_tree) and
not group.name.startswith('.'))
]
if groups:

View File

@ -485,7 +485,6 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
layout.use_property_split = True
layout.use_property_decorate = False
obj = context.object
me = context.mesh
col = layout.column()
@ -605,7 +604,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
colliding_names = []
for collection in (
# Built-in names.
{"shade_smooth": None, "normal": None, "crease": None},
{"shade_smooth": None, "crease": None},
mesh.attributes,
None if ob is None else ob.vertex_groups,
):

View File

@ -1141,6 +1141,11 @@ def brush_texture_settings(layout, brush, sculpt):
# texture_sample_bias
layout.prop(brush, "texture_sample_bias", slider=True, text="Sample Bias")
if brush.sculpt_tool == 'DRAW':
col = layout.column()
col.active = tex_slot.map_mode == 'AREA_PLANE'
col.prop(brush, "use_color_as_displacement", text="Vector Displacement")
def brush_mask_texture_settings(layout, brush):
mask_tex_slot = brush.mask_texture_slot

View File

@ -62,7 +62,6 @@ class PARTICLE_MT_context_menu(Menu):
def draw(self, context):
layout = self.layout
psys = context.particle_system
experimental = context.preferences.experimental
props = layout.operator(
"particle.copy_particle_systems",
@ -79,7 +78,7 @@ class PARTICLE_MT_context_menu(Menu):
props.use_active = False
props.remove_target_particles = True
if psys.settings.type == 'HAIR':
if psys is not None and psys.settings.type == 'HAIR':
layout.operator(
"curves.convert_from_particle_system",
text="Convert to Curves")
@ -508,7 +507,7 @@ class PARTICLE_PT_hair_dynamics_structure(ParticleButtonsPanel, Panel):
sub.prop(psys.settings, "bending_random", text="Random")
col.prop(cloth, "bending_damping", text="Damping")
# XXX has no noticeable effect with stiff hair structure springs
#col.prop(cloth, "spring_damping", text="Damping")
# col.prop(cloth, "spring_damping", text="Damping")
class PARTICLE_PT_hair_dynamics_volume(ParticleButtonsPanel, Panel):
@ -1100,7 +1099,7 @@ class PARTICLE_PT_physics_relations(ParticleButtonsPanel, Panel):
if part.physics_type == 'KEYED':
col = layout.column()
# doesn't work yet
#col.alert = key.valid
# col.alert = key.valid
col.prop(key, "object")
col.prop(key, "system", text="System")
sub = col.column(align=True)
@ -1110,7 +1109,7 @@ class PARTICLE_PT_physics_relations(ParticleButtonsPanel, Panel):
elif part.physics_type == 'BOIDS':
sub = layout.column()
# doesn't work yet
#sub.alert = key.valid
# sub.alert = key.valid
sub.prop(key, "object")
sub.prop(key, "system", text="System")
layout.prop(key, "alliance")
@ -1157,7 +1156,7 @@ class PARTICLE_PT_physics_fluid_interaction(ParticleButtonsPanel, Panel):
if key:
sub = layout.column()
# doesn't work yet
#sub.alert = key.valid
# sub.alert = key.valid
sub.prop(key, "object")
sub.prop(key, "system", text="System")

View File

@ -641,7 +641,6 @@ class RENDER_PT_eevee_next_film(RenderButtonsPanel, Panel):
scene = context.scene
rd = scene.render
props = scene.eevee
col = layout.column()
col.prop(rd, "filter_size")

View File

@ -91,7 +91,7 @@ class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
else:
layout.template_preview(tex, slot=slot)
# Show Alpha Button for Brush Textures, see T29502.
# Show Alpha Button for Brush Textures, see #29502.
idblock = context_tex_datablock(context)
if isinstance(idblock, Brush):
layout.prop(tex, "use_preview_alpha")

View File

@ -474,6 +474,9 @@ class DOPESHEET_MT_channel(Menu):
layout.separator()
layout.operator("anim.channels_fcurves_enable")
layout.separator()
layout.operator("anim.channels_view_selected")
class DOPESHEET_MT_key(Menu):
bl_label = "Key"
@ -601,6 +604,9 @@ class DOPESHEET_MT_gpencil_channel(Menu):
layout.separator()
layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
layout.separator()
layout.operator("anim.channels_view_selected")
class DOPESHEET_MT_gpencil_key(Menu):
bl_label = "Key"
@ -689,6 +695,9 @@ class DOPESHEET_MT_channel_context_menu(Menu):
# This menu is used from the graph editor too.
is_graph_editor = context.area.type == 'GRAPH_EDITOR'
layout.separator()
layout.operator("anim.channels_view_selected")
layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE'
layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE'
layout.separator()

View File

@ -22,7 +22,7 @@ class FILEBROWSER_HT_header(Header):
layout.separator_spacer()
if params.asset_library_ref != 'LOCAL':
if params.asset_library_ref not in {'LOCAL', 'ESSENTIALS'}:
layout.prop(params, "import_type", text="")
layout.separator_spacer()

View File

@ -239,6 +239,9 @@ class GRAPH_MT_channel(Menu):
layout.separator()
layout.operator("anim.channels_fcurves_enable")
layout.separator()
layout.operator("anim.channels_view_selected")
class GRAPH_MT_key(Menu):
bl_label = "Key"

View File

@ -62,7 +62,7 @@ class NODE_HT_header(Header):
types_that_support_material = {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META',
'GPENCIL', 'VOLUME', 'CURVES', 'POINTCLOUD'}
# disable material slot buttons when pinned, cannot find correct slot within id_from (T36589)
# disable material slot buttons when pinned, cannot find correct slot within id_from (#36589)
# disable also when the selected object does not support materials
has_material_slots = not snode.pin and ob_type in types_that_support_material
@ -574,6 +574,11 @@ class NODE_MT_context_menu(Menu):
layout.menu("NODE_MT_context_menu_select_menu")
layout.menu("NODE_MT_context_menu_show_hide_menu")
if active_node:
layout.separator()
props = layout.operator("wm.doc_view_manual", text="Online Manual", icon='URL')
props.doc_id = active_node.bl_idname
class NODE_PT_active_node_generic(Panel):
bl_space_type = 'NODE_EDITOR'

View File

@ -407,7 +407,7 @@ class SEQUENCER_MT_view(Menu):
if st.view_type == 'PREVIEW':
# Specifying the REGION_PREVIEW context is needed in preview-only
# mode, else the lookup for the shortcut will fail in
# wm_keymap_item_find_props() (see T32595).
# wm_keymap_item_find_props() (see #32595).
layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.prop(st, "show_region_ui")
layout.prop(st, "show_region_tool_header")
@ -429,7 +429,7 @@ class SEQUENCER_MT_view(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
if st.view_type == 'PREVIEW':
# See above (T32595)
# See above (#32595)
layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.operator("sequencer.view_selected", text="Frame Selected")
@ -931,8 +931,14 @@ class SEQUENCER_MT_strip(Menu):
if has_sequencer:
layout.operator("sequencer.split", text="Split").type = 'SOFT'
layout.operator("sequencer.split", text="Hold Split").type = 'HARD'
props = layout.operator("sequencer.split", text="Split")
props.type = 'SOFT'
props.side = 'RIGHT'
props = layout.operator("sequencer.split", text="Hold Split")
props.type = 'HARD'
props.side = 'RIGHT'
layout.separator()
if has_sequencer:

File diff suppressed because it is too large Load Diff

View File

@ -326,7 +326,7 @@ class TOPBAR_MT_file_new(Menu):
# Expand template paths.
# Use a set to avoid duplicate user/system templates.
# This is a corner case, but users managed to do it! T76849.
# This is a corner case, but users managed to do it! #76849.
app_templates = set()
for path in template_paths:
for d in os.listdir(path):

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