WIP: Rewrite asset browser as separate editor #104978

Closed
Julian Eisel wants to merge 68 commits from asset-browser-grid-view into main

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

View File

@ -866,7 +866,7 @@ if(WITH_CYCLES_DEVICE_HIP)
endif()
#-----------------------------------------------------------------------------
# Check check if submodules are cloned
# Check if submodules are cloned.
if(WITH_INTERNATIONAL)
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/datafiles/locale")
@ -889,8 +889,8 @@ if(WITH_PYTHON)
# Do this before main 'platform_*' checks,
# because UNIX will search for the old Python paths which may not exist.
# giving errors about missing paths before this case is met.
if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.9")
message(FATAL_ERROR "At least Python 3.9 is required to build, but found Python ${PYTHON_VERSION}")
if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.10")
message(FATAL_ERROR "At least Python 3.10 is required to build, but found Python ${PYTHON_VERSION}")
endif()
file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/scripts/addons")
@ -1886,7 +1886,6 @@ elseif(WITH_CYCLES_STANDALONE)
add_subdirectory(intern/glew-mx)
add_subdirectory(intern/guardedalloc)
add_subdirectory(intern/libc_compat)
add_subdirectory(intern/numaapi)
add_subdirectory(intern/sky)
add_subdirectory(intern/cycles)

View File

@ -51,20 +51,13 @@ Testing Targets
* test:
Run automated tests with ctest.
* test_cmake:
Runs our own cmake file checker
which detects errors in the cmake file list definitions
* test_pep8:
Checks all python script are pep8
which are tagged to use the stricter formatting
* test_deprecated:
Checks for deprecation tags in our code which may need to be removed
Static Source Code Checking
Not associated with building Blender.
* check_cppcheck: Run blender source through cppcheck (C & C++).
* check_clang_array: Run blender source through clang array checking script (C & C++).
* check_deprecated: Check if there is any deprecated code to remove.
* check_splint: Run blenders source through splint (C only).
* check_sparse: Run blenders source through sparse (C only).
* check_smatch: Run blenders source through smatch (C only).
@ -73,6 +66,10 @@ Static Source Code Checking
using one of the accepted licenses in 'doc/license/SPDX-license-identifiers.txt'
Append with 'SHOW_HEADERS=1' to show all unique headers
which can be useful for spotting license irregularities.
* check_cmake: Runs our own cmake file checker which detects errors in the cmake file list definitions.
* check_pep8: Checks all Python script are pep8 which are tagged to use the stricter formatting.
* check_mypy: Checks all Python scripts using mypy,
see: source/tools/check_source/check_mypy_config.py scripts which are included.
Spell Checkers
This runs the spell checker from the developer tools repositor.
@ -400,20 +397,6 @@ package_archive: .FORCE
test: .FORCE
@$(PYTHON) ./build_files/utils/make_test.py "$(BUILD_DIR)"
# run pep8 check check on scripts we distribute.
test_pep8: .FORCE
@$(PYTHON) tests/python/pep8.py > test_pep8.log 2>&1
@echo "written: test_pep8.log"
# run some checks on our CMAKE files.
test_cmake: .FORCE
@$(PYTHON) build_files/cmake/cmake_consistency_check.py > test_cmake_consistency.log 2>&1
@echo "written: test_cmake_consistency.log"
# run deprecation tests, see if we have anything to remove.
test_deprecated: .FORCE
@$(PYTHON) tests/check_deprecated.py
# -----------------------------------------------------------------------------
# Project Files
@ -491,11 +474,23 @@ check_descriptions: .FORCE
@$(BLENDER_BIN) --background -noaudio --factory-startup --python \
"$(BLENDER_DIR)/source/tools/check_source/check_descriptions.py"
check_deprecated: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
source/tools/check_source/check_deprecated.py
check_licenses: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
"$(BLENDER_DIR)/source/tools/check_source/check_licenses.py" \
"--show-headers=$(SHOW_HEADERS)"
check_pep8: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
tests/python/pep8.py
check_cmake: .FORCE
@PYTHONIOENCODING=utf_8 $(PYTHON) \
source/tools/check_source/check_cmake_consistency.py
# -----------------------------------------------------------------------------
# Utilities

View File

@ -366,7 +366,7 @@ CLANG_FORMAT_VERSION_MEX="14.0"
PYTHON_VERSION="3.10.2"
PYTHON_VERSION_SHORT="3.10"
PYTHON_VERSION_MIN="3.9"
PYTHON_VERSION_MIN="3.10"
PYTHON_VERSION_MEX="3.12"
PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_SHORT
PYTHON_FORCE_BUILD=false

View File

@ -1,387 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
# <pep8 compliant>
# Note: this code should be cleaned up / refactored.
import sys
if sys.version_info.major < 3:
print("\nPython3.x needed, found %s.\nAborting!\n" %
sys.version.partition(" ")[0])
sys.exit(1)
import os
from os.path import (
dirname,
join,
normpath,
splitext,
)
from cmake_consistency_check_config import (
IGNORE_SOURCE,
IGNORE_SOURCE_MISSING,
IGNORE_CMAKE,
UTF8_CHECK,
SOURCE_DIR,
BUILD_DIR,
)
from typing import (
Callable,
Dict,
Generator,
Iterator,
List,
Optional,
Tuple,
)
global_h = set()
global_c = set()
global_refs: Dict[str, List[Tuple[str, int]]] = {}
# Flatten `IGNORE_SOURCE_MISSING` to avoid nested looping.
IGNORE_SOURCE_MISSING_FLAT = [
(k, ignore_path) for k, ig_list in IGNORE_SOURCE_MISSING
for ignore_path in ig_list
]
# Ignore cmake file, path pairs.
global_ignore_source_missing: Dict[str, List[str]] = {}
for k, v in IGNORE_SOURCE_MISSING_FLAT:
global_ignore_source_missing.setdefault(k, []).append(v)
del IGNORE_SOURCE_MISSING_FLAT
def replace_line(f: str, i: int, text: str, keep_indent: bool = True) -> None:
file_handle = open(f, 'r')
data = file_handle.readlines()
file_handle.close()
l = data[i]
ws = l[:len(l) - len(l.lstrip())]
data[i] = "%s%s\n" % (ws, text)
file_handle = open(f, 'w')
file_handle.writelines(data)
file_handle.close()
def source_list(
path: str,
filename_check: Optional[Callable[[str], bool]] = None,
) -> Generator[str, None, None]:
for dirpath, dirnames, filenames in os.walk(path):
# skip '.git'
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
if filename_check is None or filename_check(filename):
yield os.path.join(dirpath, filename)
# extension checking
def is_cmake(filename: str) -> bool:
ext = splitext(filename)[1]
return (ext == ".cmake") or (filename == "CMakeLists.txt")
def is_c_header(filename: str) -> bool:
ext = splitext(filename)[1]
return (ext in {".h", ".hpp", ".hxx", ".hh"})
def is_c(filename: str) -> bool:
ext = splitext(filename)[1]
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".metal"})
def is_c_any(filename: str) -> bool:
return is_c(filename) or is_c_header(filename)
def cmake_get_src(f: str) -> None:
sources_h = []
sources_c = []
filen = open(f, "r", encoding="utf8")
it: Optional[Iterator[str]] = iter(filen)
found = False
i = 0
# print(f)
def is_definition(l: str, f: str, i: int, name: str) -> bool:
if l.startswith("unset("):
return False
if ('set(%s' % name) in l or ('set(' in l and l.endswith(name)):
if len(l.split()) > 1:
raise Exception("strict formatting not kept 'set(%s*' %s:%d" % (name, f, i))
return True
if ("list(APPEND %s" % name) in l or ('list(APPEND ' in l and l.endswith(name)):
if l.endswith(")"):
raise Exception("strict formatting not kept 'list(APPEND %s...)' on 1 line %s:%d" % (name, f, i))
return True
return False
while it is not None:
context_name = ""
while it is not None:
i += 1
try:
l = next(it)
except StopIteration:
it = None
break
l = l.strip()
if not l.startswith("#"):
found = is_definition(l, f, i, "SRC")
if found:
context_name = "SRC"
break
found = is_definition(l, f, i, "INC")
if found:
context_name = "INC"
break
if found:
cmake_base = dirname(f)
cmake_base_bin = os.path.join(BUILD_DIR, os.path.relpath(cmake_base, SOURCE_DIR))
# Find known missing sources list (if we have one).
f_rel = os.path.relpath(f, SOURCE_DIR)
f_rel_key = f_rel
if os.sep != "/":
f_rel_key = f_rel_key.replace(os.sep, "/")
local_ignore_source_missing = global_ignore_source_missing.get(f_rel_key, [])
while it is not None:
i += 1
try:
l = next(it)
except StopIteration:
it = None
break
l = l.strip()
if not l.startswith("#"):
# Remove in-line comments.
l = l.split(" # ")[0].rstrip()
if ")" in l:
if l.strip() != ")":
raise Exception("strict formatting not kept '*)' %s:%d" % (f, i))
break
# replace dirs
l = l.replace("${CMAKE_SOURCE_DIR}", SOURCE_DIR)
l = l.replace("${CMAKE_CURRENT_SOURCE_DIR}", cmake_base)
l = l.replace("${CMAKE_CURRENT_BINARY_DIR}", cmake_base_bin)
l = l.strip('"')
if not l:
pass
elif l in local_ignore_source_missing:
local_ignore_source_missing.remove(l)
elif l.startswith("$"):
if context_name == "SRC":
# assume if it ends with context_name we know about it
if not l.split("}")[0].endswith(context_name):
print("Can't use var '%s' %s:%d" % (l, f, i))
elif len(l.split()) > 1:
raise Exception("Multi-line define '%s' %s:%d" % (l, f, i))
else:
new_file = normpath(join(cmake_base, l))
if context_name == "SRC":
if is_c_header(new_file):
sources_h.append(new_file)
global_refs.setdefault(new_file, []).append((f, i))
elif is_c(new_file):
sources_c.append(new_file)
global_refs.setdefault(new_file, []).append((f, i))
elif l in {"PARENT_SCOPE", }:
# cmake var, ignore
pass
elif new_file.endswith(".list"):
pass
elif new_file.endswith(".def"):
pass
elif new_file.endswith(".cl"): # opencl
pass
elif new_file.endswith(".cu"): # cuda
pass
elif new_file.endswith(".osl"): # open shading language
pass
elif new_file.endswith(".glsl"):
pass
else:
raise Exception("unknown file type - not c or h %s -> %s" % (f, new_file))
elif context_name == "INC":
if new_file.startswith(BUILD_DIR):
# assume generated path
pass
elif os.path.isdir(new_file):
new_path_rel = os.path.relpath(new_file, cmake_base)
if new_path_rel != l:
print("overly relative path:\n %s:%d\n %s\n %s" % (f, i, l, new_path_rel))
# # Save time. just replace the line
# replace_line(f, i - 1, new_path_rel)
else:
raise Exception("non existent include %s:%d -> %s" % (f, i, new_file))
# print(new_file)
global_h.update(set(sources_h))
global_c.update(set(sources_c))
'''
if not sources_h and not sources_c:
raise Exception("No sources %s" % f)
sources_h_fs = list(source_list(cmake_base, is_c_header))
sources_c_fs = list(source_list(cmake_base, is_c))
'''
# find missing C files:
'''
for ff in sources_c_fs:
if ff not in sources_c:
print(" missing: " + ff)
'''
# reset
del sources_h[:]
del sources_c[:]
filen.close()
def is_ignore_source(f: str, ignore_used: List[bool]) -> bool:
for index, ignore_path in enumerate(IGNORE_SOURCE):
if ignore_path in f:
ignore_used[index] = True
return True
return False
def is_ignore_cmake(f: str, ignore_used: List[bool]) -> bool:
for index, ignore_path in enumerate(IGNORE_CMAKE):
if ignore_path in f:
ignore_used[index] = True
return True
return False
def main() -> None:
print("Scanning:", SOURCE_DIR)
ignore_used_source = [False] * len(IGNORE_SOURCE)
ignore_used_cmake = [False] * len(IGNORE_CMAKE)
for cmake in source_list(SOURCE_DIR, is_cmake):
if not is_ignore_cmake(cmake, ignore_used_cmake):
cmake_get_src(cmake)
# First do stupid check, do these files exist?
print("\nChecking for missing references:")
is_err = False
errs = []
for f in (global_h | global_c):
if f.startswith(BUILD_DIR):
continue
if not os.path.exists(f):
refs = global_refs[f]
if refs:
for cf, i in refs:
errs.append((cf, i))
else:
raise Exception("CMake references missing, internal error, aborting!")
is_err = True
errs.sort()
errs.reverse()
for cf, i in errs:
print("%s:%d" % (cf, i))
# Write a 'sed' script, useful if we get a lot of these
# print("sed '%dd' '%s' > '%s.tmp' ; mv '%s.tmp' '%s'" % (i, cf, cf, cf, cf))
if is_err:
raise Exception("CMake references missing files, aborting!")
del is_err
del errs
# now check on files not accounted for.
print("\nC/C++ Files CMake does not know about...")
for cf in sorted(source_list(SOURCE_DIR, is_c)):
if not is_ignore_source(cf, ignore_used_source):
if cf not in global_c:
print("missing_c: ", cf)
# Check if automake builds a corresponding .o file.
'''
if cf in global_c:
out1 = os.path.splitext(cf)[0] + ".o"
out2 = os.path.splitext(cf)[0] + ".Po"
out2_dir, out2_file = out2 = os.path.split(out2)
out2 = os.path.join(out2_dir, ".deps", out2_file)
if not os.path.exists(out1) and not os.path.exists(out2):
print("bad_c: ", cf)
'''
print("\nC/C++ Headers CMake does not know about...")
for hf in sorted(source_list(SOURCE_DIR, is_c_header)):
if not is_ignore_source(hf, ignore_used_source):
if hf not in global_h:
print("missing_h: ", hf)
if UTF8_CHECK:
# test encoding
import traceback
for files in (global_c, global_h):
for f in sorted(files):
if os.path.exists(f):
# ignore outside of our source tree
if "extern" not in f:
i = 1
try:
for _ in open(f, "r", encoding="utf8"):
i += 1
except UnicodeDecodeError:
print("Non utf8: %s:%d" % (f, i))
if i > 1:
traceback.print_exc()
# Check ignores aren't stale
print("\nCheck for unused 'IGNORE_SOURCE' paths...")
for index, ignore_path in enumerate(IGNORE_SOURCE):
if not ignore_used_source[index]:
print("unused ignore: %r" % ignore_path)
# Check ignores aren't stale
print("\nCheck for unused 'IGNORE_SOURCE_MISSING' paths...")
for k, v in sorted(global_ignore_source_missing.items()):
for ignore_path in v:
print("unused ignore: %r -> %r" % (ignore_path, k))
# Check ignores aren't stale
print("\nCheck for unused 'IGNORE_CMAKE' paths...")
for index, ignore_path in enumerate(IGNORE_CMAKE):
if not ignore_used_cmake[index]:
print("unused ignore: %r" % ignore_path)
if __name__ == "__main__":
main()

View File

@ -1,64 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import os
IGNORE_SOURCE = (
"/test/",
"/tests/gtests/",
"/release/",
# specific source files
"extern/audaspace/",
# Use for `WIN32` only.
"source/creator/blender_launcher_win32.c",
# specific source files
"extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp",
"extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.cpp",
"extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.cpp",
"extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.cpp",
"extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp",
"extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp",
"doc/doxygen/doxygen.extern.h",
"doc/doxygen/doxygen.intern.h",
"doc/doxygen/doxygen.main.h",
"doc/doxygen/doxygen.source.h",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h",
"extern/bullet2/src/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h",
"extern/bullet2/src/BulletCollision/CollisionShapes/btBox2dShape.h",
"extern/bullet2/src/BulletCollision/CollisionShapes/btConvex2dShape.h",
"extern/bullet2/src/BulletDynamics/Character/btKinematicCharacterController.h",
"extern/bullet2/src/BulletDynamics/ConstraintSolver/btHinge2Constraint.h",
"extern/bullet2/src/BulletDynamics/ConstraintSolver/btUniversalConstraint.h",
)
# Ignore cmake file, path pairs.
IGNORE_SOURCE_MISSING = (
( # Use for cycles stand-alone.
"intern/cycles/util/CMakeLists.txt", (
"../../third_party/numaapi/include",
)),
( # Use for `WITH_NANOVDB`.
"intern/cycles/kernel/CMakeLists.txt", (
"nanovdb/util/CSampleFromVoxels.h",
"nanovdb/util/SampleFromVoxels.h",
"nanovdb/NanoVDB.h",
"nanovdb/CNanoVDB.h",
),
),
)
IGNORE_CMAKE = (
"extern/audaspace/CMakeLists.txt",
)
UTF8_CHECK = True
SOURCE_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(os.path.dirname(__file__), "..", ".."))))
# doesn't have to exist, just use as reference
BUILD_DIR = os.path.normpath(os.path.abspath(os.path.normpath(os.path.join(SOURCE_DIR, "..", "build"))))

View File

@ -849,3 +849,45 @@ if(WITH_COMPILER_CCACHE)
set(WITH_COMPILER_CCACHE OFF)
endif()
endif()
# On some platforms certain atomic operations are not possible with assembly and/or intrinsics and
# they are emulated in software with locks. For example, on armel there is no intrinsics to grant
# 64 bit atomic operations and STL library uses libatomic to offload software emulation of atomics
# to.
# This function will check whether libatomic is required and if so will configure linker flags.
# If atomic operations are possible without libatomic then linker flags are left as-is.
function(CONFIGURE_ATOMIC_LIB_IF_NEEDED)
# Source which is used to enforce situation when software emulation of atomics is required.
# Assume that using 64bit integer gives a definitive asnwer (as in, if 64bit atomic operations
# are possible using assembly/intrinsics 8, 16, and 32 bit operations will also be possible.
set(_source
"#include <atomic>
#include <cstdint>
int main(int argc, char **argv) {
std::atomic<uint64_t> uint64; uint64++;
return 0;
}")
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("${_source}" ATOMIC_OPS_WITHOUT_LIBATOMIC)
if(NOT ATOMIC_OPS_WITHOUT_LIBATOMIC)
# Compilation of the test program has failed.
# Try it again with -latomic to see if this is what is needed, or whether something else is
# going on.
set(CMAKE_REQUIRED_LIBRARIES atomic)
check_cxx_source_compiles("${_source}" ATOMIC_OPS_WITH_LIBATOMIC)
if(ATOMIC_OPS_WITH_LIBATOMIC)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -latomic" PARENT_SCOPE)
else()
# Atomic operations are required part of Blender and it is not possible to process forward.
# We expect that either standard library or libatomic will make atomics to work. If both
# cases has failed something fishy o na bigger scope is going on.
message(FATAL_ERROR "Failed to detect required configuration for atomic operations")
endif()
endif()
endfunction()
CONFIGURE_ATOMIC_LIB_IF_NEEDED()

View File

@ -1,5 +1,6 @@
/* Override RTD theme */
.rst-versions {
display: none;
border-top: 0px;
overflow: visible;
}

View File

@ -177,7 +177,7 @@ void FFMPEGReader::init(int stream)
// get a decoder and open it
#ifndef FFMPEG_OLD_CODE
AVCodec* aCodec = avcodec_find_decoder(m_formatCtx->streams[m_stream]->codecpar->codec_id);
const AVCodec* aCodec = avcodec_find_decoder(m_formatCtx->streams[m_stream]->codecpar->codec_id);
if(!aCodec)
AUD_THROW(FileException, "File couldn't be read, no decoder found with ffmpeg.");

View File

@ -23,6 +23,7 @@
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avio.h>
#include <libavutil/channel_layout.h>
}
AUD_NAMESPACE_BEGIN
@ -171,66 +172,66 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
if(avformat_alloc_output_context2(&m_formatCtx, nullptr, formats[format], filename.c_str()) < 0)
AUD_THROW(FileException, "File couldn't be written, format couldn't be found with ffmpeg.");
AVOutputFormat* outputFmt = m_formatCtx->oformat;
const AVOutputFormat* outputFmt = m_formatCtx->oformat;
if(!outputFmt) {
avformat_free_context(m_formatCtx);
AUD_THROW(FileException, "File couldn't be written, output format couldn't be found with ffmpeg.");
}
outputFmt->audio_codec = AV_CODEC_ID_NONE;
AVCodecID audio_codec = AV_CODEC_ID_NONE;
switch(codec)
{
case CODEC_AAC:
outputFmt->audio_codec = AV_CODEC_ID_AAC;
audio_codec = AV_CODEC_ID_AAC;
break;
case CODEC_AC3:
outputFmt->audio_codec = AV_CODEC_ID_AC3;
audio_codec = AV_CODEC_ID_AC3;
break;
case CODEC_FLAC:
outputFmt->audio_codec = AV_CODEC_ID_FLAC;
audio_codec = AV_CODEC_ID_FLAC;
break;
case CODEC_MP2:
outputFmt->audio_codec = AV_CODEC_ID_MP2;
audio_codec = AV_CODEC_ID_MP2;
break;
case CODEC_MP3:
outputFmt->audio_codec = AV_CODEC_ID_MP3;
audio_codec = AV_CODEC_ID_MP3;
break;
case CODEC_OPUS:
outputFmt->audio_codec = AV_CODEC_ID_OPUS;
audio_codec = AV_CODEC_ID_OPUS;
break;
case CODEC_PCM:
switch(specs.format)
{
case FORMAT_U8:
outputFmt->audio_codec = AV_CODEC_ID_PCM_U8;
audio_codec = AV_CODEC_ID_PCM_U8;
break;
case FORMAT_S16:
outputFmt->audio_codec = AV_CODEC_ID_PCM_S16LE;
audio_codec = AV_CODEC_ID_PCM_S16LE;
break;
case FORMAT_S24:
outputFmt->audio_codec = AV_CODEC_ID_PCM_S24LE;
audio_codec = AV_CODEC_ID_PCM_S24LE;
break;
case FORMAT_S32:
outputFmt->audio_codec = AV_CODEC_ID_PCM_S32LE;
audio_codec = AV_CODEC_ID_PCM_S32LE;
break;
case FORMAT_FLOAT32:
outputFmt->audio_codec = AV_CODEC_ID_PCM_F32LE;
audio_codec = AV_CODEC_ID_PCM_F32LE;
break;
case FORMAT_FLOAT64:
outputFmt->audio_codec = AV_CODEC_ID_PCM_F64LE;
audio_codec = AV_CODEC_ID_PCM_F64LE;
break;
default:
outputFmt->audio_codec = AV_CODEC_ID_NONE;
audio_codec = AV_CODEC_ID_NONE;
break;
}
break;
case CODEC_VORBIS:
outputFmt->audio_codec = AV_CODEC_ID_VORBIS;
audio_codec = AV_CODEC_ID_VORBIS;
break;
default:
outputFmt->audio_codec = AV_CODEC_ID_NONE;
audio_codec = AV_CODEC_ID_NONE;
break;
}
@ -268,10 +269,10 @@ FFMPEGWriter::FFMPEGWriter(std::string filename, DeviceSpecs specs, Container fo
try
{
if(outputFmt->audio_codec == AV_CODEC_ID_NONE)
if(audio_codec == AV_CODEC_ID_NONE)
AUD_THROW(FileException, "File couldn't be written, audio codec not found with ffmpeg.");
AVCodec* codec = avcodec_find_encoder(outputFmt->audio_codec);
const AVCodec* codec = avcodec_find_encoder(audio_codec);
if(!codec)
AUD_THROW(FileException, "File couldn't be written, audio encoder couldn't be found with ffmpeg.");

View File

@ -34,8 +34,14 @@ endif()
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
add_definitions(${GL_DEFINITIONS})
list(APPEND INC_SYS ${GLEW_INCLUDE_DIR} ${SDL2_INCLUDE_DIRS})
list(APPEND LIBRARIES ${CYCLES_GL_LIBRARIES} ${SDL2_LIBRARIES})
list(APPEND INC_SYS
${GLEW_INCLUDE_DIR}
${SDL2_INCLUDE_DIRS}
)
list(APPEND LIBRARIES
${CYCLES_GL_LIBRARIES}
${SDL2_LIBRARIES}
)
endif()
# Common configuration.

View File

@ -75,7 +75,7 @@ bool OpenGLDisplayDriver::update_begin(const Params &params, int texture_width,
/* Update PBO dimensions if needed.
*
* NOTE: Allocate the PBO for the the size which will fit the final render resolution (as in,
* NOTE: Allocate the PBO for the size which will fit the final render resolution (as in,
* at a resolution divider 1. This was we don't need to recreate graphics interoperability
* objects which are costly and which are tied to the specific underlying buffer size.
* The downside of this approach is that when graphics interoperability is not used we are

View File

@ -493,8 +493,13 @@ void BlenderSession::render_frame_finish()
session->set_output_driver(nullptr);
session->full_buffer_written_cb = function_null;
/* The display driver holds OpenGL resources which belong to an OpenGL context held by the render
* engine on Blender side. Force destruction of those resources. */
/* The display driver is the source of drawing context for both drawing and possible graphics
* interop objects in the path trace. Once the frame is finished the OpenGL context might be
* freed form Blender side. Need to ensure that all GPU resources are freed prior to that
* point.
* Ideally would only do this when OpenGL context is actually destroyed, but there is no way to
* know when this happens (at least in the code at the time when this comment was written).
* The penalty of re-creating resources on every frame is unlikely to be noticed. */
display_driver_ = nullptr;
session->set_display_driver(nullptr);

View File

@ -191,7 +191,7 @@ device_ptr CPUDevice::mem_alloc_sub_ptr(device_memory &mem, size_t offset, size_
void CPUDevice::const_copy_to(const char *name, void *host, size_t size)
{
#if WITH_EMBREE
#ifdef WITH_EMBREE
if (strcmp(name, "__data") == 0) {
assert(size <= sizeof(KernelData));

View File

@ -54,14 +54,7 @@ PathTrace::PathTrace(Device *device,
PathTrace::~PathTrace()
{
/* Destroy any GPU resource which was used for graphics interop.
* Need to have access to the PathTraceDisplay as it is the only source of drawing context which
* is used for interop. */
if (display_) {
for (auto &&path_trace_work : path_trace_works_) {
path_trace_work->destroy_gpu_resources(display_.get());
}
}
destroy_gpu_resources();
}
void PathTrace::load_kernels()
@ -559,6 +552,11 @@ void PathTrace::set_output_driver(unique_ptr<OutputDriver> driver)
void PathTrace::set_display_driver(unique_ptr<DisplayDriver> driver)
{
/* The display driver is the source of the drawing context which might be used by
* path trace works. Make sure there is no graphics interop using resources from
* the old display, as it might no longer be available after this call. */
destroy_gpu_resources();
if (driver) {
display_ = make_unique<PathTraceDisplay>(move(driver));
}
@ -1075,6 +1073,18 @@ bool PathTrace::has_denoised_result() const
return render_state_.has_denoised_result;
}
void PathTrace::destroy_gpu_resources()
{
/* Destroy any GPU resource which was used for graphics interop.
* Need to have access to the PathTraceDisplay as it is the only source of drawing context which
* is used for interop. */
if (display_) {
for (auto &&path_trace_work : path_trace_works_) {
path_trace_work->destroy_gpu_resources(display_.get());
}
}
}
/* --------------------------------------------------------------------
* Report generation.
*/

View File

@ -226,6 +226,9 @@ class PathTrace {
void progress_set_status(const string &status, const string &substatus = "");
/* Destroy GPU resources (such as graphics interop) used by work. */
void destroy_gpu_resources();
/* Pointer to a device which is configured to be used for path tracing. If multiple devices
* are configured this is a `MultiDevice`. */
Device *device_ = nullptr;

View File

@ -244,7 +244,7 @@ void RenderScheduler::render_work_reschedule_on_cancel(RenderWork &render_work)
render_work.tile.write = tile_write;
render_work.full.write = full_write;
/* Do not write tile if it has zero samples it it, treat it similarly to all other tiles which
/* Do not write tile if it has zero samples in it, treat it similarly to all other tiles which
* got canceled. */
if (!state_.tile_result_was_written && has_rendered_samples) {
render_work.tile.write = true;

View File

@ -124,7 +124,7 @@ class RenderScheduler {
/* Get sample up to which rendering has been done.
* This is an absolute 0-based value.
*
* For example, if start sample is 10 and and 5 samples were rendered, then this call will
* For example, if start sample is 10 and 5 samples were rendered, then this call will
* return 14.
*
* If there were no samples rendered, then the behavior is undefined. */
@ -132,7 +132,7 @@ class RenderScheduler {
/* Get number of samples rendered within the current scheduling session.
*
* For example, if start sample is 10 and and 5 samples were rendered, then this call will
* For example, if start sample is 10 and 5 samples were rendered, then this call will
* return 5.
*
* Note that this is based on the scheduling information. In practice this means that if someone

View File

@ -5,27 +5,6 @@
CCL_NAMESPACE_BEGIN
/* Ray offset to avoid self intersection.
*
* This function should be used to compute a modified ray start position for
* rays leaving from a surface. This is from "A Fast and Robust Method for Avoiding
* Self-Intersection" see https://research.nvidia.com/publication/2019-03_A-Fast-and
*/
ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
{
const float int_scale = 256.0f;
int3 of_i = make_int3((int)(int_scale * Ng.x), (int)(int_scale * Ng.y), (int)(int_scale * Ng.z));
float3 p_i = make_float3(__int_as_float(__float_as_int(P.x) + ((P.x < 0) ? -of_i.x : of_i.x)),
__int_as_float(__float_as_int(P.y) + ((P.y < 0) ? -of_i.y : of_i.y)),
__int_as_float(__float_as_int(P.z) + ((P.z < 0) ? -of_i.z : of_i.z)));
const float origin = 1.0f / 32.0f;
const float float_scale = 1.0f / 65536.0f;
return make_float3(fabsf(P.x) < origin ? P.x + float_scale * Ng.x : p_i.x,
fabsf(P.y) < origin ? P.y + float_scale * Ng.y : p_i.y,
fabsf(P.z) < origin ? P.z + float_scale * Ng.z : p_i.z);
}
#if defined(__KERNEL_CPU__)
ccl_device int intersections_compare(const void *a, const void *b)
{

View File

@ -128,9 +128,10 @@ ccl_device float point_radius(KernelGlobals kg, ccl_private const ShaderData *sd
return r;
}
else {
float3 dir = make_float3(r, r, r);
const float normalized_r = r * (1.0f / M_SQRT3_F);
float3 dir = make_float3(normalized_r, normalized_r, normalized_r);
object_dir_transform(kg, sd, &dir);
return average(dir);
return len(dir);
}
}

View File

@ -30,6 +30,50 @@ ccl_device_inline float bake_clamp_mirror_repeat(float u, float max)
return ((((int)fu) & 1) ? 1.0f - u : u) * max;
}
/* Offset towards center of triangle to avoid ray-tracing precision issues. */
ccl_device const float2 bake_offset_towards_center(KernelGlobals kg,
const int prim,
const float u,
const float v)
{
float3 tri_verts[3];
triangle_vertices(kg, prim, tri_verts);
/* Empirically determined values, by no means perfect. */
const float position_offset = 1e-4f;
const float uv_offset = 1e-5f;
/* Offset position towards center, amount relative to absolute size of position coordinates. */
const float3 P = u * tri_verts[0] + v * tri_verts[1] + (1.0f - u - v) * tri_verts[2];
const float3 center = (tri_verts[0] + tri_verts[1] + tri_verts[2]) / 3.0f;
const float3 to_center = center - P;
const float3 offset_P = P + normalize(to_center) *
min(len(to_center), max(max3(fabs(P)), 1.0f) * position_offset);
/* Compute barycentric coordinates at new position. */
const float3 v1 = tri_verts[1] - tri_verts[0];
const float3 v2 = tri_verts[2] - tri_verts[0];
const float3 vP = offset_P - tri_verts[0];
const float d11 = dot(v1, v1);
const float d12 = dot(v1, v2);
const float d22 = dot(v2, v2);
const float dP1 = dot(vP, v1);
const float dP2 = dot(vP, v2);
const float denom = d11 * d22 - d12 * d12;
if (denom == 0.0f) {
return make_float2(0.0f, 0.0f);
}
const float offset_v = clamp((d22 * dP1 - d12 * dP2) / denom, uv_offset, 1.0f - uv_offset);
const float offset_w = clamp((d11 * dP2 - d12 * dP1) / denom, uv_offset, 1.0f - uv_offset);
const float offset_u = clamp(1.0f - offset_v - offset_w, uv_offset, 1.0f - uv_offset);
return make_float2(offset_u, offset_v);
}
/* Return false to indicate that this pixel is finished.
* Used by CPU implementation to not attempt to sample pixel for multiple samples once its known
* that the pixel did converge. */
@ -87,7 +131,7 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
/* Initialize path state for path integration. */
path_state_init_integrator(kg, state, sample, rng_hash);
/* Barycentric UV with sub-pixel offset. */
/* Barycentric UV. */
float u = primitive[2];
float v = primitive[3];
@ -96,6 +140,14 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg,
float dvdx = differential[2];
float dvdy = differential[3];
/* Exactly at vertex? Nudge inwards to avoid self-intersection. */
if ((u == 0.0f || u == 1.0f) && (v == 0.0f || v == 1.0f)) {
const float2 uv = bake_offset_towards_center(kg, prim, u, v);
u = uv.x;
v = uv.y;
}
/* Sub-pixel offset. */
if (sample > 0) {
u = bake_clamp_mirror_repeat(u + dudx * (filter_x - 0.5f) + dudy * (filter_y - 0.5f), 1.0f);
v = bake_clamp_mirror_repeat(v + dvdx * (filter_x - 0.5f) + dvdy * (filter_y - 0.5f),

View File

@ -352,12 +352,8 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg,
float ao_pdf;
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
if (!(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f)) {
return;
}
Ray ray ccl_optional_struct_init;
ray.P = sd->P;
ray.P = shadow_ray_offset(kg, sd, ao_D);
ray.D = ao_D;
ray.t = kernel_data.integrator.ao_bounces_distance;
ray.time = sd->time;

View File

@ -1638,12 +1638,16 @@ bool OSLRenderServices::trace(TraceOpt &options,
ray.D = TO_FLOAT3(R);
ray.t = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist - options.mindist;
ray.time = sd->time;
ray.self.object = OBJECT_NONE;
ray.self.prim = PRIM_NONE;
ray.self.light_object = OBJECT_NONE;
ray.self.light_prim = PRIM_NONE;
if (options.mindist == 0.0f) {
/* avoid self-intersections */
if (ray.P == sd->P) {
bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
ray.P = ray_offset(sd->P, (transmit) ? -sd->Ng : sd->Ng);
ray.self.object = sd->object;
ray.self.prim = sd->prim;
}
}
else {

View File

@ -58,8 +58,8 @@ ccl_device_noinline void svm_node_light_path(KernelGlobals kg,
info = (float)integrator_state_bounce(state, path_flag);
}
/* For background, light emission and shadow evaluation we from a
* surface or volume we are effective one bounce further. */
/* For background, light emission and shadow evaluation from a
* surface or volume we are effectively one bounce further. */
if (path_flag & (PATH_RAY_SHADOW | PATH_RAY_EMISSION)) {
info += 1.0f;
}

View File

@ -67,6 +67,9 @@ CCL_NAMESPACE_BEGIN
#ifndef M_SQRT2_F
# define M_SQRT2_F (1.4142135623730950f) /* sqrt(2) */
#endif
#ifndef M_SQRT3_F
# define M_SQRT3_F (1.7320508075688772f) /* sqrt(3) */
#endif
#ifndef M_LN2_F
# define M_LN2_F (0.6931471805599453f) /* ln(2) */
#endif

View File

@ -4,12 +4,13 @@
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/log.h>
}
namespace {
bool test_vcodec(AVCodec *codec, AVPixelFormat pixelformat)
bool test_vcodec(const AVCodec *codec, AVPixelFormat pixelformat)
{
av_log_set_level(AV_LOG_QUIET);
bool result = false;
@ -30,7 +31,7 @@ bool test_vcodec(AVCodec *codec, AVPixelFormat pixelformat)
}
return result;
}
bool test_acodec(AVCodec *codec, AVSampleFormat fmt)
bool test_acodec(const AVCodec *codec, AVSampleFormat fmt)
{
av_log_set_level(AV_LOG_QUIET);
bool result = false;
@ -54,7 +55,7 @@ bool test_acodec(AVCodec *codec, AVSampleFormat fmt)
bool test_codec_video_by_codecid(AVCodecID codec_id, AVPixelFormat pixelformat)
{
bool result = false;
AVCodec *codec = avcodec_find_encoder(codec_id);
const AVCodec *codec = avcodec_find_encoder(codec_id);
if (codec)
result = test_vcodec(codec, pixelformat);
return result;
@ -63,7 +64,7 @@ bool test_codec_video_by_codecid(AVCodecID codec_id, AVPixelFormat pixelformat)
bool test_codec_video_by_name(const char *codecname, AVPixelFormat pixelformat)
{
bool result = false;
AVCodec *codec = avcodec_find_encoder_by_name(codecname);
const AVCodec *codec = avcodec_find_encoder_by_name(codecname);
if (codec)
result = test_vcodec(codec, pixelformat);
return result;
@ -72,7 +73,7 @@ bool test_codec_video_by_name(const char *codecname, AVPixelFormat pixelformat)
bool test_codec_audio_by_codecid(AVCodecID codec_id, AVSampleFormat fmt)
{
bool result = false;
AVCodec *codec = avcodec_find_encoder(codec_id);
const AVCodec *codec = avcodec_find_encoder(codec_id);
if (codec)
result = test_acodec(codec, fmt);
return result;
@ -81,7 +82,7 @@ bool test_codec_audio_by_codecid(AVCodecID codec_id, AVSampleFormat fmt)
bool test_codec_audio_by_name(const char *codecname, AVSampleFormat fmt)
{
bool result = false;
AVCodec *codec = avcodec_find_encoder_by_name(codecname);
const AVCodec *codec = avcodec_find_encoder_by_name(codecname);
if (codec)
result = test_acodec(codec, fmt);
return result;

View File

@ -307,6 +307,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
case ']':
return GHOST_kKeyRightBracket;
case '`':
case '<': /* The position of '`' is equivalent to this symbol in the French layout. */
return GHOST_kKeyAccentGrave;
default:
return GHOST_kKeyUnknown;

View File

@ -53,9 +53,6 @@
#ifndef VK_COMMA
# define VK_COMMA 0xBC
#endif // VK_COMMA
#ifndef VK_QUOTE
# define VK_QUOTE 0xDE
#endif // VK_QUOTE
#ifndef VK_BACK_QUOTE
# define VK_BACK_QUOTE 0xC0
#endif // VK_BACK_QUOTE
@ -635,14 +632,32 @@ GHOST_TKey GHOST_SystemWin32::hardKey(RAWINPUT const &raw,
GHOST_TKey GHOST_SystemWin32::processSpecialKey(short vKey, short scanCode) const
{
GHOST_TKey key = GHOST_kKeyUnknown;
switch (PRIMARYLANGID(m_langId)) {
case LANG_FRENCH:
if (vKey == VK_OEM_8)
key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
char ch = (char)MapVirtualKeyA(vKey, MAPVK_VK_TO_CHAR);
switch (ch) {
case u'\"':
case u'\'':
key = GHOST_kKeyQuote;
break;
case LANG_ENGLISH:
if (SUBLANGID(m_langId) == SUBLANG_ENGLISH_UK && vKey == VK_OEM_8) // "`¬"
key = GHOST_kKeyAccentGrave;
case u'.':
key = GHOST_kKeyNumpadPeriod;
break;
case u'/':
key = GHOST_kKeySlash;
break;
case u'`':
case u'²':
key = GHOST_kKeyAccentGrave;
break;
default:
if (vKey == VK_OEM_7) {
key = GHOST_kKeyQuote;
}
else if (vKey == VK_OEM_8) {
if (PRIMARYLANGID(m_langId) == LANG_FRENCH) {
/* oem key; used purely for shortcuts. */
key = GHOST_kKeyF13;
}
}
break;
}
@ -777,9 +792,6 @@ GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short exten
case VK_CLOSE_BRACKET:
key = GHOST_kKeyRightBracket;
break;
case VK_QUOTE:
key = GHOST_kKeyQuote;
break;
case VK_GR_LESS:
key = GHOST_kKeyGrLess;
break;
@ -821,9 +833,6 @@ GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short exten
case VK_CAPITAL:
key = GHOST_kKeyCapsLock;
break;
case VK_OEM_8:
key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(vKey, scanCode);
break;
case VK_MEDIA_PLAY_PAUSE:
key = GHOST_kKeyMediaPlay;
break;
@ -836,8 +845,10 @@ GHOST_TKey GHOST_SystemWin32::convertKey(short vKey, short scanCode, short exten
case VK_MEDIA_NEXT_TRACK:
key = GHOST_kKeyMediaLast;
break;
case VK_OEM_7:
case VK_OEM_8:
default:
key = GHOST_kKeyUnknown;
key = ((GHOST_SystemWin32 *)getSystem())->processSpecialKey(vKey, scanCode);
break;
}
}

View File

@ -412,6 +412,9 @@ void GHOST_XrContext::getExtensionsToEnable(
/* Interaction profile extensions. */
try_ext.push_back(XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME);
try_ext.push_back(XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME);
#ifdef XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME
try_ext.push_back(XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME);
#endif
try_ext.push_back(XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME);
/* Controller model extension. */

View File

@ -324,7 +324,7 @@ static bool addGPULut2D(OCIO_GPUTextures &textures,
GPU_R16F;
OCIO_GPULutTexture lut;
lut.texture = GPU_texture_create_2d(texture_name, width, height, 0, format, values);
lut.texture = GPU_texture_create_2d(texture_name, width, height, 1, format, values);
if (lut.texture == nullptr) {
return false;
}
@ -356,7 +356,7 @@ static bool addGPULut3D(OCIO_GPUTextures &textures,
OCIO_GPULutTexture lut;
lut.texture = GPU_texture_create_3d(
texture_name, edgelen, edgelen, edgelen, 0, GPU_RGB16F, GPU_DATA_FLOAT, values);
texture_name, edgelen, edgelen, edgelen, 1, GPU_RGB16F, GPU_DATA_FLOAT, values);
if (lut.texture == nullptr) {
return false;
}
@ -506,11 +506,11 @@ static void updateGPUDisplayParameters(OCIO_GPUShader &shader,
data.dither = dither;
do_update = true;
}
if (data.use_predivide != use_predivide) {
if (bool(data.use_predivide) != use_predivide) {
data.use_predivide = use_predivide;
do_update = true;
}
if (data.use_overlay != use_overlay) {
if (bool(data.use_overlay) != use_overlay) {
data.use_overlay = use_overlay;
do_update = true;
}

View File

@ -140,8 +140,8 @@ GLStencilTableSSBO::~GLStencilTableSSBO()
GLComputeEvaluator::GLComputeEvaluator() : _workGroupSize(64), _patchArraysSSBO(0)
{
memset(&_stencilKernel, 0, sizeof(_stencilKernel));
memset(&_patchKernel, 0, sizeof(_patchKernel));
memset((void *)&_stencilKernel, 0, sizeof(_stencilKernel));
memset((void *)&_patchKernel, 0, sizeof(_patchKernel));
}
GLComputeEvaluator::~GLComputeEvaluator()

View File

@ -24,56 +24,103 @@
//------------------------------------------------------------------------------
layout(local_size_x=WORK_GROUP_SIZE, local_size_y=1, local_size_z=1) in;
layout(local_size_x = WORK_GROUP_SIZE, local_size_y = 1, local_size_z = 1) in;
layout(std430) buffer;
// source and destination buffers
uniform int srcOffset = 0;
uniform int dstOffset = 0;
layout(binding=0) buffer src_buffer { float srcVertexBuffer[]; };
layout(binding=1) buffer dst_buffer { float dstVertexBuffer[]; };
layout(binding = 0) buffer src_buffer
{
float srcVertexBuffer[];
};
layout(binding = 1) buffer dst_buffer
{
float dstVertexBuffer[];
};
// derivative buffers (if needed)
// derivative buffers (if needed)
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
uniform ivec3 duDesc;
uniform ivec3 dvDesc;
layout(binding=2) buffer du_buffer { float duBuffer[]; };
layout(binding=3) buffer dv_buffer { float dvBuffer[]; };
layout(binding = 2) buffer du_buffer
{
float duBuffer[];
};
layout(binding = 3) buffer dv_buffer
{
float dvBuffer[];
};
#endif
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
uniform ivec3 duuDesc;
uniform ivec3 duvDesc;
uniform ivec3 dvvDesc;
layout(binding=10) buffer duu_buffer { float duuBuffer[]; };
layout(binding=11) buffer duv_buffer { float duvBuffer[]; };
layout(binding=12) buffer dvv_buffer { float dvvBuffer[]; };
layout(binding = 10) buffer duu_buffer
{
float duuBuffer[];
};
layout(binding = 11) buffer duv_buffer
{
float duvBuffer[];
};
layout(binding = 12) buffer dvv_buffer
{
float dvvBuffer[];
};
#endif
// stencil buffers
// stencil buffers
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS)
uniform int batchStart = 0;
uniform int batchEnd = 0;
layout(binding=4) buffer stencilSizes { int _sizes[]; };
layout(binding=5) buffer stencilOffsets { int _offsets[]; };
layout(binding=6) buffer stencilIndices { int _indices[]; };
layout(binding=7) buffer stencilWeights { float _weights[]; };
layout(binding = 4) buffer stencilSizes
{
int _sizes[];
};
layout(binding = 5) buffer stencilOffsets
{
int _offsets[];
};
layout(binding = 6) buffer stencilIndices
{
int _indices[];
};
layout(binding = 7) buffer stencilWeights
{
float _weights[];
};
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
layout(binding=8) buffer stencilDuWeights { float _duWeights[]; };
layout(binding=9) buffer stencilDvWeights { float _dvWeights[]; };
#endif
# if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
layout(binding = 8) buffer stencilDuWeights
{
float _duWeights[];
};
layout(binding = 9) buffer stencilDvWeights
{
float _dvWeights[];
};
# endif
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
layout(binding=13) buffer stencilDuuWeights { float _duuWeights[]; };
layout(binding=14) buffer stencilDuvWeights { float _duvWeights[]; };
layout(binding=15) buffer stencilDvvWeights { float _dvvWeights[]; };
#endif
# if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
layout(binding = 13) buffer stencilDuuWeights
{
float _duuWeights[];
};
layout(binding = 14) buffer stencilDuvWeights
{
float _duvWeights[];
};
layout(binding = 15) buffer stencilDvvWeights
{
float _dvvWeights[];
};
# endif
uint getGlobalInvocationIndex()
{
@ -87,24 +134,36 @@ uint getGlobalInvocationIndex()
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_PATCHES)
layout(binding=4) buffer patchArray_buffer { OsdPatchArray patchArrayBuffer[]; };
layout(binding=5) buffer patchCoord_buffer { OsdPatchCoord patchCoords[]; };
layout(binding=6) buffer patchIndex_buffer { int patchIndexBuffer[]; };
layout(binding=7) buffer patchParam_buffer { OsdPatchParam patchParamBuffer[]; };
layout(binding = 4) buffer patchArray_buffer
{
OsdPatchArray patchArrayBuffer[];
};
layout(binding = 5) buffer patchCoord_buffer
{
OsdPatchCoord patchCoords[];
};
layout(binding = 6) buffer patchIndex_buffer
{
int patchIndexBuffer[];
};
layout(binding = 7) buffer patchParam_buffer
{
OsdPatchParam patchParamBuffer[];
};
OsdPatchCoord GetPatchCoord(int coordIndex)
{
return patchCoords[coordIndex];
return patchCoords[coordIndex];
}
OsdPatchArray GetPatchArray(int arrayIndex)
{
return patchArrayBuffer[arrayIndex];
return patchArrayBuffer[arrayIndex];
}
OsdPatchParam GetPatchParam(int patchIndex)
{
return patchParamBuffer[patchIndex];
return patchParamBuffer[patchIndex];
}
#endif
@ -112,141 +171,149 @@ OsdPatchParam GetPatchParam(int patchIndex)
//------------------------------------------------------------------------------
struct Vertex {
float vertexData[LENGTH];
float vertexData[LENGTH];
};
void clear(out Vertex v) {
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] = 0;
}
void clear(out Vertex v)
{
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] = 0;
}
}
Vertex readVertex(int index) {
Vertex v;
int vertexIndex = srcOffset + index * SRC_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] = srcVertexBuffer[vertexIndex + i];
}
return v;
Vertex readVertex(int index)
{
Vertex v;
int vertexIndex = srcOffset + index * SRC_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] = srcVertexBuffer[vertexIndex + i];
}
return v;
}
void writeVertex(int index, Vertex v) {
int vertexIndex = dstOffset + index * DST_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
}
void writeVertex(int index, Vertex v)
{
int vertexIndex = dstOffset + index * DST_STRIDE;
for (int i = 0; i < LENGTH; ++i) {
dstVertexBuffer[vertexIndex + i] = v.vertexData[i];
}
}
void addWithWeight(inout Vertex v, const Vertex src, float weight) {
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] += weight * src.vertexData[i];
}
void addWithWeight(inout Vertex v, const Vertex src, float weight)
{
for (int i = 0; i < LENGTH; ++i) {
v.vertexData[i] += weight * src.vertexData[i];
}
}
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
void writeDu(int index, Vertex du) {
int duIndex = duDesc.x + index * duDesc.z;
for (int i = 0; i < LENGTH; ++i) {
duBuffer[duIndex + i] = du.vertexData[i];
}
void writeDu(int index, Vertex du)
{
int duIndex = duDesc.x + index * duDesc.z;
for (int i = 0; i < LENGTH; ++i) {
duBuffer[duIndex + i] = du.vertexData[i];
}
}
void writeDv(int index, Vertex dv) {
int dvIndex = dvDesc.x + index * dvDesc.z;
for (int i = 0; i < LENGTH; ++i) {
dvBuffer[dvIndex + i] = dv.vertexData[i];
}
void writeDv(int index, Vertex dv)
{
int dvIndex = dvDesc.x + index * dvDesc.z;
for (int i = 0; i < LENGTH; ++i) {
dvBuffer[dvIndex + i] = dv.vertexData[i];
}
}
#endif
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
void writeDuu(int index, Vertex duu) {
int duuIndex = duuDesc.x + index * duuDesc.z;
for (int i = 0; i < LENGTH; ++i) {
duuBuffer[duuIndex + i] = duu.vertexData[i];
}
void writeDuu(int index, Vertex duu)
{
int duuIndex = duuDesc.x + index * duuDesc.z;
for (int i = 0; i < LENGTH; ++i) {
duuBuffer[duuIndex + i] = duu.vertexData[i];
}
}
void writeDuv(int index, Vertex duv) {
int duvIndex = duvDesc.x + index * duvDesc.z;
for (int i = 0; i < LENGTH; ++i) {
duvBuffer[duvIndex + i] = duv.vertexData[i];
}
void writeDuv(int index, Vertex duv)
{
int duvIndex = duvDesc.x + index * duvDesc.z;
for (int i = 0; i < LENGTH; ++i) {
duvBuffer[duvIndex + i] = duv.vertexData[i];
}
}
void writeDvv(int index, Vertex dvv) {
int dvvIndex = dvvDesc.x + index * dvvDesc.z;
for (int i = 0; i < LENGTH; ++i) {
dvvBuffer[dvvIndex + i] = dvv.vertexData[i];
}
void writeDvv(int index, Vertex dvv)
{
int dvvIndex = dvvDesc.x + index * dvvDesc.z;
for (int i = 0; i < LENGTH; ++i) {
dvvBuffer[dvvIndex + i] = dvv.vertexData[i];
}
}
#endif
//------------------------------------------------------------------------------
#if defined(OPENSUBDIV_GLSL_COMPUTE_KERNEL_EVAL_STENCILS)
void main() {
int current = int(getGlobalInvocationIndex()) + batchStart;
void main()
{
int current = int(getGlobalInvocationIndex()) + batchStart;
if (current>=batchEnd) {
return;
}
if (current >= batchEnd) {
return;
}
Vertex dst;
clear(dst);
Vertex dst;
clear(dst);
int offset = _offsets[current],
size = _sizes[current];
int offset = _offsets[current], size = _sizes[current];
for (int stencil = 0; stencil < size; ++stencil) {
int vindex = offset + stencil;
addWithWeight(
dst, readVertex(_indices[vindex]), _weights[vindex]);
}
for (int stencil = 0; stencil < size; ++stencil) {
int vindex = offset + stencil;
addWithWeight(dst, readVertex(_indices[vindex]), _weights[vindex]);
}
writeVertex(current, dst);
writeVertex(current, dst);
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
Vertex du, dv;
clear(du);
clear(dv);
for (int i=0; i<size; ++i) {
// expects the compiler optimizes readVertex out here.
Vertex src = readVertex(_indices[offset+i]);
addWithWeight(du, src, _duWeights[offset+i]);
addWithWeight(dv, src, _dvWeights[offset+i]);
}
# if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
Vertex du, dv;
clear(du);
clear(dv);
for (int i = 0; i < size; ++i) {
// expects the compiler optimizes readVertex out here.
Vertex src = readVertex(_indices[offset + i]);
addWithWeight(du, src, _duWeights[offset + i]);
addWithWeight(dv, src, _dvWeights[offset + i]);
}
if (duDesc.y > 0) { // length
writeDu(current, du);
}
if (dvDesc.y > 0) {
writeDv(current, dv);
}
#endif
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
Vertex duu, duv, dvv;
clear(duu);
clear(duv);
clear(dvv);
for (int i=0; i<size; ++i) {
// expects the compiler optimizes readVertex out here.
Vertex src = readVertex(_indices[offset+i]);
addWithWeight(duu, src, _duuWeights[offset+i]);
addWithWeight(duv, src, _duvWeights[offset+i]);
addWithWeight(dvv, src, _dvvWeights[offset+i]);
}
if (duDesc.y > 0) { // length
writeDu(current, du);
}
if (dvDesc.y > 0) {
writeDv(current, dv);
}
# endif
# if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
Vertex duu, duv, dvv;
clear(duu);
clear(duv);
clear(dvv);
for (int i = 0; i < size; ++i) {
// expects the compiler optimizes readVertex out here.
Vertex src = readVertex(_indices[offset + i]);
addWithWeight(duu, src, _duuWeights[offset + i]);
addWithWeight(duv, src, _duvWeights[offset + i]);
addWithWeight(dvv, src, _dvvWeights[offset + i]);
}
if (duuDesc.y > 0) { // length
writeDuu(current, duu);
}
if (duvDesc.y > 0) {
writeDuv(current, duv);
}
if (dvvDesc.y > 0) {
writeDvv(current, dvv);
}
#endif
if (duuDesc.y > 0) { // length
writeDuu(current, duu);
}
if (duvDesc.y > 0) {
writeDuv(current, duv);
}
if (dvvDesc.y > 0) {
writeDvv(current, dvv);
}
# endif
}
#endif
@ -256,61 +323,61 @@ void main() {
// PERFORMANCE: stride could be constant, but not as significant as length
void main() {
void main()
{
int current = int(gl_GlobalInvocationID.x);
int current = int(gl_GlobalInvocationID.x);
OsdPatchCoord coord = GetPatchCoord(current);
OsdPatchArray array = GetPatchArray(coord.arrayIndex);
OsdPatchParam param = GetPatchParam(coord.patchIndex);
OsdPatchCoord coord = GetPatchCoord(current);
OsdPatchArray array = GetPatchArray(coord.arrayIndex);
OsdPatchParam param = GetPatchParam(coord.patchIndex);
int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
int nPoints = OsdEvaluatePatchBasis(patchType, param,
coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
int nPoints = OsdEvaluatePatchBasis(
patchType, param, coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
Vertex dst, du, dv, duu, duv, dvv;
clear(dst);
clear(du);
clear(dv);
clear(duu);
clear(duv);
clear(dvv);
Vertex dst, du, dv, duu, duv, dvv;
clear(dst);
clear(du);
clear(dv);
clear(duu);
clear(duv);
clear(dvv);
int indexBase = array.indexBase + array.stride *
(coord.patchIndex - array.primitiveIdBase);
int indexBase = array.indexBase + array.stride * (coord.patchIndex - array.primitiveIdBase);
for (int cv = 0; cv < nPoints; ++cv) {
int index = patchIndexBuffer[indexBase + cv];
addWithWeight(dst, readVertex(index), wP[cv]);
addWithWeight(du, readVertex(index), wDu[cv]);
addWithWeight(dv, readVertex(index), wDv[cv]);
addWithWeight(duu, readVertex(index), wDuu[cv]);
addWithWeight(duv, readVertex(index), wDuv[cv]);
addWithWeight(dvv, readVertex(index), wDvv[cv]);
}
writeVertex(current, dst);
for (int cv = 0; cv < nPoints; ++cv) {
int index = patchIndexBuffer[indexBase + cv];
addWithWeight(dst, readVertex(index), wP[cv]);
addWithWeight(du, readVertex(index), wDu[cv]);
addWithWeight(dv, readVertex(index), wDv[cv]);
addWithWeight(duu, readVertex(index), wDuu[cv]);
addWithWeight(duv, readVertex(index), wDuv[cv]);
addWithWeight(dvv, readVertex(index), wDvv[cv]);
}
writeVertex(current, dst);
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
if (duDesc.y > 0) { // length
writeDu(current, du);
}
if (dvDesc.y > 0) {
writeDv(current, dv);
}
#endif
#if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
if (duuDesc.y > 0) { // length
writeDuu(current, duu);
}
if (duvDesc.y > 0) { // length
writeDuv(current, duv);
}
if (dvvDesc.y > 0) {
writeDvv(current, dvv);
}
#endif
# if defined(OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES)
if (duDesc.y > 0) { // length
writeDu(current, du);
}
if (dvDesc.y > 0) {
writeDv(current, dv);
}
# endif
# if defined(OPENSUBDIV_GLSL_COMPUTE_USE_2ND_DERIVATIVES)
if (duuDesc.y > 0) { // length
writeDuu(current, duu);
}
if (duvDesc.y > 0) { // length
writeDuv(current, duv);
}
if (dvvDesc.y > 0) {
writeDvv(current, dvv);
}
# endif
}
#endif

View File

@ -26,8 +26,8 @@ if sys.platform[:3] == "win":
env["SystemDrive"] = os.environ.get("SystemDrive", "")
env["SystemRoot"] = os.environ.get("SystemRoot", "")
inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape")
blender_bin = os.environ.get("BLENDER_BIN", "blender")
inkscape_bin = "inkscape"
blender_bin = "blender"
if sys.platform == 'darwin':
inkscape_app_path = '/Applications/Inkscape.app/Contents/MacOS/inkscape'
@ -36,6 +36,11 @@ if sys.platform == 'darwin':
blender_app_path = '/Applications/Blender.app/Contents/MacOS/Blender'
if os.path.exists(blender_app_path):
blender_bin = blender_app_path
else:
blender_bin = "Blender"
inkscape_bin = os.environ.get("INKSCAPE_BIN", inkscape_bin)
blender_bin = os.environ.get("BLENDER_BIN", blender_bin)
cmd = (
inkscape_bin,

@ -1 +1 @@
Subproject commit 2d12637a69df7643484a8a3655b7eeb6faa170a7
Subproject commit 2a5095eed3028e91624d27ca93e4c65f572b809d

View File

@ -144,7 +144,7 @@ const UserDef U_default = {
* so invert this by default, see: T67579. */
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_ZOOM_INVERT | NDOF_CAMERA_PAN_ZOOM),
.image_draw_method = IMAGE_DRAW_METHOD_AUTO,
.glalphaclip = 0.004,
.autokey_mode = (AUTOKEY_MODE_NORMAL & ~AUTOKEY_ON),

@ -1 +1 @@
Subproject commit 089aef61debbece2baff6516e33fc7491629b1d0
Subproject commit bb62f10715a871d7069d2b2c74b2efc97c3c350c

View File

@ -489,12 +489,7 @@ def disable_all():
def _blender_manual_url_prefix():
if _bpy.app.version_cycle in {"rc", "release"}:
manual_version = "%d.%d" % _bpy.app.version[:2]
else:
manual_version = "dev"
return "https://docs.blender.org/manual/en/" + manual_version
return "https://docs.blender.org/manual/en/%d.%d" % _bpy.app.version[:2]
def module_bl_info(mod, *, info_basis=None):

View File

@ -189,6 +189,7 @@ def generate(context, space_type, *, use_fallback_keys=True, use_reset=True):
'VERTEX_GPENCIL': "gpencil_vertex_tool",
'SCULPT_GPENCIL': "gpencil_sculpt_tool",
'WEIGHT_GPENCIL': "gpencil_weight_tool",
'SCULPT_CURVES': "curves_sculpt_tool",
}.get(mode, None)
else:
attr = None

View File

@ -3,10 +3,7 @@
import bpy
if bpy.app.version_cycle in {'rc', 'release'}:
manual_version = '%d.%d' % bpy.app.version[:2]
else:
manual_version = 'dev'
manual_version = '%d.%d' % bpy.app.version[:2]
url_manual_prefix = "https://docs.blender.org/manual/en/" + manual_version + "/"
@ -50,7 +47,6 @@ url_manual_mapping = (
("bpy.types.lineartgpencilmodifier.use_offset_towards_custom_camera*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-offset-towards-custom-camera"),
("bpy.types.movietrackingsettings.refine_intrinsics_principal_point*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingsettings-refine-intrinsics-principal-point"),
("bpy.types.cyclesobjectsettings.shadow_terminator_geometry_offset*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-shadow-terminator-geometry-offset"),
("bpy.types.cyclesrenderlayersettings.denoising_optix_input_passes*", "render/layers/denoising.html#bpy-types-cyclesrenderlayersettings-denoising-optix-input-passes"),
("bpy.types.sequencertoolsettings.use_snap_current_frame_to_strips*", "video_editing/sequencer/editing.html#bpy-types-sequencertoolsettings-use-snap-current-frame-to-strips"),
("bpy.types.fluiddomainsettings.sndparticle_potential_max_energy*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-potential-max-energy"),
("bpy.types.fluiddomainsettings.sndparticle_potential_min_energy*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-potential-min-energy"),
@ -114,6 +110,7 @@ url_manual_mapping = (
("bpy.types.gpencilsculptsettings.intersection_threshold*", "grease_pencil/modes/draw/tools/cutter.html#bpy-types-gpencilsculptsettings-intersection-threshold"),
("bpy.types.gpencilsculptsettings.use_multiframe_falloff*", "grease_pencil/multiframe.html#bpy-types-gpencilsculptsettings-use-multiframe-falloff"),
("bpy.types.lineartgpencilmodifier.use_intersection_mask*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-intersection-mask"),
("bpy.types.lineartgpencilmodifier.use_invert_collection*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-invert-collection"),
("bpy.types.movietrackingsettings.use_keyframe_selection*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingsettings-use-keyframe-selection"),
("bpy.types.rendersettings.simplify_gpencil_antialiasing*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-antialiasing"),
("bpy.types.sequencertimelineoverlay.show_strip_duration*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-strip-duration"),
@ -123,7 +120,6 @@ url_manual_mapping = (
("bpy.types.brush.show_multiplane_scrape_planes_preview*", "sculpt_paint/sculpting/tools/multiplane_scrape.html#bpy-types-brush-show-multiplane-scrape-planes-preview"),
("bpy.types.brushgpencilsettings.eraser_strength_factor*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-eraser-strength-factor"),
("bpy.types.cyclesmaterialsettings.volume_interpolation*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-volume-interpolation"),
("bpy.types.cyclesrendersettings.debug_optix_curves_api*", "render/cycles/render_settings/debug.html#bpy-types-cyclesrendersettings-debug-optix-curves-api"),
("bpy.types.cyclesrendersettings.denoising_input_passes*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-denoising-input-passes"),
("bpy.types.cyclesrendersettings.film_transparent_glass*", "render/cycles/render_settings/film.html#bpy-types-cyclesrendersettings-film-transparent-glass"),
("bpy.types.cyclesrendersettings.offscreen_dicing_scale*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-offscreen-dicing-scale"),
@ -358,6 +354,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.use_keyframe_insert_auto*", "editors/timeline.html#bpy-types-toolsettings-use-keyframe-insert-auto"),
("bpy.types.viewlayer.use_pass_cryptomatte_object*", "render/layers/passes.html#bpy-types-viewlayer-use-pass-cryptomatte-object"),
("bpy.ops.armature.rigify_apply_selection_colors*", "addons/rigging/rigify/metarigs.html#bpy-ops-armature-rigify-apply-selection-colors"),
("bpy.ops.ed.lib_id_generate_preview_from_object*", "editors/asset_browser.html#bpy-ops-ed-lib-id-generate-preview-from-object"),
("bpy.types.brushgpencilsettings.fill_layer_mode*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-layer-mode"),
("bpy.types.brushgpencilsettings.random_strength*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-random-strength"),
("bpy.types.brushgpencilsettings.simplify_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-simplify-factor"),
@ -379,6 +376,7 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.use_split_pattern*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-split-pattern"),
("bpy.types.freestylesettings.use_view_map_cache*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-view-map-cache"),
("bpy.types.geometrynodecurvehandletypeselection*", "modeling/geometry_nodes/curve/handle_type_selection.html#bpy-types-geometrynodecurvehandletypeselection"),
("bpy.types.geometrynodeinputmeshvertexneighbors*", "modeling/geometry_nodes/mesh/vertex_neighbors.html#bpy-types-geometrynodeinputmeshvertexneighbors"),
("bpy.types.greasepencil.curve_edit_corner_angle*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-corner-angle"),
("bpy.types.lineartgpencilmodifier.source_camera*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-source-camera"),
("bpy.types.lineartgpencilmodifier.use_face_mark*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-face-mark"),
@ -405,7 +403,6 @@ url_manual_mapping = (
("bpy.types.brushgpencilsettings.use_fill_limit*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-use-fill-limit"),
("bpy.types.clothsettings.vertex_group_pressure*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-pressure"),
("bpy.types.cyclesmaterialsettings.displacement*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-displacement"),
("bpy.types.cyclesrendersettings.debug_bvh_type*", "render/cycles/render_settings/debug.html#bpy-types-cyclesrendersettings-debug-bvh-type"),
("bpy.types.cyclesrendersettings.fast_gi_method*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-fast-gi-method"),
("bpy.types.cyclesrendersettings.glossy_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-glossy-bounces"),
("bpy.types.cyclesrendersettings.volume_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-volume-bounces"),
@ -458,6 +455,7 @@ url_manual_mapping = (
("bpy.types.cyclescamerasettings.panorama_type*", "render/cycles/object_settings/cameras.html#bpy-types-cyclescamerasettings-panorama-type"),
("bpy.types.cyclesrendersettings.dicing_camera*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-dicing-camera"),
("bpy.types.cyclesrendersettings.film_exposure*", "render/cycles/render_settings/film.html#bpy-types-cyclesrendersettings-film-exposure"),
("bpy.types.cyclesrendersettings.sample_offset*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-sample-offset"),
("bpy.types.cyclesrendersettings.texture_limit*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-texture-limit"),
("bpy.types.cyclesrendersettings.use_denoising*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-use-denoising"),
("bpy.types.editbone.bbone_custom_handle_start*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-custom-handle-start"),
@ -483,6 +481,8 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.use_dashed_line*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-dashed-line"),
("bpy.types.freestylelinestyle.use_same_object*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-same-object"),
("bpy.types.functionnodeinputspecialcharacters*", "modeling/geometry_nodes/text/special_characters.html#bpy-types-functionnodeinputspecialcharacters"),
("bpy.types.geometrynodeinputmeshedgeneighbors*", "modeling/geometry_nodes/mesh/edge_neighbors.html#bpy-types-geometrynodeinputmeshedgeneighbors"),
("bpy.types.geometrynodeinputmeshfaceneighbors*", "modeling/geometry_nodes/mesh/face_neighbors.html#bpy-types-geometrynodeinputmeshfaceneighbors"),
("bpy.types.gpencilsculptguide.reference_point*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-reference-point"),
("bpy.types.greasepencil.edit_curve_resolution*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-edit-curve-resolution"),
("bpy.types.linestylegeometrymodifier_2doffset*", "render/freestyle/view_layer/line_style/modifiers/geometry/2d_offset.html#bpy-types-linestylegeometrymodifier-2doffset"),
@ -495,6 +495,7 @@ url_manual_mapping = (
("bpy.types.sequencertimelineoverlay.show_grid*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-grid"),
("bpy.types.sequencertoolsettings.overlap_mode*", "video_editing/sequencer/editing.html#bpy-types-sequencertoolsettings-overlap-mode"),
("bpy.types.spaceclipeditor.show_green_channel*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-green-channel"),
("bpy.types.spacenodeoverlay.show_context_path*", "interface/controls/nodes/introduction.html#bpy-types-spacenodeoverlay-show-context-path"),
("bpy.types.spaceoutliner.show_restrict_column*", "editors/outliner/interface.html#bpy-types-spaceoutliner-show-restrict-column"),
("bpy.types.spacespreadsheet.object_eval_state*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-object-eval-state"),
("bpy.types.spaceuveditor.display_stretch_type*", "editors/uv/overlays.html#bpy-types-spaceuveditor-display-stretch-type"),
@ -522,6 +523,7 @@ url_manual_mapping = (
("bpy.types.freestylelineset.select_edge_mark*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-select-edge-mark"),
("bpy.types.freestylelinestyle.use_length_max*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-length-max"),
("bpy.types.freestylelinestyle.use_length_min*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-length-min"),
("bpy.types.geometrynodeinputmeshedgevertices*", "modeling/geometry_nodes/mesh/edge_vertices.html#bpy-types-geometrynodeinputmeshedgevertices"),
("bpy.types.geometrynodeinputsplineresolution*", "modeling/geometry_nodes/curve/spline_resolution.html#bpy-types-geometrynodeinputsplineresolution"),
("bpy.types.greasepencil.curve_edit_threshold*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-threshold"),
("bpy.types.materialgpencilstyle.stroke_style*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-stroke-style"),
@ -617,6 +619,7 @@ url_manual_mapping = (
("bpy.types.brush.surface_smooth_iterations*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-iterations"),
("bpy.types.brushgpencilsettings.pen_jitter*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-pen-jitter"),
("bpy.types.brushgpencilsettings.show_lasso*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-show-lasso"),
("bpy.types.compositornodeconvertcolorspace*", "compositing/types/converter/color_space.html#bpy-types-compositornodeconvertcolorspace"),
("bpy.types.cyclescurverendersettings.shape*", "render/cycles/render_settings/hair.html#bpy-types-cyclescurverendersettings-shape"),
("bpy.types.cyclesrendersettings.ao_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-ao-bounces"),
("bpy.types.cyclesrendersettings.time_limit*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-time-limit"),
@ -713,7 +716,9 @@ url_manual_mapping = (
("bpy.types.geometrynodealigneulertovector*", "modeling/geometry_nodes/utilities/align_euler_to_vector.html#bpy-types-geometrynodealigneulertovector"),
("bpy.types.geometrynodeattributestatistic*", "modeling/geometry_nodes/attribute/attribute_statistic.html#bpy-types-geometrynodeattributestatistic"),
("bpy.types.geometrynodecurvequadrilateral*", "modeling/geometry_nodes/curve_primitives/quadrilateral.html#bpy-types-geometrynodecurvequadrilateral"),
("bpy.types.geometrynodegeometrytoinstance*", "modeling/geometry_nodes/geometry/geometry_to_instance.html#bpy-types-geometrynodegeometrytoinstance"),
("bpy.types.geometrynodeinputmaterialindex*", "modeling/geometry_nodes/material/material_index.html#bpy-types-geometrynodeinputmaterialindex"),
("bpy.types.geometrynodeinputmeshedgeangle*", "modeling/geometry_nodes/mesh/edge_angle.html#bpy-types-geometrynodeinputmeshedgeangle"),
("bpy.types.geometrynodeseparatecomponents*", "modeling/geometry_nodes/geometry/separate_components.html#bpy-types-geometrynodeseparatecomponents"),
("bpy.types.geometrynodesubdivisionsurface*", "modeling/geometry_nodes/mesh/subdivision_surface.html#bpy-types-geometrynodesubdivisionsurface"),
("bpy.types.geometrynodetranslateinstances*", "modeling/geometry_nodes/instances/translate_instances.html#bpy-types-geometrynodetranslateinstances"),
@ -793,6 +798,7 @@ url_manual_mapping = (
("bpy.types.freestylesettings.use_culling*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-culling"),
("bpy.types.geometrynodeendpointselection*", "modeling/geometry_nodes/curve/endpoint_selection.html#bpy-types-geometrynodeendpointselection"),
("bpy.types.geometrynodegeometryproximity*", "modeling/geometry_nodes/geometry/geometry_proximity.html#bpy-types-geometrynodegeometryproximity"),
("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/face_area.html#bpy-types-geometrynodeinputmeshfacearea"),
("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"),
("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"),
("bpy.types.geometrynodetransferattribute*", "modeling/geometry_nodes/attribute/transfer_attribute.html#bpy-types-geometrynodetransferattribute"),
@ -822,6 +828,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.mesh_select_mode*", "modeling/meshes/selecting/introduction.html#bpy-types-toolsettings-mesh-select-mode"),
("bpy.types.toolsettings.use_snap_project*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-project"),
("bpy.types.transformorientationslot.type*", "editors/3dview/controls/orientation.html#bpy-types-transformorientationslot-type"),
("bpy.types.unitsettings.temperature_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-temperature-unit"),
("bpy.types.vertexweightproximitymodifier*", "modeling/modifiers/modify/weight_proximity.html#bpy-types-vertexweightproximitymodifier"),
("bpy.types.view3doverlay.show_wireframes*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-wireframes"),
("bpy.types.view3dshading.background_type*", "editors/3dview/display/shading.html#bpy-types-view3dshading-background-type"),
@ -879,6 +886,7 @@ url_manual_mapping = (
("bpy.types.spacetexteditor.use_find_all*", "editors/text_editor.html#bpy-types-spacetexteditor-use-find-all"),
("bpy.types.toolsettings.snap_uv_element*", "editors/uv/controls/snapping.html#bpy-types-toolsettings-snap-uv-element"),
("bpy.types.toolsettings.use_snap_rotate*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-rotate"),
("bpy.types.unitsettings.system_rotation*", "scene_layout/scene/properties.html#bpy-types-unitsettings-system-rotation"),
("bpy.types.view3doverlay.display_handle*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-display-handle"),
("bpy.types.volumedisplay.wireframe_type*", "modeling/volumes/properties.html#bpy-types-volumedisplay-wireframe-type"),
("bpy.ops.anim.channels_editable_toggle*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-editable-toggle"),
@ -923,11 +931,15 @@ url_manual_mapping = (
("bpy.types.freestylelineset.visibility*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-visibility"),
("bpy.types.freestylelinestyle.chaining*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-chaining"),
("bpy.types.freestylelinestyle.sort_key*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-sort-key"),
("bpy.types.geometrynodeaccumulatefield*", "modeling/geometry_nodes/utilities/accumulate_field.html#bpy-types-geometrynodeaccumulatefield"),
("bpy.types.geometrynodecurvesethandles*", "modeling/geometry_nodes/curve/set_handle_type.html#bpy-types-geometrynodecurvesethandles"),
("bpy.types.geometrynodecurvesplinetype*", "modeling/geometry_nodes/curve/set_spline_type.html#bpy-types-geometrynodecurvesplinetype"),
("bpy.types.geometrynodeinputmeshisland*", "modeling/geometry_nodes/mesh/mesh_island.html#bpy-types-geometrynodeinputmeshisland"),
("bpy.types.geometrynodemergebydistance*", "modeling/geometry_nodes/geometry/merge_by_distance.html#bpy-types-geometrynodemergebydistance"),
("bpy.types.geometrynodereplacematerial*", "modeling/geometry_nodes/material/replace_material.html#bpy-types-geometrynodereplacematerial"),
("bpy.types.geometrynoderotateinstances*", "modeling/geometry_nodes/instances/rotate_instances.html#bpy-types-geometrynoderotateinstances"),
("bpy.types.geometrynodesetsplinecyclic*", "modeling/geometry_nodes/curve/set_spline_cyclic.html#bpy-types-geometrynodesetsplinecyclic"),
("bpy.types.geometrynodesplineparameter*", "modeling/geometry_nodes/curve/spline_parameter.html#bpy-types-geometrynodesplineparameter"),
("bpy.types.gpencillayer.use_mask_layer*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-mask-layer"),
("bpy.types.greasepencil.use_curve_edit*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-use-curve-edit"),
("bpy.types.imagepaint.screen_grab_size*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-imagepaint-screen-grab-size"),
@ -997,9 +1009,9 @@ url_manual_mapping = (
("bpy.types.fluidflowsettings.use_flow*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-flow"),
("bpy.types.fmodifierfunctiongenerator*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierfunctiongenerator"),
("bpy.types.geometrynodecollectioninfo*", "modeling/geometry_nodes/input/collection_info.html#bpy-types-geometrynodecollectioninfo"),
("bpy.types.geometrynodecurveparameter*", "modeling/geometry_nodes/curve/curve_parameter.html#bpy-types-geometrynodecurveparameter"),
("bpy.types.geometrynodedeletegeometry*", "modeling/geometry_nodes/geometry/delete_geometry.html#bpy-types-geometrynodedeletegeometry"),
("bpy.types.geometrynodeinputcurvetilt*", "modeling/geometry_nodes/curve/curve_tilt.html#bpy-types-geometrynodeinputcurvetilt"),
("bpy.types.geometrynodeinputscenetime*", "modeling/geometry_nodes/input/scene_time.html#bpy-types-geometrynodeinputscenetime"),
("bpy.types.geometrynodepointstovolume*", "modeling/geometry_nodes/point/points_to_volume.html#bpy-types-geometrynodepointstovolume"),
("bpy.types.geometrynodescaleinstances*", "modeling/geometry_nodes/instances/scale_instances.html#bpy-types-geometrynodescaleinstances"),
("bpy.types.geometrynodesetcurveradius*", "modeling/geometry_nodes/curve/set_curve_radius.html#bpy-types-geometrynodesetcurveradius"),
@ -1079,7 +1091,6 @@ url_manual_mapping = (
("bpy.types.fluidflowsettings.density*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-density"),
("bpy.types.freestylelineset.qi_start*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-qi-start"),
("bpy.types.freestylelinestyle.rounds*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-rounds"),
("bpy.types.functionnodecomparefloats*", "modeling/geometry_nodes/utilities/compare_floats.html#bpy-types-functionnodecomparefloats"),
("bpy.types.geometrynodecurvetopoints*", "modeling/geometry_nodes/curve/curve_to_points.html#bpy-types-geometrynodecurvetopoints"),
("bpy.types.geometrynodeinputmaterial*", "modeling/geometry_nodes/input/material.html#bpy-types-geometrynodeinputmaterial"),
("bpy.types.geometrynodeinputposition*", "modeling/geometry_nodes/input/position.html#bpy-types-geometrynodeinputposition"),
@ -1087,6 +1098,7 @@ url_manual_mapping = (
("bpy.types.geometrynodemeshicosphere*", "modeling/geometry_nodes/mesh_primitives/icosphere.html#bpy-types-geometrynodemeshicosphere"),
("bpy.types.geometrynodereplacestring*", "modeling/geometry_nodes/text/replace_string.html#bpy-types-geometrynodereplacestring"),
("bpy.types.geometrynoderesamplecurve*", "modeling/geometry_nodes/curve/resample_curve.html#bpy-types-geometrynoderesamplecurve"),
("bpy.types.geometrynodescaleelements*", "modeling/geometry_nodes/mesh/scale_elements.html#bpy-types-geometrynodescaleelements"),
("bpy.types.geometrynodesubdividemesh*", "modeling/geometry_nodes/mesh/subdivide_mesh.html#bpy-types-geometrynodesubdividemesh"),
("bpy.types.geometrynodevaluetostring*", "modeling/geometry_nodes/text/value_to_string.html#bpy-types-geometrynodevaluetostring"),
("bpy.types.keyframe.handle_left_type*", "editors/graph_editor/fcurves/properties.html#bpy-types-keyframe-handle-left-type"),
@ -1110,6 +1122,7 @@ url_manual_mapping = (
("bpy.types.shadernodebsdftranslucent*", "render/shader_nodes/shader/translucent.html#bpy-types-shadernodebsdftranslucent"),
("bpy.types.shadernodebsdftransparent*", "render/shader_nodes/shader/transparent.html#bpy-types-shadernodebsdftransparent"),
("bpy.types.shadernodevectortransform*", "render/shader_nodes/vector/transform.html#bpy-types-shadernodevectortransform"),
("bpy.types.shrinkwrapgpencilmodifier*", "grease_pencil/modifiers/deform/shrinkwrap.html#bpy-types-shrinkwrapgpencilmodifier"),
("bpy.types.spaceclipeditor.show_grid*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-grid"),
("bpy.types.spaceoutliner.filter_text*", "editors/outliner/interface.html#bpy-types-spaceoutliner-filter-text"),
("bpy.types.spacetexteditor.find_text*", "editors/text_editor.html#bpy-types-spacetexteditor-find-text"),
@ -1118,6 +1131,8 @@ url_manual_mapping = (
("bpy.types.spaceuveditor.lock_bounds*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-lock-bounds"),
("bpy.types.spline.tilt_interpolation*", "modeling/curves/properties/active_spline.html#bpy-types-spline-tilt-interpolation"),
("bpy.types.transformorientation.name*", "editors/3dview/controls/orientation.html#bpy-types-transformorientation-name"),
("bpy.types.unitsettings.scale_length*", "scene_layout/scene/properties.html#bpy-types-unitsettings-scale-length"),
("bpy.types.unitsettings.use_separate*", "scene_layout/scene/properties.html#bpy-types-unitsettings-use-separate"),
("bpy.types.viewlayer.use_motion_blur*", "render/layers/introduction.html#bpy-types-viewlayer-use-motion-blur"),
("bpy.types.volumedisplay.slice_depth*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-depth"),
("bpy.types.worldmistsettings.falloff*", "render/cycles/world_settings.html#bpy-types-worldmistsettings-falloff"),
@ -1150,13 +1165,14 @@ url_manual_mapping = (
("bpy.ops.wm.previews_batch_generate*", "files/blend/previews.html#bpy-ops-wm-previews-batch-generate"),
("bpy.types.assetmetadata.active_tag*", "editors/asset_browser.html#bpy-types-assetmetadata-active-tag"),
("bpy.types.bakesettings.cage_object*", "render/cycles/baking.html#bpy-types-bakesettings-cage-object"),
("bpy.types.bakesettings.margin_type*", "render/cycles/baking.html#bpy-types-bakesettings-margin-type"),
("bpy.types.bone.use_relative_parent*", "animation/armatures/bones/properties/relations.html#bpy-types-bone-use-relative-parent"),
("bpy.types.brush.auto_smooth_factor*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-auto-smooth-factor"),
("bpy.types.brush.smooth_deform_type*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-smooth-deform-type"),
("bpy.types.brush.use_connected_only*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-connected-only"),
("bpy.types.brush.use_cursor_overlay*", "sculpt_paint/brush/cursor.html#bpy-types-brush-use-cursor-overlay"),
("bpy.types.camera.show_passepartout*", "render/cameras.html#bpy-types-camera-show-passepartout"),
("bpy.types.collection.lineart_usage*", "scene_layout/collections/properties.html#bpy-types-collection-lineart-usage"),
("bpy.types.collection.lineart_usage*", "scene_layout/collections/collections.html#bpy-types-collection-lineart-usage"),
("bpy.types.colormanagedviewsettings*", "render/color_management.html#bpy-types-colormanagedviewsettings"),
("bpy.types.compositornodebokehimage*", "compositing/types/input/bokeh_image.html#bpy-types-compositornodebokehimage"),
("bpy.types.compositornodecolormatte*", "compositing/types/matte/color_key.html#bpy-types-compositornodecolormatte"),
@ -1172,6 +1188,7 @@ url_manual_mapping = (
("bpy.types.freestylelineset.exclude*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-exclude"),
("bpy.types.freestylelinestyle.alpha*", "render/freestyle/view_layer/line_style/alpha.html#bpy-types-freestylelinestyle-alpha"),
("bpy.types.freestylelinestyle.color*", "render/freestyle/view_layer/line_style/color.html#bpy-types-freestylelinestyle-color"),
("bpy.types.geometrynodefieldatindex*", "modeling/geometry_nodes/utilities/field_at_index.html#bpy-types-geometrynodefieldatindex"),
("bpy.types.geometrynodeinputtangent*", "modeling/geometry_nodes/curve/curve_tangent.html#bpy-types-geometrynodeinputtangent"),
("bpy.types.geometrynodejoingeometry*", "modeling/geometry_nodes/geometry/join_geometry.html#bpy-types-geometrynodejoingeometry"),
("bpy.types.geometrynodemeshcylinder*", "modeling/geometry_nodes/mesh_primitives/cylinder.html#bpy-types-geometrynodemeshcylinder"),
@ -1207,6 +1224,7 @@ url_manual_mapping = (
("bpy.types.thicknessgpencilmodifier*", "grease_pencil/modifiers/deform/thickness.html#bpy-types-thicknessgpencilmodifier"),
("bpy.types.toolsettings.snap_target*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-snap-target"),
("bpy.types.transformcacheconstraint*", "animation/constraints/transform/transform_cache.html#bpy-types-transformcacheconstraint"),
("bpy.types.unitsettings.length_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-length-unit"),
("bpy.types.vertexweighteditmodifier*", "modeling/modifiers/modify/weight_edit.html#bpy-types-vertexweighteditmodifier"),
("bpy.types.volumedisplay.slice_axis*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-axis"),
("bpy.ops.anim.channels_clean_empty*", "editors/nla/editing.html#bpy-ops-anim-channels-clean-empty"),
@ -1229,7 +1247,7 @@ url_manual_mapping = (
("bpy.ops.object.vertex_group_clean*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-clean"),
("bpy.ops.poselib.create_pose_asset*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-create-pose-asset"),
("bpy.ops.preferences.theme_install*", "editors/preferences/themes.html#bpy-ops-preferences-theme-install"),
("bpy.ops.render.play-rendered-anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
("bpy.ops.render.play_rendered_anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
("bpy.ops.sculpt.set_pivot_position*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-set-pivot-position"),
("bpy.ops.sequencer.image_strip_add*", "video_editing/sequencer/strips/image.html#bpy-ops-sequencer-image-strip-add"),
("bpy.ops.sequencer.movie_strip_add*", "video_editing/sequencer/strips/movie.html#bpy-ops-sequencer-movie-strip-add"),
@ -1253,6 +1271,7 @@ url_manual_mapping = (
("bpy.types.compositornodemovieclip*", "compositing/types/input/movie_clip.html#bpy-types-compositornodemovieclip"),
("bpy.types.compositornodenormalize*", "compositing/types/vector/normalize.html#bpy-types-compositornodenormalize"),
("bpy.types.compositornodepremulkey*", "compositing/types/converter/alpha_convert.html#bpy-types-compositornodepremulkey"),
("bpy.types.compositornodescenetime*", "compositing/types/input/scene_time.html#bpy-types-compositornodescenetime"),
("bpy.types.compositornodestabilize*", "compositing/types/distort/stabilize_2d.html#bpy-types-compositornodestabilize"),
("bpy.types.compositornodetransform*", "compositing/types/distort/transform.html#bpy-types-compositornodetransform"),
("bpy.types.compositornodetranslate*", "compositing/types/distort/translate.html#bpy-types-compositornodetranslate"),
@ -1273,6 +1292,7 @@ url_manual_mapping = (
("bpy.types.geometrynodecurvelength*", "modeling/geometry_nodes/curve/curve_length.html#bpy-types-geometrynodecurvelength"),
("bpy.types.geometrynodecurvespiral*", "modeling/geometry_nodes/curve_primitives/curve_spiral.html#bpy-types-geometrynodecurvespiral"),
("bpy.types.geometrynodecurvetomesh*", "modeling/geometry_nodes/curve/curve_to_mesh.html#bpy-types-geometrynodecurvetomesh"),
("bpy.types.geometrynodeextrudemesh*", "modeling/geometry_nodes/mesh/extrude_mesh.html#bpy-types-geometrynodeextrudemesh"),
("bpy.types.geometrynodefilletcurve*", "modeling/geometry_nodes/curve/fillet_curve.html#bpy-types-geometrynodefilletcurve"),
("bpy.types.geometrynodeinputnormal*", "modeling/geometry_nodes/input/normal.html#bpy-types-geometrynodeinputnormal"),
("bpy.types.geometrynodeinputradius*", "modeling/geometry_nodes/input/radius.html#bpy-types-geometrynodeinputradius"),
@ -1332,6 +1352,7 @@ url_manual_mapping = (
("bpy.ops.mesh.primitive_plane_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-plane-add"),
("bpy.ops.mesh.primitive_torus_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-torus-add"),
("bpy.ops.mesh.select_non_manifold*", "modeling/meshes/selecting/all_by_trait.html#bpy-ops-mesh-select-non-manifold"),
("bpy.ops.object.attribute_convert*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-convert"),
("bpy.ops.object.constraints_clear*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-clear"),
("bpy.ops.object.quadriflow_remesh*", "modeling/meshes/retopology.html#bpy-ops-object-quadriflow-remesh"),
("bpy.ops.object.vertex_group_copy*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-copy"),
@ -1388,6 +1409,7 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.gap*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-gap"),
("bpy.types.freestylesettings.mode*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-mode"),
("bpy.types.geometrynodeconvexhull*", "modeling/geometry_nodes/geometry/convex_hull.html#bpy-types-geometrynodeconvexhull"),
("bpy.types.geometrynodedomainsize*", "modeling/geometry_nodes/attribute/domain_size.html#bpy-types-geometrynodedomainsize"),
("bpy.types.geometrynodefloattoint*", "modeling/geometry_nodes/utilities/float_to_integer.html#bpy-types-geometrynodefloattoint"),
("bpy.types.geometrynodeinputcolor*", "modeling/geometry_nodes/input/color.html#bpy-types-geometrynodeinputcolor"),
("bpy.types.geometrynodeinputindex*", "modeling/geometry_nodes/input/input_index.html#bpy-types-geometrynodeinputindex"),
@ -1418,6 +1440,8 @@ url_manual_mapping = (
("bpy.types.sound.use_memory_cache*", "video_editing/sequencer/sidebar/strip.html#bpy-types-sound-use-memory-cache"),
("bpy.types.spaceview3d.show_gizmo*", "editors/3dview/display/gizmo.html#bpy-types-spaceview3d-show-gizmo"),
("bpy.types.texturegpencilmodifier*", "grease_pencil/modifiers/modify/texture_mapping.html#bpy-types-texturegpencilmodifier"),
("bpy.types.unitsettings.mass_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-mass-unit"),
("bpy.types.unitsettings.time_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-time-unit"),
("bpy.types.volumedisplacemodifier*", "modeling/modifiers/deform/volume_displace.html#bpy-types-volumedisplacemodifier"),
("bpy.types.volumerender.step_size*", "modeling/volumes/properties.html#bpy-types-volumerender-step-size"),
("bpy.types.weightednormalmodifier*", "modeling/modifiers/modify/weighted_normal.html#bpy-types-weightednormalmodifier"),
@ -1435,6 +1459,7 @@ url_manual_mapping = (
("bpy.ops.gpencil.stroke_caps_set*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-caps-set"),
("bpy.ops.gpencil.stroke_separate*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-separate"),
("bpy.ops.gpencil.stroke_simplify*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-simplify"),
("bpy.ops.graph.blend_to_neighbor*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-blend-to-neighbor"),
("bpy.ops.graph.snap_cursor_value*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-snap-cursor-value"),
("bpy.ops.image.save_all_modified*", "editors/image/editing.html#bpy-ops-image-save-all-modified"),
("bpy.ops.mesh.extrude_edges_move*", "modeling/meshes/editing/edge/extrude_edges.html#bpy-ops-mesh-extrude-edges-move"),
@ -1447,6 +1472,7 @@ url_manual_mapping = (
("bpy.ops.mesh.subdivide_edgering*", "modeling/meshes/editing/edge/subdivide_edge_ring.html#bpy-ops-mesh-subdivide-edgering"),
("bpy.ops.node.hide_socket_toggle*", "interface/controls/nodes/editing.html#bpy-ops-node-hide-socket-toggle"),
("bpy.ops.node.tree_socket_remove*", "interface/controls/nodes/groups.html#bpy-ops-node-tree-socket-remove"),
("bpy.ops.object.attribute_remove*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-remove"),
("bpy.ops.object.constraints_copy*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-copy"),
("bpy.ops.object.gpencil_modifier*", "grease_pencil/modifiers/index.html#bpy-ops-object-gpencil-modifier"),
("bpy.ops.object.make_links_scene*", "scene_layout/object/editing/link_transfer/link_scene.html#bpy-ops-object-make-links-scene"),
@ -1509,6 +1535,7 @@ url_manual_mapping = (
("bpy.types.geometrynodecurvestar*", "modeling/geometry_nodes/curve_primitives/star.html#bpy-types-geometrynodecurvestar"),
("bpy.types.geometrynodeedgesplit*", "modeling/geometry_nodes/mesh/split_edges.html#bpy-types-geometrynodeedgesplit"),
("bpy.types.geometrynodefillcurve*", "modeling/geometry_nodes/curve/fill_curve.html#bpy-types-geometrynodefillcurve"),
("bpy.types.geometrynodeflipfaces*", "modeling/geometry_nodes/mesh/flip_faces.html#bpy-types-geometrynodeflipfaces"),
("bpy.types.geometrynodetransform*", "modeling/geometry_nodes/geometry/transform.html#bpy-types-geometrynodetransform"),
("bpy.types.geometrynodetrimcurve*", "modeling/geometry_nodes/curve/trim_curve.html#bpy-types-geometrynodetrimcurve"),
("bpy.types.gpencilsculptsettings*", "grease_pencil/properties/index.html#bpy-types-gpencilsculptsettings"),
@ -1552,6 +1579,7 @@ url_manual_mapping = (
("bpy.ops.curve.switch_direction*", "modeling/curves/editing/segments.html#bpy-ops-curve-switch-direction"),
("bpy.ops.gpencil.duplicate_move*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-duplicate-move"),
("bpy.ops.gpencil.stroke_arrange*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-arrange"),
("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"),
("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"),
@ -1616,6 +1644,7 @@ url_manual_mapping = (
("bpy.types.motionpath.frame_end*", "animation/motion_paths.html#bpy-types-motionpath-frame-end"),
("bpy.types.noisegpencilmodifier*", "grease_pencil/modifiers/deform/noise.html#bpy-types-noisegpencilmodifier"),
("bpy.types.object.hide_viewport*", "scene_layout/object/properties/visibility.html#bpy-types-object-hide-viewport"),
("bpy.types.object.rotation_mode*", "scene_layout/object/properties/transforms.html#bpy-types-object-rotation-mode"),
("bpy.types.object.show_in_front*", "scene_layout/object/properties/display.html#bpy-types-object-show-in-front"),
("bpy.types.posebone.rigify_type*", "addons/rigging/rigify/rig_types/index.html#bpy-types-posebone-rigify-type"),
("bpy.types.preferencesfilepaths*", "editors/preferences/file_paths.html#bpy-types-preferencesfilepaths"),
@ -1718,6 +1747,7 @@ url_manual_mapping = (
("bpy.types.cyclesworldsettings*", "render/cycles/world_settings.html#bpy-types-cyclesworldsettings"),
("bpy.types.dashgpencilmodifier*", "grease_pencil/modifiers/generate/dash.html#bpy-types-dashgpencilmodifier"),
("bpy.types.fluiddomainsettings*", "physics/fluid/type/domain/index.html#bpy-types-fluiddomainsettings"),
("bpy.types.functionnodecompare*", "modeling/geometry_nodes/utilities/compare.html#bpy-types-functionnodecompare"),
("bpy.types.geometrynodeboolean*", "modeling/geometry_nodes/input/boolean.html#bpy-types-geometrynodeboolean"),
("bpy.types.geometrynodeinputid*", "modeling/geometry_nodes/input/id.html#bpy-types-geometrynodeinputid"),
("bpy.types.geometrynodeinteger*", "modeling/geometry_nodes/input/integer.html#bpy-types-geometrynodeinteger"),
@ -1744,6 +1774,7 @@ url_manual_mapping = (
("bpy.types.shadernodelightpath*", "render/shader_nodes/input/light_path.html#bpy-types-shadernodelightpath"),
("bpy.types.shadernodemixshader*", "render/shader_nodes/shader/mix.html#bpy-types-shadernodemixshader"),
("bpy.types.shadernodenormalmap*", "render/shader_nodes/vector/normal_map.html#bpy-types-shadernodenormalmap"),
("bpy.types.shadernodepointinfo*", "render/shader_nodes/input/point_info.html#bpy-types-shadernodepointinfo"),
("bpy.types.shadernodewireframe*", "render/shader_nodes/input/wireframe.html#bpy-types-shadernodewireframe"),
("bpy.types.spacesequenceeditor*", "video_editing/index.html#bpy-types-spacesequenceeditor"),
("bpy.types.spline.resolution_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-resolution-u"),
@ -1756,6 +1787,7 @@ url_manual_mapping = (
("bpy.types.tintgpencilmodifier*", "grease_pencil/modifiers/color/tint.html#bpy-types-tintgpencilmodifier"),
("bpy.types.transformconstraint*", "animation/constraints/transform/transformation.html#bpy-types-transformconstraint"),
("bpy.types.triangulatemodifier*", "modeling/modifiers/generate/triangulate.html#bpy-types-triangulatemodifier"),
("bpy.types.unitsettings.system*", "scene_layout/scene/properties.html#bpy-types-unitsettings-system"),
("bpy.types.viewlayer.use_solid*", "render/layers/introduction.html#bpy-types-viewlayer-use-solid"),
("bpy.types.volume.frame_offset*", "modeling/volumes/properties.html#bpy-types-volume-frame-offset"),
("bpy.types.windowmanager.addon*", "editors/preferences/addons.html#bpy-types-windowmanager-addon"),
@ -1788,6 +1820,7 @@ url_manual_mapping = (
("bpy.ops.node.node_copy_color*", "interface/controls/nodes/sidebar.html#bpy-ops-node-node-copy-color"),
("bpy.ops.node.read_viewlayers*", "interface/controls/nodes/editing.html#bpy-ops-node-read-viewlayers"),
("bpy.ops.node.tree_socket_add*", "interface/controls/nodes/groups.html#bpy-ops-node-tree-socket-add"),
("bpy.ops.object.attribute_add*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-add"),
("bpy.ops.object.data_transfer*", "scene_layout/object/editing/link_transfer/transfer_mesh_data.html#bpy-ops-object-data-transfer"),
("bpy.ops.object.modifier_copy*", "modeling/modifiers/introduction.html#bpy-ops-object-modifier-copy"),
("bpy.ops.object.select_camera*", "scene_layout/object/selecting.html#bpy-ops-object-select-camera"),
@ -1819,12 +1852,12 @@ url_manual_mapping = (
("bpy.types.armature.show_axes*", "animation/armatures/properties/display.html#bpy-types-armature-show-axes"),
("bpy.types.armatureconstraint*", "animation/constraints/relationship/armature.html#bpy-types-armatureconstraint"),
("bpy.types.compositornodeblur*", "compositing/types/filter/blur_node.html#bpy-types-compositornodeblur"),
("bpy.types.compositornodecomb*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodecomb"),
("bpy.types.compositornodecomb*", "compositing/types/converter/combine_separate.html#bpy-types-compositornodecomb"),
("bpy.types.compositornodecrop*", "compositing/types/distort/crop.html#bpy-types-compositornodecrop"),
("bpy.types.compositornodeflip*", "compositing/types/distort/flip.html#bpy-types-compositornodeflip"),
("bpy.types.compositornodemask*", "compositing/types/input/mask.html#bpy-types-compositornodemask"),
("bpy.types.compositornodemath*", "compositing/types/converter/math.html#bpy-types-compositornodemath"),
("bpy.types.compositornodetime*", "compositing/types/input/time.html#bpy-types-compositornodetime"),
("bpy.types.compositornodetime*", "compositing/types/input/time_curve.html#bpy-types-compositornodetime"),
("bpy.types.constraint.enabled*", "animation/constraints/interface/header.html#bpy-types-constraint-enabled"),
("bpy.types.curve.bevel_object*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-object"),
("bpy.types.curve.resolution_u*", "modeling/curves/properties/shape.html#bpy-types-curve-resolution-u"),
@ -1860,7 +1893,6 @@ url_manual_mapping = (
("bpy.types.shadernodeemission*", "render/shader_nodes/shader/emission.html#bpy-types-shadernodeemission"),
("bpy.types.shadernodegeometry*", "render/shader_nodes/input/geometry.html#bpy-types-shadernodegeometry"),
("bpy.types.shadernodehairinfo*", "render/shader_nodes/input/hair_info.html#bpy-types-shadernodehairinfo"),
("bpy.types.shadernodepointinfo*", "render/shader_nodes/input/point_info.html#bpy-types-shadernodepointinfo"),
("bpy.types.shadernodemaprange*", "render/shader_nodes/converter/map_range.html#bpy-types-shadernodemaprange"),
("bpy.types.shadernodergbcurve*", "modeling/geometry_nodes/color/rgb_curves.html#bpy-types-shadernodergbcurve"),
("bpy.types.shadernodeseparate*", "render/shader_nodes/converter/combine_separate.html#bpy-types-shadernodeseparate"),
@ -1892,6 +1924,7 @@ url_manual_mapping = (
("bpy.ops.curve.smooth_weight*", "modeling/curves/editing/control_points.html#bpy-ops-curve-smooth-weight"),
("bpy.ops.file.pack_libraries*", "files/blend/packed_data.html#bpy-ops-file-pack-libraries"),
("bpy.ops.font.change_spacing*", "modeling/texts/editing.html#bpy-ops-font-change-spacing"),
("bpy.ops.gpencil.layer_merge*", "grease_pencil/properties/layers.html#bpy-ops-gpencil-layer-merge"),
("bpy.ops.gpencil.stroke_flip*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-flip"),
("bpy.ops.gpencil.stroke_join*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-join"),
("bpy.ops.gpencil.stroke_trim*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-trim"),
@ -1949,7 +1982,7 @@ url_manual_mapping = (
("bpy.types.collisionmodifier*", "physics/collision.html#bpy-types-collisionmodifier"),
("bpy.types.collisionsettings*", "physics/collision.html#bpy-types-collisionsettings"),
("bpy.types.compositornodergb*", "compositing/types/input/rgb.html#bpy-types-compositornodergb"),
("bpy.types.compositornodesep*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodesep"),
("bpy.types.compositornodesep*", "compositing/types/converter/combine_separate.html#bpy-types-compositornodesep"),
("bpy.types.curve.bevel_depth*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-depth"),
("bpy.types.curve.use_stretch*", "modeling/curves/properties/shape.html#bpy-types-curve-use-stretch"),
("bpy.types.edgesplitmodifier*", "modeling/modifiers/generate/edge_split.html#bpy-types-edgesplitmodifier"),
@ -2172,6 +2205,7 @@ url_manual_mapping = (
("bpy.types.floorconstraint*", "animation/constraints/relationship/floor.html#bpy-types-floorconstraint"),
("bpy.types.fmodifiercycles*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifiercycles"),
("bpy.types.fmodifierlimits*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierlimits"),
("bpy.types.geometrynodearc*", "modeling/geometry_nodes/curve_primitives/arc.html#bpy-types-geometrynodearc"),
("bpy.types.imagepaint.mode*", "sculpt_paint/texture_paint/tool_settings/texture_slots.html#bpy-types-imagepaint-mode"),
("bpy.types.latticemodifier*", "modeling/modifiers/deform/lattice.html#bpy-types-latticemodifier"),
("bpy.types.materiallineart*", "render/materials/line_art.html#bpy-types-materiallineart"),
@ -2289,6 +2323,7 @@ url_manual_mapping = (
("bpy.ops.fluid.free_mesh*", "physics/fluid/type/domain/liquid/mesh.html#bpy-ops-fluid-free-mesh"),
("bpy.ops.font.select_all*", "modeling/texts/selecting.html#bpy-ops-font-select-all"),
("bpy.ops.gpencil.convert*", "grease_pencil/modes/object/convert_to_geometry.html#bpy-ops-gpencil-convert"),
("bpy.ops.graph.breakdown*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-breakdown"),
("bpy.ops.mask.parent_set*", "movie_clip/masking/editing.html#bpy-ops-mask-parent-set"),
("bpy.ops.mask.select_all*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-all"),
("bpy.ops.mask.select_box*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-box"),
@ -2475,6 +2510,7 @@ url_manual_mapping = (
("bpy.ops.sculpt.expand*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-expand"),
("bpy.ops.view3d.select*", "editors/3dview/selecting.html#bpy-ops-view3d-select"),
("bpy.ops.wm.debug_menu*", "advanced/operators.html#bpy-ops-wm-debug-menu"),
("bpy.ops.wm.obj_export*", "files/import_export/obj.html#bpy-ops-wm-obj-export"),
("bpy.ops.wm.properties*", "files/data_blocks.html#bpy-ops-wm-properties"),
("bpy.ops.wm.usd_export*", "files/import_export/usd.html#bpy-ops-wm-usd-export"),
("bpy.types.addsequence*", "video_editing/sequencer/strips/effects/add.html#bpy-types-addsequence"),
@ -2578,6 +2614,7 @@ url_manual_mapping = (
("bpy.types.node.name*", "interface/controls/nodes/sidebar.html#bpy-types-node-name"),
("bpy.types.nodeframe*", "interface/controls/nodes/frame.html#bpy-types-nodeframe"),
("bpy.types.nodegroup*", "interface/controls/nodes/groups.html#bpy-types-nodegroup"),
("bpy.types.scene.muv*", "addons/uv/magic_uv.html#bpy-types-scene-muv"),
("bpy.types.spotlight*", "render/lights/light_object.html#bpy-types-spotlight"),
("bpy.types.textcurve*", "modeling/texts/index.html#bpy-types-textcurve"),
("bpy.types.udimtiles*", "modeling/meshes/uv/workflows/udims.html#bpy-types-udimtiles"),
@ -2713,6 +2750,7 @@ url_manual_mapping = (
("bpy.ops.render*", "render/index.html#bpy-ops-render"),
("bpy.ops.script*", "advanced/scripting/index.html#bpy-ops-script"),
("bpy.ops.sculpt*", "sculpt_paint/sculpting/index.html#bpy-ops-sculpt"),
("bpy.ops.uv.muv*", "addons/uv/magic_uv.html#bpy-ops-uv-muv"),
("bpy.ops.uv.pin*", "modeling/meshes/uv/editing.html#bpy-ops-uv-pin"),
("bpy.ops.uv.rip*", "modeling/meshes/uv/tools/rip.html#bpy-ops-uv-rip"),
("bpy.ops.view3d*", "editors/3dview/index.html#bpy-ops-view3d"),

View File

@ -208,6 +208,9 @@ class Params:
# ------------------------------------------------------------------------------
# Constants
from math import pi
pi_2 = pi / 2.0
# Physical layout.
NUMBERS_1 = ('ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIGHT', 'NINE', 'ZERO')
# Numeric order.
@ -387,6 +390,11 @@ def _template_items_uv_select_mode(params):
]
else:
return [
# TODO(@campbellbarton): should this be kept?
# Seems it was included in the new key-map by accident, check on removing
# although it's not currently used for anything else.
op_menu("IMAGE_MT_uvs_select_mode", {"type": 'TAB', "value": 'PRESS', "ctrl": True}),
*_template_items_editmode_mesh_select_mode(params),
# Hack to prevent fall-through, when sync select isn't enabled (and the island button isn't visible).
("mesh.select_mode", {"type": 'FOUR', "value": 'PRESS'}, None),
@ -861,7 +869,6 @@ def km_mask_editing(params):
items.extend([
("mask.select", {"type": 'RIGHTMOUSE', "value": 'PRESS'},
{"properties": [("deselect_all", not params.legacy)]}),
("transform.translate", {"type": 'EVT_TWEAK_R', "value": 'ANY'}, None),
])
items.extend([
@ -1205,7 +1212,6 @@ def km_uv_editor(params):
if not params.legacy else
op_menu("IMAGE_MT_uvs_snap", {"type": 'S', "value": 'PRESS', "shift": True})
),
op_menu("IMAGE_MT_uvs_select_mode", {"type": 'TAB', "value": 'PRESS', "ctrl": True}),
*_template_items_proportional_editing(
params, connected=False, toggle_data_path='tool_settings.use_proportional_edit'),
("transform.translate", {"type": params.select_tweak, "value": 'ANY'}, None),
@ -1370,7 +1376,6 @@ def km_view3d(params):
*(() if not params.use_pie_click_drag else
(("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'CLICK'}, None),)),
("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "shift": True}, None),
("view3d.navigate", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "shift": True}, None),
# Numpad views.
("view3d.view_camera", {"type": 'NUMPAD_0', "value": 'PRESS'}, None),
("view3d.view_axis", {"type": 'NUMPAD_1', "value": 'PRESS'},
@ -1407,7 +1412,7 @@ def km_view3d(params):
("view3d.view_roll", {"type": 'NUMPAD_6', "value": 'PRESS', "shift": True, "repeat": True},
{"properties": [("type", 'RIGHT')]}),
("view3d.view_orbit", {"type": 'NUMPAD_9', "value": 'PRESS'},
{"properties": [("angle", 3.1415927), ("type", 'ORBITRIGHT')]}),
{"properties": [("angle", pi), ("type", 'ORBITRIGHT')]}),
("view3d.view_axis", {"type": 'NUMPAD_1', "value": 'PRESS', "shift": True},
{"properties": [("type", 'FRONT'), ("align_active", True)]}),
("view3d.view_axis", {"type": 'NUMPAD_3', "value": 'PRESS', "shift": True},
@ -1451,10 +1456,10 @@ def km_view3d(params):
("view3d.ndof_all", {"type": 'NDOF_MOTION', "value": 'ANY', "shift": True, "ctrl": True}, None),
("view3d.view_selected", {"type": 'NDOF_BUTTON_FIT', "value": 'PRESS'},
{"properties": [("use_all_regions", False)]}),
("view3d.view_roll", {"type": 'NDOF_BUTTON_ROLL_CW', "value": 'PRESS'},
{"properties": [("angle", pi_2)]}),
("view3d.view_roll", {"type": 'NDOF_BUTTON_ROLL_CCW', "value": 'PRESS'},
{"properties": [("type", 'LEFT')]}),
("view3d.view_roll", {"type": 'NDOF_BUTTON_ROLL_CCW', "value": 'PRESS'},
{"properties": [("type", 'RIGHT')]}),
{"properties": [("angle", -pi_2)]}),
("view3d.view_axis", {"type": 'NDOF_BUTTON_FRONT', "value": 'PRESS'},
{"properties": [("type", 'FRONT')]}),
("view3d.view_axis", {"type": 'NDOF_BUTTON_BACK', "value": 'PRESS'},
@ -2062,14 +2067,19 @@ def km_node_editor(params):
("node.translate_attach",
{"type": 'EVT_TWEAK_L', "value": 'ANY'},
{"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
("node.translate_attach",
{"type": params.select_tweak, "value": 'ANY'},
{"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
# Avoid duplicating the previous item.
*([] if params.select_tweak == 'EVT_TWEAK_L' else (
("node.translate_attach", {"type": params.select_tweak, "value": 'ANY'},
{"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}),
)),
("transform.translate", {"type": 'G', "value": 'PRESS'}, {"properties": [("view2d_edge_pan", True)]}),
("transform.translate", {"type": 'EVT_TWEAK_L', "value": 'ANY'},
{"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}),
("transform.translate", {"type": params.select_tweak, "value": 'ANY'},
{"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}),
# Avoid duplicating the previous item.
*([] if params.select_tweak == 'EVT_TWEAK_L' else (
("transform.translate", {"type": params.select_tweak, "value": 'ANY'},
{"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}),
)),
("transform.rotate", {"type": 'R', "value": 'PRESS'}, None),
("transform.resize", {"type": 'S', "value": 'PRESS'}, None),
("node.move_detach_links",
@ -4673,7 +4683,9 @@ def _template_paint_radial_control(paint, rotation=False, secondary_rotation=Fal
return items
def _template_view3d_select(*, type, value, legacy):
def _template_view3d_select(*, type, value, legacy, 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_rmb` is enabled. See T92467.
return [(
"view3d.select",
{"type": type, "value": value, **{m: True for m in mods}},
@ -4687,7 +4699,7 @@ def _template_view3d_select(*, type, value, legacy):
(("center", "enumerate"), ("ctrl", "alt")),
(("toggle", "enumerate"), ("shift", "alt")),
(("toggle", "center", "enumerate"), ("shift", "ctrl", "alt")),
)]
) if exclude_mod is None or exclude_mod not in mods]
def _template_view3d_gpencil_select(*, type, value, legacy, use_select_mouse=True):
@ -5471,6 +5483,22 @@ def km_font(params):
return keymap
def km_sculpt_curves(params):
items = []
keymap = (
"Sculpt Curves",
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
{"items": items},
)
items.extend([
("sculpt_curves.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
*_template_paint_radial_control("curves_sculpt"),
])
return keymap
def km_object_non_modal(params):
items = []
keymap = (
@ -6495,7 +6523,7 @@ def km_3d_view_tool_select(params, *, fallback):
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
params, "view3d.select", "view3d.cursor3d", extend="toggle")),
*([] if (not params.use_fallback_tool_rmb) else _template_view3d_select(
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)),
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy, exclude_mod="ctrl")),
]},
)
@ -7793,6 +7821,7 @@ def generate_keymaps(params=None):
km_lattice(params),
km_particle(params),
km_font(params),
km_sculpt_curves(params),
km_object_non_modal(params),
# Modal maps.

View File

@ -3408,9 +3408,6 @@ def km_sculpt(params):
("sculpt.set_detail_size", {"type": 'D', "value": 'PRESS', "shift": True, "alt": True}, None),
# Remesh
("object.voxel_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
("object.quadriflow_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True, "alt": True}, None),
# Remesh
("object.voxel_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
("object.voxel_size_edit", {"type": 'R', "value": 'PRESS', "shift": True}, None),
("object.quadriflow_remesh", {"type": 'R', "value": 'PRESS', "ctrl": True, "alt": True}, None),
# Brush properties

View File

@ -963,21 +963,19 @@ class WM_OT_url_open(Operator):
return {'FINISHED'}
# NOTE: needed for Python 3.10 since there are name-space issues with annotations.
# This can be moved into the class as a static-method once Python 3.9x is dropped.
def _wm_url_open_preset_type_items(_self, _context):
return [item for (item, _) in WM_OT_url_open_preset.preset_items]
class WM_OT_url_open_preset(Operator):
"""Open a preset website in the web browser"""
bl_idname = "wm.url_open_preset"
bl_label = "Open Preset Website"
bl_options = {'INTERNAL'}
@staticmethod
def _wm_url_open_preset_type_items(_self, _context):
return [item for (item, _) in WM_OT_url_open_preset.preset_items]
type: EnumProperty(
name="Site",
items=_wm_url_open_preset_type_items,
items=WM_OT_url_open_preset._wm_url_open_preset_type_items,
)
id: StringProperty(
@ -997,11 +995,10 @@ class WM_OT_url_open_preset(Operator):
return "https://www.blender.org/download/releases/%d-%d/" % bpy.app.version[:2]
def _url_from_manual(self, _context):
if bpy.app.version_cycle in {"rc", "release"}:
manual_version = "%d.%d" % bpy.app.version[:2]
else:
manual_version = "dev"
return "https://docs.blender.org/manual/en/" + manual_version + "/"
return "https://docs.blender.org/manual/en/%d.%d/" % bpy.app.version[:2]
def _url_from_api(self, _context):
return "https://docs.blender.org/api/%d.%d/" % bpy.app.version[:2]
# This list is: (enum_item, url) pairs.
# Allow dynamically extending.
@ -1016,9 +1013,12 @@ class WM_OT_url_open_preset(Operator):
(('RELEASE_NOTES', "Release Notes",
"Read about what's new in this version of Blender"),
_url_from_release_notes),
(('MANUAL', "Manual",
(('MANUAL', "User Manual",
"The reference manual for this version of Blender"),
_url_from_manual),
(('API', "Python API Reference",
"The API reference manual for this version of Blender"),
_url_from_api),
# Static URL's.
(('FUND', "Development Fund",
@ -1233,11 +1233,7 @@ class WM_OT_doc_view(Operator):
bl_label = "View Documentation"
doc_id: doc_id
if bpy.app.version_cycle in {"release", "rc", "beta"}:
_prefix = ("https://docs.blender.org/api/%d.%d" %
(bpy.app.version[0], bpy.app.version[1]))
else:
_prefix = ("https://docs.blender.org/api/master")
_prefix = "https://docs.blender.org/api/%d.%d" % bpy.app.version[:2]
def execute(self, _context):
url = _wm_doc_get_id(self.doc_id, do_url=True, url_prefix=self._prefix, report=self.report)
@ -1283,12 +1279,6 @@ rna_vector_subtype_items = (
)
# NOTE: needed for Python 3.10 since there are name-space issues with annotations.
# This can be moved into the class as a static-method once Python 3.9x is dropped.
def _wm_properties_edit_subtype_items(_self, _context):
return WM_OT_properties_edit.subtype_items
class WM_OT_properties_edit(Operator):
"""Change a custom property's type, or adjust how it is displayed in the interface"""
bl_idname = "wm.properties_edit"
@ -1395,7 +1385,7 @@ class WM_OT_properties_edit(Operator):
)
subtype: EnumProperty(
name="Subtype",
items=_wm_properties_edit_subtype_items,
items=WM_OT_properties_edit.subtype_items,
)
# String properties.

View File

@ -24,55 +24,55 @@ class MotionPathButtonsPanel:
layout.use_property_split = True
layout.use_property_decorate = False
row = layout.row(align=True)
row.prop(mps, "type")
if mps.type == 'RANGE':
if bones:
row.operator("pose.paths_range_update", text="", icon='TIME')
else:
row.operator("object.paths_range_update", text="", icon='TIME')
# Display Range
col = layout.column(align=True)
col.prop(mps, "type")
col = layout.column(align=True)
if mps.type == 'CURRENT_FRAME':
col = layout.column(align=True)
col.prop(mps, "frame_before", text="Frame Range Before")
col.prop(mps, "frame_after", text="After")
col.prop(mps, "frame_step", text="Step")
elif mps.type == 'RANGE':
col = layout.column(align=True)
col.prop(mps, "frame_start", text="Frame Range Start")
col.prop(mps, "frame_end", text="End")
col.prop(mps, "frame_step", text="Step")
col.prop(mps, "frame_step", text="Step")
# Calculation Range
col = layout.column(align=True)
row = col.row(align=True)
row.prop(mps, "range", text="Calculation Range")
if mpath:
col = layout.column(align=True)
col.enabled = False
if bones:
col.prop(mpath, "frame_start", text="Bone Cache From")
else:
col.prop(mpath, "frame_start", text="Cache From")
col.prop(mpath, "frame_end", text="To")
row = col.row(align=True)
row.enabled = False
row.prop(mpath, "frame_start", text="Cached Range")
row.prop(mpath, "frame_end", text="")
col = layout.column(align=True)
row = col.row(align=True)
if bones:
col.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA')
row.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA')
row.operator("pose.paths_clear", text="", icon='X').only_selected = True
row = col.row(align=True)
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
row.operator("pose.paths_clear", text="", icon='X').only_selected = False
else:
col.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA')
row.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA')
row.operator("object.paths_clear", text="", icon='X').only_selected = True
row = col.row(align=True)
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
row.operator("object.paths_clear", text="", icon='X').only_selected = False
else:
col = layout.column(align=True)
col.label(text="Nothing to show yet...", icon='ERROR')
col.label(text="No Motion Path generated yet", icon='ERROR')
# Don't invoke settings popup because settings are right above
col.operator_context = 'EXEC_REGION_WIN'
if bones:
col.operator("pose.paths_calculate", text="Calculate...", icon='BONE_DATA')
col.operator(
"pose.paths_calculate", text="Generate for selected bones", icon='BONE_DATA')
else:
col.operator("object.paths_calculate", text="Calculate...", icon='OBJECT_DATA')
row = col.row(align=True)
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
if bones:
row.operator("pose.paths_clear", text="", icon='X')
else:
row.operator("object.paths_clear", text="", icon='X')
col.operator("object.paths_calculate", text="Generate", icon='OBJECT_DATA')
row = col.row(align=True)
row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
row.operator("object.paths_clear", text="", icon='X').only_selected = False
class MotionPathButtonsPanel_display:

View File

@ -35,6 +35,17 @@ class DATA_PT_context_curves(DataButtonsPanel, Panel):
layout.template_ID(space, "pin_id")
class DATA_PT_curves_surface(DataButtonsPanel, Panel):
bl_label = "Surface"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
layout = self.layout
ob = context.object
layout.prop(ob.data, "surface")
class CURVES_MT_add_attribute(Menu):
bl_label = "Add Attribute"
@ -115,6 +126,7 @@ class DATA_PT_custom_props_curves(DataButtonsPanel, PropertyPanel, Panel):
classes = (
DATA_PT_context_curves,
DATA_PT_CURVES_attributes,
DATA_PT_curves_surface,
DATA_PT_custom_props_curves,
CURVES_MT_add_attribute,
CURVES_UL_attributes,

View File

@ -79,6 +79,8 @@ class UnifiedPaintPanel:
return tool_settings.gpencil_weight_paint
elif mode == 'VERTEX_GPENCIL':
return tool_settings.gpencil_vertex_paint
elif mode == 'SCULPT_CURVES':
return tool_settings.curves_sculpt
return None
@staticmethod

View File

@ -663,6 +663,10 @@ class DOPESHEET_MT_context_menu(Menu):
layout.operator_menu_enum("action.mirror", "type", text="Mirror")
layout.operator_menu_enum("action.snap", "type", text="Snap")
if st.mode == 'DOPESHEET':
layout.separator()
layout.menu("VIEW3D_MT_motion_path")
class DOPESHEET_MT_channel_context_menu(Menu):
bl_label = "Dope Sheet Channel Context Menu"

View File

@ -390,6 +390,9 @@ class GRAPH_MT_context_menu(Menu):
layout.operator_menu_enum("graph.mirror", "type", text="Mirror")
layout.operator_menu_enum("graph.snap", "type", text="Snap")
layout.separator()
layout.menu("VIEW3D_MT_motion_path")
class GRAPH_MT_pivot_pie(Menu):
bl_label = "Pivot Point"

View File

@ -1038,9 +1038,6 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False):
if props is None:
print("Error:", gizmo_group, "could not access properties!")
else:
for key in props.bl_rna.properties.keys():
props.property_unset(key)
gizmo_properties = item.widget_properties
if gizmo_properties is not None:
if not isinstance(gizmo_properties, list):

View File

@ -2306,6 +2306,19 @@ class _defs_gpencil_weight:
)
class _defs_curves_sculpt:
@staticmethod
def generate_from_brushes(context):
return generate_from_enum_ex(
context,
idname_prefix="builtin_brush.",
icon_prefix="ops.curves.sculpt_",
type= bpy.types.Brush,
attr="curves_sculpt_tool",
)
class _defs_gpencil_vertex:
@staticmethod
@ -3065,6 +3078,9 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
else ()
),
],
'SCULPT_CURVES': [
_defs_curves_sculpt.generate_from_brushes,
],
}

View File

@ -448,8 +448,7 @@ class TOPBAR_MT_file_import(Menu):
def draw(self, _context):
if bpy.app.build_options.collada:
self.layout.operator("wm.collada_import",
text="Collada (Default) (.dae)")
self.layout.operator("wm.collada_import", text="Collada (.dae)")
if bpy.app.build_options.alembic:
self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
if bpy.app.build_options.usd:
@ -467,8 +466,7 @@ class TOPBAR_MT_file_export(Menu):
def draw(self, _context):
self.layout.operator("wm.obj_export", text="Wavefront OBJ (.obj)")
if bpy.app.build_options.collada:
self.layout.operator("wm.collada_export",
text="Collada (Default) (.dae)")
self.layout.operator("wm.collada_export", text="Collada (.dae)")
if bpy.app.build_options.alembic:
self.layout.operator("wm.alembic_export", text="Alembic (.abc)")
if bpy.app.build_options.usd:
@ -690,8 +688,8 @@ class TOPBAR_MT_help(Menu):
layout.separator()
layout.operator(
"wm.url_open", text="Python API Reference", icon='URL',
).url = bpy.types.WM_OT_doc_view._prefix
"wm.url_open_preset", text="Python API Reference", icon='URL',
).type = 'API'
if show_developer:
layout.operator(

View File

@ -1719,6 +1719,7 @@ class USERPREF_PT_ndof_settings(Panel):
if show_3dview_settings:
col.prop(props, "ndof_show_guide")
col.prop(props, "ndof_zoom_invert")
col.prop(props, "ndof_lock_camera_pan_zoom")
row = col.row(heading="Pan")
row.prop(props, "ndof_pan_yz_swap_axis", text="Swap Y and Z Axes")

View File

@ -468,6 +468,38 @@ class _draw_tool_settings_context_mode:
return True
@staticmethod
def SCULPT_CURVES(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return False
paint = context.tool_settings.curves_sculpt
layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True)
brush = paint.brush
if brush is None:
return False
UnifiedPaintPanel.prop_unified(
layout,
context,
brush,
"size",
unified_name="use_unified_size",
text="Radius",
slider=True,
header=True
)
UnifiedPaintPanel.prop_unified(
layout,
context,
brush,
"strength",
unified_name="use_unified_strength",
header=True
)
class VIEW3D_HT_header(Header):
bl_space_type = 'VIEW_3D'
@ -1899,6 +1931,13 @@ class VIEW3D_MT_select_paint_mask_vertex(Menu):
layout.operator("paint.vert_select_ungrouped", text="Ungrouped Vertices")
class VIEW3D_MT_select_edit_curves(Menu):
bl_label = "Select"
def draw(self, _context):
pass
class VIEW3D_MT_angle_control(Menu):
bl_label = "Angle Control"
@ -2344,6 +2383,25 @@ class VIEW3D_MT_object_clear(Menu):
layout.operator("object.origin_clear", text="Origin")
class VIEW3D_MT_motion_path(Menu):
bl_label = "Motion Paths"
def draw(self, _context):
layout = self.layout
ob = _context.object
if ob.mode == 'OBJECT':
layout.operator("object.paths_calculate")
layout.operator("object.paths_update")
layout.operator("object.paths_update_visible")
layout.operator("object.paths_clear", text="Clear all").only_selected = False
layout.operator("object.paths_clear", text="Clear selected").only_selected = True
elif ob.mode == 'POSE':
layout.operator("pose.paths_calculate")
layout.operator("pose.paths_update")
layout.operator("pose.paths_clear", text="Clear all").only_selected = False
layout.operator("pose.paths_clear", text="Clear selected").only_selected = True
class VIEW3D_MT_object_context_menu(Menu):
bl_label = "Object Context Menu"
@ -2545,6 +2603,7 @@ class VIEW3D_MT_object_context_menu(Menu):
layout.menu("VIEW3D_MT_mirror")
layout.menu("VIEW3D_MT_snap")
layout.menu("VIEW3D_MT_object_parent")
layout.menu("VIEW3D_MT_motion_path")
layout.operator_context = 'INVOKE_REGION_WIN'
if view and view.local_view:
@ -3592,10 +3651,10 @@ class VIEW3D_MT_pose_context_menu(Menu):
layout.separator()
layout.operator("pose.paths_calculate", text="Calculate Motion Paths")
layout.operator("pose.paths_clear", text="Clear Motion Paths")
layout.operator("pose.paths_update", text="Update Armature Motion Paths")
layout.operator("object.paths_update_visible", text="Update All Motion Paths")
layout.operator("pose.paths_calculate")
layout.operator("pose.paths_update")
layout.operator("pose.paths_clear", text="Clear all").only_selected = False
layout.operator("pose.paths_clear", text="Clear selected").only_selected = True
layout.separator()
@ -5123,6 +5182,13 @@ class VIEW3D_MT_edit_gpencil_showhide(Menu):
layout.operator("gpencil.hide", text="Hide Inactive Layers").unselected = True
class VIEW3D_MT_edit_curves(Menu):
bl_label = "Curves"
def draw(self, _context):
pass
class VIEW3D_MT_object_mode_pie(Menu):
bl_label = "Mode"
@ -7544,6 +7610,7 @@ classes = (
VIEW3D_MT_select_gpencil,
VIEW3D_MT_select_paint_mask,
VIEW3D_MT_select_paint_mask_vertex,
VIEW3D_MT_select_edit_curves,
VIEW3D_MT_angle_control,
VIEW3D_MT_mesh_add,
VIEW3D_MT_curve_add,
@ -7576,6 +7643,7 @@ classes = (
VIEW3D_MT_object_quick_effects,
VIEW3D_MT_object_showhide,
VIEW3D_MT_object_cleanup,
VIEW3D_MT_motion_path,
VIEW3D_MT_make_single_user,
VIEW3D_MT_make_links,
VIEW3D_MT_brush_paint_modes,
@ -7666,6 +7734,7 @@ classes = (
VIEW3D_MT_edit_armature_names,
VIEW3D_MT_edit_armature_delete,
VIEW3D_MT_edit_gpencil_transform,
VIEW3D_MT_edit_curves,
VIEW3D_MT_object_mode_pie,
VIEW3D_MT_view_pie,
VIEW3D_MT_transform_gizmo_pie,

View File

@ -142,6 +142,7 @@ def mesh_node_items(context):
yield NodeItem("GeometryNodeInputMeshEdgeVertices")
yield NodeItem("GeometryNodeInputMeshFaceArea")
yield NodeItem("GeometryNodeInputMeshFaceNeighbors")
yield NodeItem("GeometryNodeInputMeshFaceIsPlanar")
yield NodeItem("GeometryNodeInputMeshIsland")
yield NodeItem("GeometryNodeInputShadeSmooth")
yield NodeItem("GeometryNodeInputMeshVertexNeighbors")
@ -164,6 +165,7 @@ def geometry_node_items(context):
yield NodeItem("GeometryNodeBoundBox")
yield NodeItem("GeometryNodeConvexHull")
yield NodeItem("GeometryNodeDeleteGeometry")
yield NodeItem("GeometryNodeDuplicateElements")
yield NodeItem("GeometryNodeGeometryToInstance")
yield NodeItem("GeometryNodeMergeByDistance")
yield NodeItem("GeometryNodeProximity")

View File

@ -227,7 +227,7 @@ struct WriteAttributeLookup {
* - An output attribute can live side by side with an existing attribute with a different domain
* or data type. The old attribute will only be overwritten when the #save function is called.
*
* \note The lifetime of an output attribute should not be longer than the the lifetime of the
* \note The lifetime of an output attribute should not be longer than the lifetime of the
* geometry component it comes from, since it can keep a reference to the component for use in
* the #save method.
*/

View File

@ -25,13 +25,13 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 3
#define BLENDER_FILE_SUBVERSION 4
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
* was written with too new a version. */
#define BLENDER_FILE_MIN_VERSION 300
#define BLENDER_FILE_MIN_SUBVERSION 42
#define BLENDER_FILE_MIN_SUBVERSION 43
/** User readable version string. */
const char *BKE_blender_version_string(void);

View File

@ -8,13 +8,13 @@
* General operations for brushes.
*/
#include "DNA_color_types.h"
#include "DNA_object_enums.h"
#ifdef __cplusplus
extern "C" {
#endif
enum eCurveMappingPreset;
struct Brush;
struct ImBuf;
struct ImagePool;

View File

@ -106,6 +106,7 @@ typedef enum eContextObjectMode {
CTX_MODE_EDIT_ARMATURE,
CTX_MODE_EDIT_METABALL,
CTX_MODE_EDIT_LATTICE,
CTX_MODE_EDIT_CURVES,
CTX_MODE_POSE,
CTX_MODE_SCULPT,
CTX_MODE_PAINT_WEIGHT,

View File

@ -82,6 +82,8 @@ class CurvesGeometry : public ::CurvesGeometry {
int points_size() const;
int curves_size() const;
IndexRange points_range() const;
IndexRange curves_range() const;
/**
* The total number of points in the evaluated poly curve.

View File

@ -693,7 +693,7 @@ class CurveComponent : public GeometryComponent {
/**
* Holds a reference to conceptually unique geometry or a pointer to object/collection data
* that is is instanced with a transform in #InstancesComponent.
* that is instanced with a transform in #InstancesComponent.
*/
class InstanceReference {
public:

View File

@ -208,11 +208,13 @@ void BKE_gpencil_point_coords_apply_with_mat4(struct bGPdata *gpd,
* \param gpd: Grease pencil data-block
* \param gps: Stroke to sample
* \param dist: Distance of one segment
* \param sharp_threshold: Threshold for preserving sharp corners
*/
bool BKE_gpencil_stroke_sample(struct bGPdata *gpd,
struct bGPDstroke *gps,
float dist,
bool select);
const float dist,
const bool select,
const float sharp_threshold);
/**
* Apply smooth position to stroke point.
* \param gps: Stroke to smooth

View File

@ -169,7 +169,7 @@ struct IDProperty *IDP_GetPropertyTypeFromGroup(const struct IDProperty *prop,
/*-------- Main Functions --------*/
/**
* Get the Group property that contains the id properties for ID id.
* Get the Group property that contains the id properties for ID `id`.
*
* \param create_if_needed: Set to create the group property and attach it to id if it doesn't
* exist; otherwise the function will return NULL if there's no Group property attached to the ID.

View File

@ -230,7 +230,7 @@ extern IDTypeInfo IDType_ID_SCE;
extern IDTypeInfo IDType_ID_LI;
extern IDTypeInfo IDType_ID_OB;
extern IDTypeInfo IDType_ID_ME;
extern IDTypeInfo IDType_ID_CU;
extern IDTypeInfo IDType_ID_CU_LEGACY;
extern IDTypeInfo IDType_ID_MB;
extern IDTypeInfo IDType_ID_MA;
extern IDTypeInfo IDType_ID_TE;

View File

@ -92,7 +92,13 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
*
* \param id_hierarchy_root: the override ID that is the root of the hierarchy. May be NULL, in
* which case it is assumed that the given `id_root_reference` is tagged for override, and its
* newly created override will be used as hierarchy root.
* newly created override will be used as hierarchy root. Must be NULL if
* `id_hierarchy_root_reference` is not NULL.
*
* \param id_hierarchy_root_reference: the linked ID that is the root of the hierarchy. Must be
* tagged for override. May be NULL, in which case it is assumed that the given `id_root_reference`
* is tagged for override, and its newly created override will be used as hierarchy root. Must be
* NULL if `id_hierarchy_root` is not NULL.
*
* \param do_no_main: Create the new override data outside of Main database.
* Used for resyncing of linked overrides.
@ -103,6 +109,7 @@ bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
struct Library *owner_library,
const struct ID *id_root_reference,
struct ID *id_hierarchy_root,
const struct ID *id_hierarchy_root_reference,
bool do_no_main);
/**
* Advanced 'smart' function to create fully functional overrides.
@ -119,11 +126,18 @@ bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
* \param owner_library: the library in which the overrides should be created. Besides versioning
* and resync code path, this should always be NULL (i.e. the local .blend file).
*
* \param id_root: The root ID to create an override from.
* \param id_root_reference: The linked root ID to create an override from. May be a sub-root of
* the overall hierarchy, in which case calling code is expected to have already tagged required
* 'path' of IDs leading from the given `id_hierarchy_root` to the given `id_root`.
*
* \param id_reference: Some reference ID used to do some post-processing after overrides have been
* created, may be NULL. Typically, the Empty object instantiating the linked collection we
* override, currently.
* \param id_hierarchy_root_reference: The ID to be used a hierarchy root of the overrides to be
* created. Can be either the linked root ID of the whole override hierarchy, (typically the same
* as `id_root`, unless a sub-part only of the hierarchy is overridden), or the already existing
* override hierarchy root if part of the hierarchy is already overridden.
*
* \param id_instance_hint: Some ID used as hint/reference to do some post-processing after
* overrides have been created, may be NULL. Typically, the Empty object instantiating the linked
* collection we override, currently.
*
* \param r_id_root_override: if not NULL, the override generated for the given \a id_root.
*
@ -133,8 +147,9 @@ bool BKE_lib_override_library_create(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
struct Library *owner_library,
struct ID *id_root,
struct ID *id_reference,
struct ID *id_root_reference,
struct ID *id_hierarchy_root_reference,
struct ID *id_instance_hint,
struct ID **r_id_root_override);
/**
* Create a library override template.

View File

@ -69,6 +69,13 @@ struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm,
const struct CustomData_MeshMasks *cd_mask_extra,
const struct Mesh *me_settings);
/**
* Add original index (#CD_ORIGINDEX) layers if they don't already exist. This is meant to be used
* when creating an evaluated mesh from an original edit mode mesh, to allow mapping from the
* evaluated vertices to the originals.
*/
void BKE_mesh_ensure_default_orig_index_customdata(struct Mesh *mesh);
/**
* Find the index of the loop in 'poly' which references vertex,
* returns -1 if not found
@ -332,8 +339,7 @@ int BKE_mesh_tessface_calc_ex(struct CustomData *fdata,
struct MVert *mvert,
int totface,
int totloop,
int totpoly,
bool do_face_nor_copy);
int totpoly);
void BKE_mesh_tessface_calc(struct Mesh *mesh);
/**
@ -399,6 +405,9 @@ void BKE_mesh_assert_normals_dirty_or_calculated(const struct Mesh *mesh);
* \note In order to clear the dirty flag, this function should be followed by a call to
* #BKE_mesh_vertex_normals_clear_dirty. This is separate so that normals are still tagged dirty
* while they are being assigned.
*
* \warning The memory returned by this function is not initialized if it was not previously
* allocated.
*/
float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3];
@ -409,9 +418,23 @@ float (*BKE_mesh_vertex_normals_for_write(struct Mesh *mesh))[3];
* \note In order to clear the dirty flag, this function should be followed by a call to
* #BKE_mesh_poly_normals_clear_dirty. This is separate so that normals are still tagged dirty
* while they are being assigned.
*
* \warning The memory returned by this function is not initialized if it was not previously
* allocated.
*/
float (*BKE_mesh_poly_normals_for_write(struct Mesh *mesh))[3];
/**
* Free any cached vertex or poly normals. Face corner (loop) normals are also derived data,
* but are not handled with the same method yet, so they are not included. It's important that this
* is called after the mesh changes size, since otherwise cached normal arrays might not be large
* enough (though it may be called indirectly by other functions).
*
* \note Normally it's preferred to call #BKE_mesh_normals_tag_dirty instead,
* but this can be used in specific situations to reset a mesh or reduce memory usage.
*/
void BKE_mesh_clear_derived_normals(struct Mesh *mesh);
/**
* Mark the mesh's vertex normals non-dirty, for when they are calculated or assigned manually.
*/

View File

@ -1514,6 +1514,8 @@ struct TexResult;
#define GEO_NODE_SCALE_ELEMENTS 1151
#define GEO_NODE_EXTRUDE_MESH 1152
#define GEO_NODE_MERGE_BY_DISTANCE 1153
#define GEO_NODE_DUPLICATE_ELEMENTS 1154
#define GEO_NODE_INPUT_MESH_FACE_IS_PLANAR 1155
/** \} */

View File

@ -74,9 +74,11 @@ typedef enum ePaintMode {
PAINT_MODE_VERTEX_GPENCIL = 7,
PAINT_MODE_SCULPT_GPENCIL = 8,
PAINT_MODE_WEIGHT_GPENCIL = 9,
/** Curves. */
PAINT_MODE_SCULPT_CURVES = 10,
/** Keep last. */
PAINT_MODE_INVALID = 10,
PAINT_MODE_INVALID = 11,
} ePaintMode;
#define PAINT_MODE_HAS_BRUSH(mode) !ELEM(mode, PAINT_MODE_SCULPT_UV)

View File

@ -10,6 +10,8 @@
#include "FN_generic_virtual_array.hh"
#include "DNA_curves_types.h"
#include "BLI_float4x4.hh"
#include "BLI_math_vec_types.hh"
#include "BLI_vector.hh"
@ -49,12 +51,6 @@ using SplinePtr = std::unique_ptr<Spline>;
*/
class Spline {
public:
enum class Type {
Bezier,
NURBS,
Poly,
};
enum NormalCalculationMode {
ZUp,
Minimum,
@ -65,7 +61,7 @@ class Spline {
blender::bke::CustomDataAttributes attributes;
protected:
Type type_;
CurveType type_;
bool is_cyclic_ = false;
/** Direction of the spline at each evaluated point. */
@ -85,7 +81,7 @@ class Spline {
public:
virtual ~Spline() = default;
Spline(const Type type) : type_(type)
Spline(const CurveType type) : type_(type)
{
}
Spline(Spline &other) : attributes(other.attributes), type_(other.type_)
@ -107,7 +103,7 @@ class Spline {
SplinePtr copy_without_attributes() const;
static void copy_base_settings(const Spline &src, Spline &dst);
Spline::Type type() const;
CurveType type() const;
/** Return the number of control points. */
virtual int size() const = 0;
@ -252,26 +248,13 @@ class Spline {
* factors and indices in a list of floats, which is then used to interpolate any other data.
*/
class BezierSpline final : public Spline {
public:
enum class HandleType {
/** The handle can be moved anywhere, and doesn't influence the point's other handle. */
Free,
/** The location is automatically calculated to be smooth. */
Auto,
/** The location is calculated to point to the next/previous control point. */
Vector,
/** The location is constrained to point in the opposite direction as the other handle. */
Align,
};
private:
blender::Vector<blender::float3> positions_;
blender::Vector<float> radii_;
blender::Vector<float> tilts_;
int resolution_;
blender::Vector<HandleType> handle_types_left_;
blender::Vector<HandleType> handle_types_right_;
blender::Vector<int8_t> handle_types_left_;
blender::Vector<int8_t> handle_types_right_;
/* These are mutable to allow lazy recalculation of #Auto and #Vector handle positions. */
mutable blender::Vector<blender::float3> handle_positions_left_;
@ -296,7 +279,7 @@ class BezierSpline final : public Spline {
mutable bool mapping_cache_dirty_ = true;
public:
BezierSpline() : Spline(Type::Bezier)
BezierSpline() : Spline(CURVE_TYPE_BEZIER)
{
}
BezierSpline(const BezierSpline &other)
@ -323,8 +306,8 @@ class BezierSpline final : public Spline {
blender::Span<float> radii() const final;
blender::MutableSpan<float> tilts() final;
blender::Span<float> tilts() const final;
blender::Span<HandleType> handle_types_left() const;
blender::MutableSpan<HandleType> handle_types_left();
blender::Span<int8_t> handle_types_left() const;
blender::MutableSpan<int8_t> handle_types_left();
blender::Span<blender::float3> handle_positions_left() const;
/**
* Get writable access to the handle position.
@ -333,8 +316,8 @@ class BezierSpline final : public Spline {
* uninitialized memory while auto-generating handles.
*/
blender::MutableSpan<blender::float3> handle_positions_left(bool write_only = false);
blender::Span<HandleType> handle_types_right() const;
blender::MutableSpan<HandleType> handle_types_right();
blender::Span<int8_t> handle_types_right() const;
blender::MutableSpan<int8_t> handle_types_right();
blender::Span<blender::float3> handle_positions_right() const;
/**
* Get writable access to the handle position.
@ -519,7 +502,7 @@ class NURBSpline final : public Spline {
mutable bool position_cache_dirty_ = true;
public:
NURBSpline() : Spline(Type::NURBS)
NURBSpline() : Spline(CURVE_TYPE_NURBS)
{
}
NURBSpline(const NURBSpline &other)
@ -586,7 +569,7 @@ class PolySpline final : public Spline {
blender::Vector<float> tilts_;
public:
PolySpline() : Spline(Type::Poly)
PolySpline() : Spline(CURVE_TYPE_POLY)
{
}
PolySpline(const PolySpline &other)
@ -658,7 +641,7 @@ struct CurveEval {
* \note If you are looping over all of the splines in the same scope anyway,
* it's better to avoid calling this function, in case there are many splines.
*/
bool has_spline_with_type(const Spline::Type type) const;
bool has_spline_with_type(const CurveType type) const;
void resize(int size);
/**

View File

@ -24,18 +24,30 @@ void BKE_subsurf_modifier_subdiv_settings_init(struct SubdivSettings *settings,
const struct SubsurfModifierData *smd,
bool use_render_params);
bool BKE_subsurf_modifier_use_custom_loop_normals(const struct SubsurfModifierData *smd,
const struct Mesh *mesh);
/**
* Return true if GPU subdivision evaluation is disabled by force due to incompatible mesh or
* modifier settings. This will only return true if GPU subdivision is enabled in the preferences
* and supported by the GPU. It is mainly useful for showing UI messages.
*/
bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(
const struct SubsurfModifierData *smd, const struct Mesh *mesh);
/**
* \param skip_check_is_last: When true, we assume that the modifier passed is the last enabled
* modifier in the stack.
*/
bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const struct Scene *scene,
const struct Object *ob,
const struct Mesh *mesh,
const struct SubsurfModifierData *smd,
int required_mode,
bool skip_check_is_last);
bool BKE_subsurf_modifier_can_do_gpu_subdiv(const struct Scene *scene,
const struct Object *ob,
const struct Mesh *mesh,
int required_mode);
extern void (*BKE_subsurf_modifier_free_gpu_cache_cb)(struct Subdiv *subdiv);

View File

@ -69,12 +69,8 @@ void BKE_ffmpeg_filepath_get(char *string,
void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset);
void BKE_ffmpeg_image_type_verify(struct RenderData *rd, struct ImageFormatData *imf);
void BKE_ffmpeg_codec_settings_verify(struct RenderData *rd);
bool BKE_ffmpeg_alpha_channel_is_supported(const struct RenderData *rd);
int BKE_ffmpeg_property_add_string(struct RenderData *rd, const char *type, const char *str);
void BKE_ffmpeg_property_del(struct RenderData *rd, void *type, void *prop_);
void *BKE_ffmpeg_context_create(void);
void BKE_ffmpeg_context_free(void *context_v);

View File

@ -377,6 +377,7 @@ set(SRC
BKE_idprop.hh
BKE_idtype.h
BKE_image.h
BKE_image_partial_update.hh
BKE_image_save.h
BKE_ipo.h
BKE_kelvinlet.h

View File

@ -546,6 +546,7 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer)
if (em) {
mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, nullptr, me);
BKE_mesh_ensure_default_orig_index_customdata(mesh);
}
else {
mesh = BKE_mesh_copy_for_eval(me, true);
@ -1364,6 +1365,12 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
em_input, &final_datamask, nullptr, mesh_input);
}
/* The mesh from edit mode should not have any original index layers already, since those
* are added during evaluation when necessary and are redundant on an original mesh. */
BLI_assert(CustomData_get_layer(&em_input->bm->pdata, CD_ORIGINDEX) == nullptr &&
CustomData_get_layer(&em_input->bm->edata, CD_ORIGINDEX) == nullptr &&
CustomData_get_layer(&em_input->bm->pdata, CD_ORIGINDEX) == nullptr);
/* Clear errors before evaluation. */
BKE_modifiers_clear_errors(ob);
@ -1402,6 +1409,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
if (mesh_final == nullptr) {
mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, nullptr, mesh_input);
BKE_mesh_ensure_default_orig_index_customdata(mesh_final);
ASSERT_IS_VALID_MESH(mesh_final);
}
BLI_assert(deformed_verts != nullptr);
@ -1819,9 +1827,8 @@ Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph,
mesh_eval = BKE_object_get_evaluated_mesh(ob);
}
if (mesh_eval != nullptr) {
BLI_assert(!(mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL));
}
BKE_mesh_assert_normals_dirty_or_calculated(mesh_eval);
return mesh_eval;
}

View File

@ -1244,7 +1244,7 @@ void BKE_pose_update_constraint_flags(bPose *pose)
/* if we have a valid target, make sure that this will get updated on frame-change
* (needed for when there is no anim-data for this pose)
*/
if ((data->tar) && (data->tar->type == OB_CURVE)) {
if ((data->tar) && (data->tar->type == OB_CURVES_LEGACY)) {
pose->flag |= POSE_CONSTRAINTS_TIMEDEPEND;
}
}

View File

@ -763,7 +763,7 @@ static bool fcurves_path_rename_fix(ID *owner_id,
if (fcu->rna_path != old_path) {
bActionGroup *agrp = fcu->grp;
is_changed = true;
if ((agrp != NULL) && STREQ(oldName, agrp->name)) {
if (oldName != NULL && (agrp != NULL) && STREQ(oldName, agrp->name)) {
BLI_strncpy(agrp->name, newName, sizeof(agrp->name));
}
}

View File

@ -55,7 +55,7 @@ float BKE_anim_path_get_length(const CurveCache *curve_cache)
void BKE_anim_path_calc_data(Object *ob)
{
if (ob == NULL || ob->type != OB_CURVE) {
if (ob == NULL || ob->type != OB_CURVES_LEGACY) {
return;
}
if (ob->runtime.curve_cache == NULL) {
@ -222,7 +222,7 @@ bool BKE_where_on_path(const Object *ob,
float *r_radius,
float *r_weight)
{
if (ob == NULL || ob->type != OB_CURVE) {
if (ob == NULL || ob->type != OB_CURVES_LEGACY) {
return false;
}
Curve *cu = ob->data;

View File

@ -153,6 +153,11 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports,
if ((mpath->start_frame != mpath->end_frame) && (mpath->length > 0)) {
/* outer check ensures that we have some curve data for this path */
if (mpath->length == expected_length) {
/* The length might be the same, but the start and end could be different */
if (mpath->start_frame != avs->path_sf) {
mpath->start_frame = avs->path_sf;
mpath->end_frame = avs->path_ef;
}
/* return/use this as it is already valid length */
return mpath;
}

View File

@ -70,7 +70,7 @@ static void splineik_init_tree_from_pchan(Scene *UNUSED(scene),
ik_data = con->data;
/* Target can only be a curve. */
if ((ik_data->tar == NULL) || (ik_data->tar->type != OB_CURVE)) {
if ((ik_data->tar == NULL) || (ik_data->tar->type != OB_CURVES_LEGACY)) {
continue;
}
/* Skip if disabled. */

View File

@ -52,7 +52,7 @@ TEST_F(AssetLibraryTest, bke_asset_library_load)
ASSERT_NE(nullptr, service);
/* Check that the catalogs defined in the library are actually loaded. This just tests one single
* catalog, as that indicates the file has been loaded. Testing that that loading went OK is for
* catalog, as that indicates the file has been loaded. Testing that loading went OK is for
* the asset catalog service tests. */
const bUUID uuid_poses_ellie("df60e1f6-2259-475b-93d9-69a1b4a8db78");
AssetCatalog *poses_ellie = service->find_catalog(uuid_poses_ellie);

View File

@ -144,7 +144,7 @@ static void brush_make_local(Main *bmain, ID *id, const int flags)
/* FIXME: Recursive calls affecting other non-embedded IDs are really bad and should be avoided
* in IDType callbacks. Higher-level ID management code usually does not expect such things and
* does not deal properly with it. */
/* NOTE: assert below ensures that the comment above is valid, and that that exception is
/* NOTE: assert below ensures that the comment above is valid, and that exception is
* acceptable for the time being. */
BKE_lib_id_make_local(bmain, &brush->clone.image->id, 0);
BLI_assert(!ID_IS_LINKED(brush->clone.image) && brush->clone.image->id.newid == NULL);

View File

@ -529,8 +529,8 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[
float vec[3] = {0.0f, 0.0f, 0.0f};
float normal[3] = {0.0f, 0.0f, 0.0f};
float weightsum = 0.0f;
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
if (me_eval) {
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me_eval);
const MDeformVert *dvert = CustomData_get_layer(&me_eval->vdata, CD_MDEFORMVERT);
int numVerts = me_eval->totvert;
@ -1493,7 +1493,7 @@ static void followpath_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
{
bFollowPathConstraint *data = con->data;
if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) {
if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVES_LEGACY)) {
Curve *cu = ct->tar->data;
float vec[4], dir[3], radius;
float curvetime;
@ -2479,7 +2479,7 @@ static void pycon_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
#endif
if (VALID_CONS_TARGET(ct)) {
if (ct->tar->type == OB_CURVE && ct->tar->runtime.curve_cache == NULL) {
if (ct->tar->type == OB_CURVES_LEGACY && ct->tar->runtime.curve_cache == NULL) {
unit_m4(ct->matrix);
return;
}
@ -3867,7 +3867,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
bConstraintTarget *ct = targets->first;
/* only evaluate if there is a target and it is a curve */
if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) {
if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVES_LEGACY)) {
float obmat[4][4], ownLoc[3];
float curveMin[3], curveMax[3];
float targetMatrix[4][4];

View File

@ -1157,7 +1157,7 @@ enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit,
switch (obedit->type) {
case OB_MESH:
return CTX_MODE_EDIT_MESH;
case OB_CURVE:
case OB_CURVES_LEGACY:
return CTX_MODE_EDIT_CURVE;
case OB_SURF:
return CTX_MODE_EDIT_SURFACE;
@ -1169,6 +1169,8 @@ enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit,
return CTX_MODE_EDIT_METABALL;
case OB_LATTICE:
return CTX_MODE_EDIT_LATTICE;
case OB_CURVES:
return CTX_MODE_EDIT_CURVES;
}
}
else {
@ -1236,6 +1238,7 @@ static const char *data_mode_strings[] = {
"armature_edit",
"mball_edit",
"lattice_edit",
"curves_edit",
"posemode",
"sculpt_mode",
"weightpaint",

View File

@ -293,14 +293,14 @@ static void curve_blend_read_expand(BlendExpander *expander, ID *id)
BLO_expand(expander, cu->textoncurve);
}
IDTypeInfo IDType_ID_CU = {
/* id_code */ ID_CU,
/* id_filter */ FILTER_ID_CU,
/* main_listbase_index */ INDEX_ID_CU,
IDTypeInfo IDType_ID_CU_LEGACY = {
/* id_code */ ID_CU_LEGACY,
/* id_filter */ FILTER_ID_CU_LEGACY,
/* main_listbase_index */ INDEX_ID_CU_LEGACY,
/* struct_size */ sizeof(Curve),
/* name */ "Curve",
/* name_plural */ "curves",
/* translation_context */ BLT_I18NCONTEXT_ID_CURVE,
/* translation_context */ BLT_I18NCONTEXT_ID_CURVE_LEGACY,
/* flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
/* asset_type_info */ nullptr,
@ -406,7 +406,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
Curve *cu;
/* We cannot use #BKE_id_new here as we need some custom initialization code. */
cu = (Curve *)BKE_libblock_alloc(bmain, ID_CU, name, 0);
cu = (Curve *)BKE_libblock_alloc(bmain, ID_CU_LEGACY, name, 0);
BKE_curve_init(cu, type);
@ -440,7 +440,7 @@ short BKE_curve_type_get(const Curve *cu)
}
if (!cu->type) {
type = OB_CURVE;
type = OB_CURVES_LEGACY;
LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
if (nu->pntsv > 1) {
@ -473,7 +473,7 @@ void BKE_curve_type_test(Object *ob)
{
ob->type = BKE_curve_type_get((Curve *)ob->data);
if (ob->type == OB_CURVE) {
if (ob->type == OB_CURVES_LEGACY) {
Curve *cu = (Curve *)ob->data;
if (CU_IS_2D(cu)) {
BKE_curve_dimension_update(cu);

View File

@ -228,7 +228,7 @@ static void curve_bevel_make_from_object(const Curve *cu, ListBase *disp)
if (cu->bevobj == NULL) {
return;
}
if (cu->bevobj->type != OB_CURVE) {
if (cu->bevobj->type != OB_CURVES_LEGACY) {
return;
}

View File

@ -27,7 +27,7 @@ static Curve *curve_from_font_object(Object *object, Depsgraph *depsgraph)
Object *evaluated_object = DEG_get_evaluated_object(depsgraph, object);
BKE_vfont_to_curve_nubase(evaluated_object, FO_EDIT, &new_curve->nurb);
new_curve->type = OB_CURVE;
new_curve->type = OB_CURVES_LEGACY;
new_curve->flag &= ~CU_3D;
BKE_curve_dimension_update(new_curve);
@ -55,7 +55,7 @@ static Curve *curve_from_curve_object(Object *object, Depsgraph *depsgraph, bool
Curve *BKE_curve_new_from_object(Object *object, Depsgraph *depsgraph, bool apply_modifiers)
{
if (!ELEM(object->type, OB_FONT, OB_CURVE)) {
if (!ELEM(object->type, OB_FONT, OB_CURVES_LEGACY)) {
return NULL;
}

View File

@ -211,7 +211,7 @@ static void curve_deform_coords_impl(const Object *ob_curve,
bool use_dverts = false;
int cd_dvert_offset;
if (ob_curve->type != OB_CURVE) {
if (ob_curve->type != OB_CURVES_LEGACY) {
return;
}
@ -404,7 +404,7 @@ void BKE_curve_deform_co(const Object *ob_curve,
CurveDeform cd;
float quat[4];
if (ob_curve->type != OB_CURVE) {
if (ob_curve->type != OB_CURVES_LEGACY) {
unit_m3(r_mat);
return;
}

View File

@ -36,7 +36,7 @@ blender::MutableSpan<SplinePtr> CurveEval::splines()
return splines_;
}
bool CurveEval::has_spline_with_type(const Spline::Type type) const
bool CurveEval::has_spline_with_type(const CurveType type) const
{
for (const SplinePtr &spline : this->splines()) {
if (spline->type() == type) {
@ -160,24 +160,24 @@ void CurveEval::mark_cache_invalid()
}
}
static BezierSpline::HandleType handle_type_from_dna_bezt(const eBezTriple_Handle dna_handle_type)
static HandleType handle_type_from_dna_bezt(const eBezTriple_Handle dna_handle_type)
{
switch (dna_handle_type) {
case HD_FREE:
return BezierSpline::HandleType::Free;
return BEZIER_HANDLE_FREE;
case HD_AUTO:
return BezierSpline::HandleType::Auto;
return BEZIER_HANDLE_AUTO;
case HD_VECT:
return BezierSpline::HandleType::Vector;
return BEZIER_HANDLE_VECTOR;
case HD_ALIGN:
return BezierSpline::HandleType::Align;
return BEZIER_HANDLE_ALIGN;
case HD_AUTO_ANIM:
return BezierSpline::HandleType::Auto;
return BEZIER_HANDLE_AUTO;
case HD_ALIGN_DOUBLESIDE:
return BezierSpline::HandleType::Align;
return BEZIER_HANDLE_ALIGN;
}
BLI_assert_unreachable();
return BezierSpline::HandleType::Auto;
return BEZIER_HANDLE_AUTO;
}
static Spline::NormalCalculationMode normal_mode_from_dna_curve(const int twist_mode)
@ -220,8 +220,8 @@ static SplinePtr spline_from_dna_bezier(const Nurb &nurb)
MutableSpan<float3> positions = spline->positions();
MutableSpan<float3> handle_positions_left = spline->handle_positions_left(true);
MutableSpan<float3> handle_positions_right = spline->handle_positions_right(true);
MutableSpan<BezierSpline::HandleType> handle_types_left = spline->handle_types_left();
MutableSpan<BezierSpline::HandleType> handle_types_right = spline->handle_types_right();
MutableSpan<int8_t> handle_types_left = spline->handle_types_left();
MutableSpan<int8_t> handle_types_right = spline->handle_types_right();
MutableSpan<float> radii = spline->radii();
MutableSpan<float> tilts = spline->tilts();

View File

@ -172,7 +172,8 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info,
}
}
if (fill_caps && profile.is_cyclic()) {
const bool has_caps = fill_caps && profile.is_cyclic() && !spline.is_cyclic();
if (has_caps) {
const int poly_size = info.spline_edge_len * info.profile_edge_len;
const int cap_loop_offset = info.loop_offset + poly_size * 4;
const int cap_poly_offset = info.poly_offset + poly_size;
@ -225,7 +226,7 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info,
}
/* Mark edge loops from sharp vector control points sharp. */
if (profile.type() == Spline::Type::Bezier) {
if (profile.type() == CURVE_TYPE_BEZIER) {
const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(profile);
Span<int> control_point_offsets = bezier_spline.control_point_offsets();
for (const int i : IndexRange(bezier_spline.size())) {
@ -256,7 +257,8 @@ static inline int spline_extrude_loop_size(const Spline &curve,
const bool fill_caps)
{
const int tube = curve.evaluated_edges_size() * profile.evaluated_edges_size() * 4;
const int caps = (fill_caps && profile.is_cyclic()) ? profile.evaluated_edges_size() * 2 : 0;
const bool has_caps = fill_caps && profile.is_cyclic() && !curve.is_cyclic();
const int caps = has_caps ? profile.evaluated_edges_size() * 2 : 0;
return tube + caps;
}
@ -265,7 +267,8 @@ static inline int spline_extrude_poly_size(const Spline &curve,
const bool fill_caps)
{
const int tube = curve.evaluated_edges_size() * profile.evaluated_edges_size();
const int caps = (fill_caps && profile.is_cyclic()) ? 2 : 0;
const bool has_caps = fill_caps && profile.is_cyclic() && !curve.is_cyclic();
const int caps = has_caps ? 2 : 0;
return tube + caps;
}

View File

@ -114,6 +114,7 @@ static void curves_foreach_id(ID *id, LibraryForeachIDData *data)
for (int i = 0; i < curves->totcol; i++) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, curves->mat[i], IDWALK_CB_USER);
}
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, curves->surface, IDWALK_CB_NOP);
}
static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_address)
@ -186,6 +187,7 @@ static void curves_blend_read_lib(BlendLibReader *reader, ID *id)
for (int a = 0; a < curves->totcol; a++) {
BLO_read_id_address(reader, curves->id.lib, &curves->mat[a]);
}
BLO_read_id_address(reader, curves->id.lib, &curves->surface);
}
static void curves_blend_read_expand(BlendExpander *expander, ID *id)
@ -194,6 +196,7 @@ static void curves_blend_read_expand(BlendExpander *expander, ID *id)
for (int a = 0; a < curves->totcol; a++) {
BLO_expand(expander, curves->mat[a]);
}
BLO_expand(expander, curves->surface);
}
IDTypeInfo IDType_ID_CV = {
@ -358,16 +361,16 @@ static Curves *curves_evaluate_modifiers(struct Depsgraph *depsgraph,
curves = BKE_curves_copy_for_eval(curves, true);
}
/* Ensure we are not overwriting referenced data. */
CustomData_duplicate_referenced_layer_named(&curves->geometry.point_data,
CD_PROP_FLOAT3,
ATTR_POSITION,
curves->geometry.point_size);
update_custom_data_pointers(*curves);
/* Created deformed coordinates array on demand. */
mti->deformVerts(
md, &mectx, nullptr, curves->geometry.position, curves->geometry.point_size);
blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(
curves->geometry);
MutableSpan<float3> positions = geometry.positions();
mti->deformVerts(md,
&mectx,
nullptr,
reinterpret_cast<float(*)[3]>(positions.data()),
curves->geometry.point_size);
}
}

View File

@ -106,6 +106,15 @@ int CurvesGeometry::curves_size() const
{
return this->curve_size;
}
IndexRange CurvesGeometry::points_range() const
{
return IndexRange(this->points_size());
}
IndexRange CurvesGeometry::curves_range() const
{
return IndexRange(this->curves_size());
}
int CurvesGeometry::evaluated_points_size() const
{
/* TODO: Implement when there are evaluated points. */
@ -136,14 +145,13 @@ MutableSpan<int8_t> CurvesGeometry::curve_types()
nullptr,
this->curve_size,
ATTR_CURVE_TYPE.c_str());
BLI_assert(data != nullptr);
return {data, this->curve_size};
}
MutableSpan<float3> CurvesGeometry::positions()
{
CustomData_duplicate_referenced_layer(&this->point_data, CD_PROP_FLOAT3, this->point_size);
this->update_customdata_pointers();
this->position = (float(*)[3])CustomData_duplicate_referenced_layer_named(
&this->point_data, CD_PROP_FLOAT3, ATTR_POSITION.c_str(), this->point_size);
return {(float3 *)this->position, this->point_size};
}
Span<float3> CurvesGeometry::positions() const

View File

@ -1777,7 +1777,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 44: CD_RADIUS */
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 45: CD_PROP_INT8 */
{sizeof(int8_t), "MInt8Property", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
{sizeof(int8_t), "MInt8Property", 1, N_("Int8"), nullptr, nullptr, nullptr, nullptr, nullptr},
/* 46: CD_HAIRMAPPING */ /* UNUSED */
{-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 47: CD_PROP_COLOR */
@ -1959,10 +1959,10 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_EVERYTHING = {
/* vmask */ (CD_MASK_MVERT | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_NORMAL |
CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_ORCO |
CD_MASK_CLOTH_ORCO | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX |
CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_CREASE),
/* vmask */ (CD_MASK_MVERT | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT |
CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO |
CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK |
CD_MASK_PROP_ALL | CD_MASK_PROP_COLOR | CD_MASK_CREASE),
/* emask */
(CD_MASK_MEDGE | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_BWEIGHT | CD_MASK_CREASE |
CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
@ -1971,7 +1971,7 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL |
CD_MASK_PROP_ALL),
/* pmask */
(CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_NORMAL | CD_MASK_FACEMAP |
(CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP |
CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS),
/* lmask */
(CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_MLOOPUV |

View File

@ -263,7 +263,6 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
/* This should be ensured by cddata_masks we pass to code generating/giving us me_src now. */
BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != NULL);
BLI_assert(CustomData_get_layer(&me_src->pdata, CD_NORMAL) != NULL);
(void)me_src;
float(*loop_nors_dst)[3];
@ -318,15 +317,12 @@ static void data_transfer_dtdata_type_postprocess(Object *UNUSED(ob_src),
const int num_polys_dst = me_dst->totpoly;
MLoop *loops_dst = me_dst->mloop;
const int num_loops_dst = me_dst->totloop;
CustomData *pdata_dst = &me_dst->pdata;
CustomData *ldata_dst = &me_dst->ldata;
const float(*poly_nors_dst)[3] = CustomData_get_layer(pdata_dst, CD_NORMAL);
const float(*poly_nors_dst)[3] = BKE_mesh_poly_normals_ensure(me_dst);
float(*loop_nors_dst)[3] = CustomData_get_layer(ldata_dst, CD_NORMAL);
short(*custom_nors_dst)[2] = CustomData_get_layer(ldata_dst, CD_CUSTOMLOOPNORMAL);
BLI_assert(poly_nors_dst);
if (!custom_nors_dst) {
custom_nors_dst = CustomData_add_layer(
ldata_dst, CD_CUSTOMLOOPNORMAL, CD_CALLOC, NULL, num_loops_dst);
@ -1379,7 +1375,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
BLI_assert((ob_src != ob_dst) && (ob_src->type == OB_MESH) && (ob_dst->type == OB_MESH));
if (me_dst) {
dirty_nors_dst = (me_dst->runtime.cd_dirty_vert & CD_NORMAL) != 0;
dirty_nors_dst = BKE_mesh_vertex_normals_are_dirty(me_dst);
/* Never create needed custom layers on passed destination mesh
* (assumed to *not* be ob_dst->data, aka modifier case). */
use_create = false;

View File

@ -590,7 +590,7 @@ static float displist_calc_taper(Depsgraph *depsgraph,
Object *taperobj,
float fac)
{
if (taperobj == nullptr || taperobj->type != OB_CURVE) {
if (taperobj == nullptr || taperobj->type != OB_CURVES_LEGACY) {
return 1.0;
}
@ -1263,7 +1263,7 @@ static GeometrySet evaluate_curve_type_object(Depsgraph *depsgraph,
const bool for_render,
ListBase *r_dispbase)
{
BLI_assert(ELEM(ob->type, OB_CURVE, OB_FONT));
BLI_assert(ELEM(ob->type, OB_CURVES_LEGACY, OB_FONT));
const Curve *cu = (const Curve *)ob->data;
ListBase *deformed_nurbs = &ob->runtime.curve_cache->deformed_nurbs;
@ -1473,7 +1473,7 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
Object *ob,
const bool for_render)
{
BLI_assert(ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT));
BLI_assert(ELEM(ob->type, OB_SURF, OB_CURVES_LEGACY, OB_FONT));
Curve &cow_curve = *(Curve *)ob->data;
BKE_object_free_derived_caches(ob);

View File

@ -143,7 +143,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef
BLI_rng_srandom(eff->pd->rng, eff->pd->seed + cfra);
}
if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type == OB_CURVE) {
if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type == OB_CURVES_LEGACY) {
Curve *cu = eff->ob->data;
if (cu->flag & CU_PATH) {
if (eff->ob->runtime.curve_cache == NULL ||
@ -161,7 +161,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef
}
else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) {
eff->surmd = (SurfaceModifierData *)BKE_modifiers_findby_type(eff->ob, eModifierType_Surface);
if (eff->ob->type == OB_CURVE) {
if (eff->ob->type == OB_CURVES_LEGACY) {
eff->flag |= PE_USE_NORMAL_DATA;
}
}

View File

@ -3292,7 +3292,7 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds,
mpolys = me->mpoly;
mloops = me->mloop;
/* Get size (dimension) but considering scaling scaling. */
/* Get size (dimension) but considering scaling. */
copy_v3_v3(cell_size_scaled, fds->cell_size);
mul_v3_v3(cell_size_scaled, ob->scale);
madd_v3fl_v3fl_v3fl_v3i(min, fds->p0, cell_size_scaled, fds->res_min);

View File

@ -128,7 +128,7 @@ const Curve *CurveComponent::get_curve_for_render() const
return curve_for_render_;
}
curve_for_render_ = (Curve *)BKE_id_new_nomain(ID_CU, nullptr);
curve_for_render_ = (Curve *)BKE_id_new_nomain(ID_CU_LEGACY, nullptr);
curve_for_render_->curve_eval = curve_;
return curve_for_render_;
@ -420,15 +420,18 @@ static Array<float3> curve_normal_point_domain(const CurveEval &curve)
const Spline &spline = *splines[i];
MutableSpan spline_normals{normals.as_mutable_span().slice(offsets[i], spline.size())};
switch (splines[i]->type()) {
case Spline::Type::Bezier:
case CURVE_TYPE_BEZIER:
calculate_bezier_normals(static_cast<const BezierSpline &>(spline), spline_normals);
break;
case Spline::Type::Poly:
case CURVE_TYPE_POLY:
calculate_poly_normals(static_cast<const PolySpline &>(spline), spline_normals);
break;
case Spline::Type::NURBS:
case CURVE_TYPE_NURBS:
calculate_nurbs_normals(static_cast<const NURBSpline &>(spline), spline_normals);
break;
case CURVE_TYPE_CATMULL_ROM:
BLI_assert_unreachable();
break;
}
}
});
@ -447,7 +450,7 @@ VArray<float3> curve_normals_varray(const CurveComponent &component, const Attri
/* Use a reference to evaluated normals if possible to avoid an allocation and a copy.
* This is only possible when there is only one poly spline. */
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
if (splines.size() == 1 && splines.first()->type() == CURVE_TYPE_POLY) {
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
return VArray<float3>::ForSpan(spline.evaluated_normals());
}
@ -877,15 +880,7 @@ class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl<float3> {
{
const PointIndices indices = lookup_point_indices(offsets_, index);
Spline &spline = *splines_[indices.spline_index];
if (BezierSpline *bezier_spline = dynamic_cast<BezierSpline *>(&spline)) {
const float3 delta = value - bezier_spline->positions()[indices.point_index];
bezier_spline->handle_positions_left()[indices.point_index] += delta;
bezier_spline->handle_positions_right()[indices.point_index] += delta;
bezier_spline->positions()[indices.point_index] = value;
}
else {
spline.positions()[indices.point_index] = value;
}
spline.positions()[indices.point_index] = value;
}
void set_all(Span<float3> src) final
@ -894,20 +889,7 @@ class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl<float3> {
Spline &spline = *splines_[spline_index];
const int offset = offsets_[spline_index];
const int next_offset = offsets_[spline_index + 1];
if (BezierSpline *bezier_spline = dynamic_cast<BezierSpline *>(&spline)) {
MutableSpan<float3> positions = bezier_spline->positions();
MutableSpan<float3> handle_positions_left = bezier_spline->handle_positions_left();
MutableSpan<float3> handle_positions_right = bezier_spline->handle_positions_right();
for (const int i : IndexRange(next_offset - offset)) {
const float3 delta = src[offset + i] - positions[i];
handle_positions_left[i] += delta;
handle_positions_right[i] += delta;
positions[i] = src[offset + i];
}
}
else {
spline.positions().copy_from(src.slice(offset, next_offset - offset));
}
spline.positions().copy_from(src.slice(offset, next_offset - offset));
}
}
@ -955,7 +937,7 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
{
const PointIndices indices = lookup_point_indices(offsets_, index);
const Spline &spline = *splines_[indices.spline_index];
if (spline.type() == Spline::Type::Bezier) {
if (spline.type() == CURVE_TYPE_BEZIER) {
const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(spline);
return is_right_ ? bezier_spline.handle_positions_right()[indices.point_index] :
bezier_spline.handle_positions_left()[indices.point_index];
@ -967,13 +949,13 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
{
const PointIndices indices = lookup_point_indices(offsets_, index);
Spline &spline = *splines_[indices.spline_index];
if (spline.type() == Spline::Type::Bezier) {
if (spline.type() == CURVE_TYPE_BEZIER) {
BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline);
if (is_right_) {
bezier_spline.set_handle_position_right(indices.point_index, value);
bezier_spline.handle_positions_right()[indices.point_index] = value;
}
else {
bezier_spline.set_handle_position_left(indices.point_index, value);
bezier_spline.handle_positions_left()[indices.point_index] = value;
}
bezier_spline.mark_cache_invalid();
}
@ -983,18 +965,18 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
{
for (const int spline_index : splines_.index_range()) {
Spline &spline = *splines_[spline_index];
if (spline.type() == Spline::Type::Bezier) {
if (spline.type() == CURVE_TYPE_BEZIER) {
const int offset = offsets_[spline_index];
BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline);
if (is_right_) {
for (const int i : IndexRange(bezier_spline.size())) {
bezier_spline.set_handle_position_right(i, src[offset + i]);
bezier_spline.handle_positions_right()[i] = src[offset + i];
}
}
else {
for (const int i : IndexRange(bezier_spline.size())) {
bezier_spline.set_handle_position_left(i, src[offset + i]);
bezier_spline.handle_positions_left()[i] = src[offset + i];
}
}
bezier_spline.mark_cache_invalid();
@ -1024,7 +1006,7 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
{
Array<Span<float3>> spans(splines.size());
for (const int i : spans.index_range()) {
if (splines[i]->type() == Spline::Type::Bezier) {
if (splines[i]->type() == CURVE_TYPE_BEZIER) {
BezierSpline &bezier_spline = static_cast<BezierSpline &>(*splines[i]);
spans[i] = is_right ? bezier_spline.handle_positions_right() :
bezier_spline.handle_positions_left();
@ -1214,7 +1196,7 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo
/* Use the regular position virtual array when there aren't any Bezier splines
* to avoid the overhead of checking the spline type for every point. */
if (!curve->has_spline_with_type(Spline::Type::Bezier)) {
if (!curve->has_spline_with_type(CURVE_TYPE_BEZIER)) {
return BuiltinPointAttributeProvider<float3>::try_get_for_write(component);
}
@ -1255,7 +1237,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
return {};
}
if (!curve->has_spline_with_type(Spline::Type::Bezier)) {
if (!curve->has_spline_with_type(CURVE_TYPE_BEZIER)) {
return {};
}
@ -1273,7 +1255,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
return {};
}
if (!curve->has_spline_with_type(Spline::Type::Bezier)) {
if (!curve->has_spline_with_type(CURVE_TYPE_BEZIER)) {
return {};
}
@ -1304,7 +1286,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
return false;
}
return curve->has_spline_with_type(Spline::Type::Bezier) &&
return curve->has_spline_with_type(CURVE_TYPE_BEZIER) &&
component.attribute_domain_size(ATTR_DOMAIN_POINT) != 0;
}
};

View File

@ -632,7 +632,7 @@ bool BKE_object_has_geometry_set_instances(const Object *ob)
is_instance = ob->type != OB_VOLUME;
break;
case GEO_COMPONENT_TYPE_CURVE:
is_instance = !ELEM(ob->type, OB_CURVE, OB_FONT);
is_instance = !ELEM(ob->type, OB_CURVES_LEGACY, OB_FONT);
break;
}
if (is_instance) {

View File

@ -443,7 +443,7 @@ static void gpencil_convert_spline(Main *bmain,
}
if (sample > 0.0f) {
BKE_gpencil_stroke_sample(gpd, gps, sample, false);
BKE_gpencil_stroke_sample(gpd, gps, sample, false, 0);
}
/* Recalc fill geometry. */

View File

@ -202,8 +202,8 @@ static int stroke_march_next_point(const bGPDstroke *gps,
int next_point_index = index_next_pt;
bGPDspoint *pt = nullptr;
if (!(next_point_index < gps->totpoints)) {
return -1;
if (next_point_index == gps->totpoints) {
next_point_index = 0;
}
copy_v3_v3(step_start, current);
@ -211,15 +211,33 @@ static int stroke_march_next_point(const bGPDstroke *gps,
copy_v3_v3(point, &pt->x);
remaining_till_next = len_v3v3(point, step_start);
while (remaining_till_next < remaining_march) {
while (remaining_till_next < remaining_march && next_point_index) {
remaining_march -= remaining_till_next;
pt = &gps->points[next_point_index];
if (pt->flag & GP_SPOINT_TEMP_TAG) {
pt = &gps->points[next_point_index];
copy_v3_v3(result, &pt->x);
*pressure = gps->points[next_point_index].pressure;
*strength = gps->points[next_point_index].strength;
memcpy(vert_color, gps->points[next_point_index].vert_color, sizeof(float[4]));
*index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1);
*index_to = next_point_index;
*ratio_result = 1.0f;
next_point_index++;
return next_point_index == 0 ? gps->totpoints : next_point_index;
}
next_point_index++;
copy_v3_v3(point, &pt->x);
copy_v3_v3(step_start, point);
next_point_index++;
if (!(next_point_index < gps->totpoints)) {
next_point_index = gps->totpoints - 1;
break;
if (gps->flag & GP_STROKE_CYCLIC) {
next_point_index = 0;
}
else {
next_point_index = gps->totpoints - 1;
break;
}
}
pt = &gps->points[next_point_index];
copy_v3_v3(point, &pt->x);
@ -232,35 +250,37 @@ static int stroke_march_next_point(const bGPDstroke *gps,
*strength = gps->points[next_point_index].strength;
memcpy(vert_color, gps->points[next_point_index].vert_color, sizeof(float[4]));
*index_from = next_point_index - 1;
*index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1);
*index_to = next_point_index;
*ratio_result = 1.0f;
return 0;
}
*index_from = next_point_index == 0 ? (gps->totpoints - 1) : (next_point_index - 1);
*index_to = next_point_index;
float ratio = remaining_march / remaining_till_next;
interp_v3_v3v3(result, step_start, point, ratio);
*ratio_result = ratio;
*pressure = interpf(
gps->points[next_point_index].pressure, gps->points[next_point_index - 1].pressure, ratio);
gps->points[next_point_index].pressure, gps->points[*index_from].pressure, ratio);
*strength = interpf(
gps->points[next_point_index].strength, gps->points[next_point_index - 1].strength, ratio);
gps->points[next_point_index].strength, gps->points[*index_from].strength, ratio);
interp_v4_v4v4(vert_color,
gps->points[next_point_index - 1].vert_color,
gps->points[*index_from].vert_color,
gps->points[next_point_index].vert_color,
ratio);
*index_from = next_point_index - 1;
*index_to = next_point_index;
*ratio_result = ratio;
return next_point_index;
return next_point_index == 0 ? gps->totpoints : next_point_index;
}
static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
const int index_next_pt,
const float *current,
const float dist,
const float sharp_threshold,
float *result)
{
float remaining_till_next = 0.0f;
@ -270,8 +290,8 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
int next_point_index = index_next_pt;
bGPDspoint *pt = nullptr;
if (!(next_point_index < gps->totpoints)) {
return -1;
if (next_point_index == gps->totpoints) {
next_point_index = 0;
}
copy_v3_v3(step_start, current);
@ -279,15 +299,29 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
copy_v3_v3(point, &pt->x);
remaining_till_next = len_v3v3(point, step_start);
while (remaining_till_next < remaining_march) {
while (remaining_till_next < remaining_march && next_point_index) {
remaining_march -= remaining_till_next;
pt = &gps->points[next_point_index];
if (next_point_index < gps->totpoints - 1 &&
angle_v3v3v3(&gps->points[next_point_index - 1].x,
&gps->points[next_point_index].x,
&gps->points[next_point_index + 1].x) < sharp_threshold) {
copy_v3_v3(result, &pt->x);
pt->flag |= GP_SPOINT_TEMP_TAG;
next_point_index++;
return next_point_index == 0 ? gps->totpoints : next_point_index;
}
next_point_index++;
copy_v3_v3(point, &pt->x);
copy_v3_v3(step_start, point);
next_point_index++;
if (!(next_point_index < gps->totpoints)) {
next_point_index = gps->totpoints - 1;
break;
if (gps->flag & GP_STROKE_CYCLIC) {
next_point_index = 0;
}
else {
next_point_index = gps->totpoints - 1;
break;
}
}
pt = &gps->points[next_point_index];
copy_v3_v3(point, &pt->x);
@ -296,15 +330,16 @@ static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
if (remaining_till_next < remaining_march) {
pt = &gps->points[next_point_index];
copy_v3_v3(result, &pt->x);
/* Stroke marching only terminates here. */
return 0;
}
float ratio = remaining_march / remaining_till_next;
interp_v3_v3v3(result, step_start, point, ratio);
return next_point_index;
return next_point_index == 0 ? gps->totpoints : next_point_index;
}
static int stroke_march_count(const bGPDstroke *gps, const float dist)
static int stroke_march_count(const bGPDstroke *gps, const float dist, const float sharp_threshold)
{
int point_count = 0;
float point[3];
@ -315,8 +350,13 @@ static int stroke_march_count(const bGPDstroke *gps, const float dist)
copy_v3_v3(point, &pt->x);
point_count++;
/* Sharp points will be tagged by the stroke_march_next_point_no_interp() call below. */
for (int i = 0; i < gps->totpoints; i++) {
gps->points[i].flag &= (~GP_SPOINT_TEMP_TAG);
}
while ((next_point_index = stroke_march_next_point_no_interp(
gps, next_point_index, point, dist, point)) > -1) {
gps, next_point_index, point, dist, sharp_threshold, point)) > -1) {
point_count++;
if (next_point_index == 0) {
break; /* last point finished */
@ -394,7 +434,11 @@ static void stroke_interpolate_deform_weights(
}
}
bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist, const bool select)
bool BKE_gpencil_stroke_sample(bGPdata *gpd,
bGPDstroke *gps,
const float dist,
const bool select,
const float sharp_threshold)
{
bGPDspoint *pt = gps->points;
bGPDspoint *pt1 = nullptr;
@ -406,7 +450,7 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist,
return false;
}
/* TODO: Implement feature point preservation. */
int count = stroke_march_count(gps, dist);
int count = stroke_march_count(gps, dist, sharp_threshold);
bGPDspoint *new_pt = (bGPDspoint *)MEM_callocN(sizeof(bGPDspoint) * count,
"gp_stroke_points_sampled");
@ -491,6 +535,8 @@ bool BKE_gpencil_stroke_sample(bGPdata *gpd, bGPDstroke *gps, const float dist,
gps->totpoints = i;
gps->flag &= (~GP_STROKE_CYCLIC);
/* Calc geometry data. */
BKE_gpencil_stroke_geometry_update(gpd, gps);

View File

@ -59,7 +59,7 @@ static void id_type_init(void)
INIT_TYPE(ID_LI);
INIT_TYPE(ID_OB);
INIT_TYPE(ID_ME);
INIT_TYPE(ID_CU);
INIT_TYPE(ID_CU_LEGACY);
INIT_TYPE(ID_MB);
INIT_TYPE(ID_MA);
INIT_TYPE(ID_TE);
@ -215,7 +215,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(BR);
CASE_IDFILTER(CA);
CASE_IDFILTER(CF);
CASE_IDFILTER(CU);
CASE_IDFILTER(CU_LEGACY);
CASE_IDFILTER(GD);
CASE_IDFILTER(GR);
CASE_IDFILTER(CV);
@ -264,7 +264,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
CASE_IDFILTER(BR);
CASE_IDFILTER(CA);
CASE_IDFILTER(CF);
CASE_IDFILTER(CU);
CASE_IDFILTER(CU_LEGACY);
CASE_IDFILTER(GD);
CASE_IDFILTER(GR);
CASE_IDFILTER(CV);
@ -312,7 +312,7 @@ int BKE_idtype_idcode_to_index(const short idcode)
CASE_IDINDEX(BR);
CASE_IDINDEX(CA);
CASE_IDINDEX(CF);
CASE_IDINDEX(CU);
CASE_IDINDEX(CU_LEGACY);
CASE_IDINDEX(GD);
CASE_IDINDEX(GR);
CASE_IDINDEX(CV);
@ -371,7 +371,7 @@ short BKE_idtype_idcode_from_index(const int index)
CASE_IDCODE(BR);
CASE_IDCODE(CA);
CASE_IDCODE(CF);
CASE_IDCODE(CU);
CASE_IDCODE(CU_LEGACY);
CASE_IDCODE(GD);
CASE_IDCODE(GR);
CASE_IDCODE(CV);

View File

@ -1090,7 +1090,7 @@ static char *get_rna_access(ID *id,
propname = particle_adrcodes_to_paths(adrcode, &dummy_index);
break;
case ID_CU: /* curve */
case ID_CU_LEGACY: /* curve */
/* this used to be a 'dummy' curve which got evaluated on the fly...
* now we've got real var for this!
*/

View File

@ -281,7 +281,7 @@ Key *BKE_key_add(Main *bmain, ID *id) /* common function */
key->elemsize = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
break;
case ID_CU:
case ID_CU_LEGACY:
el = key->elemstr;
el[0] = KEYELEM_ELEM_SIZE_CURVE;
@ -659,7 +659,7 @@ static bool key_pointer_size(const Key *key, const int mode, int *poinsize, int
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
*poinsize = *ofs;
break;
case ID_CU:
case ID_CU_LEGACY:
if (mode == KEY_MODE_BPOINT) {
*ofs = sizeof(float[KEYELEM_FLOAT_LEN_BPOINT]);
*step = KEYELEM_ELEM_LEN_BPOINT;
@ -1524,7 +1524,7 @@ float *BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t
tot = lt->pntsu * lt->pntsv * lt->pntsw;
size = tot * sizeof(float[KEYELEM_FLOAT_LEN_COORD]);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
Curve *cu = ob->data;
tot = BKE_keyblock_curve_element_count(&cu->nurb);
@ -1570,7 +1570,7 @@ float *BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t
MEM_freeN(weights);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
cp_cu_key(ob->data, key, actkb, kb, 0, tot, out, tot);
}
}
@ -1582,7 +1582,7 @@ float *BKE_key_evaluate_object_ex(Object *ob, int *r_totelem, float *arr, size_t
else if (ob->type == OB_LATTICE) {
do_latt_key(ob, key, out, tot);
}
else if (ob->type == OB_CURVE) {
else if (ob->type == OB_CURVES_LEGACY) {
do_curve_key(ob, key, out, tot);
}
else if (ob->type == OB_SURF) {
@ -1714,7 +1714,7 @@ bool BKE_key_idtype_support(const short id_type)
{
switch (id_type) {
case ID_ME:
case ID_CU:
case ID_CU_LEGACY:
case ID_LT:
return true;
default:
@ -1729,7 +1729,7 @@ Key **BKE_key_from_id_p(ID *id)
Mesh *me = (Mesh *)id;
return &me->key;
}
case ID_CU: {
case ID_CU_LEGACY: {
Curve *cu = (Curve *)id;
if (cu->vfont == NULL) {
return &cu->key;
@ -2269,7 +2269,7 @@ void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, const float (*ve
Lattice *lt = ob->data;
BLI_assert((lt->pntsu * lt->pntsv * lt->pntsw) == kb->totelem);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
Curve *cu = ob->data;
BLI_assert(BKE_keyblock_curve_element_count(&cu->nurb) == kb->totelem);
}
@ -2293,7 +2293,7 @@ void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, const float (*ve
copy_v3_v3(fp, *co);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
Curve *cu = (Curve *)ob->data;
Nurb *nu;
BezTriple *bezt;
@ -2335,7 +2335,7 @@ void BKE_keyblock_convert_from_vertcos(Object *ob, KeyBlock *kb, const float (*v
tot = lt->pntsu * lt->pntsv * lt->pntsw;
elemsize = lt->key->elemsize;
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
Curve *cu = (Curve *)ob->data;
elemsize = cu->key->elemsize;
tot = BKE_keyblock_curve_element_count(&cu->nurb);
@ -2366,7 +2366,7 @@ float (*BKE_keyblock_convert_to_vertcos(Object *ob, KeyBlock *kb))[3]
Lattice *lt = (Lattice *)ob->data;
tot = lt->pntsu * lt->pntsv * lt->pntsw;
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
Curve *cu = (Curve *)ob->data;
tot = BKE_nurbList_verts_count(&cu->nurb);
}
@ -2383,7 +2383,7 @@ float (*BKE_keyblock_convert_to_vertcos(Object *ob, KeyBlock *kb))[3]
copy_v3_v3(*co, fp);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
Curve *cu = (Curve *)ob->data;
Nurb *nu;
BezTriple *bezt;
@ -2422,7 +2422,7 @@ void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, const float (*ofs
add_v3_v3(fp, *ofs);
}
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF)) {
Curve *cu = (Curve *)ob->data;
Nurb *nu;
BezTriple *bezt;

View File

@ -67,9 +67,11 @@ Object **BKE_view_layer_array_selected_objects_params(
}
FOREACH_SELECTED_OBJECT_END;
object_array = MEM_reallocN(object_array, sizeof(*object_array) * BLI_array_len(object_array));
/* We always need a valid allocation (prevent crash on free). */
if (object_array == NULL) {
if (object_array != NULL) {
BLI_array_trim(object_array);
}
else {
/* We always need a valid allocation (prevent crash on free). */
object_array = MEM_mallocN(0, __func__);
}
*r_len = BLI_array_len(object_array);
@ -121,9 +123,11 @@ Base **BKE_view_layer_array_from_bases_in_mode_params(ViewLayer *view_layer,
}
FOREACH_BASE_IN_MODE_END;
base_array = MEM_reallocN(base_array, sizeof(*base_array) * BLI_array_len(base_array));
/* We always need a valid allocation (prevent crash on free). */
if (base_array == NULL) {
if (base_array != NULL) {
BLI_array_trim(base_array);
}
else {
base_array = MEM_mallocN(0, __func__);
}
*r_len = BLI_array_len(base_array);

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